diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index 3722537ae..88f18ea29 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -1,6 +1,9 @@
version: 2
updates:
-
+ - package-ecosystem: "maven"
+ directory: "/aws-lambda-java-runtime-interface"
+ schedule:
+ interval: "weekly"
- package-ecosystem: "github-actions"
directory: "/"
schedule:
diff --git a/.github/workflows/aws-lambda-java-core.yml b/.github/workflows/aws-lambda-java-core.yml
index 267d901c9..b1bed919f 100644
--- a/.github/workflows/aws-lambda-java-core.yml
+++ b/.github/workflows/aws-lambda-java-core.yml
@@ -14,13 +14,16 @@ on:
- 'aws-lambda-java-core/**'
- '.github/workflows/aws-lambda-java-core.yml'
+permissions:
+ contents: read
+
jobs:
build:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v5
- name: Set up JDK 1.8
uses: actions/setup-java@v4
with:
diff --git a/.github/workflows/aws-lambda-java-events-sdk-transformer.yml b/.github/workflows/aws-lambda-java-events-sdk-transformer.yml
index 66f6b2bfe..1f1f08870 100644
--- a/.github/workflows/aws-lambda-java-events-sdk-transformer.yml
+++ b/.github/workflows/aws-lambda-java-events-sdk-transformer.yml
@@ -14,13 +14,16 @@ on:
- 'aws-lambda-java-events-sdk-transformer/**'
- '.github/workflows/aws-lambda-java-events-sdk-transformer.yml'
+permissions:
+ contents: read
+
jobs:
build:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v5
- name: Set up JDK 1.8
uses: actions/setup-java@v4
with:
diff --git a/.github/workflows/aws-lambda-java-events.yml b/.github/workflows/aws-lambda-java-events.yml
index 04ab53a50..2d101018d 100644
--- a/.github/workflows/aws-lambda-java-events.yml
+++ b/.github/workflows/aws-lambda-java-events.yml
@@ -14,13 +14,16 @@ on:
- 'aws-lambda-java-events/**'
- '.github/workflows/aws-lambda-java-events.yml'
+permissions:
+ contents: read
+
jobs:
build:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v5
- name: Set up JDK 1.8
uses: actions/setup-java@v4
with:
diff --git a/.github/workflows/aws-lambda-java-log4j2.yml b/.github/workflows/aws-lambda-java-log4j2.yml
index 7ae54cbe1..e9f6a56c1 100644
--- a/.github/workflows/aws-lambda-java-log4j2.yml
+++ b/.github/workflows/aws-lambda-java-log4j2.yml
@@ -14,13 +14,16 @@ on:
- 'aws-lambda-java-log4j2/**'
- '.github/workflows/aws-lambda-java-log4j2.yml'
+permissions:
+ contents: read
+
jobs:
build:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v5
- name: Set up JDK 1.8
uses: actions/setup-java@v4
with:
diff --git a/.github/workflows/aws-lambda-java-profiler.yml b/.github/workflows/aws-lambda-java-profiler.yml
index db9fc225e..a3afe3729 100644
--- a/.github/workflows/aws-lambda-java-profiler.yml
+++ b/.github/workflows/aws-lambda-java-profiler.yml
@@ -22,7 +22,7 @@ jobs:
contents: read
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v5
- name: Set up JDK
uses: actions/setup-java@v4
@@ -58,6 +58,10 @@ jobs:
working-directory: ./experimental/aws-lambda-java-profiler
run: ./integration_tests/invoke_function.sh
+ - name: Invoke Java Custom Options function
+ working-directory: ./experimental/aws-lambda-java-profiler
+ run: ./integration_tests/invoke_function_custom_options.sh
+
- name: Download from s3
working-directory: ./experimental/aws-lambda-java-profiler
run: ./integration_tests/download_from_s3.sh
diff --git a/.github/workflows/aws-lambda-java-serialization.yml b/.github/workflows/aws-lambda-java-serialization.yml
index c24c48d72..13b7e08b0 100644
--- a/.github/workflows/aws-lambda-java-serialization.yml
+++ b/.github/workflows/aws-lambda-java-serialization.yml
@@ -14,13 +14,16 @@ on:
- 'aws-lambda-java-serialization/**'
- '.github/workflows/aws-lambda-java-serialization.yml'
+permissions:
+ contents: read
+
jobs:
build:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v5
- name: Set up JDK 1.8
uses: actions/setup-java@v4
with:
diff --git a/.github/workflows/aws-lambda-java-tests.yml b/.github/workflows/aws-lambda-java-tests.yml
index a28bca886..720c52c11 100644
--- a/.github/workflows/aws-lambda-java-tests.yml
+++ b/.github/workflows/aws-lambda-java-tests.yml
@@ -14,13 +14,16 @@ on:
- 'aws-lambda-java-tests/**'
- '.github/workflows/aws-lambda-java-tests.yml'
+permissions:
+ contents: read
+
jobs:
build:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v5
- name: Set up JDK 1.8
uses: actions/setup-java@v4
with:
diff --git a/.github/workflows/repo-sync.yml b/.github/workflows/repo-sync.yml
index 25f05029a..2d97bc868 100644
--- a/.github/workflows/repo-sync.yml
+++ b/.github/workflows/repo-sync.yml
@@ -9,6 +9,10 @@ on:
- '.github/workflows/repo-sync.yml'
workflow_dispatch:
+permissions:
+ contents: write
+ pull-requests: write
+
jobs:
repo-sync:
name: Repo Sync
@@ -16,7 +20,7 @@ jobs:
env:
IS_CONFIGURED: ${{ secrets.SOURCE_REPO != '' }}
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v5
if: ${{ env.IS_CONFIGURED == 'true' }}
- uses: repo-sync/github-sync@v2
name: Sync repo to branch
diff --git a/.github/workflows/runtime-interface-client_merge_to_main.yml b/.github/workflows/runtime-interface-client_merge_to_main.yml
index e07b191e1..3560207f3 100644
--- a/.github/workflows/runtime-interface-client_merge_to_main.yml
+++ b/.github/workflows/runtime-interface-client_merge_to_main.yml
@@ -28,7 +28,7 @@ jobs:
contents: read
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v5
- name: Set up JDK 1.8
uses: actions/setup-java@v4
@@ -47,6 +47,10 @@ jobs:
- name: Available buildx platforms
run: echo ${{ steps.buildx.outputs.platforms }}
+ - name: Build and install serialization dependency locally
+ working-directory: ./aws-lambda-java-serialization
+ run: mvn clean install
+
- name: Test Runtime Interface Client xplatform build - Run 'build' target
working-directory: ./aws-lambda-java-runtime-interface-client
run: make build
diff --git a/.github/workflows/runtime-interface-client_pr.yml b/.github/workflows/runtime-interface-client_pr.yml
index 33c6df50b..dcad4fa0a 100644
--- a/.github/workflows/runtime-interface-client_pr.yml
+++ b/.github/workflows/runtime-interface-client_pr.yml
@@ -10,18 +10,29 @@ on:
- 'aws-lambda-java-runtime-interface-client/**'
- '.github/workflows/runtime-interface-client_*.yml'
+permissions:
+ contents: read
+
jobs:
smoke-test:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v5
- name: Set up JDK 1.8
uses: actions/setup-java@v4
with:
java-version: 8
distribution: corretto
+
+ - name: Build and install core dependency locally
+ working-directory: ./aws-lambda-java-core
+ run: mvn clean install
+
+ - name: Build and install serialization dependency locally
+ working-directory: ./aws-lambda-java-serialization
+ run: mvn clean install
- name: Runtime Interface Client smoke tests - Run 'pr' target
working-directory: ./aws-lambda-java-runtime-interface-client
@@ -32,7 +43,7 @@ jobs:
build:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v5
- name: Set up JDK 1.8
uses: actions/setup-java@v4
@@ -50,6 +61,14 @@ jobs:
- name: Available buildx platforms
run: echo ${{ steps.buildx.outputs.platforms }}
+
+ - name: Build and install core dependency locally
+ working-directory: ./aws-lambda-java-core
+ run: mvn clean install
+
+ - name: Build and install serialization dependency locally
+ working-directory: ./aws-lambda-java-serialization
+ run: mvn clean install
- name: Test Runtime Interface Client xplatform build - Run 'build' target
working-directory: ./aws-lambda-java-runtime-interface-client
diff --git a/.github/workflows/samples.yml b/.github/workflows/samples.yml
index 8346b7c2f..aebb708a7 100644
--- a/.github/workflows/samples.yml
+++ b/.github/workflows/samples.yml
@@ -14,11 +14,14 @@ on:
- 'samples/**'
- '.github/workflows/samples.yml'
+permissions:
+ contents: read
+
jobs:
build:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v5
- name: Set up JDK 1.8
uses: actions/setup-java@v4
with:
@@ -42,7 +45,7 @@ jobs:
custom-serialization:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v5
# Set up both Java 8 and 21
- name: Set up Java 8 and 21
uses: actions/setup-java@v4
diff --git a/.gitignore b/.gitignore
index 9f99cc415..1adf36493 100644
--- a/.gitignore
+++ b/.gitignore
@@ -35,3 +35,4 @@ experimental/aws-lambda-java-profiler/extension/build/
experimental/aws-lambda-java-profiler/integration_tests/helloworld/bin
!experimental/aws-lambda-java-profiler/extension/gradle/wrapper/*.jar
/scratch/
+.vscode
diff --git a/README.md b/README.md
index b5153a87f..b6c67b9e8 100644
--- a/README.md
+++ b/README.md
@@ -163,7 +163,7 @@ The purpose of this package is to allow developers to deploy their applications
com.amazonaws
aws-lambda-java-runtime-interface-client
- 2.7.0
+ 2.8.6
```
diff --git a/aws-lambda-java-core/RELEASE.CHANGELOG.md b/aws-lambda-java-core/RELEASE.CHANGELOG.md
index 527e7dd46..aebc8ecd9 100644
--- a/aws-lambda-java-core/RELEASE.CHANGELOG.md
+++ b/aws-lambda-java-core/RELEASE.CHANGELOG.md
@@ -1,3 +1,7 @@
+### September 3, 2025
+`1.4.0`
+- Getter support for x-ray trace ID through the Context object
+
### May 26, 2025
`1.3.0`
- Adding support for multi tenancy ([#545](https://github.com/aws/aws-lambda-java-libs/pull/545))
diff --git a/aws-lambda-java-core/pom.xml b/aws-lambda-java-core/pom.xml
index 2b3abc0ba..cca9d0cdf 100644
--- a/aws-lambda-java-core/pom.xml
+++ b/aws-lambda-java-core/pom.xml
@@ -5,7 +5,7 @@
com.amazonaws
aws-lambda-java-core
- 1.3.0
+ 1.4.0
jar
AWS Lambda Java Core Library
@@ -36,13 +36,6 @@
1.8
-
-
- sonatype-nexus-staging
- https://oss.sonatype.org/service/local/staging/deploy/maven2/
-
-
-
dev
@@ -115,14 +108,12 @@
- org.sonatype.plugins
- nexus-staging-maven-plugin
- 1.6.3
+ org.sonatype.central
+ central-publishing-maven-plugin
+ 0.8.0
true
- sonatype-nexus-staging
- https://aws.oss.sonatype.org/
- false
+ central
diff --git a/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/Context.java b/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/Context.java
index 152765df1..ed9311a11 100644
--- a/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/Context.java
+++ b/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/Context.java
@@ -109,4 +109,14 @@ public interface Context {
default String getTenantId() {
return null;
}
+
+ /**
+ *
+ * Returns the X-Ray trace ID associated with the request.
+ *
+ * @return null by default
+ */
+ default String getXrayTraceId() {
+ return null;
+ }
}
diff --git a/aws-lambda-java-events-sdk-transformer/pom.xml b/aws-lambda-java-events-sdk-transformer/pom.xml
index 6a2b1735c..d719ec8ac 100644
--- a/aws-lambda-java-events-sdk-transformer/pom.xml
+++ b/aws-lambda-java-events-sdk-transformer/pom.xml
@@ -5,7 +5,7 @@
com.amazonaws
aws-lambda-java-events-sdk-transformer
- 3.1.0
+ 3.1.1
jar
AWS Lambda Java Events SDK Transformer Library
@@ -63,7 +63,7 @@
com.amazonaws
aws-lambda-java-events
- 3.11.2
+ 3.16.1
provided
@@ -160,18 +160,16 @@
- org.sonatype.plugins
- nexus-staging-maven-plugin
- 1.6.3
+ org.sonatype.central
+ central-publishing-maven-plugin
+ 0.8.0
true
- sonatype-nexus-staging
- https://aws.oss.sonatype.org/
- false
+ central
-
+
\ No newline at end of file
diff --git a/aws-lambda-java-events/pom.xml b/aws-lambda-java-events/pom.xml
index 8799966be..714c825d9 100644
--- a/aws-lambda-java-events/pom.xml
+++ b/aws-lambda-java-events/pom.xml
@@ -1,11 +1,11 @@
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
4.0.0
com.amazonaws
aws-lambda-java-events
- 3.16.0
+ 3.16.1
jar
AWS Lambda Java Events Library
@@ -37,6 +37,8 @@
1.18.22
UTF-8
UTF-8
+ 2.20.1
+ 2.40.1
@@ -62,13 +64,13 @@
com.fasterxml.jackson.core
jackson-databind
- 2.14.2
+ ${jackson.version}
test
net.javacrumbs.json-unit
json-unit-assertj
- 2.36.1
+ ${json.unit}
test
@@ -152,20 +154,18 @@
- org.sonatype.plugins
- nexus-staging-maven-plugin
- 1.6.3
+ org.sonatype.central
+ central-publishing-maven-plugin
+ 0.8.0
true
- sonatype-nexus-staging
- https://aws.oss.sonatype.org/
- false
+ central
org.apache.maven.plugins
maven-resources-plugin
- 3.2.0
+ 3.3.1
UTF-8
@@ -173,7 +173,7 @@
org.apache.maven.plugins
maven-compiler-plugin
- 3.8.1
+ 3.11.0
@@ -189,4 +189,4 @@
-
+
\ No newline at end of file
diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/ConnectEvent.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/ConnectEvent.java
index 38547ac2a..e94875614 100644
--- a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/ConnectEvent.java
+++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/ConnectEvent.java
@@ -59,7 +59,7 @@ public static class ContactData implements Serializable, Cloneable {
private String initiationMethod;
private String instanceArn;
private String previousContactId;
- private String queue;
+ private Queue queue;
private SystemEndpoint systemEndpoint;
}
@@ -80,4 +80,13 @@ public static class SystemEndpoint implements Serializable, Cloneable {
private String address;
private String type;
}
+ @Data
+ @Builder(setterPrefix = "with")
+ @NoArgsConstructor
+ @AllArgsConstructor
+ public static class Queue implements Serializable, Cloneable {
+ private String name;
+ private String ARN;
+ }
+
}
diff --git a/aws-lambda-java-log4j2/README.md b/aws-lambda-java-log4j2/README.md
index b1b739b69..f13121750 100644
--- a/aws-lambda-java-log4j2/README.md
+++ b/aws-lambda-java-log4j2/README.md
@@ -39,7 +39,7 @@ If using maven shade plugin, set the plugin configuration as follows
org.apache.maven.plugins
maven-shade-plugin
- 2.4.3
+ 3.6.1
package
diff --git a/aws-lambda-java-log4j2/pom.xml b/aws-lambda-java-log4j2/pom.xml
index b33300ef2..0124598a0 100644
--- a/aws-lambda-java-log4j2/pom.xml
+++ b/aws-lambda-java-log4j2/pom.xml
@@ -5,7 +5,7 @@
com.amazonaws
aws-lambda-java-log4j2
- 1.6.0
+ 1.6.1
jar
AWS Lambda Java Log4j 2.x Libraries
@@ -34,7 +34,7 @@
1.8
1.8
- 2.17.1
+ 2.25.3
@@ -134,18 +134,16 @@
- org.sonatype.plugins
- nexus-staging-maven-plugin
- 1.6.3
+ org.sonatype.central
+ central-publishing-maven-plugin
+ 0.8.0
true
- sonatype-nexus-staging
- https://aws.oss.sonatype.org/
- false
+ central
-
+
\ No newline at end of file
diff --git a/aws-lambda-java-runtime-interface-client/Dockerfile.rie b/aws-lambda-java-runtime-interface-client/Dockerfile.rie
new file mode 100644
index 000000000..66a01c834
--- /dev/null
+++ b/aws-lambda-java-runtime-interface-client/Dockerfile.rie
@@ -0,0 +1,8 @@
+FROM public.ecr.aws/lambda/java:21
+
+COPY target/aws-lambda-java-runtime-interface-client-*.jar ${LAMBDA_TASK_ROOT}/
+COPY target/aws-lambda-java-core-*.jar ${LAMBDA_TASK_ROOT}/
+COPY target/aws-lambda-java-serialization-*.jar ${LAMBDA_TASK_ROOT}/
+COPY test-handlers/EchoHandler.class ${LAMBDA_TASK_ROOT}/
+
+CMD ["EchoHandler::handleRequest"]
\ No newline at end of file
diff --git a/aws-lambda-java-runtime-interface-client/Makefile b/aws-lambda-java-runtime-interface-client/Makefile
index b3a204213..6c3a268fb 100644
--- a/aws-lambda-java-runtime-interface-client/Makefile
+++ b/aws-lambda-java-runtime-interface-client/Makefile
@@ -65,6 +65,10 @@ publish:
test-publish:
./ric-dev-environment/test-platform-specific-jar-snapshot.sh
+.PHONY: test-rie
+test-rie:
+ ./scripts/test-rie.sh "EchoHandler::handleRequest"
+
define HELP_MESSAGE
Usage: $ make [TARGETS]
@@ -74,5 +78,5 @@ TARGETS
dev Run all development tests after a change.
pr Perform all checks before submitting a Pull Request.
test Run the Unit tests.
-
+ test-rie Build and test RIC locally with Lambda Runtime Interface Emulator. (Requires building the project first)
endef
diff --git a/aws-lambda-java-runtime-interface-client/README.md b/aws-lambda-java-runtime-interface-client/README.md
index d49201bd5..4e03f041f 100644
--- a/aws-lambda-java-runtime-interface-client/README.md
+++ b/aws-lambda-java-runtime-interface-client/README.md
@@ -70,7 +70,7 @@ pom.xml
com.amazonaws
aws-lambda-java-runtime-interface-client
- 2.7.0
+ 2.8.7
@@ -138,6 +138,49 @@ This command invokes the function running in the container image and returns a r
*Alternately, you can also include RIE as a part of your base image. See the AWS documentation on how to [Build RIE into your base image](https://docs.aws.amazon.com/lambda/latest/dg/images-test.html#images-test-alternative).*
+### Automated Local Testing
+
+For developers working on this runtime interface client, we provide an automated testing script that handles RIE setup, dependency management, and Docker orchestration.
+
+*Prerequisites:*
+- Build the project first: `mvn clean install`
+- Docker must be installed and running
+
+*To run automated tests:*
+
+```shell script
+make test-rie
+```
+
+This single command will:
+- Automatically download required dependencies (aws-lambda-java-core, aws-lambda-java-serialization)
+- Build a Docker image with RIE pre-installed
+- Compile and run a test Lambda function (EchoHandler)
+- Execute the function and validate the response
+- Clean up containers automatically
+
+The test uses a simple EchoHandler that returns the input event, making it easy to verify the runtime interface client is working correctly.
+
+## Test Coverage
+
+This project uses JaCoCo for code coverage analysis. To exclude classes from JaCoCo coverage, add them to the `jacoco-maven-plugin` configuration:
+
+```xml
+
+ org.jacoco
+ jacoco-maven-plugin
+
+
+ **/*Exception.class
+ **/dto/*.class
+ **/YourClassName.class
+
+
+
+```
+
+This project excludes by default: exceptions, interfaces, DTOs, constants, and runtime-only classes.
+
### Troubleshooting
While running integration tests, you might encounter the Docker Hub rate limit error with the following body:
@@ -160,7 +203,7 @@ platform-specific JAR by setting the ``.
com.amazonaws
aws-lambda-java-runtime-interface-client
- 2.7.0
+ 2.8.7
linux-x86_64
```
diff --git a/aws-lambda-java-runtime-interface-client/RELEASE.CHANGELOG.md b/aws-lambda-java-runtime-interface-client/RELEASE.CHANGELOG.md
index ac073ae85..93d8cf23a 100644
--- a/aws-lambda-java-runtime-interface-client/RELEASE.CHANGELOG.md
+++ b/aws-lambda-java-runtime-interface-client/RELEASE.CHANGELOG.md
@@ -1,3 +1,36 @@
+### September 22, 2025
+`2.8.7`
+- Remove Minimum and Maximum Limits of AWS_LAMBDA_MAX_CONCURRENCY.
+
+### September 22, 2025
+`2.8.6`
+- Set Multiconcurrent Trace ID using utils-lite.
+
+### September 17, 2025
+`2.8.5`
+- Log errorType and errorMessage from RAPID in C++ Client.
+- Performance Upgrade for Multiconcurrency Mode.
+
+### September 9, 2025
+`2.8.4`
+- Make Trace ID Accessible through Context Object.
+
+### July 19, 2025
+`2.8.3`
+- Ensure EventHandlerLoader Thread Safety.
+
+### June 26, 2025
+`2.8.2`
+- Allow AWS_LAMBDA_MAX_CONCURRENCY to be One. Crash the RIC if it is set to an un-parsable string to an integer or an out of bounds value.
+
+### June 26, 2025
+`2.8.1`
+- Refactoring
+
+### June 26, 2025
+`2.8.0`
+- Refactoring
+
### May 21, 2025
`2.7.0`
- Adding support for multi tenancy ([#540](https://github.com/aws/aws-lambda-java-libs/pull/540))
diff --git a/aws-lambda-java-runtime-interface-client/pom.xml b/aws-lambda-java-runtime-interface-client/pom.xml
index d4f7fd5e3..ab7166c84 100644
--- a/aws-lambda-java-runtime-interface-client/pom.xml
+++ b/aws-lambda-java-runtime-interface-client/pom.xml
@@ -1,10 +1,10 @@
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
4.0.0
com.amazonaws
aws-lambda-java-runtime-interface-client
- 2.7.0
+ 2.9.0
jar
AWS Lambda Java Runtime Interface Client
@@ -47,9 +47,9 @@
separately from the Runtime Interface Client functionality until we figure something else out.
-->
true
-
-
-
+
+
+
+ **/*Exception.class
+
+ **/Resource.class
+
+ **/dto/*.class
+
+ **/ReservedRuntimeEnvironmentVariables.class
+ **/RapidErrorType.class
+
+ **/FrameType.class
+ **/StructuredLogMessage.class
+
+ **/AWSLambda.class
+
+
default-prepare-agent
@@ -251,7 +273,7 @@
-
+
org.apache.maven.plugins
maven-checkstyle-plugin
${maven-checkstyle-plugin.version}
@@ -347,16 +369,52 @@
- org.sonatype.plugins
- nexus-staging-maven-plugin
- 1.6.3
+ org.sonatype.central
+ central-publishing-maven-plugin
+ 0.8.0
true
- sonatype-nexus-staging
- https://aws.oss.sonatype.org/
- false
+ central
+
+ org.codehaus.mojo
+ build-helper-maven-plugin
+ 3.4.0
+
+
+ attach-platform-artifacts
+ package
+
+ attach-artifact
+
+
+
+
+ ${project.build.directory}/${project.build.finalName}-linux-x86_64.jar
+ jar
+ linux-x86_64
+
+
+ ${project.build.directory}/${project.build.finalName}-linux-aarch_64.jar
+ jar
+ linux-aarch_64
+
+
+ ${project.build.directory}/${project.build.finalName}-linux_musl-x86_64.jar
+ jar
+ linux_musl-x86_64
+
+
+ ${project.build.directory}/${project.build.finalName}-linux_musl-aarch_64.jar
+ jar
+ linux_musl-aarch_64
+
+
+
+
+
+
diff --git a/aws-lambda-java-runtime-interface-client/scripts/test-rie.sh b/aws-lambda-java-runtime-interface-client/scripts/test-rie.sh
new file mode 100755
index 000000000..b69c967a1
--- /dev/null
+++ b/aws-lambda-java-runtime-interface-client/scripts/test-rie.sh
@@ -0,0 +1,46 @@
+#!/bin/bash
+set -euo pipefail
+
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
+SERIALIZATION_ROOT="$(dirname "$PROJECT_ROOT")/aws-lambda-java-serialization"
+
+if ! ls "$PROJECT_ROOT"/target/aws-lambda-java-runtime-interface-client-*.jar >/dev/null 2>&1; then
+ echo "RIC jar not found. Please build the project first with 'mvn package'."
+ exit 1
+fi
+
+IMAGE_TAG="java-ric-rie-test"
+
+HANDLER="${1:-EchoHandler::handleRequest}"
+
+echo "Starting RIE test setup for Java..."
+
+# Build local dependencies if not present
+CORE_ROOT="$(dirname "$PROJECT_ROOT")/aws-lambda-java-core"
+if ! ls "$PROJECT_ROOT"/target/aws-lambda-java-core-*.jar >/dev/null 2>&1; then
+ echo "Building local aws-lambda-java-core..."
+ (cd "$CORE_ROOT" && mvn package -DskipTests)
+ cp "$CORE_ROOT"/target/aws-lambda-java-core-*.jar "$PROJECT_ROOT/target/"
+fi
+
+if ! ls "$PROJECT_ROOT"/target/aws-lambda-java-serialization-*.jar >/dev/null 2>&1; then
+ echo "Building local aws-lambda-java-serialization..."
+ (cd "$SERIALIZATION_ROOT" && mvn package -DskipTests)
+ cp "$SERIALIZATION_ROOT"/target/aws-lambda-java-serialization-*.jar "$PROJECT_ROOT/target/"
+fi
+
+echo "Compiling EchoHandler..."
+javac -source 21 -target 21 -cp "$(ls "$PROJECT_ROOT"/target/aws-lambda-java-runtime-interface-client-*.jar):$(ls "$PROJECT_ROOT"/target/aws-lambda-java-core-*.jar):$(ls "$PROJECT_ROOT"/target/aws-lambda-java-serialization-*.jar)" \
+ -d "$PROJECT_ROOT/test-handlers/" "$PROJECT_ROOT/test-handlers/EchoHandler.java"
+
+echo "Building test Docker image..."
+docker build -t "$IMAGE_TAG" -f "$PROJECT_ROOT/Dockerfile.rie" "$PROJECT_ROOT"
+
+echo "Starting test container on port 9000..."
+echo ""
+echo "In another terminal, invoke with:"
+echo "curl -s -X POST -H 'Content-Type: application/json' \"http://localhost:9000/2015-03-31/functions/function/invocations\" -d '{\"message\":\"test\"}'"
+echo ""
+
+exec docker run -it -p 9000:8080 -e _HANDLER="$HANDLER" "$IMAGE_TAG"
\ No newline at end of file
diff --git a/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/AWSLambda.java b/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/AWSLambda.java
index 2eeb14e3d..e5b221a80 100644
--- a/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/AWSLambda.java
+++ b/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/AWSLambda.java
@@ -15,10 +15,12 @@
import com.amazonaws.services.lambda.runtime.api.client.runtimeapi.LambdaError;
import com.amazonaws.services.lambda.runtime.api.client.runtimeapi.LambdaRuntimeApiClient;
import com.amazonaws.services.lambda.runtime.api.client.runtimeapi.LambdaRuntimeApiClientImpl;
+import com.amazonaws.services.lambda.runtime.api.client.runtimeapi.LambdaRuntimeClientMaxRetriesExceededException;
import com.amazonaws.services.lambda.runtime.api.client.runtimeapi.RapidErrorType;
import com.amazonaws.services.lambda.runtime.api.client.runtimeapi.converters.LambdaErrorConverter;
import com.amazonaws.services.lambda.runtime.api.client.runtimeapi.converters.XRayErrorCauseConverter;
import com.amazonaws.services.lambda.runtime.api.client.runtimeapi.dto.InvocationRequest;
+import com.amazonaws.services.lambda.runtime.api.client.util.ConcurrencyConfig;
import com.amazonaws.services.lambda.runtime.api.client.util.LambdaOutputStream;
import com.amazonaws.services.lambda.runtime.api.client.util.UnsafeUtil;
import com.amazonaws.services.lambda.runtime.logging.LogFormat;
@@ -35,6 +37,10 @@
import java.net.URLClassLoader;
import java.security.Security;
import java.util.Properties;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+import software.amazon.awssdk.utilslite.SdkInternalThreadLocal;
/**
* The entrypoint of this class is {@link AWSLambda#startRuntime}. It performs two main tasks:
@@ -49,8 +55,8 @@
*/
public class AWSLambda {
- protected static URLClassLoader customerClassLoader;
-
+ private static URLClassLoader customerClassLoader;
+
private static final String TRUST_STORE_PROPERTY = "javax.net.ssl.trustStore";
private static final String JAVA_SECURITY_PROPERTIES = "java.security.properties";
@@ -69,8 +75,8 @@ public class AWSLambda {
private static final String AWS_LAMBDA_INITIALIZATION_TYPE = System.getenv(ReservedRuntimeEnvironmentVariables.AWS_LAMBDA_INITIALIZATION_TYPE);
- private static LambdaRuntimeApiClient runtimeClient;
-
+ private static final String CONCURRENT_TRACE_ID_KEY = "AWS_LAMBDA_X_TRACE_ID";
+
static {
// Override the disabledAlgorithms setting to match configuration for openjdk8-u181.
// This is to keep DES ciphers around while we deploying security updates.
@@ -137,15 +143,13 @@ private static LambdaRequestHandler findRequestHandler(final String handlerStrin
return requestHandler;
}
- private static LambdaRequestHandler getLambdaRequestHandlerObject(String handler, LambdaContextLogger lambdaLogger) throws ClassNotFoundException, IOException {
+ private static LambdaRequestHandler getLambdaRequestHandlerObject(String handler, LambdaContextLogger lambdaLogger, LambdaRuntimeApiClient runtimeClient) throws ClassNotFoundException, IOException {
UnsafeUtil.disableIllegalAccessWarning();
System.setOut(new PrintStream(new LambdaOutputStream(System.out), false, "UTF-8"));
System.setErr(new PrintStream(new LambdaOutputStream(System.err), false, "UTF-8"));
setupRuntimeLogger(lambdaLogger);
- runtimeClient = new LambdaRuntimeApiClientImpl(LambdaEnvironment.RUNTIME_API);
-
String taskRoot = System.getProperty("user.dir");
String libRoot = "/opt/java";
// Make system classloader the customer classloader's parent to ensure any aws-lambda-java-core classes
@@ -167,13 +171,13 @@ private static LambdaRequestHandler getLambdaRequestHandlerObject(String handler
}
if (INIT_TYPE_SNAP_START.equals(AWS_LAMBDA_INITIALIZATION_TYPE)) {
- onInitComplete(lambdaLogger);
+ onInitComplete(lambdaLogger, runtimeClient);
}
return requestHandler;
}
- public static void setupRuntimeLogger(LambdaLogger lambdaLogger)
+ private static void setupRuntimeLogger(LambdaLogger lambdaLogger)
throws ClassNotFoundException {
ReflectUtil.setStaticField(
Class.forName("com.amazonaws.services.lambda.runtime.LambdaRuntime"),
@@ -213,10 +217,11 @@ private static LogSink createLogSink() {
}
public static void main(String[] args) throws Throwable {
- try (LambdaContextLogger logger = initLogger()) {
- LambdaRequestHandler lambdaRequestHandler = getLambdaRequestHandlerObject(args[0], logger);
- startRuntimeLoop(lambdaRequestHandler, logger);
-
+ try (LambdaContextLogger lambdaLogger = initLogger()) {
+ LambdaRuntimeApiClient runtimeClient = new LambdaRuntimeApiClientImpl(LambdaEnvironment.RUNTIME_API);
+ LambdaRequestHandler lambdaRequestHandler = getLambdaRequestHandlerObject(args[0], lambdaLogger, runtimeClient);
+ ConcurrencyConfig concurrencyConfig = new ConcurrencyConfig(lambdaLogger);
+ startRuntimeLoops(lambdaRequestHandler, lambdaLogger, concurrencyConfig, runtimeClient);
} catch (IOException | ClassNotFoundException t) {
throw new Error(t);
}
@@ -232,50 +237,111 @@ private static LambdaContextLogger initLogger() {
return logger;
}
- private static void startRuntimeLoop(LambdaRequestHandler requestHandler, LambdaContextLogger lambdaLogger) throws Throwable {
- boolean shouldExit = false;
- while (!shouldExit) {
- UserFault userFault = null;
- InvocationRequest request = runtimeClient.nextInvocation();
- if (request.getXrayTraceId() != null) {
- System.setProperty(LAMBDA_TRACE_HEADER_PROP, request.getXrayTraceId());
- } else {
- System.clearProperty(LAMBDA_TRACE_HEADER_PROP);
+ private static void startRuntimeLoopWithExecutor(LambdaRequestHandler lambdaRequestHandler, LambdaContextLogger lambdaLogger, ExecutorService executorService, LambdaRuntimeApiClient runtimeClient) {
+ executorService.submit(() -> {
+ try {
+ startRuntimeLoop(lambdaRequestHandler, lambdaLogger, runtimeClient, false);
+ } catch (Exception e) {
+ lambdaLogger.log(String.format("Runtime Loop on Thread ID: %s Failed.\n%s", Thread.currentThread().getName(), UserFault.trace(e)), lambdaLogger.getLogFormat() == LogFormat.JSON ? LogLevel.ERROR : LogLevel.UNDEFINED);
}
+ });
+ }
- ByteArrayOutputStream payload;
+ protected static void startRuntimeLoops(LambdaRequestHandler lambdaRequestHandler, LambdaContextLogger lambdaLogger, ConcurrencyConfig concurrencyConfig, LambdaRuntimeApiClient runtimeClient) throws Exception {
+ if (concurrencyConfig.isMultiConcurrent()) {
+ lambdaLogger.log(concurrencyConfig.getConcurrencyConfigMessage(), lambdaLogger.getLogFormat() == LogFormat.JSON ? LogLevel.INFO : LogLevel.UNDEFINED);
+ ExecutorService platformThreadExecutor = Executors.newFixedThreadPool(concurrencyConfig.getNumberOfPlatformThreads());
try {
- payload = requestHandler.call(request);
- runtimeClient.reportInvocationSuccess(request.getId(), payload.toByteArray());
- // clear interrupted flag in case if it was set by user's code
- Thread.interrupted();
- } catch (UserFault f) {
- shouldExit = f.fatal;
- userFault = f;
- UserFault.filterStackTrace(f);
- LambdaError error = new LambdaError(
- LambdaErrorConverter.fromUserFault(f),
- RapidErrorType.BadFunctionCode);
- runtimeClient.reportInvocationError(request.getId(), error);
- } catch (Throwable t) {
- shouldExit = t instanceof VirtualMachineError || t instanceof IOError;
- UserFault.filterStackTrace(t);
- userFault = UserFault.makeUserFault(t);
-
- LambdaError error = new LambdaError(
- LambdaErrorConverter.fromThrowable(t),
- XRayErrorCauseConverter.fromThrowable(t),
- RapidErrorType.UserException);
- runtimeClient.reportInvocationError(request.getId(), error);
+ for (int i = 0; i < concurrencyConfig.getNumberOfPlatformThreads(); i++) {
+ startRuntimeLoopWithExecutor(lambdaRequestHandler, lambdaLogger, platformThreadExecutor, runtimeClient);
+ }
} finally {
- if (userFault != null) {
- lambdaLogger.log(userFault.reportableError(), lambdaLogger.getLogFormat() == LogFormat.JSON ? LogLevel.ERROR : LogLevel.UNDEFINED);
+ platformThreadExecutor.shutdown();
+ try {
+ platformThreadExecutor.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
}
}
+ } else {
+ startRuntimeLoop(lambdaRequestHandler, lambdaLogger, runtimeClient, true);
+ }
+ }
+
+ private static LambdaError createLambdaErrorFromThrowableOrUserFault(Throwable t) {
+ if (t instanceof UserFault) {
+ return new LambdaError(
+ LambdaErrorConverter.fromUserFault((UserFault) t),
+ RapidErrorType.BadFunctionCode);
+ } else {
+ return new LambdaError(
+ LambdaErrorConverter.fromThrowable(t),
+ XRayErrorCauseConverter.fromThrowable(t),
+ RapidErrorType.UserException);
}
}
- static void onInitComplete(final LambdaContextLogger lambdaLogger) throws IOException {
+ private static void setEnvVarForXrayTraceId(InvocationRequest request) {
+ if (request.getXrayTraceId() != null) {
+ System.setProperty(LAMBDA_TRACE_HEADER_PROP, request.getXrayTraceId());
+ } else {
+ System.clearProperty(LAMBDA_TRACE_HEADER_PROP);
+ }
+ }
+
+ private static void reportNonLoopTerminatingException(LambdaContextLogger lambdaLogger, Throwable t) {
+ lambdaLogger.log(
+ String.format(
+ "Runtime Loop on Thread ID: %s Faced and Exception. This exception will not stop the runtime loop.\nException:\n%s",
+ Thread.currentThread().getName(), UserFault.trace(t)),
+ lambdaLogger.getLogFormat() == LogFormat.JSON ? LogLevel.ERROR : LogLevel.UNDEFINED);
+ }
+
+ /*
+ * In multiconcurrent mode (exitLoopOnErrors = false), The Runtime Loop will not exit unless LambdaRuntimeClientMaxRetriesExceededException is thrown when calling nextInvocationWithExponentialBackoff.
+ * In normal/sequential mode (exitLoopOnErrors = true), The Runtime Loop will exit if nextInvocation call fails, when UserFault is fatal, or an Error of type VirtualMachineError or IOError is thrown.
+ */
+ private static void startRuntimeLoop(LambdaRequestHandler lambdaRequestHandler, LambdaContextLogger lambdaLogger, LambdaRuntimeApiClient runtimeClient, boolean exitLoopOnErrors) throws Exception {
+ boolean shouldExit = false;
+ while (!shouldExit) {
+ try {
+ UserFault userFault = null;
+ InvocationRequest request = exitLoopOnErrors ? runtimeClient.nextInvocation() : runtimeClient.nextInvocationWithExponentialBackoff(lambdaLogger);
+ if (exitLoopOnErrors) {
+ setEnvVarForXrayTraceId(request);
+ } else {
+ SdkInternalThreadLocal.put(CONCURRENT_TRACE_ID_KEY, request.getXrayTraceId());
+ }
+
+ try {
+ ByteArrayOutputStream payload = lambdaRequestHandler.call(request);
+ runtimeClient.reportInvocationSuccess(request.getId(), payload.toByteArray());
+ // clear interrupted flag in case if it was set by user's code
+ Thread.interrupted();
+ } catch (Throwable t) {
+ UserFault.filterStackTrace(t);
+ userFault = UserFault.makeUserFault(t);
+ shouldExit = exitLoopOnErrors && (t instanceof VirtualMachineError || t instanceof IOError || userFault.fatal);
+ LambdaError error = createLambdaErrorFromThrowableOrUserFault(t);
+ runtimeClient.reportInvocationError(request.getId(), error);
+ } finally {
+ if (userFault != null) {
+ lambdaLogger.log(userFault.reportableError(), lambdaLogger.getLogFormat() == LogFormat.JSON ? LogLevel.ERROR : LogLevel.UNDEFINED);
+ }
+
+ SdkInternalThreadLocal.remove(CONCURRENT_TRACE_ID_KEY);
+ }
+ } catch (Throwable t) {
+ if (exitLoopOnErrors || t instanceof LambdaRuntimeClientMaxRetriesExceededException) {
+ throw t;
+ }
+
+ reportNonLoopTerminatingException(lambdaLogger, t);
+ }
+ }
+ }
+
+ private static void onInitComplete(final LambdaContextLogger lambdaLogger, LambdaRuntimeApiClient runtimeClient) throws IOException {
try {
Core.getGlobalContext().beforeCheckpoint(null);
runtimeClient.restoreNext();
@@ -303,4 +369,8 @@ private static void logExceptionCloudWatch(LambdaContextLogger lambdaLogger, Exc
UserFault userFault = UserFault.makeUserFault(exc, true);
lambdaLogger.log(userFault.reportableError(), lambdaLogger.getLogFormat() == LogFormat.JSON ? LogLevel.ERROR : LogLevel.UNDEFINED);
}
+
+ protected static URLClassLoader getCustomerClassLoader() {
+ return customerClassLoader;
+ }
}
diff --git a/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/EventHandlerLoader.java b/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/EventHandlerLoader.java
index db6ceceb2..f679c217c 100644
--- a/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/EventHandlerLoader.java
+++ b/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/EventHandlerLoader.java
@@ -57,10 +57,10 @@ private enum Platform {
UNKNOWN
}
- private static volatile PojoSerializer contextSerializer;
- private static volatile PojoSerializer cognitoSerializer;
+ private static volatile ThreadLocal> contextSerializer = new ThreadLocal<>();
+ private static volatile ThreadLocal> cognitoSerializer = new ThreadLocal<>();
- private static final EnumMap>> typeCache = new EnumMap<>(Platform.class);
+ private static final ThreadLocal>>> typeCache = ThreadLocal.withInitial(() -> new EnumMap<>(Platform.class));
private static final Comparator methodPriority = new Comparator() {
public int compare(Method lhs, Method rhs) {
@@ -116,7 +116,7 @@ private static PojoSerializer