Skip to content

Commit e57dae0

Browse files
committed
feat(serialization): Split SAM and SAM native example
1 parent 11b42fb commit e57dae0

File tree

32 files changed

+720
-3
lines changed

32 files changed

+720
-3
lines changed

examples/pom.xml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@
3838
<module>powertools-examples-idempotency</module>
3939
<module>powertools-examples-parameters/sam</module>
4040
<module>powertools-examples-parameters/sam-graalvm</module>
41-
<module>powertools-examples-serialization</module>
41+
<module>powertools-examples-serialization/sam</module>
42+
<module>powertools-examples-serialization/sam-graalvm</module>
4243
<module>powertools-examples-kafka</module>
4344
<module>powertools-examples-batch</module>
4445
<module>powertools-examples-validation</module>
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#Use the official AWS SAM base image for Java 21
2+
FROM public.ecr.aws/sam/build-java21:latest
3+
4+
#Install GraalVM dependencies
5+
RUN curl -4 -L curl https://download.oracle.com/graalvm/21/latest/graalvm-jdk-21_linux-x64_bin.tar.gz | tar -xvz
6+
RUN mv graalvm-jdk-21.* /usr/lib/graalvm
7+
8+
#Make native image and mvn available on CLI
9+
RUN ln -s /usr/lib/graalvm/bin/native-image /usr/bin/native-image
10+
RUN ln -s /usr/lib/maven/bin/mvn /usr/bin/mvn
11+
12+
#Set GraalVM as default
13+
ENV JAVA_HOME=/usr/lib/graalvm
14+
ENV PATH=/usr/lib/graalvm/bin:$PATH
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
build-APIGatewayDeserializationFunction:
2+
#mvn clean package -P native-image
3+
chmod +x target/hello-world
4+
cp target/hello-world $(ARTIFACTS_DIR) # (ARTIFACTS_DIR --> https://github.com/aws/aws-lambda-builders/blob/develop/aws_lambda_builders/workflows/custom_make/DESIGN.md#implementation)
5+
chmod +x src/main/config/bootstrap
6+
cp src/main/config/bootstrap $(ARTIFACTS_DIR)
7+
8+
build-SQSEventDeserializationFunction:
9+
#mvn clean package -P native-image
10+
chmod +x target/hello-world
11+
cp target/hello-world $(ARTIFACTS_DIR) # (ARTIFACTS_DIR --> https://github.com/aws/aws-lambda-builders/blob/develop/aws_lambda_builders/workflows/custom_make/DESIGN.md#implementation)
12+
chmod +x src/main/config/bootstrap
13+
cp src/main/config/bootstrap $(ARTIFACTS_DIR)
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
# Powertools for AWS Lambda (Java) - Serialization Example
2+
3+
This project contains an example of Lambda function using the serialization utilities module of Powertools for AWS Lambda (Java). For more information on this module, please refer to the [documentation](https://docs.powertools.aws.dev/lambda-java/utilities/serialization/).
4+
5+
The project contains two `RequestHandler`s -
6+
7+
* [APIGatewayRequestDeserializationFunction](src/main/java/org/demo/serialization/APIGatewayRequestDeserializationFunction.java) - Uses the serialization library to deserialize an API Gateway request body
8+
* [SQSEventDeserializationFunction](src/main/java/org/demo/serialization/SQSEventDeserializationFunction.java) - Uses the serialization library to deserialize an SQS message body
9+
10+
In both cases, the output of the serialized message will be printed to the function logs. The message format
11+
in JSON looks like this:
12+
13+
```json
14+
{
15+
"id":1234,
16+
"name":"product",
17+
"price":42
18+
}
19+
```
20+
21+
## Deploy the sample application
22+
23+
This sample is based on Serverless Application Model (SAM). To deploy it, check out the instructions for getting
24+
started with SAM in [the examples directory](../../README.md)
25+
26+
## Test the application
27+
28+
### 1. API Gateway Endpoint
29+
30+
To test the HTTP endpoint, we can post a product to the test URL:
31+
32+
```bash
33+
curl -X POST https://gct1q3gaw0.execute-api.eu-west-1.amazonaws.com/Prod/product/ -H "Content-Type: application/json" -d '{"id": 1234, "name": "product", "price": 42}'
34+
```
35+
36+
The result will indicate that the handler has successfully deserialized the request body:
37+
38+
```
39+
Received request for productId: 1234
40+
```
41+
42+
If we look at the logs using `sam logs --tail --stack-name $MY_STACK`, we will see the full deserialized request:
43+
44+
```json
45+
{
46+
...
47+
"level": "INFO",
48+
"loggerName": "org.demo.serialization.APIGatewayRequestDeserializationFunction",
49+
"message": "product=Product{id=1234, name='product', price=42.0}\n",
50+
...
51+
}
52+
```
53+
54+
### 2. SQS Queue
55+
For the SQS handler, we have to send a request to our queue. We can either construct the Queue URL (see below), or
56+
find it from the SQS section of the AWS console.
57+
58+
```bash
59+
aws sqs send-message --queue-url "https://sqs.[REGION].amazonaws.com/[ACCOUNT-ID]/sqs-event-deserialization-queue" --message-body '{"id": 1234, "name": "product", "price": 123}'
60+
```
61+
62+
Here we can find the message by filtering through the logs for messages that have come back from our SQS handler:
63+
64+
```bash
65+
sam logs --tail --stack-name $MY_STACK --filter SQS
66+
```
67+
68+
```bash
69+
{
70+
...
71+
"level": "INFO",
72+
"loggerName": "org.demo.serialization.SQSEventDeserializationFunction",
73+
"message": "products=[Product{id=1234, name='product', price=42.0}]\n",
74+
...
75+
}
76+
77+
```
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
2+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
3+
<modelVersion>4.0.0</modelVersion>
4+
<groupId>software.amazon.lambda.examples</groupId>
5+
<version>2.1.0</version>
6+
<artifactId>powertools-examples-serialization-sam-graalvm</artifactId>
7+
<packaging>jar</packaging>
8+
<name>Powertools for AWS Lambda (Java) - Examples - Serialization GraalVM</name>
9+
10+
<properties>
11+
<maven.compiler.source>11</maven.compiler.source>
12+
<maven.compiler.target>11</maven.compiler.target>
13+
</properties>
14+
15+
<dependencies>
16+
<dependency>
17+
<groupId>software.amazon.lambda</groupId>
18+
<artifactId>powertools-logging-log4j</artifactId>
19+
<version>${project.version}</version>
20+
</dependency>
21+
<dependency>
22+
<groupId>software.amazon.lambda</groupId>
23+
<artifactId>powertools-serialization</artifactId>
24+
<version>${project.version}</version>
25+
</dependency>
26+
<dependency>
27+
<groupId>com.amazonaws</groupId>
28+
<artifactId>aws-lambda-java-core</artifactId>
29+
<version>1.2.3</version>
30+
</dependency>
31+
<dependency>
32+
<groupId>com.amazonaws</groupId>
33+
<artifactId>aws-lambda-java-events</artifactId>
34+
<version>3.15.0</version>
35+
</dependency>
36+
<dependency>
37+
<groupId>com.amazonaws</groupId>
38+
<artifactId>aws-lambda-java-runtime-interface-client</artifactId>
39+
<version>2.1.1</version>
40+
</dependency>
41+
</dependencies>
42+
43+
<build>
44+
<plugins>
45+
<!-- Don't deploy the example -->
46+
<plugin>
47+
<groupId>org.apache.maven.plugins</groupId>
48+
<artifactId>maven-deploy-plugin</artifactId>
49+
<version>3.1.2</version>
50+
<configuration>
51+
<skip>true</skip>
52+
</configuration>
53+
</plugin>
54+
</plugins>
55+
</build>
56+
<profiles>
57+
<profile>
58+
<id>native-image</id>
59+
<build>
60+
<plugins>
61+
<plugin>
62+
<groupId>org.graalvm.buildtools</groupId>
63+
<artifactId>native-maven-plugin</artifactId>
64+
<version>0.10.1</version>
65+
<extensions>true</extensions>
66+
<executions>
67+
<execution>
68+
<id>build-native</id>
69+
<goals>
70+
<goal>build</goal>
71+
</goals>
72+
<phase>package</phase>
73+
</execution>
74+
</executions>
75+
<configuration>
76+
<imageName>hello-world</imageName>
77+
<mainClass>com.amazonaws.services.lambda.runtime.api.client.AWSLambda</mainClass>
78+
<buildArgs>
79+
<!-- required for AWS Lambda Runtime Interface Client -->
80+
<arg>--enable-url-protocols=http</arg>
81+
<arg>--add-opens java.base/java.util=ALL-UNNAMED</arg>
82+
</buildArgs>
83+
</configuration>
84+
</plugin>
85+
</plugins>
86+
</build>
87+
</profile>
88+
</profiles>
89+
</project>
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#!/bin/bash
2+
set -e
3+
4+
./hello-world $_HANDLER
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
[
2+
{
3+
"name":"com.amazonaws.services.lambda.runtime.LambdaRuntime",
4+
"methods":[{"name":"<init>","parameterTypes":[] }],
5+
"fields":[{"name":"logger"}],
6+
"allPublicMethods":true
7+
},
8+
{
9+
"name":"com.amazonaws.services.lambda.runtime.LambdaRuntimeInternal",
10+
"methods":[{"name":"<init>","parameterTypes":[] }],
11+
"allPublicMethods":true
12+
}
13+
]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
[
2+
{
3+
"name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent",
4+
"allDeclaredFields": true,
5+
"allDeclaredMethods": true,
6+
"allDeclaredConstructors": true
7+
},
8+
{
9+
"name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent$ProxyRequestContext",
10+
"allDeclaredFields": true,
11+
"allDeclaredMethods": true,
12+
"allDeclaredConstructors": true
13+
},
14+
{
15+
"name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent$RequestIdentity",
16+
"allDeclaredFields": true,
17+
"allDeclaredMethods": true,
18+
"allDeclaredConstructors": true
19+
},
20+
{
21+
"name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent",
22+
"allDeclaredFields": true,
23+
"allDeclaredMethods": true,
24+
"allDeclaredConstructors": true
25+
},
26+
{
27+
"name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent",
28+
"allDeclaredConstructors": true,
29+
"allPublicConstructors": true,
30+
"allDeclaredMethods": true,
31+
"allPublicMethods": true,
32+
"allDeclaredClasses": true,
33+
"allPublicClasses": true
34+
}
35+
]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
[
2+
{
3+
"name":"com.amazonaws.services.lambda.runtime.api.client.runtimeapi.LambdaRuntimeClientException",
4+
"methods":[{"name":"<init>","parameterTypes":["java.lang.String","int"] }]
5+
},
6+
{
7+
"name":"com.amazonaws.services.lambda.runtime.api.client.runtimeapi.InvocationRequest",
8+
"fields":[{"name":"id"}, {"name":"invokedFunctionArn"}, {"name":"deadlineTimeInMs"}, {"name":"xrayTraceId"}, {"name":"clientContext"}, {"name":"cognitoIdentity"}, {"name":"content"}],
9+
"allPublicMethods":true
10+
}
11+
]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Args = --initialize-at-build-time=jdk.xml.internal.SecuritySupport
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
[
2+
{
3+
"name":"com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.Deserializers[]"
4+
},
5+
{
6+
"name":"com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.Java7SupportImpl",
7+
"methods":[{"name":"<init>","parameterTypes":[] }]
8+
},
9+
{
10+
"name":"com.amazonaws.services.lambda.runtime.LambdaRuntime",
11+
"fields":[{"name":"logger"}]
12+
},
13+
{
14+
"name":"java.lang.Void",
15+
"methods":[{"name":"<init>","parameterTypes":[] }]
16+
},
17+
{
18+
"name":"java.util.Collections$UnmodifiableMap",
19+
"fields":[{"name":"m"}]
20+
},
21+
{
22+
"name":"jdk.internal.module.IllegalAccessLogger",
23+
"fields":[{"name":"logger"}]
24+
},
25+
{
26+
"name":"sun.misc.Unsafe",
27+
"fields":[{"name":"theUnsafe"}]
28+
},
29+
{
30+
"name":"com.amazonaws.services.lambda.runtime.api.client.runtimeapi.InvocationRequest",
31+
"fields":[{"name":"id"}, {"name":"invokedFunctionArn"}, {"name":"deadlineTimeInMs"}, {"name":"xrayTraceId"}, {"name":"clientContext"}, {"name":"cognitoIdentity"}, {"name":"content"}],
32+
"allPublicMethods":true
33+
},
34+
{
35+
"name":"software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor",
36+
"fields":[{"name":"IS_COLD_START"},{"name":"SERVICE_NAME"}]
37+
}
38+
]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"resources": {
3+
"includes": [
4+
{
5+
"pattern": "\\Qaarch64/aws-lambda-runtime-interface-client.glibc.so\\E"
6+
},
7+
{
8+
"pattern": "\\Qaarch64/aws-lambda-runtime-interface-client.musl.so\\E"
9+
},
10+
{
11+
"pattern": "\\Qx86_64/aws-lambda-runtime-interface-client.glibc.so\\E"
12+
},
13+
{
14+
"pattern": "\\Qx86_64/aws-lambda-runtime-interface-client.musl.so\\E"
15+
}
16+
]
17+
},
18+
"bundles": []
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
[
2+
{
3+
"name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.Deserializers[]"
4+
},
5+
{
6+
"name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.Java7HandlersImpl",
7+
"methods": [{ "name": "<init>", "parameterTypes": [] }]
8+
},
9+
{
10+
"name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.Java7SupportImpl",
11+
"methods": [{ "name": "<init>", "parameterTypes": [] }]
12+
},
13+
{
14+
"name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.Serializers[]"
15+
},
16+
{
17+
"name": "org.joda.time.DateTime",
18+
"allDeclaredConstructors": true,
19+
"allPublicConstructors": true,
20+
"allDeclaredMethods": true,
21+
"allPublicMethods": true,
22+
"allDeclaredClasses": true,
23+
"allPublicClasses": true
24+
}
25+
]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Args = --enable-url-protocols=http,https \
2+
--initialize-at-run-time=\
3+
software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor

0 commit comments

Comments
 (0)