Skip to content

Commit 1151699

Browse files
committed
Configure GraalVM profile for idempotency-dynamodb. Refactor unit tests to treat DynamoDBLocal as external process instead of starting it via JVM which is not compatible with GraalVM.
1 parent 6c8d6c6 commit 1151699

File tree

6 files changed

+264
-181
lines changed

6 files changed

+264
-181
lines changed

pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,11 @@
443443
<artifactId>maven-gpg-plugin</artifactId>
444444
<version>${maven-gpg-plugin.version}</version>
445445
</plugin>
446+
<plugin>
447+
<groupId>org.codehaus.mojo</groupId>
448+
<artifactId>exec-maven-plugin</artifactId>
449+
<version>3.5.1</version>
450+
</plugin>
446451
</plugins>
447452
</pluginManagement>
448453
<plugins>

powertools-idempotency/powertools-idempotency-dynamodb/pom.xml

Lines changed: 148 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,29 @@
6363
</dependency>
6464

6565
<!-- Test dependencies -->
66+
<dependency>
67+
<groupId>org.junit.jupiter</groupId>
68+
<artifactId>junit-jupiter-api</artifactId>
69+
<scope>test</scope>
70+
</dependency>
71+
<dependency>
72+
<groupId>org.junit.jupiter</groupId>
73+
<artifactId>junit-jupiter-engine</artifactId>
74+
<scope>test</scope>
75+
</dependency>
76+
<dependency>
77+
<groupId>org.slf4j</groupId>
78+
<artifactId>slf4j-simple</artifactId>
79+
<scope>test</scope>
80+
</dependency>
81+
<dependency>
82+
<groupId>software.amazon.lambda</groupId>
83+
<artifactId>powertools-common</artifactId>
84+
<version>${project.version}</version>
85+
<type>test-jar</type>
86+
<scope>test</scope>
87+
</dependency>
88+
<!-- DynamoDB Local for testing -->
6689
<dependency>
6790
<groupId>com.amazonaws</groupId>
6891
<artifactId>DynamoDBLocal</artifactId>
@@ -71,17 +94,124 @@
7194
<version>2.2.0</version>
7295
<scope>test</scope>
7396
</dependency>
74-
<!--Needed when building locally on M1 Mac-->
75-
<dependency>
76-
<groupId>io.github.ganadist.sqlite4java</groupId>
77-
<artifactId>libsqlite4java-osx-aarch64</artifactId>
78-
<version>1.0.392</version>
79-
<scope>test</scope>
80-
<type>dylib</type>
81-
</dependency>
8297
</dependencies>
98+
99+
<profiles>
100+
<profile>
101+
<id>generate-graalvm-files</id>
102+
<build>
103+
<plugins>
104+
<plugin>
105+
<groupId>org.apache.maven.plugins</groupId>
106+
<artifactId>maven-surefire-plugin</artifactId>
107+
<configuration>
108+
<argLine>
109+
-Dorg.graalvm.nativeimage.imagecode=agent
110+
-agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-idempotency-dynamodb,experimental-class-define-support
111+
--add-opens java.base/java.util=ALL-UNNAMED
112+
--add-opens java.base/java.lang=ALL-UNNAMED
113+
</argLine>
114+
</configuration>
115+
</plugin>
116+
</plugins>
117+
</build>
118+
</profile>
119+
<profile>
120+
<id>graalvm-native</id>
121+
<build>
122+
<plugins>
123+
<plugin>
124+
<groupId>org.graalvm.buildtools</groupId>
125+
<artifactId>native-maven-plugin</artifactId>
126+
<version>0.11.0</version>
127+
<extensions>true</extensions>
128+
<executions>
129+
<execution>
130+
<id>test-native</id>
131+
<goals>
132+
<goal>test</goal>
133+
</goals>
134+
<phase>test</phase>
135+
</execution>
136+
</executions>
137+
<configuration>
138+
<imageName>powertools-idempotency-dynamodb</imageName>
139+
<exclusions>
140+
<exclusion>
141+
<groupId>com.amazonaws</groupId>
142+
<artifactId>DynamoDBLocal</artifactId>
143+
</exclusion>
144+
</exclusions>
145+
<buildArgs>
146+
<buildArg>--add-opens java.base/java.util=ALL-UNNAMED</buildArg>
147+
<buildArg>--add-opens java.base/java.lang=ALL-UNNAMED</buildArg>
148+
<buildArg>--enable-url-protocols=http</buildArg>
149+
<buildArg>--no-fallback</buildArg>
150+
<buildArg>--verbose</buildArg>
151+
<buildArg>--native-image-info</buildArg>
152+
<buildArg>-H:+UnlockExperimentalVMOptions</buildArg>
153+
<buildArg>-H:Log=registerResource:5</buildArg>
154+
<buildArg>-H:+ReportExceptionStackTraces</buildArg>
155+
</buildArgs>
156+
</configuration>
157+
</plugin>
158+
</plugins>
159+
</build>
160+
</profile>
161+
</profiles>
162+
83163
<build>
84164
<plugins>
165+
<!-- Copy DynamoDB Local JAR -->
166+
<plugin>
167+
<groupId>org.apache.maven.plugins</groupId>
168+
<artifactId>maven-dependency-plugin</artifactId>
169+
<executions>
170+
<execution>
171+
<id>copy-dynamodb-local</id>
172+
<phase>generate-test-resources</phase>
173+
<goals>
174+
<goal>copy-dependencies</goal>
175+
</goals>
176+
<configuration>
177+
<includeScope>test</includeScope>
178+
<excludeTransitive>false</excludeTransitive>
179+
<includeGroupIds>
180+
com.amazonaws,software.amazon.awssdk,org.eclipse.jetty,com.fasterxml.jackson.core,com.fasterxml.jackson.dataformat,com.fasterxml.jackson.datatype,com.almworks.sqlite4java,commons-cli,org.apache.commons,commons-logging,org.apache.logging.log4j,org.slf4j,org.reactivestreams,org.antlr,com.google.guava,jakarta.transaction</includeGroupIds>
181+
<outputDirectory>${project.build.directory}/dynamodb-local</outputDirectory>
182+
</configuration>
183+
</execution>
184+
</executions>
185+
</plugin>
186+
<!-- Start DynamoDB Local before tests -->
187+
<plugin>
188+
<groupId>org.codehaus.mojo</groupId>
189+
<artifactId>exec-maven-plugin</artifactId>
190+
<executions>
191+
<execution>
192+
<id>start-dynamodb-local</id>
193+
<phase>process-test-classes</phase>
194+
<goals>
195+
<goal>exec</goal>
196+
</goals>
197+
<configuration>
198+
<executable>java</executable>
199+
<workingDirectory>${project.build.directory}/dynamodb-local</workingDirectory>
200+
<arguments>
201+
<argument>-Djava.library.path=${project.build.directory}/dynamodb-local</argument>
202+
<argument>-cp</argument>
203+
<argument>${project.build.directory}/dynamodb-local/*</argument>
204+
<argument>com.amazonaws.services.dynamodbv2.local.main.ServerRunner</argument>
205+
<argument>-inMemory</argument>
206+
<argument>-port</argument>
207+
<argument>8000</argument>
208+
</arguments>
209+
<async>true</async>
210+
<asyncDestroyOnShutdown>true</asyncDestroyOnShutdown>
211+
</configuration>
212+
</execution>
213+
</executions>
214+
</plugin>
85215
<plugin>
86216
<groupId>org.apache.maven.plugins</groupId>
87217
<artifactId>maven-jar-plugin</artifactId>
@@ -94,6 +224,16 @@
94224
</archive>
95225
</configuration>
96226
</plugin>
227+
<!-- Configure Surefire to expose external DynamoDB Local address -->
228+
<plugin>
229+
<groupId>org.apache.maven.plugins</groupId>
230+
<artifactId>maven-surefire-plugin</artifactId>
231+
<configuration>
232+
<systemPropertyVariables>
233+
<dynamodb.endpoint>http://localhost:8000</dynamodb.endpoint>
234+
</systemPropertyVariables>
235+
</configuration>
236+
</plugin>
97237
<plugin>
98238
<groupId>dev.aspectj</groupId>
99239
<artifactId>aspectj-maven-plugin</artifactId>

powertools-idempotency/powertools-idempotency-dynamodb/src/test/java/software/amazon/lambda/powertools/idempotency/persistence/dynamodb/DynamoDBConfig.java

Lines changed: 16 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,10 @@
1414

1515
package software.amazon.lambda.powertools.idempotency.persistence.dynamodb;
1616

17-
import java.io.IOException;
18-
import java.net.ServerSocket;
1917
import java.net.URI;
2018

21-
import org.junit.jupiter.api.AfterAll;
2219
import org.junit.jupiter.api.BeforeAll;
2320

24-
import com.amazonaws.services.dynamodbv2.local.main.ServerRunner;
25-
import com.amazonaws.services.dynamodbv2.local.server.DynamoDBProxyServer;
26-
2721
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
2822
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
2923
import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient;
@@ -32,71 +26,40 @@
3226
import software.amazon.awssdk.services.dynamodb.model.AttributeDefinition;
3327
import software.amazon.awssdk.services.dynamodb.model.BillingMode;
3428
import software.amazon.awssdk.services.dynamodb.model.CreateTableRequest;
35-
import software.amazon.awssdk.services.dynamodb.model.DescribeTableRequest;
36-
import software.amazon.awssdk.services.dynamodb.model.DescribeTableResponse;
3729
import software.amazon.awssdk.services.dynamodb.model.KeySchemaElement;
3830
import software.amazon.awssdk.services.dynamodb.model.KeyType;
31+
import software.amazon.awssdk.services.dynamodb.model.ResourceInUseException;
3932
import software.amazon.awssdk.services.dynamodb.model.ScalarAttributeType;
4033

41-
public class DynamoDBConfig {
34+
class DynamoDBConfig {
4235
protected static final String TABLE_NAME = "idempotency_table";
43-
protected static DynamoDBProxyServer dynamoProxy;
4436
protected static DynamoDbClient client;
4537

4638
@BeforeAll
47-
public static void setupDynamo() {
48-
int port = getFreePort();
49-
try {
50-
dynamoProxy = ServerRunner.createServerFromCommandLineArgs(new String[] {
51-
"-inMemory",
52-
"-port",
53-
Integer.toString(port)
54-
});
55-
dynamoProxy.start();
56-
} catch (Exception e) {
57-
throw new RuntimeException();
58-
}
39+
static void setupDynamo() {
40+
String endpoint = System.getProperty("dynamodb.endpoint", "http://localhost:8000");
5941

6042
client = DynamoDbClient.builder()
6143
.httpClient(UrlConnectionHttpClient.builder().build())
6244
.region(Region.EU_WEST_1)
63-
.endpointOverride(URI.create("http://localhost:" + port))
45+
.endpointOverride(URI.create(endpoint))
6446
.credentialsProvider(StaticCredentialsProvider.create(
6547
AwsBasicCredentials.create("FAKE", "FAKE")))
6648
.build();
6749

68-
client.createTable(CreateTableRequest.builder()
69-
.tableName(TABLE_NAME)
70-
.keySchema(KeySchemaElement.builder().keyType(KeyType.HASH).attributeName("id").build())
71-
.attributeDefinitions(
72-
AttributeDefinition.builder().attributeName("id").attributeType(ScalarAttributeType.S).build())
73-
.billingMode(BillingMode.PAY_PER_REQUEST)
74-
.build());
75-
76-
DescribeTableResponse response = client
77-
.describeTable(DescribeTableRequest.builder().tableName(TABLE_NAME).build());
78-
if (response == null) {
79-
throw new RuntimeException("Table was not created within expected time");
80-
}
81-
}
82-
83-
@AfterAll
84-
public static void teardownDynamo() {
8550
try {
86-
dynamoProxy.stop();
51+
client.createTable(CreateTableRequest.builder()
52+
.tableName(TABLE_NAME)
53+
.keySchema(KeySchemaElement.builder().keyType(KeyType.HASH).attributeName("id").build())
54+
.attributeDefinitions(
55+
AttributeDefinition.builder().attributeName("id").attributeType(ScalarAttributeType.S)
56+
.build())
57+
.billingMode(BillingMode.PAY_PER_REQUEST)
58+
.build());
59+
} catch (ResourceInUseException e) {
60+
// Table already exists, ignore
8761
} catch (Exception e) {
88-
throw new RuntimeException();
89-
}
90-
}
91-
92-
private static int getFreePort() {
93-
try {
94-
ServerSocket socket = new ServerSocket(0);
95-
int port = socket.getLocalPort();
96-
socket.close();
97-
return port;
98-
} catch (IOException ioe) {
99-
throw new RuntimeException(ioe);
62+
throw new RuntimeException("Failed to create DynamoDB table", e);
10063
}
10164
}
10265
}

0 commit comments

Comments
 (0)