Skip to content

Commit a079165

Browse files
authored
Merge branch 'main' into dependabot/maven/org.apache.logging.log4j-log4j-transform-maven-shade-plugin-extensions-0.2.0
2 parents c014705 + 8998bc9 commit a079165

File tree

103 files changed

+10650
-794
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

103 files changed

+10650
-794
lines changed

.github/workflows/check-build.yml

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -87,11 +87,19 @@ jobs:
8787
mvn -B -q install --file pom.xml
8888
8989
graalvm-build:
90-
runs-on: ubuntu-latest
90+
runs-on: aws-powertools_ubuntu-latest_8-core
9191
steps:
9292
- id: checkout
9393
name: Checkout repository
9494
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
95+
with:
96+
fetch-depth: 0
97+
- name: Get changed files
98+
id: changed-files
99+
uses: tj-actions/changed-files@ed68ef82c095e0d48ec87eccea555d944a631a4c # v46.0.5
100+
with:
101+
files: |
102+
powertools-*/**
95103
- name: Setup GraalVM
96104
uses: graalvm/setup-graalvm@7f488cf82a3629ee755e4e97342c01d6bed318fa # v1.3.5
97105
with:
@@ -100,18 +108,36 @@ jobs:
100108
cache: maven
101109
- id: graalvm-native-test
102110
name: GraalVM Native Test
111+
if: steps.changed-files.outputs.any_changed == 'true'
112+
env:
113+
CHANGED_FILES: ${{ steps.changed-files.outputs.all_changed_files }}
103114
run: |
104115
# Build the entire project first to ensure test-jar dependencies are available
116+
echo "::group::Building project dependencies"
105117
mvn -B -q install -DskipTests
118+
echo "::endgroup::"
119+
120+
echo "Changes detected in powertools modules: $CHANGED_FILES"
106121
107-
# Find modules with graalvm-native profile and run tests recursively.
108-
# This will make sure to discover new GraalVM supported modules automatically in the future.
122+
# Find modules with graalvm-native profile and run tests
109123
find . -name "pom.xml" -path "./powertools-*" | while read module; do
110124
if grep -q "<id>graalvm-native</id>" "$module"; then
111125
module_dir=$(dirname "$module")
112-
echo "Regenerating GraalVM metadata for $module_dir"
113-
mvn -B -q -f "$module" -Pgenerate-graalvm-files clean test
114-
echo "Running GraalVM native tests for $module_dir"
115-
mvn -B -q -f "$module" -Pgraalvm-native test
126+
module_name=$(basename "$module_dir")
127+
128+
# Check if this specific module or common dependencies changed
129+
if echo "$CHANGED_FILES" | grep -q "$module_name/" || \
130+
echo " $CHANGED_FILES " | grep -q " pom.xml " || \
131+
echo "$CHANGED_FILES" | grep -q "powertools-common/"; then
132+
echo "::group::Building $module_name with GraalVM"
133+
echo "Changes detected in $module_name - running GraalVM tests"
134+
echo "Regenerating GraalVM metadata for $module_dir"
135+
mvn -B -q -f "$module" -Pgenerate-graalvm-files clean test
136+
echo "Running GraalVM native tests for $module_dir"
137+
mvn -B -q -f "$module" -Pgraalvm-native test
138+
echo "::endgroup::"
139+
else
140+
echo "No changes detected in $module_name - skipping GraalVM tests"
141+
fi
116142
fi
117143
done

.github/workflows/security-dependencies-check.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,6 @@ jobs:
2626
- name: Checkout Repository
2727
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
2828
- name: Verify Contents
29-
uses: actions/dependency-review-action@bc41886e18ea39df68b1b1245f4184881938e050 # v4.7.2
29+
uses: actions/dependency-review-action@595b5aeba73380359d98a5e087f648dbb0edce1b # v4.7.3
3030
with:
3131
config-file: './.github/dependency-review-config.yml'

GraalVM.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,5 +56,31 @@ java.lang.InternalError: com.oracle.svm.core.jdk.UnsupportedFeatureError: Defini
5656
```
5757
- This has been [fixed](https://github.com/apache/logging-log4j2/discussions/2364#discussioncomment-8950077) in Log4j 2.24.x. PT has been updated to use this version of Log4j
5858

59+
3. **Test Class Organization**
60+
- **Issue**: Anonymous inner classes and lambda expressions in Mockito matchers cause `NoSuchMethodError` in GraalVM native tests
61+
- **Solution**:
62+
- Extract static inner test classes to separate concrete classes in the same package as the class under test
63+
- Replace lambda expressions in `ArgumentMatcher` with concrete implementations
64+
- Use `mockito-subclass` dependency in GraalVM profiles
65+
- **Example**: Replace `argThat(resp -> resp.getStatus() != expectedStatus)` with:
66+
```java
67+
argThat(new ArgumentMatcher<Response>() {
68+
@Override
69+
public boolean matches(Response resp) {
70+
return resp != null && resp.getStatus() != expectedStatus;
71+
}
72+
})
73+
```
74+
75+
4. **Package Visibility Issues**
76+
- **Issue**: Test handler classes cannot access package-private methods when placed in subpackages
77+
- **Solution**: Place test handler classes in the same package as the class under test, not in subpackages like `handlers/`
78+
- **Example**: Use `software.amazon.lambda.powertools.cloudformation` instead of `software.amazon.lambda.powertools.cloudformation.handlers`
79+
80+
5. **Test Stubs Best Practice**
81+
- **Best Practice**: Avoid mocking where possible and use concrete test stubs provided by `powertools-common` package
82+
- **Solution**: Use `TestLambdaContext` and other test stubs from `powertools-common` test-jar instead of Mockito mocks
83+
- **Implementation**: Add `powertools-common` test-jar dependency and replace `mock(Context.class)` with `new TestLambdaContext()`
84+
5985
## Reference Implementation
6086
Working example is available in the [examples](examples/powertools-examples-core-utilities/sam-graalvm).

docs/utilities/validation.md

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,3 +292,53 @@ If you need to configure the Jackson ObjectMapper, you can use the `ValidationCo
292292
}
293293
}
294294
```
295+
296+
## Advanced
297+
298+
### Lambda SnapStart priming
299+
300+
The Validation utility integrates with AWS Lambda SnapStart to improve restore durations. To make sure the SnapStart priming logic of this utility runs correctly, you need an explicit reference to `ValidationConfig` in your code to allow the library to register before SnapStart takes a memory snapshot. Learn more about what priming is in this [blog post](https://aws.amazon.com/blogs/compute/optimizing-cold-start-performance-of-aws-lambda-using-advanced-priming-strategies-with-snapstart/){target="_blank"}.
301+
302+
If you don't set a custom `ValidationConfig` in your code yet, make sure to reference `ValidationConfig` in your Lambda handler initialization code. This can be done by adding one of the following lines to your handler class:
303+
304+
=== "Constructor"
305+
306+
```java hl_lines="7"
307+
import software.amazon.lambda.powertools.validation.Validation;
308+
import software.amazon.lambda.powertools.validation.ValidationConfig;
309+
310+
public class MyFunctionHandler implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {
311+
312+
public MyFunctionHandler() {
313+
ValidationConfig.get(); // Ensure ValidationConfig is loaded for SnapStart
314+
}
315+
316+
@Override
317+
@Validation(inboundSchema = "classpath:/schema_in.json", outboundSchema = "classpath:/schema_out.json")
318+
public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent input, Context context) {
319+
// ...
320+
return something;
321+
}
322+
}
323+
```
324+
325+
=== "Static Initializer"
326+
327+
```java hl_lines="7"
328+
import software.amazon.lambda.powertools.validation.Validation;
329+
import software.amazon.lambda.powertools.validation.ValidationConfig;
330+
331+
public class MyFunctionHandler implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {
332+
333+
static {
334+
ValidationConfig.get(); // Ensure ValidationConfig is loaded for SnapStart
335+
}
336+
337+
@Override
338+
@Validation(inboundSchema = "classpath:/schema_in.json", outboundSchema = "classpath:/schema_out.json")
339+
public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent input, Context context) {
340+
// ...
341+
return something;
342+
}
343+
}
344+
```

examples/README.md

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,35 @@
11
# Powertools for AWS Lambda (Java) Examples
22

33
This directory holds example projects demoing different components of the Powertools for AWS Lambda (Java).
4+
45
Each example can be copied from its subdirectory and used independently of the rest of this repository.
56

67
## Examples
78

89
* [powertools-examples-core-utilities](powertools-examples-core-utilities) - Demonstrates the core logging, tracing, and metrics modules with different build tools and languages
910
* [CDK](./powertools-examples-core-utilities/cdk)
10-
* [Gradle](./powertools-examples-core-utilities/gradle)
1111
* [SAM](./powertools-examples-core-utilities/sam)
12+
* [SAM GraalVM](./powertools-examples-core-utilities/sam-graalvm)
1213
* [Serverless](./powertools-examples-core-utilities/serverless)
14+
* [Terraform](./powertools-examples-core-utilities/terraform)
15+
* [Gradle](./powertools-examples-core-utilities/gradle)
1316
* [Kotlin](./powertools-examples-core-utilities/kotlin)
1417
* [powertools-examples-idempotency](powertools-examples-idempotency) - An idempotent HTTP API
18+
* [SAM](./powertools-examples-idempotency/sam)
19+
* [SAM GraalVM](./powertools-examples-idempotency/sam-graalvm)
1520
* [powertools-examples-parameters](powertools-examples-parameters) - Uses the parameters module to provide runtime parameters to a function
21+
* [SAM](./powertools-examples-parameters/sam)
22+
* [SAM GraalVM](./powertools-examples-parameters/sam-graalvm)
1623
* [powertools-examples-serialization](powertools-examples-serialization) - Uses the serialization module to serialize and deserialize API Gateway & SQS payloads
24+
* [SAM](./powertools-examples-serialization/sam)
25+
* [SAM GraalVM](./powertools-examples-serialization/sam-graalvm)
1726
* [powertools-examples-validation](powertools-examples-validation) - Uses the validation module to validate user requests received via API Gateway
1827
* [powertools-examples-cloudformation](powertools-examples-cloudformation) - Deploys a Cloudformation custom resource
1928
* [powertools-examples-batch](powertools-examples-batch) - Examples for each of the different batch processing deployments
29+
* [powertools-examples-kafka](powertools-examples-kafka) - Examples for Kafka event processing
2030

2131
## Working with AWS Serverless Application Model (SAM) Examples
22-
Many of the examples use [AWS Serverless Application Model](https://aws.amazon.com/serverless/sam/) (SAM). To get started
23-
with them, you can use the SAM Command Line Interface (SAM CLI) to build it and deploy an example to AWS.
32+
Many of the examples use [AWS Serverless Application Model](https://aws.amazon.com/serverless/sam/) (SAM). To get started with them, you can use the SAM Command Line Interface (SAM CLI) to build it and deploy an example to AWS.
2433

2534
To use the SAM CLI, you need the following tools.
2635

@@ -29,17 +38,13 @@ To use the SAM CLI, you need the following tools.
2938
* Maven - [Install Maven](https://maven.apache.org/install.html)
3039
* Docker - [Install Docker community edition](https://hub.docker.com/search/?type=edition&offering=community)
3140

32-
To learn more about SAM,
33-
[check out the developer guide](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/using-sam-cli.html).
34-
You can use the CLI to [test events locally](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/using-sam-cli-local-invoke.html),
35-
and [run the application locally](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/using-sam-cli-local-start-api.html),
36-
amongst other things.
41+
To learn more about SAM, [check out the developer guide](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/using-sam-cli.html). You can use the CLI to [test events locally](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/using-sam-cli-local-invoke.html), and [run the application locally](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/using-sam-cli-local-start-api.html), amongst other things.
3742

3843
To build and deploy an example application for the first time, run the following in your shell:
3944

4045
```bash
4146
# Switch to the directory containing an example for the powertools-idempotency module
42-
$ cd powertools-examples-idempotency
47+
$ cd powertools-examples-idempotency/sam
4348

4449
# Build and deploy the example
4550
$ sam build
@@ -56,7 +61,7 @@ The first command will build the source of your application. The second command
5661

5762
You can find your API Gateway Endpoint URL in the output values displayed after deployment.
5863

59-
If you're not using SAM, you can look for examples for other tools under [powertools-examples-core](./powertools-examples-core)
64+
If you're not using SAM, you can look for examples for other tools under [powertools-examples-core-utilities](./powertools-examples-core-utilities)
6065

6166
### External examples
6267

@@ -69,10 +74,9 @@ You can find more examples in the https://github.com/aws/aws-sam-cli-app-templat
6974

7075
### SAM - Other Tools
7176

72-
If you prefer to use an integrated development environment (IDE) to build and test your application, you can use the AWS Toolkit.
73-
The AWS Toolkit is an open source plug-in for popular IDEs that uses the SAM CLI to build and deploy serverless applications on AWS. The AWS Toolkit also adds a simplified step-through debugging experience for Lambda function code. See the following links to get started.
77+
If you prefer to use an integrated development environment (IDE) to build and test your application, you can use the AWS Toolkit. The AWS Toolkit is an open source plug-in for popular IDEs that uses the SAM CLI to build and deploy serverless applications on AWS. The AWS Toolkit also adds a simplified step-through debugging experience for Lambda function code. See the following links to get started.
7478

7579
* [PyCharm](https://docs.aws.amazon.com/toolkit-for-jetbrains/latest/userguide/welcome.html)
7680
* [IntelliJ](https://docs.aws.amazon.com/toolkit-for-jetbrains/latest/userguide/welcome.html)
7781
* [VS Code](https://docs.aws.amazon.com/toolkit-for-vscode/latest/userguide/welcome.html)
78-
* [Visual Studio](https://docs.aws.amazon.com/toolkit-for-visual-studio/latest/user-guide/welcome.html)
82+
* [Visual Studio](https://docs.aws.amazon.com/toolkit-for-visual-studio/latest/user-guide/welcome.html)

examples/pom.xml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@
3535
<module>powertools-examples-core-utilities/cdk/infra</module>
3636
<module>powertools-examples-core-utilities/serverless</module>
3737
<module>powertools-examples-core-utilities/terraform</module>
38-
<module>powertools-examples-idempotency</module>
38+
<module>powertools-examples-idempotency/sam</module>
39+
<module>powertools-examples-idempotency/sam-graalvm</module>
3940
<module>powertools-examples-parameters/sam</module>
4041
<module>powertools-examples-parameters/sam-graalvm</module>
4142
<module>powertools-examples-serialization/sam</module>
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
build-HelloWorldFunction:
2+
chmod +x target/hello-world
3+
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)
4+
chmod +x src/main/config/bootstrap
5+
cp src/main/config/bootstrap $(ARTIFACTS_DIR)
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@sha256:a5554d68374e19450c6c88448516ac95a9acedc779f318040f5c230134b4e461
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: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# Powertools for AWS Lambda (Java) - CloudFormation Custom Resource Example with SAM on GraalVM
2+
3+
This project contains an example of a Lambda function using the CloudFormation 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/custom_resources/).
4+
5+
In this example you pass in a bucket name as a parameter and upon CloudFormation events a call is made to a lambda. That lambda attempts to create the bucket on CREATE events, create a new bucket if the name changes with an UPDATE event and delete the bucket upon DELETE events.
6+
7+
Have a look at [App.java](../../src/main/java/helloworld/App.java) for the full details.
8+
9+
## Build the sample application
10+
11+
> [!NOTE]
12+
> Building AWS Lambda packages on macOS (ARM64/Intel) for deployment on AWS Lambda (Linux x86_64 or ARM64) will result in incompatible binary dependencies that cause import errors at runtime.
13+
14+
Choose the appropriate build method based on your operating system:
15+
16+
### Build locally using Docker
17+
18+
Recommended for macOS and Windows users: Cross-compile using Docker to match target platform of Lambda:
19+
20+
```shell
21+
docker build --platform linux/amd64 . -t powertools-examples-cloudformation-sam-graalvm
22+
docker run --platform linux/amd64 -it -v `pwd`/../..:`pwd`/../.. -w `pwd`/../.. -v ~/.m2:/root/.m2 powertools-examples-cloudformation-sam-graalvm mvn clean -Pnative-image package -DskipTests
23+
sam build --use-container --build-image powertools-examples-cloudformation-sam-graalvm
24+
```
25+
26+
**Note**: The Docker run command mounts your local Maven cache (`~/.m2`) and builds the native binary with SNAPSHOT support, then SAM packages the pre-built binary.
27+
28+
### Build on native OS
29+
30+
For Linux users with GraalVM installed:
31+
32+
```shell
33+
export JAVA_HOME=<path to GraalVM>
34+
cd ../..
35+
mvn clean -Pnative-image package -DskipTests
36+
cd infra/sam-graalvm
37+
sam build
38+
```
39+
40+
## Deploy the sample application
41+
42+
```shell
43+
sam deploy --guided --parameter-overrides BucketNameParam=my-unique-bucket-2.3.0718
44+
```
45+
46+
This sample is based on Serverless Application Model (SAM). To deploy it, check out the instructions for getting started with SAM in [the examples directory](../../../README.md)
47+
48+
## Test the application
49+
50+
The CloudFormation custom resource will be triggered automatically during stack deployment. You can monitor the Lambda function execution in CloudWatch Logs to see the custom resource handling CREATE, UPDATE, and DELETE events for the S3 bucket.
51+
52+
Check out [App.java](../../src/main/java/helloworld/App.java) to see how it works!
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
AWSTemplateFormatVersion: '2010-09-09'
2+
Transform: AWS::Serverless-2016-10-31
3+
Description: >
4+
powertools-examples-cloudformation-graalvm
5+
6+
Sample SAM Template for powertools-examples-cloudformation with GraalVM native image
7+
8+
Globals:
9+
Function:
10+
Timeout: 20
11+
12+
Parameters:
13+
BucketNameParam:
14+
Type: String
15+
16+
Resources:
17+
HelloWorldCustomResource:
18+
Type: AWS::CloudFormation::CustomResource
19+
Properties:
20+
ServiceToken: !GetAtt HelloWorldFunction.Arn
21+
BucketName: !Ref BucketNameParam
22+
23+
HelloWorldFunction:
24+
Type: AWS::Serverless::Function
25+
Properties:
26+
CodeUri: ../../
27+
Handler: helloworld.App::handleRequest
28+
Runtime: provided.al2023
29+
Architectures:
30+
- x86_64
31+
MemorySize: 512
32+
Policies:
33+
- Statement:
34+
- Sid: bucketaccess1
35+
Effect: Allow
36+
Action:
37+
- s3:GetLifecycleConfiguration
38+
- s3:PutLifecycleConfiguration
39+
- s3:CreateBucket
40+
- s3:ListBucket
41+
- s3:DeleteBucket
42+
Resource: '*'
43+
Metadata:
44+
BuildMethod: makefile
45+
46+
Outputs:
47+
HelloWorldFunction:
48+
Description: "Hello World Lambda Function ARN"
49+
Value: !GetAtt HelloWorldFunction.Arn

0 commit comments

Comments
 (0)