diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 00000000..3722537a
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,7 @@
+version: 2
+updates:
+
+ - package-ecosystem: "github-actions"
+ directory: "/"
+ schedule:
+ interval: "weekly"
\ No newline at end of file
diff --git a/.github/workflows/aws-lambda-java-core.yml b/.github/workflows/aws-lambda-java-core.yml
index 0b553bbc..39ff1291 100644
--- a/.github/workflows/aws-lambda-java-core.yml
+++ b/.github/workflows/aws-lambda-java-core.yml
@@ -7,11 +7,12 @@ on:
push:
branches: [ main ]
paths:
- - 'aws-lambda-java-core/**'
+ - 'aws-lambda-java-core/**'
pull_request:
branches: [ '*' ]
paths:
- - 'aws-lambda-java-core/**'
+ - 'aws-lambda-java-core/**'
+ - '.github/workflows/aws-lambda-java-core.yml'
jobs:
build:
@@ -21,7 +22,7 @@ jobs:
steps:
- uses: actions/checkout@v3
- name: Set up JDK 1.8
- uses: actions/setup-java@v3
+ uses: actions/setup-java@v4
with:
java-version: 8
distribution: corretto
@@ -38,3 +39,5 @@ jobs:
- name: Run 'pr' target
working-directory: ./aws-lambda-java-runtime-interface-client
run: make pr
+ env:
+ IS_JAVA_8: true
diff --git a/.github/workflows/aws-lambda-java-events-sdk-transformer.yml b/.github/workflows/aws-lambda-java-events-sdk-transformer.yml
index 679639d3..05a870ad 100644
--- a/.github/workflows/aws-lambda-java-events-sdk-transformer.yml
+++ b/.github/workflows/aws-lambda-java-events-sdk-transformer.yml
@@ -7,11 +7,12 @@ on:
push:
branches: [ main ]
paths:
- - 'aws-lambda-java-events-sdk-transformer/**'
+ - 'aws-lambda-java-events-sdk-transformer/**'
pull_request:
branches: [ '*' ]
paths:
- - 'aws-lambda-java-events-sdk-transformer/**'
+ - 'aws-lambda-java-events-sdk-transformer/**'
+ - '.github/workflows/aws-lambda-java-events-sdk-transformer.yml'
jobs:
build:
@@ -21,7 +22,7 @@ jobs:
steps:
- uses: actions/checkout@v3
- name: Set up JDK 1.8
- uses: actions/setup-java@v3
+ uses: actions/setup-java@v4
with:
java-version: 8
distribution: corretto
diff --git a/.github/workflows/aws-lambda-java-events.yml b/.github/workflows/aws-lambda-java-events.yml
index bdd01eb7..634d803e 100644
--- a/.github/workflows/aws-lambda-java-events.yml
+++ b/.github/workflows/aws-lambda-java-events.yml
@@ -7,11 +7,12 @@ on:
push:
branches: [ main ]
paths:
- - 'aws-lambda-java-events/**'
+ - 'aws-lambda-java-events/**'
pull_request:
branches: [ '*' ]
paths:
- - 'aws-lambda-java-events/**'
+ - 'aws-lambda-java-events/**'
+ - '.github/workflows/aws-lambda-java-events.yml'
jobs:
build:
@@ -21,7 +22,7 @@ jobs:
steps:
- uses: actions/checkout@v3
- name: Set up JDK 1.8
- uses: actions/setup-java@v3
+ uses: actions/setup-java@v4
with:
java-version: 8
distribution: corretto
diff --git a/.github/workflows/aws-lambda-java-log4j2.yml b/.github/workflows/aws-lambda-java-log4j2.yml
index 427c7536..ab86f200 100644
--- a/.github/workflows/aws-lambda-java-log4j2.yml
+++ b/.github/workflows/aws-lambda-java-log4j2.yml
@@ -7,11 +7,12 @@ on:
push:
branches: [ main ]
paths:
- - 'aws-lambda-java-log4j2/**'
+ - 'aws-lambda-java-log4j2/**'
pull_request:
branches: [ '*' ]
paths:
- - 'aws-lambda-java-log4j2/**'
+ - 'aws-lambda-java-log4j2/**'
+ - '.github/workflows/aws-lambda-java-log4j2.yml'
jobs:
build:
@@ -21,7 +22,7 @@ jobs:
steps:
- uses: actions/checkout@v3
- name: Set up JDK 1.8
- uses: actions/setup-java@v3
+ uses: actions/setup-java@v4
with:
java-version: 8
distribution: corretto
diff --git a/.github/workflows/aws-lambda-java-serialization.yml b/.github/workflows/aws-lambda-java-serialization.yml
index 9d71cbab..baa6052f 100644
--- a/.github/workflows/aws-lambda-java-serialization.yml
+++ b/.github/workflows/aws-lambda-java-serialization.yml
@@ -7,11 +7,12 @@ on:
push:
branches: [ main ]
paths:
- - 'aws-lambda-java-serialization/**'
+ - 'aws-lambda-java-serialization/**'
pull_request:
branches: [ '*' ]
paths:
- - 'aws-lambda-java-serialization/**'
+ - 'aws-lambda-java-serialization/**'
+ - '.github/workflows/aws-lambda-java-serialization.yml'
jobs:
build:
@@ -21,7 +22,7 @@ jobs:
steps:
- uses: actions/checkout@v3
- name: Set up JDK 1.8
- uses: actions/setup-java@v3
+ uses: actions/setup-java@v4
with:
java-version: 8
distribution: corretto
diff --git a/.github/workflows/aws-lambda-java-tests.yml b/.github/workflows/aws-lambda-java-tests.yml
index fc587e8e..bf17ed2a 100644
--- a/.github/workflows/aws-lambda-java-tests.yml
+++ b/.github/workflows/aws-lambda-java-tests.yml
@@ -7,11 +7,12 @@ on:
push:
branches: [ main ]
paths:
- - 'aws-lambda-java-tests/**'
+ - 'aws-lambda-java-tests/**'
pull_request:
branches: [ '*' ]
paths:
- - 'aws-lambda-java-tests/**'
+ - 'aws-lambda-java-tests/**'
+ - '.github/workflows/aws-lambda-java-tests.yml'
jobs:
build:
@@ -21,7 +22,7 @@ jobs:
steps:
- uses: actions/checkout@v3
- name: Set up JDK 1.8
- uses: actions/setup-java@v3
+ uses: actions/setup-java@v4
with:
java-version: 8
distribution: corretto
diff --git a/.github/workflows/repo-sync.yml b/.github/workflows/repo-sync.yml
index 91054f9e..c667bceb 100644
--- a/.github/workflows/repo-sync.yml
+++ b/.github/workflows/repo-sync.yml
@@ -3,6 +3,10 @@ name: Repo Sync
on:
schedule:
- cron: "0 8 * * 1-5" # At 08:00 on every day-of-week from Monday through Friday
+ pull_request:
+ branches: [ '*' ]
+ paths:
+ - '.github/workflows/repo-sync.yml'
workflow_dispatch:
jobs:
diff --git a/.github/workflows/runtime-interface-client_merge_to_main.yml b/.github/workflows/runtime-interface-client_merge_to_main.yml
index 1783f1cd..27b22fd7 100644
--- a/.github/workflows/runtime-interface-client_merge_to_main.yml
+++ b/.github/workflows/runtime-interface-client_merge_to_main.yml
@@ -15,6 +15,7 @@ on:
branches: [ main ]
paths:
- 'aws-lambda-java-runtime-interface-client/**'
+ workflow_dispatch:
jobs:
@@ -29,13 +30,13 @@ jobs:
- uses: actions/checkout@v3
- name: Set up JDK 1.8
- uses: actions/setup-java@v3
+ uses: actions/setup-java@v4
with:
java-version: 8
distribution: corretto
- name: Set up QEMU
- uses: docker/setup-qemu-action@v2
+ uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
@@ -48,9 +49,11 @@ jobs:
- name: Test Runtime Interface Client xplatform build - Run 'build' target
working-directory: ./aws-lambda-java-runtime-interface-client
run: make build
+ env:
+ IS_JAVA_8: true
- name: Issue AWS credentials
- uses: aws-actions/configure-aws-credentials@v1
+ uses: aws-actions/configure-aws-credentials@v4
with:
aws-region: ${{ secrets.AWS_REGION }}
role-to-assume: ${{ secrets.AWS_ROLE }}
diff --git a/.github/workflows/runtime-interface-client_pr.yml b/.github/workflows/runtime-interface-client_pr.yml
index 7a7f602e..b935f4f7 100644
--- a/.github/workflows/runtime-interface-client_pr.yml
+++ b/.github/workflows/runtime-interface-client_pr.yml
@@ -7,7 +7,8 @@ on:
pull_request:
branches: [ '*' ]
paths:
- - 'aws-lambda-java-runtime-interface-client/**'
+ - 'aws-lambda-java-runtime-interface-client/**'
+ - '.github/workflows/runtime-interface-client_pr.yml'
jobs:
@@ -17,7 +18,7 @@ jobs:
- uses: actions/checkout@v3
- name: Set up JDK 1.8
- uses: actions/setup-java@v3
+ uses: actions/setup-java@v4
with:
java-version: 8
distribution: corretto
@@ -25,6 +26,8 @@ jobs:
- name: Runtime Interface Client smoke tests - Run 'pr' target
working-directory: ./aws-lambda-java-runtime-interface-client
run: make pr
+ env:
+ IS_JAVA_8: true
build:
runs-on: ubuntu-latest
@@ -32,13 +35,13 @@ jobs:
- uses: actions/checkout@v3
- name: Set up JDK 1.8
- uses: actions/setup-java@v3
+ uses: actions/setup-java@v4
with:
java-version: 8
distribution: corretto
- name: Set up QEMU
- uses: docker/setup-qemu-action@v2
+ uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
@@ -51,9 +54,11 @@ jobs:
- name: Test Runtime Interface Client xplatform build - Run 'build' target
working-directory: ./aws-lambda-java-runtime-interface-client
run: make build
+ env:
+ IS_JAVA_8: true
- name: Save the built jar
- uses: actions/upload-artifact@v3
+ uses: actions/upload-artifact@v4
with:
name: aws-lambda-java-runtime-interface-client
path: ./aws-lambda-java-runtime-interface-client/target/aws-lambda-java-runtime-interface-client-*.jar
diff --git a/.github/workflows/samples.yml b/.github/workflows/samples.yml
index 2171ae78..cd665549 100644
--- a/.github/workflows/samples.yml
+++ b/.github/workflows/samples.yml
@@ -12,6 +12,7 @@ on:
branches: [ '*' ]
paths:
- 'samples/kinesis-firehose-event-handler/**'
+ - '.github/workflows/samples.yml'
jobs:
build:
@@ -21,7 +22,7 @@ jobs:
steps:
- uses: actions/checkout@v3
- name: Set up JDK 1.8
- uses: actions/setup-java@v3
+ uses: actions/setup-java@v4
with:
java-version: 8
distribution: corretto
diff --git a/.gitignore b/.gitignore
index 2f2f0af4..371bed6b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -24,4 +24,7 @@ dependency-reduced-pom.xml
.project
# OSX
-.DS_Store
\ No newline at end of file
+.DS_Store
+
+# snapshot process
+aws-lambda-java-runtime-interface-client/pom.xml.versionsBackup
diff --git a/README.md b/README.md
index 445e35f9..94f842fb 100644
--- a/README.md
+++ b/README.md
@@ -140,7 +140,7 @@ The purpose of this package is to allow developers to deploy their applications
com.amazonaws
aws-lambda-java-runtime-interface-client
- 2.5.0
+ 2.5.1
```
diff --git a/aws-lambda-java-events/README.md b/aws-lambda-java-events/README.md
index 8c60b3a2..92bea0ea 100644
--- a/aws-lambda-java-events/README.md
+++ b/aws-lambda-java-events/README.md
@@ -16,7 +16,9 @@
* `AppSyncLambdaAuthorizerResponse`
* `CloudFormationCustomResourceEvent`
* `CloudFrontEvent`
+* `CloudWatchCompositeAlarmEvent`
* `CloudWatchLogsEvent`
+* `CloudWatchMetricAlarmEvent`
* `CodeCommitEvent`
* `CognitoEvent`
* `CognitoUserPoolCreateAuthChallengeEvent`
@@ -44,6 +46,8 @@
* `KinesisFirehoseEvent`
* `LambdaDestinationEvent`
* `LexEvent`
+* `MSKFirehoseEvent`
+* `MSKFirehoseResponse`
* `RabbitMQEvent`
* `S3BatchEvent`
* `S3BatchResponse`
diff --git a/aws-lambda-java-events/pom.xml b/aws-lambda-java-events/pom.xml
index 2c7442c0..4abea0f8 100644
--- a/aws-lambda-java-events/pom.xml
+++ b/aws-lambda-java-events/pom.xml
@@ -35,6 +35,8 @@
1.8
1.8
1.18.22
+ UTF-8
+ UTF-8
diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/CloudWatchCompositeAlarmEvent.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/CloudWatchCompositeAlarmEvent.java
new file mode 100644
index 00000000..d4090b55
--- /dev/null
+++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/CloudWatchCompositeAlarmEvent.java
@@ -0,0 +1,70 @@
+package com.amazonaws.services.lambda.runtime.events;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * Represents an CloudWatch Composite Alarm event. This event occurs when a composite alarm is triggered.
+ *
+ * @see Using Amazon CloudWatch alarms
+ */
+@Data
+@Builder(setterPrefix = "with")
+@NoArgsConstructor
+@AllArgsConstructor
+public class CloudWatchCompositeAlarmEvent {
+ private String source;
+ private String alarmArn;
+ private String accountId;
+ private String time;
+ private String region;
+ private AlarmData alarmData;
+
+ @Data
+ @Builder(setterPrefix = "with")
+ @NoArgsConstructor
+ @AllArgsConstructor
+ public static class AlarmData {
+ private String alarmName;
+ private State state;
+ private PreviousState previousState;
+ private Configuration configuration;
+ }
+
+ @Data
+ @Builder(setterPrefix = "with")
+ @NoArgsConstructor
+ @AllArgsConstructor
+ public static class State {
+ private String value;
+ private String reason;
+ private String reasonData;
+ private String timestamp;
+ }
+
+ @Data
+ @Builder(setterPrefix = "with")
+ @NoArgsConstructor
+ @AllArgsConstructor
+ public static class PreviousState {
+ private String value;
+ private String reason;
+ private String reasonData;
+ private String timestamp;
+ private String actionsSuppressedBy;
+ private String actionsSuppressedReason;
+ }
+
+ @Data
+ @Builder(setterPrefix = "with")
+ @NoArgsConstructor
+ @AllArgsConstructor
+ public static class Configuration {
+ private String alarmRule;
+ private String actionsSuppressor;
+ private Integer actionsSuppressorWaitPeriod;
+ private Integer actionsSuppressorExtensionPeriod;
+ }
+}
diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/CloudWatchMetricAlarmEvent.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/CloudWatchMetricAlarmEvent.java
new file mode 100644
index 00000000..2b5f503c
--- /dev/null
+++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/CloudWatchMetricAlarmEvent.java
@@ -0,0 +1,99 @@
+package com.amazonaws.services.lambda.runtime.events;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Represents an CloudWatch Metric Alarm event. This event occurs when a metric alarm is triggered.
+ *
+ * @see Using Amazon CloudWatch alarms
+ */
+@Data
+@Builder(setterPrefix = "with")
+@NoArgsConstructor
+@AllArgsConstructor
+public class CloudWatchMetricAlarmEvent {
+ private String source;
+ private String alarmArn;
+ private String accountId;
+ private String time;
+ private String region;
+ private AlarmData alarmData;
+
+ @Data
+ @Builder(setterPrefix = "with")
+ @NoArgsConstructor
+ @AllArgsConstructor
+ public static class AlarmData {
+ private String alarmName;
+ private State state;
+ private PreviousState previousState;
+ private Configuration configuration;
+ }
+
+ @Data
+ @Builder(setterPrefix = "with")
+ @NoArgsConstructor
+ @AllArgsConstructor
+ public static class State {
+ private String value;
+ private String reason;
+ private String timestamp;
+ }
+
+ @Data
+ @Builder(setterPrefix = "with")
+ @NoArgsConstructor
+ @AllArgsConstructor
+ public static class PreviousState {
+ private String value;
+ private String reason;
+ private String reasonData;
+ private String timestamp;
+ }
+
+ @Data
+ @Builder(setterPrefix = "with")
+ @NoArgsConstructor
+ @AllArgsConstructor
+ public static class Configuration {
+ private String description;
+ private List metrics;
+ }
+
+ @Data
+ @Builder(setterPrefix = "with")
+ @NoArgsConstructor
+ @AllArgsConstructor
+ public static class Metric {
+ private String id;
+ private MetricStat metricStat;
+ private Boolean returnData;
+ }
+
+ @Data
+ @Builder(setterPrefix = "with")
+ @NoArgsConstructor
+ @AllArgsConstructor
+ public static class MetricStat {
+ private MetricDetail metric;
+ private Integer period;
+ private String stat;
+ private String unit;
+ }
+
+ @Data
+ @Builder(setterPrefix = "with")
+ @NoArgsConstructor
+ @AllArgsConstructor
+ public static class MetricDetail {
+ private String namespace;
+ private String name;
+ private Map dimensions;
+ }
+}
diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/MSKFirehoseEvent.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/MSKFirehoseEvent.java
new file mode 100644
index 00000000..1af40ce4
--- /dev/null
+++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/MSKFirehoseEvent.java
@@ -0,0 +1,51 @@
+/*
+Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+SPDX-License-Identifier: Apache-2.0
+*/
+
+package com.amazonaws.services.lambda.runtime.events;
+
+import java.nio.ByteBuffer;
+import java.util.List;
+import java.util.Map;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@Builder(setterPrefix = "with")
+@NoArgsConstructor
+@AllArgsConstructor
+
+public class MSKFirehoseEvent {
+
+ private String invocationId;
+
+ private String deliveryStreamArn;
+
+ private String sourceMSKArn;
+
+ private String region;
+
+ private List records;
+
+ @Data
+ @Builder(setterPrefix = "with")
+ @NoArgsConstructor
+ @AllArgsConstructor
+ public static class Record {
+
+ private ByteBuffer kafkaRecordValue;
+
+ private String recordId;
+
+ private Long approximateArrivalEpoch;
+
+ private Long approximateArrivalTimestamp;
+
+ private Map mskRecordMetadata;
+
+ }
+}
diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/MSKFirehoseResponse.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/MSKFirehoseResponse.java
new file mode 100644
index 00000000..18b5aa13
--- /dev/null
+++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/MSKFirehoseResponse.java
@@ -0,0 +1,61 @@
+/*
+Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+SPDX-License-Identifier: Apache-2.0
+*/
+
+package com.amazonaws.services.lambda.runtime.events;
+
+import java.nio.ByteBuffer;
+import java.util.List;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * Response model for Amazon Data Firehose Lambda transformation with MSK as a source.
+ * [+] Amazon Data Firehose Data Transformation - Data Transformation and Status Model - ...
+ * OK : Indicates that processing of this item succeeded.
+ * ProcessingFailed : Indicate that the processing of this item failed.
+ * Dropped : Indicates that this item should be silently dropped
+ */
+
+@Data
+@Builder(setterPrefix = "with")
+@NoArgsConstructor
+@AllArgsConstructor
+
+public class MSKFirehoseResponse {
+
+ public enum Result {
+
+ /**
+ * Indicates that processing of this item succeeded.
+ */
+ Ok,
+
+ /**
+ * Indicate that the processing of this item failed
+ */
+ ProcessingFailed,
+
+ /**
+ * Indicates that this item should be silently dropped
+ */
+ Dropped
+ }
+ public List records;
+
+ @Data
+ @NoArgsConstructor
+ @Builder(setterPrefix = "with")
+ @AllArgsConstructor
+
+ public static class Record {
+ public String recordId;
+ public Result result;
+ public ByteBuffer kafkaRecordValue;
+
+ }
+}
diff --git a/aws-lambda-java-runtime-interface-client/Makefile b/aws-lambda-java-runtime-interface-client/Makefile
index e57daf3a..b3a20421 100644
--- a/aws-lambda-java-runtime-interface-client/Makefile
+++ b/aws-lambda-java-runtime-interface-client/Makefile
@@ -4,6 +4,13 @@ ARCHITECTURE := $(shell arch)
ARCHITECTURE_ALIAS := $($(shell echo "$(ARCHITECTURE)_ALIAS"))
ARCHITECTURE_ALIAS := $(or $(ARCHITECTURE_ALIAS),amd64) # on any other archs defaulting to amd64
+# Java 8 does not support passing some args (such add --add-opens) so we need to clear them
+ifeq ($(IS_JAVA_8),true)
+ EXTRA_LOAD_ARG := -DargLineForReflectionTestOnly=""
+else
+ EXTRA_LOAD_ARG :=
+endif
+
# This optional module exports MAVEN_REPO_URL, MAVEN_REPO_USERNAME and MAVEN_REPO_PASSWORD environment variables
# making it possible to publish resulting artifacts to a codeartifact maven repository
-include ric-dev-environment/codeartifact-repo.mk
@@ -15,7 +22,7 @@ target:
.PHONY: test
test:
- mvn test
+ mvn test $(EXTRA_LOAD_ARG)
.PHONY: setup-codebuild-agent
setup-codebuild-agent:
@@ -44,11 +51,11 @@ pr: test test-smoke
.PHONY: build
build:
- mvn clean install
- mvn install -P linux-x86_64
- mvn install -P linux_musl-x86_64
- mvn install -P linux-aarch64
- mvn install -P linux_musl-aarch64
+ mvn clean install $(EXTRA_LOAD_ARG)
+ mvn install -P linux-x86_64 $(EXTRA_LOAD_ARG)
+ mvn install -P linux_musl-x86_64 $(EXTRA_LOAD_ARG)
+ mvn install -P linux-aarch64 $(EXTRA_LOAD_ARG)
+ mvn install -P linux_musl-aarch64 $(EXTRA_LOAD_ARG)
.PHONY: publish
publish:
diff --git a/aws-lambda-java-runtime-interface-client/README.md b/aws-lambda-java-runtime-interface-client/README.md
index 13f8658f..ae299c77 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.5.0
+ 2.5.1
@@ -160,7 +160,7 @@ platform-specific JAR by setting the ``.
com.amazonaws
aws-lambda-java-runtime-interface-client
- 2.5.0
+ 2.5.1
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 1fefd0e2..bb5794c2 100644
--- a/aws-lambda-java-runtime-interface-client/RELEASE.CHANGELOG.md
+++ b/aws-lambda-java-runtime-interface-client/RELEASE.CHANGELOG.md
@@ -1,3 +1,8 @@
+### June 28, 2024
+`2.5.1`
+- Runtime API client improvements: fix a DNS cache issue
+- Runtime API client improvements: fix circular exception references causing stackOverflow
+
### March 20, 2024
`2.5.0`
- Runtime API client improvements ([#471](https://github.com/aws/aws-lambda-java-libs/pull/471))
diff --git a/aws-lambda-java-runtime-interface-client/pom.xml b/aws-lambda-java-runtime-interface-client/pom.xml
index 29d20c8d..a4f022a4 100644
--- a/aws-lambda-java-runtime-interface-client/pom.xml
+++ b/aws-lambda-java-runtime-interface-client/pom.xml
@@ -4,7 +4,7 @@
4.0.0
com.amazonaws
aws-lambda-java-runtime-interface-client
- 2.5.0
+ 2.5.1
jar
AWS Lambda Java Runtime Interface Client
@@ -35,6 +35,8 @@
UTF-8
UTF-8
0.8.8
+ 2.4
+ 3.1.1
5.9.2
+ --add-opens java.base/java.net=ALL-UNNAMED
@@ -90,9 +97,22 @@
+
+ maven-install-plugin
+ org.apache.maven.plugins
+ ${maven-install-plugin.version}
+
+
+ maven-deploy-plugin
+ org.apache.maven.plugins
+ ${maven-deploy-plugin.version}
+
maven-surefire-plugin
3.0.0-M9
+
+ ${argLineForReflectionTestOnly}
+
org.junit.jupiter
@@ -110,6 +130,24 @@
maven-antrun-plugin
1.7
+
+ build-jni-lib-for-tests
+ generate-test-sources
+
+ run
+
+
+
+
+
+
+
+
+
+
+
+
build-jni-lib
prepare-package
diff --git a/aws-lambda-java-runtime-interface-client/ric-dev-environment/publish_snapshot.sh b/aws-lambda-java-runtime-interface-client/ric-dev-environment/publish_snapshot.sh
index cf5969e1..9d2f9837 100755
--- a/aws-lambda-java-runtime-interface-client/ric-dev-environment/publish_snapshot.sh
+++ b/aws-lambda-java-runtime-interface-client/ric-dev-environment/publish_snapshot.sh
@@ -18,6 +18,10 @@ else
echo "Already -SNAPSHOT version"
fi
+# get the updated project version
+snapshotProjectVersion=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout)
+echo "Updated project version is ${snapshotProjectVersion}"
+
CLASSIFIERS_ARRAY=("linux-x86_64" "linux_musl-x86_64" "linux-aarch_64" "linux_musl-aarch_64")
for str in "${CLASSIFIERS_ARRAY[@]}"; do
@@ -36,7 +40,7 @@ mvn -B -X -P ci-repo \
-DgroupId=com.amazonaws \
-DartifactId=aws-lambda-java-runtime-interface-client \
-Dpackaging=jar \
- -Dversion=$projectVersion \
+ -Dversion=$snapshotProjectVersion \
-Dfile=./target/aws-lambda-java-runtime-interface-client-$projectVersion.jar \
-Dfiles=$FILES \
-Dclassifiers=$CLASSIFIERS \
diff --git a/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/crac/ContextImpl.java b/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/crac/ContextImpl.java
index ac4bc648..87fb0ff2 100644
--- a/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/crac/ContextImpl.java
+++ b/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/crac/ContextImpl.java
@@ -23,25 +23,9 @@ public class ContextImpl extends Context {
@Override
public synchronized void beforeCheckpoint(Context extends Resource> context) throws CheckpointException {
-
- List exceptionsThrown = new ArrayList<>();
- for (Resource resource : getCheckpointQueueReverseOrderOfRegistration()) {
- try {
- resource.beforeCheckpoint(this);
- } catch (CheckpointException e) {
- Collections.addAll(exceptionsThrown, e.getSuppressed());
- } catch (Exception e) {
- exceptionsThrown.add(e);
- }
- }
-
- if (!exceptionsThrown.isEmpty()) {
- CheckpointException checkpointException = new CheckpointException();
- for (Throwable t : exceptionsThrown) {
- checkpointException.addSuppressed(t);
- }
- throw checkpointException;
- }
+ executeBeforeCheckpointHooks();
+ DNSManager.clearCache();
+ System.gc();
}
@Override
@@ -87,4 +71,25 @@ private List getCheckpointQueueForwardOrderOfRegistration() {
.map(Map.Entry::getKey)
.collect(Collectors.toList());
}
+
+ private void executeBeforeCheckpointHooks() throws CheckpointException {
+ List exceptionsThrown = new ArrayList<>();
+ for (Resource resource : getCheckpointQueueReverseOrderOfRegistration()) {
+ try {
+ resource.beforeCheckpoint(this);
+ } catch (CheckpointException e) {
+ Collections.addAll(exceptionsThrown, e.getSuppressed());
+ } catch (Exception e) {
+ exceptionsThrown.add(e);
+ }
+ }
+
+ if (!exceptionsThrown.isEmpty()) {
+ CheckpointException checkpointException = new CheckpointException();
+ for (Throwable t : exceptionsThrown) {
+ checkpointException.addSuppressed(t);
+ }
+ throw checkpointException;
+ }
+ }
}
diff --git a/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/crac/DNSManager.java b/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/crac/DNSManager.java
new file mode 100644
index 00000000..4c1a6cd5
--- /dev/null
+++ b/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/crac/DNSManager.java
@@ -0,0 +1,10 @@
+/*
+Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+SPDX-License-Identifier: Apache-2.0
+*/
+
+package com.amazonaws.services.lambda.crac;
+
+class DNSManager {
+ static native void clearCache();
+}
\ 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/UserFault.java b/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/UserFault.java
index bc95af57..fc8eb005 100644
--- a/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/UserFault.java
+++ b/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/UserFault.java
@@ -4,6 +4,8 @@
import java.io.PrintWriter;
import java.io.StringWriter;
+import java.util.HashSet;
+import java.util.Set;
public final class UserFault extends RuntimeException {
private static final long serialVersionUID = -479308856905162038L;
@@ -65,6 +67,16 @@ public static String trace(Throwable t) {
* the same object for convenience.
*/
public static T filterStackTrace(T t) {
+ return filterStackTrace(t, new HashSet<>(), new HashSet<>());
+ }
+
+ private static T filterStackTrace(T t, Set visited, Set visitedSuppressed) {
+ if (visited.contains(t)) {
+ return t;
+ }
+
+ visited.add(t);
+
StackTraceElement[] trace = t.getStackTrace();
for (int i = 0; i < trace.length; i++) {
if (trace[i].getClassName().startsWith(packagePrefix)) {
@@ -78,12 +90,15 @@ public static T filterStackTrace(T t) {
Throwable cause = t.getCause();
if (cause != null) {
- filterStackTrace(cause);
+ filterStackTrace(cause, visited, visitedSuppressed);
}
Throwable[] suppressedExceptions = t.getSuppressed();
- for (Throwable suppressed : suppressedExceptions) {
- filterStackTrace(suppressed);
+ for(Throwable suppressed: suppressedExceptions) {
+ if (!visitedSuppressed.contains(suppressed)) {
+ visitedSuppressed.add(suppressed);
+ filterStackTrace(suppressed, visited, visitedSuppressed);
+ }
}
return t;
diff --git a/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/runtimeapi/JniHelper.java b/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/runtimeapi/JniHelper.java
new file mode 100644
index 00000000..82586d27
--- /dev/null
+++ b/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/runtimeapi/JniHelper.java
@@ -0,0 +1,64 @@
+/*
+Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+SPDX-License-Identifier: Apache-2.0
+*/
+package com.amazonaws.services.lambda.runtime.api.client.runtimeapi;
+
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.nio.file.StandardCopyOption;
+import java.util.ArrayList;
+import java.util.List;
+
+public class JniHelper {
+
+ private static final String NATIVE_LIB_PATH = "/tmp/.libaws-lambda-jni.so";
+ private static final String NATIVE_CLIENT_JNI_PROPERTY = "com.amazonaws.services.lambda.runtime.api.client.runtimeapi.NativeClient.JNI";
+
+ /**
+ * Unpacks JNI library from the JAR to a temporary location and tries to load it using System.load()
+ * Implementation based on AWS CRT
+ * (ref. ...)
+ *
+ * @param libsToTry - array of native libraries to try
+ */
+ public static void load() {
+ String jniLib = System.getProperty(NATIVE_CLIENT_JNI_PROPERTY);
+ if (jniLib != null) {
+ System.load(jniLib);
+ } else {
+ String[] libsToTry = new String[]{
+ "libaws-lambda-jni.linux-x86_64.so",
+ "libaws-lambda-jni.linux-aarch_64.so",
+ "libaws-lambda-jni.linux_musl-x86_64.so",
+ "libaws-lambda-jni.linux_musl-aarch_64.so"
+ };
+ unpackAndLoad(libsToTry, NativeClient.class);
+ }
+ }
+
+ private static void unpackAndLoad(String[] libsToTry, Class clazz) {
+ List errorMessages = new ArrayList<>();
+ for (String libToTry : libsToTry) {
+ try (InputStream inputStream = clazz.getResourceAsStream(
+ Paths.get("/jni", libToTry).toString())) {
+ if (inputStream == null) {
+ throw new FileNotFoundException("Specified file not in the JAR: " + libToTry);
+ }
+ Files.copy(inputStream, Paths.get(NATIVE_LIB_PATH), StandardCopyOption.REPLACE_EXISTING);
+ System.load(NATIVE_LIB_PATH);
+ return;
+ } catch (UnsatisfiedLinkError | Exception e) {
+ errorMessages.add(e.getMessage());
+ }
+ }
+
+ for (int i = 0; i < libsToTry.length; ++i) {
+ System.err.println("Failed to load the native runtime interface client library " + libsToTry[i] +
+ ". Exception: " + errorMessages.get(i));
+ }
+ System.exit(-1);
+ }
+}
diff --git a/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/runtimeapi/NativeClient.java b/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/runtimeapi/NativeClient.java
index a311ff00..10e6bafd 100644
--- a/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/runtimeapi/NativeClient.java
+++ b/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/runtimeapi/NativeClient.java
@@ -5,14 +5,7 @@
package com.amazonaws.services.lambda.runtime.api.client.runtimeapi;
import com.amazonaws.services.lambda.runtime.api.client.runtimeapi.dto.InvocationRequest;
-
-import java.io.FileNotFoundException;
-import java.io.InputStream;
-import java.nio.file.Files;
-import java.nio.file.Paths;
-import java.nio.file.StandardCopyOption;
-import java.util.ArrayList;
-import java.util.List;
+import com.amazonaws.services.lambda.runtime.api.client.runtimeapi.JniHelper;
import static com.amazonaws.services.lambda.runtime.api.client.runtimeapi.LambdaRuntimeApiClientImpl.USER_AGENT;
@@ -21,60 +14,11 @@
* interactions with the Runtime API.
*/
class NativeClient {
- private static final String NATIVE_LIB_PATH = "/tmp/.libaws-lambda-jni.so";
- public static final String NATIVE_CLIENT_JNI_PROPERTY = "com.amazonaws.services.lambda.runtime.api.client.runtimeapi.NativeClient.JNI";
static void init() {
- loadJNILib();
+ JniHelper.load();
initializeClient(USER_AGENT.getBytes());
}
-
- private static void loadJNILib() {
- String jniLib = System.getProperty(NATIVE_CLIENT_JNI_PROPERTY);
- if (jniLib != null) {
- System.load(jniLib);
- } else {
- String[] libsToTry = new String[]{
- "libaws-lambda-jni.linux-x86_64.so",
- "libaws-lambda-jni.linux-aarch_64.so",
- "libaws-lambda-jni.linux_musl-x86_64.so",
- "libaws-lambda-jni.linux_musl-aarch_64.so"
- };
- unpackAndLoadNativeLibrary(libsToTry);
- }
- }
-
-
- /**
- * Unpacks JNI library from the JAR to a temporary location and tries to load it using System.load()
- * Implementation based on AWS CRT
- * (ref. ...)
- *
- * @param libsToTry - array of native libraries to try
- */
- static void unpackAndLoadNativeLibrary(String[] libsToTry) {
-
- List errorMessages = new ArrayList<>();
- for (String libToTry : libsToTry) {
- try (InputStream inputStream = NativeClient.class.getResourceAsStream(
- Paths.get("/jni", libToTry).toString())) {
- if (inputStream == null) {
- throw new FileNotFoundException("Specified file not in the JAR: " + libToTry);
- }
- Files.copy(inputStream, Paths.get(NATIVE_LIB_PATH), StandardCopyOption.REPLACE_EXISTING);
- System.load(NATIVE_LIB_PATH);
- return;
- } catch (UnsatisfiedLinkError | Exception e) {
- errorMessages.add(e.getMessage());
- }
- }
-
- for (int i = 0; i < libsToTry.length; ++i) {
- System.err.println("Failed to load the native runtime interface client library " + libsToTry[i] +
- ". Exception: " + errorMessages.get(i));
- }
- System.exit(-1);
- }
-
+
static native void initializeClient(byte[] userAgent);
static native InvocationRequest next();
diff --git a/aws-lambda-java-runtime-interface-client/src/main/jni/Dockerfile.glibc b/aws-lambda-java-runtime-interface-client/src/main/jni/Dockerfile.glibc
index dd4fdb22..1cfcfbb1 100644
--- a/aws-lambda-java-runtime-interface-client/src/main/jni/Dockerfile.glibc
+++ b/aws-lambda-java-runtime-interface-client/src/main/jni/Dockerfile.glibc
@@ -53,9 +53,16 @@ RUN /usr/bin/c++ -c \
-I${JAVA_HOME}/include/linux \
-I ./deps/artifacts/include \
com_amazonaws_services_lambda_runtime_api_client_runtimeapi_NativeClient.cpp -o com_amazonaws_services_lambda_runtime_api_client_runtimeapi_NativeClient.o && \
+ /usr/bin/c++ -c \
+ -std=gnu++11 \
+ -fPIC \
+ -I${JAVA_HOME}/include \
+ -I${JAVA_HOME}/include/linux \
+ -I ./deps/artifacts/include \
+ com_amazonaws_services_lambda_crac_DNSManager.cpp -o com_amazonaws_services_lambda_crac_DNSManager.o && \
/usr/bin/c++ -shared \
-std=gnu++11 \
- -o aws-lambda-runtime-interface-client.so com_amazonaws_services_lambda_runtime_api_client_runtimeapi_NativeClient.o \
+ -o aws-lambda-runtime-interface-client.so com_amazonaws_services_lambda_runtime_api_client_runtimeapi_NativeClient.o com_amazonaws_services_lambda_crac_DNSManager.o \
-L ./deps/artifacts/lib64/ \
-L ./deps/artifacts/lib/ \
-laws-lambda-runtime \
diff --git a/aws-lambda-java-runtime-interface-client/src/main/jni/Dockerfile.musl b/aws-lambda-java-runtime-interface-client/src/main/jni/Dockerfile.musl
index e15f6adc..64725c14 100644
--- a/aws-lambda-java-runtime-interface-client/src/main/jni/Dockerfile.musl
+++ b/aws-lambda-java-runtime-interface-client/src/main/jni/Dockerfile.musl
@@ -54,9 +54,16 @@ RUN /usr/bin/c++ -c \
-I${JAVA_HOME}/include/linux \
-I ./deps/artifacts/include \
com_amazonaws_services_lambda_runtime_api_client_runtimeapi_NativeClient.cpp -o com_amazonaws_services_lambda_runtime_api_client_runtimeapi_NativeClient.o && \
+ /usr/bin/c++ -c \
+ -std=gnu++11 \
+ -fPIC \
+ -I${JAVA_HOME}/include \
+ -I${JAVA_HOME}/include/linux \
+ -I ./deps/artifacts/include \
+ com_amazonaws_services_lambda_crac_DNSManager.cpp -o com_amazonaws_services_lambda_crac_DNSManager.o && \
/usr/bin/c++ -shared \
-std=gnu++11 \
- -o aws-lambda-runtime-interface-client.so com_amazonaws_services_lambda_runtime_api_client_runtimeapi_NativeClient.o \
+ -o aws-lambda-runtime-interface-client.so com_amazonaws_services_lambda_runtime_api_client_runtimeapi_NativeClient.o com_amazonaws_services_lambda_crac_DNSManager.o \
-L ./deps/artifacts/lib/ \
-laws-lambda-runtime \
-lcurl \
diff --git a/aws-lambda-java-runtime-interface-client/src/main/jni/build-jni-lib.sh b/aws-lambda-java-runtime-interface-client/src/main/jni/build-jni-lib.sh
index 3b505e74..b7dbb5a8 100755
--- a/aws-lambda-java-runtime-interface-client/src/main/jni/build-jni-lib.sh
+++ b/aws-lambda-java-runtime-interface-client/src/main/jni/build-jni-lib.sh
@@ -51,10 +51,21 @@ function build_for_libc_arch() {
echo "multi-arch not requested, assuming this is a workaround to goofyness when docker buildx is enabled on Linux CI environments."
echo "enabling docker buildx often updates the docker api version, so assuming that docker cli is also too old to use --output type=tar, so doing alternative build-tag-run approach"
image_name="lambda-java-jni-lib-${libc_impl}-${arch}"
+
+ # GitHub actions is using dockerx build under the hood. We need to pass --load option to be able to run the image
+ # This args is NOT part of the classic docker build command, so we need to check against a GitHub Action env var not to make local build crash.
+ if [[ "${GITHUB_RUN_ID:+isset}" == "isset" ]]; then
+ EXTRA_LOAD_ARG="--load"
+ else
+ EXTRA_LOAD_ARG=""
+ fi
+
docker build --platform="${docker_platform}" \
-t "${image_name}" \
-f "${SRC_DIR}/Dockerfile.${libc_impl}" \
- --build-arg CURL_VERSION=${CURL_VERSION} "${SRC_DIR}"
+ --build-arg CURL_VERSION=${CURL_VERSION} "${SRC_DIR}" ${EXTRA_LOAD_ARG}
+
+ echo "Docker image has been successfully built"
docker run --rm --entrypoint /bin/cat "${image_name}" \
/src/aws-lambda-runtime-interface-client.so > "${artifact}"
diff --git a/aws-lambda-java-runtime-interface-client/src/main/jni/com_amazonaws_services_lambda_crac_DNSManager.cpp b/aws-lambda-java-runtime-interface-client/src/main/jni/com_amazonaws_services_lambda_crac_DNSManager.cpp
new file mode 100644
index 00000000..ccf5481b
--- /dev/null
+++ b/aws-lambda-java-runtime-interface-client/src/main/jni/com_amazonaws_services_lambda_crac_DNSManager.cpp
@@ -0,0 +1,27 @@
+/*
+Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+SPDX-License-Identifier: Apache-2.0
+*/
+#include
+#include "macro.h"
+#include "com_amazonaws_services_lambda_crac_DNSManager.h"
+
+JNIEXPORT void JNICALL Java_com_amazonaws_services_lambda_crac_DNSManager_clearCache
+ (JNIEnv *env, jclass thisClass) {
+ jclass iNetAddressClass;
+ jclass concurrentMap;
+ jfieldID cacheFieldID;
+ jobject cacheObj;
+ jmethodID clearMethodID;
+ CHECK_EXCEPTION(env, iNetAddressClass = env->FindClass("java/net/InetAddress"));
+ CHECK_EXCEPTION(env, concurrentMap = env->FindClass("java/util/concurrent/ConcurrentMap"));
+ CHECK_EXCEPTION(env, cacheFieldID = env->GetStaticFieldID(iNetAddressClass, "cache", "Ljava/util/concurrent/ConcurrentMap;"));
+ CHECK_EXCEPTION(env, cacheObj = (jobject) env->GetStaticObjectField(iNetAddressClass, cacheFieldID));
+ CHECK_EXCEPTION(env, clearMethodID = env->GetMethodID(concurrentMap, "clear", "()V"));
+ CHECK_EXCEPTION(env, env->CallVoidMethod(cacheObj, clearMethodID));
+ return;
+
+ ERROR:
+ // we need to fail silently here
+ env->ExceptionClear();
+}
diff --git a/aws-lambda-java-runtime-interface-client/src/main/jni/com_amazonaws_services_lambda_crac_DNSManager.h b/aws-lambda-java-runtime-interface-client/src/main/jni/com_amazonaws_services_lambda_crac_DNSManager.h
new file mode 100644
index 00000000..f26639ba
--- /dev/null
+++ b/aws-lambda-java-runtime-interface-client/src/main/jni/com_amazonaws_services_lambda_crac_DNSManager.h
@@ -0,0 +1,19 @@
+/*
+Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+SPDX-License-Identifier: Apache-2.0
+*/
+#include
+
+#ifndef _Included_com_amazonaws_services_lambda_crac_DNSManager
+#define _Included_com_amazonaws_services_lambda_crac_DNSManager
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+JNIEXPORT void JNICALL Java_com_amazonaws_services_lambda_crac_DNSManager_clearCache
+ (JNIEnv *, jclass);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/aws-lambda-java-runtime-interface-client/src/main/jni/com_amazonaws_services_lambda_runtime_api_client_runtimeapi_NativeClient.cpp b/aws-lambda-java-runtime-interface-client/src/main/jni/com_amazonaws_services_lambda_runtime_api_client_runtimeapi_NativeClient.cpp
index 02cfeb7e..db71b819 100644
--- a/aws-lambda-java-runtime-interface-client/src/main/jni/com_amazonaws_services_lambda_runtime_api_client_runtimeapi_NativeClient.cpp
+++ b/aws-lambda-java-runtime-interface-client/src/main/jni/com_amazonaws_services_lambda_runtime_api_client_runtimeapi_NativeClient.cpp
@@ -1,27 +1,13 @@
/*
- * Copyright 2019-present Amazon.com, Inc. or its affiliates. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License").
- * You may not use this file except in compliance with the License.
- * A copy of the License is located at
- *
- * http://aws.amazon.com/apache2.0
- *
- * or in the "license" file accompanying this file. This file is distributed
- * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
- * express or implied. See the License for the specific language governing
- * permissions and limitations under the License.
- */
+Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+SPDX-License-Identifier: Apache-2.0
+*/
#include
+#include "macro.h"
#include "com_amazonaws_services_lambda_runtime_api_client_runtimeapi_NativeClient.h"
#include "aws/lambda-runtime/runtime.h"
#include "aws/lambda-runtime/version.h"
-#define CHECK_EXCEPTION(env, expr) \
- expr; \
- if ((env)->ExceptionOccurred()) \
- goto ERROR;
-
static aws::lambda_runtime::runtime * CLIENT = nullptr;
static jint JNI_VERSION = JNI_VERSION_1_8;
diff --git a/aws-lambda-java-runtime-interface-client/src/main/jni/com_amazonaws_services_lambda_runtime_api_client_runtimeapi_NativeClient.h b/aws-lambda-java-runtime-interface-client/src/main/jni/com_amazonaws_services_lambda_runtime_api_client_runtimeapi_NativeClient.h
index 28a6f444..27c63611 100644
--- a/aws-lambda-java-runtime-interface-client/src/main/jni/com_amazonaws_services_lambda_runtime_api_client_runtimeapi_NativeClient.h
+++ b/aws-lambda-java-runtime-interface-client/src/main/jni/com_amazonaws_services_lambda_runtime_api_client_runtimeapi_NativeClient.h
@@ -1,3 +1,7 @@
+/*
+Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+SPDX-License-Identifier: Apache-2.0
+*/
#include
#ifndef _Included_com_amazonaws_services_lambda_runtime_api_client_runtimeapi_NativeClient
diff --git a/aws-lambda-java-runtime-interface-client/src/main/jni/macro.h b/aws-lambda-java-runtime-interface-client/src/main/jni/macro.h
new file mode 100644
index 00000000..df5759af
--- /dev/null
+++ b/aws-lambda-java-runtime-interface-client/src/main/jni/macro.h
@@ -0,0 +1,14 @@
+/*
+Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+SPDX-License-Identifier: Apache-2.0
+*/
+
+#ifndef _Included_macros
+#define _Included_macros
+
+#define CHECK_EXCEPTION(env, expr) \
+ expr; \
+ if ((env)->ExceptionOccurred()) \
+ goto ERROR;
+
+#endif
diff --git a/aws-lambda-java-runtime-interface-client/src/test/java/com/amazonaws/services/lambda/crac/ContextImplTest.java b/aws-lambda-java-runtime-interface-client/src/test/java/com/amazonaws/services/lambda/crac/ContextImplTest.java
index b8166073..bad72ea2 100644
--- a/aws-lambda-java-runtime-interface-client/src/test/java/com/amazonaws/services/lambda/crac/ContextImplTest.java
+++ b/aws-lambda-java-runtime-interface-client/src/test/java/com/amazonaws/services/lambda/crac/ContextImplTest.java
@@ -1,22 +1,35 @@
/*
- * Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
- */
-
+Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+SPDX-License-Identifier: Apache-2.0
+*/
package com.amazonaws.services.lambda.crac;
+import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.condition.DisabledOnOs;
+import org.junit.jupiter.api.condition.OS;
import org.mockito.ArgumentMatchers;
import org.mockito.InOrder;
import org.mockito.Mockito;
-import static org.junit.jupiter.api.Assertions.*;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
import static org.mockito.Mockito.doThrow;
+import com.amazonaws.services.lambda.runtime.api.client.runtimeapi.JniHelper;
+
+@DisabledOnOs(OS.MAC)
public class ContextImplTest {
private Resource throwsWithSuppressedException, noop, noop2, throwsException, throwCustomException;
+ @BeforeAll
+ public static void jniLoad() {
+ JniHelper.load();
+ }
+
@BeforeEach
public void setup() throws Exception {
diff --git a/aws-lambda-java-runtime-interface-client/src/test/java/com/amazonaws/services/lambda/crac/DNSCacheManagerTest.java b/aws-lambda-java-runtime-interface-client/src/test/java/com/amazonaws/services/lambda/crac/DNSCacheManagerTest.java
new file mode 100644
index 00000000..5eb6f749
--- /dev/null
+++ b/aws-lambda-java-runtime-interface-client/src/test/java/com/amazonaws/services/lambda/crac/DNSCacheManagerTest.java
@@ -0,0 +1,124 @@
+/*
+Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+SPDX-License-Identifier: Apache-2.0
+*/
+
+package com.amazonaws.services.lambda.crac;
+
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.condition.DisabledOnOs;
+import org.junit.jupiter.api.condition.OS;
+
+import com.amazonaws.services.lambda.runtime.api.client.runtimeapi.JniHelper;
+
+import java.util.Map;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.lang.reflect.Field;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.fail;
+
+@DisabledOnOs(OS.MAC)
+public class DNSCacheManagerTest {
+
+ static String CACHE_FIELD_NAME = "cache";
+
+ // this should have no effect, as the DNS cache is cleared explicitly in these tests
+ static {
+ java.security.Security.setProperty("networkaddress.cache.ttl" , "10000");
+ java.security.Security.setProperty("networkaddress.cache.negative.ttl" , "10000");
+ }
+
+ @BeforeAll
+ public static void jniLoad() {
+ JniHelper.load();
+ }
+
+ @BeforeEach
+ public void setup() {
+ Core.resetGlobalContext();
+ DNSManager.clearCache();
+ }
+
+ static class StatefulResource implements Resource {
+
+ int state = 0;
+
+ @Override
+ public void afterRestore(Context extends Resource> context) {
+ state += 1;
+ }
+
+ @Override
+ public void beforeCheckpoint(Context extends Resource> context) {
+ state += 2;
+ }
+
+ int getValue() {
+ return state;
+ }
+ }
+
+ @Test
+ public void positiveDnsCacheShouldBeEmpty() throws CheckpointException, RestoreException, UnknownHostException, ReflectiveOperationException {
+ int baselineDNSEntryCount = getDNSEntryCount();
+
+ StatefulResource resource = new StatefulResource();
+ Core.getGlobalContext().register(resource);
+
+ String[] hosts = {"www.stackoverflow.com", "www.amazon.com", "www.yahoo.com"};
+ for(String singleHost : hosts) {
+ InetAddress address = InetAddress.getByName(singleHost);
+ }
+ // n hosts -> n DNS entries
+ assertEquals(hosts.length, getDNSEntryCount() - baselineDNSEntryCount);
+
+ // this should call the native static method clearDNSCache
+ Core.getGlobalContext().beforeCheckpoint(null);
+
+ // cache should be cleared
+ assertEquals(0, getDNSEntryCount());
+ }
+
+ @Test
+ public void negativeDnsCacheShouldBeEmpty() throws CheckpointException, RestoreException, UnknownHostException, ReflectiveOperationException {
+ int baselineDNSEntryCount = getDNSEntryCount();
+
+ StatefulResource resource = new StatefulResource();
+ Core.getGlobalContext().register(resource);
+
+ String invalidHost = "not.a.valid.host";
+ try {
+ InetAddress address = InetAddress.getByName(invalidHost);
+ fail();
+ } catch(UnknownHostException uhe) {
+ // this is actually fine
+ }
+
+ // 1 host -> 1 DNS entry
+ assertEquals(1, getDNSEntryCount() - baselineDNSEntryCount);
+
+ // this should the native static method clearDNSCache
+ Core.getGlobalContext().beforeCheckpoint(null);
+
+ // cache should be cleared
+ assertEquals(0, getDNSEntryCount());
+ }
+
+ // helper functions to access the cache via reflection (see maven-surefire-plugin command args)
+ protected static Map, ?> getDNSCache() throws ReflectiveOperationException {
+ Class klass = InetAddress.class;
+ Field acf = klass.getDeclaredField(CACHE_FIELD_NAME);
+ acf.setAccessible(true);
+ Object addressCache = acf.get(null);
+ return (Map, ?>) acf.get(addressCache);
+ }
+
+ protected static int getDNSEntryCount() throws ReflectiveOperationException {
+ Map, ?> cache = getDNSCache();
+ return cache.size();
+ }
+}
diff --git a/aws-lambda-java-runtime-interface-client/src/test/java/com/amazonaws/services/lambda/runtime/api/client/UserFaultTest.java b/aws-lambda-java-runtime-interface-client/src/test/java/com/amazonaws/services/lambda/runtime/api/client/UserFaultTest.java
index 9e88024b..5a57e6e0 100644
--- a/aws-lambda-java-runtime-interface-client/src/test/java/com/amazonaws/services/lambda/runtime/api/client/UserFaultTest.java
+++ b/aws-lambda-java-runtime-interface-client/src/test/java/com/amazonaws/services/lambda/runtime/api/client/UserFaultTest.java
@@ -84,4 +84,44 @@ public void testSuppressedExceptionsAreIncluded() {
assertTrue(reportableUserFault.contains("Suppressed: java.lang.RuntimeException: error 2"), "Suppressed error 2 missing in reported UserFault");
}
}
+
+ @Test
+ public void testCircularExceptionReference() {
+ RuntimeException e1 = new RuntimeException();
+ RuntimeException e2 = new RuntimeException(e1);
+ e1.initCause(e2);
+
+ try {
+ throw e2;
+ } catch (Exception e) {
+ String stackTrace = UserFault.trace(e);
+ String expectedStackTrace = "java.lang.RuntimeException: java.lang.RuntimeException\n" +
+ "Caused by: java.lang.RuntimeException\n" +
+ "Caused by: [CIRCULAR REFERENCE: java.lang.RuntimeException: java.lang.RuntimeException]\n";
+
+ assertEquals(expectedStackTrace, stackTrace);
+ }
+ }
+
+ @Test
+ public void testCircularSuppressedExceptionReference() {
+ RuntimeException e1 = new RuntimeException("Primary Exception");
+ RuntimeException e2 = new RuntimeException(e1);
+ RuntimeException e3 = new RuntimeException("Exception with suppressed");
+
+ e1.addSuppressed(e2);
+ e3.addSuppressed(e2);
+
+ try {
+ throw e3;
+ } catch (Exception e) {
+ String stackTrace = UserFault.trace(e);
+ String expectedStackTrace = "java.lang.RuntimeException: Exception with suppressed\n" +
+ "\tSuppressed: java.lang.RuntimeException: java.lang.RuntimeException: Primary Exception\n" +
+ "\tCaused by: java.lang.RuntimeException: Primary Exception\n" +
+ "\t\tSuppressed: [CIRCULAR REFERENCE: java.lang.RuntimeException: java.lang.RuntimeException: Primary Exception]\n";
+
+ assertEquals(expectedStackTrace, stackTrace);
+ }
+ }
}
diff --git a/aws-lambda-java-runtime-interface-client/test/integration/codebuild/buildspec.os.alpine.yml b/aws-lambda-java-runtime-interface-client/test/integration/codebuild/buildspec.os.alpine.yml
index 4f8caf39..cdc27a65 100644
--- a/aws-lambda-java-runtime-interface-client/test/integration/codebuild/buildspec.os.alpine.yml
+++ b/aws-lambda-java-runtime-interface-client/test/integration/codebuild/buildspec.os.alpine.yml
@@ -44,7 +44,7 @@ phases:
- (cd aws-lambda-java-events && mvn install)
# Install serialization (dependency of RIC)
- (cd aws-lambda-java-serialization && mvn install)
- - (cd aws-lambda-java-runtime-interface-client && mvn install)
+ - (cd aws-lambda-java-runtime-interface-client && mvn install -DargLineForReflectionTestOnly="")
- (cd aws-lambda-java-runtime-interface-client/test/integration/test-handler && mvn install)
- export IMAGE_TAG="java-${OS_DISTRIBUTION}-${DISTRO_VERSION}:${RUNTIME_VERSION}"
- echo "Extracting and including Runtime Interface Emulator"
diff --git a/aws-lambda-java-runtime-interface-client/test/integration/codebuild/buildspec.os.amazoncorretto.yml b/aws-lambda-java-runtime-interface-client/test/integration/codebuild/buildspec.os.amazoncorretto.yml
index fd45aabb..67dd7617 100644
--- a/aws-lambda-java-runtime-interface-client/test/integration/codebuild/buildspec.os.amazoncorretto.yml
+++ b/aws-lambda-java-runtime-interface-client/test/integration/codebuild/buildspec.os.amazoncorretto.yml
@@ -43,7 +43,7 @@ phases:
- (cd aws-lambda-java-events && mvn install)
# Install serialization (dependency of RIC)
- (cd aws-lambda-java-serialization && mvn install)
- - (cd aws-lambda-java-runtime-interface-client && mvn install)
+ - (cd aws-lambda-java-runtime-interface-client && mvn install -DargLineForReflectionTestOnly="")
- (cd aws-lambda-java-runtime-interface-client/test/integration/test-handler && mvn install)
- export IMAGE_TAG="java-${OS_DISTRIBUTION}-${DISTRO_VERSION}:${RUNTIME_VERSION}"
- echo "Extracting and including Runtime Interface Emulator"
diff --git a/aws-lambda-java-runtime-interface-client/test/integration/codebuild/buildspec.os.amazonlinux.1.yml b/aws-lambda-java-runtime-interface-client/test/integration/codebuild/buildspec.os.amazonlinux.1.yml
index 197e9724..04c486a8 100644
--- a/aws-lambda-java-runtime-interface-client/test/integration/codebuild/buildspec.os.amazonlinux.1.yml
+++ b/aws-lambda-java-runtime-interface-client/test/integration/codebuild/buildspec.os.amazonlinux.1.yml
@@ -38,7 +38,7 @@ phases:
- (cd aws-lambda-java-events && mvn install)
# Install serialization (dependency of RIC)
- (cd aws-lambda-java-serialization && mvn install)
- - (cd aws-lambda-java-runtime-interface-client && mvn install -DmultiArch=false)
+ - (cd aws-lambda-java-runtime-interface-client && mvn install -DmultiArch=false -DargLineForReflectionTestOnly="")
- (cd aws-lambda-java-runtime-interface-client/test/integration/test-handler && mvn install)
- export IMAGE_TAG="java-${OS_DISTRIBUTION}-${DISTRO_VERSION}:${RUNTIME_VERSION}"
- echo "Extracting and including Runtime Interface Emulator"
diff --git a/aws-lambda-java-runtime-interface-client/test/integration/codebuild/buildspec.os.amazonlinux.2.yml b/aws-lambda-java-runtime-interface-client/test/integration/codebuild/buildspec.os.amazonlinux.2.yml
index 75b816e8..8222bb41 100644
--- a/aws-lambda-java-runtime-interface-client/test/integration/codebuild/buildspec.os.amazonlinux.2.yml
+++ b/aws-lambda-java-runtime-interface-client/test/integration/codebuild/buildspec.os.amazonlinux.2.yml
@@ -42,7 +42,7 @@ phases:
- (cd aws-lambda-java-events && mvn install)
# Install serialization (dependency of RIC)
- (cd aws-lambda-java-serialization && mvn install)
- - (cd aws-lambda-java-runtime-interface-client && mvn install)
+ - (cd aws-lambda-java-runtime-interface-client && mvn install -DargLineForReflectionTestOnly="")
- (cd aws-lambda-java-runtime-interface-client/test/integration/test-handler && mvn install)
- export IMAGE_TAG="java-${OS_DISTRIBUTION}-${DISTRO_VERSION}:${RUNTIME_VERSION}"
- echo "Extracting and including Runtime Interface Emulator"
diff --git a/aws-lambda-java-runtime-interface-client/test/integration/test-handler/pom.xml b/aws-lambda-java-runtime-interface-client/test/integration/test-handler/pom.xml
index dd69c8e0..40c79fe9 100644
--- a/aws-lambda-java-runtime-interface-client/test/integration/test-handler/pom.xml
+++ b/aws-lambda-java-runtime-interface-client/test/integration/test-handler/pom.xml
@@ -15,7 +15,7 @@
com.amazonaws
aws-lambda-java-runtime-interface-client
- 2.5.0
+ 2.5.1
diff --git a/aws-lambda-java-tests/src/main/java/com/amazonaws/services/lambda/runtime/tests/EventLoader.java b/aws-lambda-java-tests/src/main/java/com/amazonaws/services/lambda/runtime/tests/EventLoader.java
index aa600749..77812267 100644
--- a/aws-lambda-java-tests/src/main/java/com/amazonaws/services/lambda/runtime/tests/EventLoader.java
+++ b/aws-lambda-java-tests/src/main/java/com/amazonaws/services/lambda/runtime/tests/EventLoader.java
@@ -45,10 +45,18 @@ public static CloudFrontEvent loadCloudFrontEvent(String filename) {
return loadEvent(filename, CloudFrontEvent.class);
}
+ public static CloudWatchCompositeAlarmEvent loadCloudWatchCompositeAlarmEvent(String filename) {
+ return loadEvent(filename, CloudWatchCompositeAlarmEvent.class);
+ }
+
public static CloudWatchLogsEvent loadCloudWatchLogsEvent(String filename) {
return loadEvent(filename, CloudWatchLogsEvent.class);
}
+ public static CloudWatchMetricAlarmEvent loadCloudWatchMetricAlarmEvent(String filename) {
+ return loadEvent(filename, CloudWatchMetricAlarmEvent.class);
+ }
+
public static CodeCommitEvent loadCodeCommitEvent(String filename) {
return loadEvent(filename, CodeCommitEvent.class);
}
@@ -89,6 +97,10 @@ public static LexEvent loadLexEvent(String filename) {
return loadEvent(filename, LexEvent.class);
}
+ public static MSKFirehoseEvent loadMSKFirehoseEvent(String filename) {
+ return loadEvent(filename, MSKFirehoseEvent.class);
+ }
+
public static S3Event loadS3Event(String filename) {
return loadEvent(filename, S3Event.class);
}
diff --git a/aws-lambda-java-tests/src/test/java/com/amazonaws/services/lambda/runtime/tests/EventLoaderTest.java b/aws-lambda-java-tests/src/test/java/com/amazonaws/services/lambda/runtime/tests/EventLoaderTest.java
index 1c9d17e1..4aa920f8 100644
--- a/aws-lambda-java-tests/src/test/java/com/amazonaws/services/lambda/runtime/tests/EventLoaderTest.java
+++ b/aws-lambda-java-tests/src/test/java/com/amazonaws/services/lambda/runtime/tests/EventLoaderTest.java
@@ -1,6 +1,38 @@
/* Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. */
package com.amazonaws.services.lambda.runtime.tests;
+import com.amazonaws.services.lambda.runtime.events.APIGatewayCustomAuthorizerEvent;
+import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent;
+import com.amazonaws.services.lambda.runtime.events.APIGatewayV2CustomAuthorizerEvent;
+import com.amazonaws.services.lambda.runtime.events.APIGatewayV2HTTPEvent;
+import com.amazonaws.services.lambda.runtime.events.ActiveMQEvent;
+import com.amazonaws.services.lambda.runtime.events.ApplicationLoadBalancerRequestEvent;
+import com.amazonaws.services.lambda.runtime.events.CloudFormationCustomResourceEvent;
+import com.amazonaws.services.lambda.runtime.events.CloudFrontEvent;
+import com.amazonaws.services.lambda.runtime.events.CloudWatchCompositeAlarmEvent;
+import com.amazonaws.services.lambda.runtime.events.CloudWatchCompositeAlarmEvent.AlarmData;
+import com.amazonaws.services.lambda.runtime.events.CloudWatchCompositeAlarmEvent.Configuration;
+import com.amazonaws.services.lambda.runtime.events.CloudWatchCompositeAlarmEvent.PreviousState;
+import com.amazonaws.services.lambda.runtime.events.CloudWatchCompositeAlarmEvent.State;
+import com.amazonaws.services.lambda.runtime.events.CloudWatchLogsEvent;
+import com.amazonaws.services.lambda.runtime.events.CloudWatchMetricAlarmEvent;
+import com.amazonaws.services.lambda.runtime.events.CodeCommitEvent;
+import com.amazonaws.services.lambda.runtime.events.CognitoUserPoolPreTokenGenerationEventV2;
+import com.amazonaws.services.lambda.runtime.events.ConfigEvent;
+import com.amazonaws.services.lambda.runtime.events.ConnectEvent;
+import com.amazonaws.services.lambda.runtime.events.DynamodbEvent;
+import com.amazonaws.services.lambda.runtime.events.KafkaEvent;
+import com.amazonaws.services.lambda.runtime.events.KinesisEvent;
+import com.amazonaws.services.lambda.runtime.events.KinesisFirehoseEvent;
+import com.amazonaws.services.lambda.runtime.events.LambdaDestinationEvent;
+import com.amazonaws.services.lambda.runtime.events.LexEvent;
+import com.amazonaws.services.lambda.runtime.events.MSKFirehoseEvent;
+import com.amazonaws.services.lambda.runtime.events.RabbitMQEvent;
+import com.amazonaws.services.lambda.runtime.events.S3Event;
+import com.amazonaws.services.lambda.runtime.events.SNSEvent;
+import com.amazonaws.services.lambda.runtime.events.SQSEvent;
+import com.amazonaws.services.lambda.runtime.events.ScheduledEvent;
+import com.amazonaws.services.lambda.runtime.events.SecretsManagerRotationEvent;
import com.amazonaws.services.lambda.runtime.events.models.dynamodb.AttributeValue;
import com.amazonaws.services.lambda.runtime.events.models.dynamodb.Record;
import com.amazonaws.services.lambda.runtime.events.models.dynamodb.StreamRecord;
@@ -15,8 +47,6 @@
import static java.time.Instant.ofEpochSecond;
import static org.assertj.core.api.Assertions.*;
-import com.amazonaws.services.lambda.runtime.events.*;
-
public class EventLoaderTest {
@Test
@@ -118,6 +148,19 @@ public void testLoadKinesisFirehoseEvent() {
assertThat(event.getRecords().get(0).getData().array()).asString().isEqualTo("Hello, this is a test 123.");
}
+ @Test
+ public void testLoadMSKFirehoseEvent() {
+ MSKFirehoseEvent event = EventLoader.loadMSKFirehoseEvent("msk_firehose_event.json");
+
+ assertThat(event).isNotNull();
+ assertThat(event.getSourceMSKArn()).isEqualTo("arn:aws:kafka:EXAMPLE");
+ assertThat(event.getDeliveryStreamArn()).isEqualTo("arn:aws:firehose:EXAMPLE");
+ assertThat(event.getRecords()).hasSize(1);
+ assertThat(event.getRecords().get(0).getKafkaRecordValue().array()).asString().isEqualTo("{\"Name\":\"Hello World\"}");
+ assertThat(event.getRecords().get(0).getApproximateArrivalTimestamp()).asString().isEqualTo("1716369573887");
+ assertThat(event.getRecords().get(0).getMskRecordMetadata()).asString().isEqualTo("{offset=0, partitionId=1, approximateArrivalTimestamp=1716369573887}");
+ }
+
@Test
public void testLoadS3Event() {
S3Event event = EventLoader.loadS3Event("s3_event.json");
@@ -376,4 +419,108 @@ public void testLoadCognitoUserPoolPreTokenGenerationEventV2() {
String[] requestScopes = request.getScopes();
assertThat("aws.cognito.signin.user.admin").isEqualTo(requestScopes[0]);
}
+
+ @Test
+ public void testCloudWatchCompositeAlarmEvent() {
+ CloudWatchCompositeAlarmEvent event = EventLoader.loadCloudWatchCompositeAlarmEvent("cloudwatch_composite_alarm.json");
+ assertThat(event).isNotNull();
+ assertThat(event)
+ .returns("aws.cloudwatch", from(CloudWatchCompositeAlarmEvent::getSource))
+ .returns("arn:aws:cloudwatch:us-east-1:111122223333:alarm:SuppressionDemo.Main", from(CloudWatchCompositeAlarmEvent::getAlarmArn))
+ .returns("111122223333", from(CloudWatchCompositeAlarmEvent::getAccountId))
+ .returns("2023-08-04T12:56:46.138+0000", from(CloudWatchCompositeAlarmEvent::getTime))
+ .returns("us-east-1", from(CloudWatchCompositeAlarmEvent::getRegion));
+
+ AlarmData alarmData = event.getAlarmData();
+ assertThat(alarmData).isNotNull();
+ assertThat(alarmData)
+ .returns("CompositeDemo.Main", from(AlarmData::getAlarmName));
+
+ State state = alarmData.getState();
+ assertThat(state).isNotNull();
+ assertThat(state)
+ .returns("ALARM", from(State::getValue))
+ .returns("arn:aws:cloudwatch:us-east-1:111122223333:alarm:CompositeDemo.FirstChild transitioned to ALARM at Friday 04 August, 2023 12:54:46 UTC", from(State::getReason))
+ .returns("{\"triggeringAlarms\":[{\"arn\":\"arn:aws:cloudwatch:us-east-1:111122223333:alarm:CompositeDemo.FirstChild\",\"state\":{\"value\":\"ALARM\",\"timestamp\":\"2023-08-04T12:54:46.138+0000\"}}]}", from(State::getReasonData))
+ .returns("2023-08-04T12:56:46.138+0000", from(State::getTimestamp));
+
+ PreviousState previousState = alarmData.getPreviousState();
+ assertThat(previousState).isNotNull();
+ assertThat(previousState)
+ .returns("ALARM", from(PreviousState::getValue))
+ .returns("arn:aws:cloudwatch:us-east-1:111122223333:alarm:CompositeDemo.FirstChild transitioned to ALARM at Friday 04 August, 2023 12:54:46 UTC", from(PreviousState::getReason))
+ .returns("{\"triggeringAlarms\":[{\"arn\":\"arn:aws:cloudwatch:us-east-1:111122223333:alarm:CompositeDemo.FirstChild\",\"state\":{\"value\":\"ALARM\",\"timestamp\":\"2023-08-04T12:54:46.138+0000\"}}]}", from(PreviousState::getReasonData))
+ .returns("2023-08-04T12:54:46.138+0000", from(PreviousState::getTimestamp))
+ .returns("WaitPeriod", from(PreviousState::getActionsSuppressedBy))
+ .returns("Actions suppressed by WaitPeriod", from(PreviousState::getActionsSuppressedReason));
+
+ Configuration configuration = alarmData.getConfiguration();
+ assertThat(configuration).isNotNull();
+ assertThat(configuration)
+ .returns("ALARM(CompositeDemo.FirstChild) OR ALARM(CompositeDemo.SecondChild)", from(Configuration::getAlarmRule))
+ .returns("CompositeDemo.ActionsSuppressor", from(Configuration::getActionsSuppressor))
+ .returns(120, from(Configuration::getActionsSuppressorWaitPeriod))
+ .returns(180, from(Configuration::getActionsSuppressorExtensionPeriod));
+ }
+
+ @Test
+ public void testCloudWatchMetricAlarmEvent() {
+ CloudWatchMetricAlarmEvent event = EventLoader.loadCloudWatchMetricAlarmEvent("cloudwatch_metric_alarm.json");
+ assertThat(event).isNotNull();
+ assertThat(event)
+ .returns("aws.cloudwatch", from(CloudWatchMetricAlarmEvent::getSource))
+ .returns("arn:aws:cloudwatch:us-east-1:444455556666:alarm:lambda-demo-metric-alarm", from(CloudWatchMetricAlarmEvent::getAlarmArn))
+ .returns("444455556666", from(CloudWatchMetricAlarmEvent::getAccountId))
+ .returns("2023-08-04T12:36:15.490+0000", from(CloudWatchMetricAlarmEvent::getTime))
+ .returns("us-east-1", from(CloudWatchMetricAlarmEvent::getRegion));
+
+ CloudWatchMetricAlarmEvent.AlarmData alarmData = event.getAlarmData();
+ assertThat(alarmData).isNotNull();
+ assertThat(alarmData)
+ .returns("lambda-demo-metric-alarm", from(CloudWatchMetricAlarmEvent.AlarmData::getAlarmName));
+
+ CloudWatchMetricAlarmEvent.State state = alarmData.getState();
+ assertThat(state).isNotNull();
+ assertThat(state)
+ .returns("ALARM", from(CloudWatchMetricAlarmEvent.State::getValue))
+ .returns("test", from(CloudWatchMetricAlarmEvent.State::getReason))
+ .returns("2023-08-04T12:36:15.490+0000", from(CloudWatchMetricAlarmEvent.State::getTimestamp));
+
+ CloudWatchMetricAlarmEvent.PreviousState previousState = alarmData.getPreviousState();
+ assertThat(previousState).isNotNull();
+ assertThat(previousState)
+ .returns("INSUFFICIENT_DATA", from(CloudWatchMetricAlarmEvent.PreviousState::getValue))
+ .returns("Insufficient Data: 5 datapoints were unknown.", from(CloudWatchMetricAlarmEvent.PreviousState::getReason))
+ .returns("{\"version\":\"1.0\",\"queryDate\":\"2023-08-04T12:31:29.591+0000\",\"statistic\":\"Average\",\"period\":60,\"recentDatapoints\":[],\"threshold\":5.0,\"evaluatedDatapoints\":[{\"timestamp\":\"2023-08-04T12:30:00.000+0000\"},{\"timestamp\":\"2023-08-04T12:29:00.000+0000\"},{\"timestamp\":\"2023-08-04T12:28:00.000+0000\"},{\"timestamp\":\"2023-08-04T12:27:00.000+0000\"},{\"timestamp\":\"2023-08-04T12:26:00.000+0000\"}]}", from(CloudWatchMetricAlarmEvent.PreviousState::getReasonData))
+ .returns("2023-08-04T12:31:29.595+0000", from(CloudWatchMetricAlarmEvent.PreviousState::getTimestamp));
+
+ CloudWatchMetricAlarmEvent.Configuration configuration = alarmData.getConfiguration();
+ assertThat(configuration).isNotNull();
+ assertThat(configuration)
+ .returns("Metric Alarm to test Lambda actions", from(CloudWatchMetricAlarmEvent.Configuration::getDescription));
+
+ List metrics = configuration.getMetrics();
+ assertThat(metrics).hasSize(1);
+ CloudWatchMetricAlarmEvent.Metric metric = metrics.get(0);
+ assertThat(metric)
+ .returns("1234e046-06f0-a3da-9534-EXAMPLEe4c", from(CloudWatchMetricAlarmEvent.Metric::getId));
+
+ CloudWatchMetricAlarmEvent.MetricStat metricStat = metric.getMetricStat();
+ assertThat(metricStat).isNotNull();
+ assertThat(metricStat)
+ .returns(60, from(CloudWatchMetricAlarmEvent.MetricStat::getPeriod))
+ .returns("Average", from(CloudWatchMetricAlarmEvent.MetricStat::getStat))
+ .returns("Percent", from(CloudWatchMetricAlarmEvent.MetricStat::getUnit));
+
+ CloudWatchMetricAlarmEvent.MetricDetail metricDetail = metricStat.getMetric();
+ assertThat(metricDetail).isNotNull();
+ assertThat(metricDetail)
+ .returns("AWS/Logs", from(CloudWatchMetricAlarmEvent.MetricDetail::getNamespace))
+ .returns("CallCount", from(CloudWatchMetricAlarmEvent.MetricDetail::getName));
+
+ Map dimensions = metricDetail.getDimensions();
+ assertThat(dimensions).isNotEmpty().hasSize(1);
+ assertThat(dimensions)
+ .contains(entry("InstanceId", "i-12345678"));
+ }
}
diff --git a/aws-lambda-java-tests/src/test/resources/cloudwatch_composite_alarm.json b/aws-lambda-java-tests/src/test/resources/cloudwatch_composite_alarm.json
new file mode 100644
index 00000000..353d470a
--- /dev/null
+++ b/aws-lambda-java-tests/src/test/resources/cloudwatch_composite_alarm.json
@@ -0,0 +1,30 @@
+{
+ "source": "aws.cloudwatch",
+ "alarmArn": "arn:aws:cloudwatch:us-east-1:111122223333:alarm:SuppressionDemo.Main",
+ "accountId": "111122223333",
+ "time": "2023-08-04T12:56:46.138+0000",
+ "region": "us-east-1",
+ "alarmData": {
+ "alarmName": "CompositeDemo.Main",
+ "state": {
+ "value": "ALARM",
+ "reason": "arn:aws:cloudwatch:us-east-1:111122223333:alarm:CompositeDemo.FirstChild transitioned to ALARM at Friday 04 August, 2023 12:54:46 UTC",
+ "reasonData": "{\"triggeringAlarms\":[{\"arn\":\"arn:aws:cloudwatch:us-east-1:111122223333:alarm:CompositeDemo.FirstChild\",\"state\":{\"value\":\"ALARM\",\"timestamp\":\"2023-08-04T12:54:46.138+0000\"}}]}",
+ "timestamp": "2023-08-04T12:56:46.138+0000"
+ },
+ "previousState": {
+ "value": "ALARM",
+ "reason": "arn:aws:cloudwatch:us-east-1:111122223333:alarm:CompositeDemo.FirstChild transitioned to ALARM at Friday 04 August, 2023 12:54:46 UTC",
+ "reasonData": "{\"triggeringAlarms\":[{\"arn\":\"arn:aws:cloudwatch:us-east-1:111122223333:alarm:CompositeDemo.FirstChild\",\"state\":{\"value\":\"ALARM\",\"timestamp\":\"2023-08-04T12:54:46.138+0000\"}}]}",
+ "timestamp": "2023-08-04T12:54:46.138+0000",
+ "actionsSuppressedBy": "WaitPeriod",
+ "actionsSuppressedReason": "Actions suppressed by WaitPeriod"
+ },
+ "configuration": {
+ "alarmRule": "ALARM(CompositeDemo.FirstChild) OR ALARM(CompositeDemo.SecondChild)",
+ "actionsSuppressor": "CompositeDemo.ActionsSuppressor",
+ "actionsSuppressorWaitPeriod": 120,
+ "actionsSuppressorExtensionPeriod": 180
+ }
+ }
+}
\ No newline at end of file
diff --git a/aws-lambda-java-tests/src/test/resources/cloudwatch_metric_alarm.json b/aws-lambda-java-tests/src/test/resources/cloudwatch_metric_alarm.json
new file mode 100644
index 00000000..61b4187b
--- /dev/null
+++ b/aws-lambda-java-tests/src/test/resources/cloudwatch_metric_alarm.json
@@ -0,0 +1,42 @@
+{
+ "source": "aws.cloudwatch",
+ "alarmArn": "arn:aws:cloudwatch:us-east-1:444455556666:alarm:lambda-demo-metric-alarm",
+ "accountId": "444455556666",
+ "time": "2023-08-04T12:36:15.490+0000",
+ "region": "us-east-1",
+ "alarmData": {
+ "alarmName": "lambda-demo-metric-alarm",
+ "state": {
+ "value": "ALARM",
+ "reason": "test",
+ "timestamp": "2023-08-04T12:36:15.490+0000"
+ },
+ "previousState": {
+ "value": "INSUFFICIENT_DATA",
+ "reason": "Insufficient Data: 5 datapoints were unknown.",
+ "reasonData": "{\"version\":\"1.0\",\"queryDate\":\"2023-08-04T12:31:29.591+0000\",\"statistic\":\"Average\",\"period\":60,\"recentDatapoints\":[],\"threshold\":5.0,\"evaluatedDatapoints\":[{\"timestamp\":\"2023-08-04T12:30:00.000+0000\"},{\"timestamp\":\"2023-08-04T12:29:00.000+0000\"},{\"timestamp\":\"2023-08-04T12:28:00.000+0000\"},{\"timestamp\":\"2023-08-04T12:27:00.000+0000\"},{\"timestamp\":\"2023-08-04T12:26:00.000+0000\"}]}",
+ "timestamp": "2023-08-04T12:31:29.595+0000"
+ },
+ "configuration": {
+ "description": "Metric Alarm to test Lambda actions",
+ "metrics": [
+ {
+ "id": "1234e046-06f0-a3da-9534-EXAMPLEe4c",
+ "metricStat": {
+ "metric": {
+ "namespace": "AWS/Logs",
+ "name": "CallCount",
+ "dimensions": {
+ "InstanceId": "i-12345678"
+ }
+ },
+ "period": 60,
+ "stat": "Average",
+ "unit": "Percent"
+ },
+ "returnData": true
+ }
+ ]
+ }
+ }
+}
\ No newline at end of file
diff --git a/aws-lambda-java-tests/src/test/resources/msk_firehose_event.json b/aws-lambda-java-tests/src/test/resources/msk_firehose_event.json
new file mode 100644
index 00000000..6b839912
--- /dev/null
+++ b/aws-lambda-java-tests/src/test/resources/msk_firehose_event.json
@@ -0,0 +1,18 @@
+{
+ "invocationId": "12345621-4787-0000-a418-36e56Example",
+ "sourceMSKArn": "arn:aws:kafka:EXAMPLE",
+ "deliveryStreamArn": "arn:aws:firehose:EXAMPLE",
+ "region": "us-east-1",
+ "records": [
+ {
+ "recordId": "00000000000000000000000000000000000000000000000000000000000000",
+ "approximateArrivalTimestamp": 1716369573887,
+ "mskRecordMetadata": {
+ "offset": "0",
+ "partitionId": "1",
+ "approximateArrivalTimestamp": 1716369573887
+ },
+ "kafkaRecordValue": "eyJOYW1lIjoiSGVsbG8gV29ybGQifQ=="
+ }
+ ]
+}
diff --git a/samples/msk-firehose-event-handler/src/main/java/example/MSKFirehoseEventHandler.java b/samples/msk-firehose-event-handler/src/main/java/example/MSKFirehoseEventHandler.java
new file mode 100644
index 00000000..f5e51349
--- /dev/null
+++ b/samples/msk-firehose-event-handler/src/main/java/example/MSKFirehoseEventHandler.java
@@ -0,0 +1,39 @@
+/*
+Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+SPDX-License-Identifier: Apache-2.0
+*/
+
+package example;
+
+import com.amazonaws.services.lambda.runtime.Context;
+import com.amazonaws.services.lambda.runtime.RequestHandler;
+import com.amazonaws.services.lambda.runtime.events.MSKFirehoseResponse;
+import com.amazonaws.services.lambda.runtime.events.MSKFirehoseEvent;
+import org.json.JSONObject;
+
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A sample MSKFirehoseEvent handler
+ * For more information see the developer guide - ...
+ */
+public class MSKFirehoseEventHandler implements RequestHandler {
+
+ @Override
+ public MSKFirehoseResponse handleRequest(MSKFirehoseEvent MSKFirehoseEvent, Context context) {
+ List records = new ArrayList<>();
+
+ for (MSKFirehoseEvent.Record record : MSKFirehoseEvent.getRecords()) {
+ String recordData = new String(record.getKafkaRecordValue().array());
+ // Your business logic
+ JSONObject jsonObject = new JSONObject(recordData);
+ records.add(new MSKFirehoseResponse.Record(record.getRecordId(), MSKFirehoseResponse.Result.Ok, encode(jsonObject.toString())));
+ }
+ return new MSKFirehoseResponse(records);
+ }
+ private ByteBuffer encode(String content) {
+ return ByteBuffer.wrap(content.getBytes());
+ }
+}
diff --git a/samples/msk-firehose-event-handler/src/test/java/example/MSKFirehoseEventHandlerTest.java b/samples/msk-firehose-event-handler/src/test/java/example/MSKFirehoseEventHandlerTest.java
new file mode 100644
index 00000000..77223e51
--- /dev/null
+++ b/samples/msk-firehose-event-handler/src/test/java/example/MSKFirehoseEventHandlerTest.java
@@ -0,0 +1,32 @@
+/*
+Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+SPDX-License-Identifier: Apache-2.0
+*/
+
+package example;
+
+import com.amazonaws.services.lambda.runtime.Context;
+import com.amazonaws.services.lambda.runtime.tests.annotations.Event;
+import com.amazonaws.services.lambda.runtime.events.MSKFirehoseEvent;
+import com.amazonaws.services.lambda.runtime.events.MSKFirehoseResponse;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.params.ParameterizedTest;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+public class MSKFirehoseEventHandlerTest {
+
+ private Context context; // intentionally null as it's not used in the test
+
+ @ParameterizedTest
+ @Event(value = "event.json", type = MSKFirehoseEvent.class)
+ public void testEventHandler(MSKFirehoseEvent event) {
+ MSKFirehoseEventHandler Sample = new MSKFirehoseEventHandler();
+ MSKFirehoseResponse response = Sample.handleRequest(event, context);
+
+ String expectedString = "{\"Name\":\"Hello World\"}";
+ MSKFirehoseResponse.Record firstRecord = response.getRecords().get(0);
+ Assertions.assertEquals(expectedString, UTF_8.decode(firstRecord.getKafkaRecordValue()).toString());
+ Assertions.assertEquals(MSKFirehoseResponse.Result.Ok, firstRecord.getResult());
+ }
+}
diff --git a/samples/msk-firehose-event-handler/src/test/resources/event.json b/samples/msk-firehose-event-handler/src/test/resources/event.json
new file mode 100644
index 00000000..91c4b420
--- /dev/null
+++ b/samples/msk-firehose-event-handler/src/test/resources/event.json
@@ -0,0 +1,18 @@
+{
+ "invocationId": "12345621-4787-0000-a418-36e56Example",
+ "sourceMSKArn": "",
+ "deliveryStreamArn": "",
+ "region": "us-east-1",
+ "records": [
+ {
+ "recordId": "00000000000000000000000000000000000000000000000000000000000000",
+ "approximateArrivalTimestamp": 1716369573887,
+ "mskRecordMetadata": {
+ "offset": "0",
+ "partitionId": "1",
+ "approximateArrivalTimestamp": 1716369573887
+ },
+ "kafkaRecordValue": "eyJOYW1lIjoiSGVsbG8gV29ybGQifQ=="
+ }
+ ]
+}