@@ -52,7 +56,7 @@ public App(DynamoDbClient client) {
*
Second call (and next ones) will retrieve from the cache (if cache is enabled, which is by default) or from the store, the handler won't be called. Until the expiration happens (by default 1 hour).
*
*/
- @Idempotent // *** THE MAGIC IS HERE ***
+ @Idempotent // The magic is here!
@Logging(logEvent = true)
public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) {
Map headers = new HashMap<>();
@@ -65,6 +69,7 @@ public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEv
APIGatewayProxyResponseEvent response = new APIGatewayProxyResponseEvent()
.withHeaders(headers);
try {
+ // Read the 'address' field from the JSON post body
String address = JsonConfig.get().getObjectMapper().readTree(input.getBody()).get("address").asText();
final String pageContents = this.getPageContents(address);
String output = String.format("{ \"message\": \"hello world\", \"location\": \"%s\" }", pageContents);
@@ -81,8 +86,18 @@ public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEv
}
}
- // we could also put the @Idempotent annotation here, but using it on the handler avoids executing the handler (cost reduction).
- // Use it on other methods to handle multiple items (with SQS batch processing for example)
+
+ /**
+ * Helper to retrieve the contents of the given URL and return them as a string.
+ *
+ * We could also put the @Idempotent annotation here if we only wanted this sub-operation to be idempotent. Putting
+ * it on the handler, however, reduces total execution time and saves us time!
+ *
+ * @param address The URL to fetch
+ * @return The contents of the given URL
+ *
+ * @throws IOException
+ */
private String getPageContents(String address) throws IOException {
URL url = new URL(address);
try (BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream(), "UTF-8"))) {
diff --git a/examples/powertools-examples-parameters/README.md b/examples/powertools-examples-parameters/README.md
index 0f843d455..a65307f69 100644
--- a/examples/powertools-examples-parameters/README.md
+++ b/examples/powertools-examples-parameters/README.md
@@ -1,21 +1,38 @@
-# Parameters
+# Powertools for AWS Lambda (Java) - Parameters Example
This project contains an example of Lambda function using the parameters module of Powertools for AWS Lambda (Java). For more information on this module, please refer to the [documentation](https://docs.powertools.aws.dev/lambda-java/utilities/parameters/).
+The example uses the [SSM Parameter Store](https://docs.powertools.aws.dev/lambda/java/utilities/parameters/#ssm-parameter-store)
+and the [Secrets Manager](https://docs.powertools.aws.dev/lambda/java/utilities/parameters/#secrets-manager) to inject
+runtime parameters into the application.
+Have a look at [ParametersFunction.java](src/main/java/org/demo/parameters/ParametersFunction.java) for the full details.
+
## Deploy the sample application
-This sample is based on Serverless Application Model (SAM) and you can use the SAM Command Line Interface (SAM CLI) to build it and deploy it to AWS.
+This sample is based on Serverless Application Model (SAM). To deploy it, check out the instructions for getting
+started with SAM in [the examples directory](../README.md)
-To use the SAM CLI, you need the following tools.
+## Test the application
-* SAM CLI - [Install the SAM CLI](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html)
-* Java11 - [Install the Java 11](https://docs.aws.amazon.com/corretto/latest/corretto-11-ug/downloads-list.html)
-* Maven - [Install Maven](https://maven.apache.org/install.html)
-* Docker - [Install Docker community edition](https://hub.docker.com/search/?type=edition&offering=community)
+First, hit the URL of the application. You can do this with curl or your browser:
-To build and deploy your application for the first time, run the following in your shell:
+```bash
+ curl https://[REST-API-ID].execute-api.[REGION].amazonaws.com/Prod/params/
+```
+You will get your IP address back. The contents of the logs will be more interesting, and show you the values
+of the parameters injected into the handler:
```bash
-sam build
-sam deploy --guided
+sam logs --stack-name $MY_STACK_NAME --tail
+```
+
+```json
+{
+ ...
+ "thread": "main",
+ "level": "INFO",
+ "loggerName": "org.demo.parameters.ParametersFunction",
+ "message": "secretjsonobj=MyObject{id=23443, code='hk38543oj24kn796kp67bkb234gkj679l68'}\n",
+ ...
+}
```
diff --git a/examples/powertools-examples-parameters/template.yaml b/examples/powertools-examples-parameters/template.yaml
index 052cfcdc7..9d3bf8b0e 100644
--- a/examples/powertools-examples-parameters/template.yaml
+++ b/examples/powertools-examples-parameters/template.yaml
@@ -19,6 +19,9 @@ Resources:
Handler: org.demo.parameters.ParametersFunction::handleRequest
MemorySize: 512
Tracing: Active
+ Environment:
+ Variables:
+ LOG_LEVEL: INFO
Policies:
- AWSSecretsManagerGetSecretValuePolicy:
SecretArn: !Ref UserPwd
diff --git a/examples/powertools-examples-serialization/README.md b/examples/powertools-examples-serialization/README.md
index 7f70da1f2..4e3f66eb0 100644
--- a/examples/powertools-examples-serialization/README.md
+++ b/examples/powertools-examples-serialization/README.md
@@ -1,21 +1,77 @@
-# Deserialization
+# Powertools for AWS Lambda (Java) - Serialization Example
This project contains an example of Lambda function using the serialization utilities module of Powertools for AWS Lambda (Java). For more information on this module, please refer to the [documentation](https://docs.powertools.aws.dev/lambda-java/utilities/serialization/).
+The project contains two `RequestHandler`s -
+
+* [APIGatewayRequestDeserializationFunction](src/main/java/org/demo/serialization/APIGatewayRequestDeserializationFunction.java) - Uses the serialization library to deserialize an API Gateway request body
+* [SQSEventDeserializationFunction](src/main/java/org/demo/serialization/SQSEventDeserializationFunction.java) - Uses the serialization library to deserialize an SQS message body
+
+In both cases, the output of the serialized message will be printed to the function logs. The message format
+in JSON looks like this:
+
+```json
+{
+ "id":1234,
+ "name":"product",
+ "price":42
+}
+```
+
## Deploy the sample application
-This sample is based on Serverless Application Model (SAM) and you can use the SAM Command Line Interface (SAM CLI) to build it and deploy it to AWS.
+This sample is based on Serverless Application Model (SAM). To deploy it, check out the instructions for getting
+started with SAM in [the examples directory](../README.md)
+
+## Test the application
+
+### 1. API Gateway Endpoint
+
+To test the HTTP endpoint, we can post a product to the test URL:
+
+```bash
+curl -X POST https://[REST-API-ID].execute-api.[REGION].amazonaws.com/Prod/product/ -H "Content-Type: application/json" -d '{"id": 1234, "name": "product", "price": 42}'
+```
+
+The result will indicate that the handler has successfully deserialized the request body:
-To use the SAM CLI, you need the following tools.
+```
+Received request for productId: 1234
+```
+
+If we look at the logs using `sam logs --tail --stack-name $MY_STACK`, we will see the full deserialized request:
+
+```json
+{
+ ...
+ "level": "INFO",
+ "loggerName": "org.demo.serialization.APIGatewayRequestDeserializationFunction",
+ "message": "product=Product{id=1234, name='product', price=42.0}\n",
+ ...
+}
+```
+
+### 2. SQS Queue
+For the SQS handler, we have to send a request to our queue. We can either construct the Queue URL (see below), or
+find it from the SQS section of the AWS console.
-* SAM CLI - [Install the SAM CLI](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html)
-* Java11 - [Install the Java 11](https://docs.aws.amazon.com/corretto/latest/corretto-11-ug/downloads-list.html)
-* Maven - [Install Maven](https://maven.apache.org/install.html)
-* Docker - [Install Docker community edition](https://hub.docker.com/search/?type=edition&offering=community)
+```bash
+ aws sqs send-message --queue-url "https://sqs.[REGION].amazonaws.com/[ACCOUNT-ID]/sqs-event-deserialization-queue" --message-body '{"id": 1234, "name": "product", "price": 123}'
+```
+
+Here we can find the message by filtering through the logs for messages that have come back from our SQS handler:
-To build and deploy your application for the first time, run the following in your shell:
+```bash
+sam logs --tail --stack-name $MY_STACK --filter SQS
+```
```bash
-sam build
-sam deploy --guided
+ {
+ ...
+ "level": "INFO",
+ "loggerName": "org.demo.serialization.SQSEventDeserializationFunction",
+ "message": "products=[Product{id=1234, name='product', price=42.0}]\n",
+ ...
+}
+
```
diff --git a/examples/powertools-examples-serialization/template.yaml b/examples/powertools-examples-serialization/template.yaml
index 539d2d615..f330ec146 100644
--- a/examples/powertools-examples-serialization/template.yaml
+++ b/examples/powertools-examples-serialization/template.yaml
@@ -32,7 +32,7 @@ Resources:
SQSEventDeserializationFunction:
Type: AWS::Serverless::Function
Properties:
- CodeUri: Function
+ CodeUri: .
Handler: org.demo.serialization.SQSEventDeserializationFunction::handleRequest
Policies:
- Statement:
diff --git a/examples/powertools-examples-sqs/README.md b/examples/powertools-examples-sqs/README.md
index 2b6da65b5..45f4a4a74 100644
--- a/examples/powertools-examples-sqs/README.md
+++ b/examples/powertools-examples-sqs/README.md
@@ -1,3 +1,56 @@
-## SqsBatchProcessingDemo
+# Powertools for AWS Lambda (Java) - SQS Batch Processing Example
-Demos setup of SQS Batch processing via Powertools
+This project contains an example of Lambda function using the batch processing utilities module of Powertools for AWS Lambda (Java).
+For more information on this module, please refer to the [documentation](https://docs.powertools.aws.dev/lambda/java/utilities/batch/).
+
+The project contains two functions:
+
+* [SqsMessageSender](src/main/java/org/demo/sqs/SqsMessageSender.java) - Sends a set of messages to an SQS queue.
+This function is triggered every 5 minutes by an EventBridge schedule rule.
+* [SqsPoller](src/main/java/org/demo/sqs/SqsPoller.java) - Listens to the same queue, processing items off in batches
+
+The poller intentionally fails intermittently processing messages to demonstrate the replay behaviour of the batch
+module:
+
+
+
+SqsPoller.java
+
+[SqsPoller.java:43](src/main/java/org/demo/sqs/SqsPoller.java)
+
+```java
+ public String process(SQSMessage message) {
+ log.info("Processing message with id {}", message.getMessageId());
+
+ int nextInt = random.nextInt(100);
+
+ if(nextInt <= 10) {
+ log.info("Randomly picked message with id {} as business validation failure.", message.getMessageId());
+ throw new IllegalArgumentException("Failed business validation. No point of retrying. Move me to DLQ." + message.getMessageId());
+ }
+
+ if(nextInt > 90) {
+ log.info("Randomly picked message with id {} as intermittent failure.", message.getMessageId());
+ throw new RuntimeException("Failed due to intermittent issue. Will be sent back for retry." + message.getMessageId());
+ }
+
+ return "Success";
+ }
+```
+
+
+
+## Deploy the sample application
+
+This sample is based on Serverless Application Model (SAM). To deploy it, check out the instructions for getting
+started with SAM in [the examples directory](../README.md)
+
+## Test the application
+
+As the test is pushing through a batch every 5 minutes, we can simply watch the logs to see the batches being processed:
+
+```bash
+ sam logs --tail --stack-name $MY_STACK
+```
+
+As the handler intentionally introduces intermittent failures, we should expect to see error messages too!
diff --git a/examples/powertools-examples-validation/README.md b/examples/powertools-examples-validation/README.md
index 39afc48b9..3f6790b0c 100644
--- a/examples/powertools-examples-validation/README.md
+++ b/examples/powertools-examples-validation/README.md
@@ -1,21 +1,26 @@
-# Validation
+# Powertools for AWS Lambda (Java) - Validation Example
-This project contains an example of Lambda function using the validation module of Powertools for AWS Lambda (Java). For more information on this module, please refer to the [documentation](https://docs.powertools.aws.dev/lambda-java/utilities/validation/).
+This project contains an example of Lambda function using the validation module of Powertools for AWS Lambda (Java).
+For more information on this module, please refer to the [documentation](https://docs.powertools.aws.dev/lambda-java/utilities/validation/).
+
+The handler [InboundValidation](src/main/java/org/demo/validation/InboundValidation.java) validates incoming HTTP requests
+received from the API gateway against [schema.json](src/main/resources/schema.json).
## Deploy the sample application
-This sample is based on Serverless Application Model (SAM) and you can use the SAM Command Line Interface (SAM CLI) to build it and deploy it to AWS.
+This sample is based on Serverless Application Model (SAM). To deploy it, check out the instructions for getting
+started with SAM in [the examples directory](../README.md)
-To use the SAM CLI, you need the following tools.
+## Test the application
-* SAM CLI - [Install the SAM CLI](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html)
-* Java11 - [Install the Java 11](https://docs.aws.amazon.com/corretto/latest/corretto-11-ug/downloads-list.html)
-* Maven - [Install Maven](https://maven.apache.org/install.html)
-* Docker - [Install Docker community edition](https://hub.docker.com/search/?type=edition&offering=community)
+To test the validation, we can POST a JSON object shaped like our schema:
+```bash
+ curl -X POST https://[REST-API-ID].execute-api.[REGION].amazonaws.com/Prod/hello/ -H "Content-Type: application/json" -d '{"address": "https://checkip.amazonaws.com"}'
+```
-To build and deploy your application for the first time, run the following in your shell:
+If we break the schema - for instance, by removing one of the compulsory fields,
+we will get an error back from our API and will see a `ValidationException` in the logs:
```bash
-sam build
-sam deploy --guided
+ sam logs --tail --stack-name $MY_STACK
```
From 577d03f38cc8895aa4c10ee61dd5924d92a03fe9 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Thu, 20 Jul 2023 13:24:05 +0200
Subject: [PATCH 043/666] build(deps): bump aws.sdk.version from 2.20.105 to
2.20.107 (#1300)
Bumps `aws.sdk.version` from 2.20.105 to 2.20.107.
Updates `software.amazon.awssdk:bom` from 2.20.105 to 2.20.107
Updates `http-client-spi` from 2.20.105 to 2.20.107
Updates `url-connection-client` from 2.20.105 to 2.20.107
Updates `s3` from 2.20.105 to 2.20.107
Updates `lambda` from 2.20.105 to 2.20.107
Updates `cloudwatch` from 2.20.105 to 2.20.107
Updates `xray` from 2.20.105 to 2.20.107
Updates `cloudformation` from 2.20.105 to 2.20.107
Updates `sts` from 2.20.105 to 2.20.107
---
updated-dependencies:
- dependency-name: software.amazon.awssdk:bom
dependency-type: direct:production
update-type: version-update:semver-patch
- dependency-name: software.amazon.awssdk:http-client-spi
dependency-type: direct:production
update-type: version-update:semver-patch
- dependency-name: software.amazon.awssdk:url-connection-client
dependency-type: direct:development
update-type: version-update:semver-patch
- dependency-name: software.amazon.awssdk:s3
dependency-type: direct:development
update-type: version-update:semver-patch
- dependency-name: software.amazon.awssdk:lambda
dependency-type: direct:development
update-type: version-update:semver-patch
- dependency-name: software.amazon.awssdk:cloudwatch
dependency-type: direct:development
update-type: version-update:semver-patch
- dependency-name: software.amazon.awssdk:xray
dependency-type: direct:development
update-type: version-update:semver-patch
- dependency-name: software.amazon.awssdk:cloudformation
dependency-type: direct:development
update-type: version-update:semver-patch
- dependency-name: software.amazon.awssdk:sts
dependency-type: direct:development
update-type: version-update:semver-patch
...
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
examples/powertools-examples-cloudformation/pom.xml | 2 +-
examples/powertools-examples-sqs/pom.xml | 2 +-
pom.xml | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml
index c46bed1de..98703c60a 100644
--- a/examples/powertools-examples-cloudformation/pom.xml
+++ b/examples/powertools-examples-cloudformation/pom.xml
@@ -16,7 +16,7 @@
true1.2.23.11.2
- 2.20.105
+ 2.20.107
diff --git a/examples/powertools-examples-sqs/pom.xml b/examples/powertools-examples-sqs/pom.xml
index d66f6dda5..0fbfd284c 100644
--- a/examples/powertools-examples-sqs/pom.xml
+++ b/examples/powertools-examples-sqs/pom.xml
@@ -28,7 +28,7 @@
software.amazon.awssdkurl-connection-client
- 2.20.105
+ 2.20.107com.amazonaws
diff --git a/pom.xml b/pom.xml
index 462ad1164..859b20cf1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -60,7 +60,7 @@
2.20.02.15.21.9.7
- 2.20.105
+ 2.20.1072.14.02.1.3UTF-8
From ac5ce9d89c1e788694c6a01c249787d06b844491 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Fri, 21 Jul 2023 13:33:37 +0200
Subject: [PATCH 044/666] build(deps): bump aws.sdk.version from 2.20.107 to
2.20.108 (#1304)
Bumps `aws.sdk.version` from 2.20.107 to 2.20.108.
Updates `software.amazon.awssdk:bom` from 2.20.107 to 2.20.108
Updates `software.amazon.awssdk:http-client-spi` from 2.20.107 to 2.20.108
Updates `software.amazon.awssdk:url-connection-client` from 2.20.107 to 2.20.108
Updates `software.amazon.awssdk:s3` from 2.20.107 to 2.20.108
Updates `software.amazon.awssdk:lambda` from 2.20.107 to 2.20.108
Updates `software.amazon.awssdk:cloudwatch` from 2.20.107 to 2.20.108
Updates `software.amazon.awssdk:xray` from 2.20.107 to 2.20.108
Updates `software.amazon.awssdk:cloudformation` from 2.20.107 to 2.20.108
Updates `software.amazon.awssdk:sts` from 2.20.107 to 2.20.108
---
updated-dependencies:
- dependency-name: software.amazon.awssdk:bom
dependency-type: direct:production
update-type: version-update:semver-patch
- dependency-name: software.amazon.awssdk:http-client-spi
dependency-type: direct:production
update-type: version-update:semver-patch
- dependency-name: software.amazon.awssdk:url-connection-client
dependency-type: direct:development
update-type: version-update:semver-patch
- dependency-name: software.amazon.awssdk:s3
dependency-type: direct:development
update-type: version-update:semver-patch
- dependency-name: software.amazon.awssdk:lambda
dependency-type: direct:development
update-type: version-update:semver-patch
- dependency-name: software.amazon.awssdk:cloudwatch
dependency-type: direct:development
update-type: version-update:semver-patch
- dependency-name: software.amazon.awssdk:xray
dependency-type: direct:development
update-type: version-update:semver-patch
- dependency-name: software.amazon.awssdk:cloudformation
dependency-type: direct:development
update-type: version-update:semver-patch
- dependency-name: software.amazon.awssdk:sts
dependency-type: direct:development
update-type: version-update:semver-patch
...
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
examples/powertools-examples-cloudformation/pom.xml | 2 +-
examples/powertools-examples-sqs/pom.xml | 2 +-
pom.xml | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml
index 98703c60a..c7e35c8d8 100644
--- a/examples/powertools-examples-cloudformation/pom.xml
+++ b/examples/powertools-examples-cloudformation/pom.xml
@@ -16,7 +16,7 @@
true1.2.23.11.2
- 2.20.107
+ 2.20.108
diff --git a/examples/powertools-examples-sqs/pom.xml b/examples/powertools-examples-sqs/pom.xml
index 0fbfd284c..71c0eb131 100644
--- a/examples/powertools-examples-sqs/pom.xml
+++ b/examples/powertools-examples-sqs/pom.xml
@@ -28,7 +28,7 @@
software.amazon.awssdkurl-connection-client
- 2.20.107
+ 2.20.108com.amazonaws
diff --git a/pom.xml b/pom.xml
index 859b20cf1..197e84a91 100644
--- a/pom.xml
+++ b/pom.xml
@@ -60,7 +60,7 @@
2.20.02.15.21.9.7
- 2.20.107
+ 2.20.1082.14.02.1.3UTF-8
From 4c4235969ddb33222ab1f18af2c9120b361dca07 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Fri, 21 Jul 2023 13:39:08 +0200
Subject: [PATCH 045/666] build(deps-dev): bump
software.amazon.awscdk:aws-cdk-lib (#1305)
Bumps [software.amazon.awscdk:aws-cdk-lib](https://github.com/aws/aws-cdk) from 2.87.0 to 2.88.0.
- [Release notes](https://github.com/aws/aws-cdk/releases)
- [Changelog](https://github.com/aws/aws-cdk/blob/main/CHANGELOG.v2.md)
- [Commits](https://github.com/aws/aws-cdk/compare/v2.87.0...v2.88.0)
---
updated-dependencies:
- dependency-name: software.amazon.awscdk:aws-cdk-lib
dependency-type: direct:development
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
powertools-e2e-tests/pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml
index 8754117db..5b6b50511 100644
--- a/powertools-e2e-tests/pom.xml
+++ b/powertools-e2e-tests/pom.xml
@@ -17,7 +17,7 @@
1.81.810.2.69
- 2.87.0
+ 2.88.0true
From 3594bbd1d4e0380fb1cd4fd143ac491b00f17181 Mon Sep 17 00:00:00 2001
From: Alexander Sparkowsky
Date: Mon, 24 Jul 2023 11:31:37 +0200
Subject: [PATCH 046/666] fix: use default credentials provider for all
provided SDK clients (#1303)
---------
Co-authored-by: Scott Gerring
---
.../core/internal/LambdaConstants.java | 4 ++++
.../persistence/DynamoDBPersistenceStore.java | 19 +++---------------
.../parameters/AppConfigProvider.java | 20 +++----------------
.../parameters/DynamoDbProvider.java | 20 +++----------------
.../powertools/parameters/SSMProvider.java | 20 +++----------------
.../parameters/SecretsProvider.java | 19 +++---------------
6 files changed, 19 insertions(+), 83 deletions(-)
diff --git a/powertools-core/src/main/java/software/amazon/lambda/powertools/core/internal/LambdaConstants.java b/powertools-core/src/main/java/software/amazon/lambda/powertools/core/internal/LambdaConstants.java
index bb5fc4666..ea6a6ff44 100644
--- a/powertools-core/src/main/java/software/amazon/lambda/powertools/core/internal/LambdaConstants.java
+++ b/powertools-core/src/main/java/software/amazon/lambda/powertools/core/internal/LambdaConstants.java
@@ -16,7 +16,11 @@
public class LambdaConstants {
public static final String LAMBDA_FUNCTION_NAME_ENV = "AWS_LAMBDA_FUNCTION_NAME";
public static final String AWS_REGION_ENV = "AWS_REGION";
+ // Also you can use AWS_LAMBDA_INITIALIZATION_TYPE to distinguish between on-demand and SnapStart initialization
+ // it's not recommended to use this env variable to initialize SDK clients or other resources.
+ @Deprecated
public static final String AWS_LAMBDA_INITIALIZATION_TYPE = "AWS_LAMBDA_INITIALIZATION_TYPE";
+ @Deprecated
public static final String ON_DEMAND = "on-demand";
public static final String X_AMZN_TRACE_ID = "_X_AMZN_TRACE_ID";
public static final String AWS_SAM_LOCAL = "AWS_SAM_LOCAL";
diff --git a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/DynamoDBPersistenceStore.java b/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/DynamoDBPersistenceStore.java
index 6b5d0fcb2..783b029bb 100644
--- a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/DynamoDBPersistenceStore.java
+++ b/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/DynamoDBPersistenceStore.java
@@ -15,11 +15,9 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import software.amazon.awssdk.auth.credentials.EnvironmentVariableCredentialsProvider;
import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
-import software.amazon.awssdk.services.dynamodb.DynamoDbClientBuilder;
import software.amazon.awssdk.services.dynamodb.model.*;
import software.amazon.awssdk.utils.StringUtils;
import software.amazon.lambda.powertools.idempotency.Constants;
@@ -34,10 +32,8 @@
import java.util.stream.Collectors;
import java.util.stream.Stream;
-import static software.amazon.lambda.powertools.core.internal.LambdaConstants.AWS_LAMBDA_INITIALIZATION_TYPE;
import static software.amazon.lambda.powertools.core.internal.LambdaConstants.AWS_REGION_ENV;
import static software.amazon.lambda.powertools.core.internal.LambdaConstants.LAMBDA_FUNCTION_NAME_ENV;
-import static software.amazon.lambda.powertools.core.internal.LambdaConstants.ON_DEMAND;
import static software.amazon.lambda.powertools.idempotency.persistence.DataRecord.Status.INPROGRESS;
/**
@@ -88,19 +84,10 @@ private DynamoDBPersistenceStore(String tableName,
} else {
String idempotencyDisabledEnv = System.getenv().get(Constants.IDEMPOTENCY_DISABLED_ENV);
if (idempotencyDisabledEnv == null || idempotencyDisabledEnv.equalsIgnoreCase("false")) {
- DynamoDbClientBuilder ddbBuilder = DynamoDbClient.builder()
+ this.dynamoDbClient = DynamoDbClient.builder()
.httpClient(UrlConnectionHttpClient.builder().build())
- .region(Region.of(System.getenv(AWS_REGION_ENV)));
-
- // AWS_LAMBDA_INITIALIZATION_TYPE has two values on-demand and snap-start
- // when using snap-start mode, the env var creds provider isn't used and causes a fatal error if set
- // fall back to the default provider chain if the mode is anything other than on-demand.
- String initializationType = System.getenv().get(AWS_LAMBDA_INITIALIZATION_TYPE);
- if (initializationType != null && initializationType.equals(ON_DEMAND)) {
- ddbBuilder.credentialsProvider(EnvironmentVariableCredentialsProvider.create());
- }
-
- this.dynamoDbClient = ddbBuilder.build();
+ .region(Region.of(System.getenv(AWS_REGION_ENV)))
+ .build();
} else {
// we do not want to create a DynamoDbClient if idempotency is disabled
// null is ok as idempotency won't be called
diff --git a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/AppConfigProvider.java b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/AppConfigProvider.java
index e0255125d..c62d7a2e5 100644
--- a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/AppConfigProvider.java
+++ b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/AppConfigProvider.java
@@ -1,23 +1,18 @@
package software.amazon.lambda.powertools.parameters;
-import software.amazon.awssdk.auth.credentials.EnvironmentVariableCredentialsProvider;
import software.amazon.awssdk.core.SdkSystemSetting;
import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.appconfigdata.AppConfigDataClient;
-import software.amazon.awssdk.services.appconfigdata.AppConfigDataClientBuilder;
import software.amazon.awssdk.services.appconfigdata.model.GetLatestConfigurationRequest;
import software.amazon.awssdk.services.appconfigdata.model.GetLatestConfigurationResponse;
import software.amazon.awssdk.services.appconfigdata.model.StartConfigurationSessionRequest;
-import software.amazon.lambda.powertools.core.internal.LambdaConstants;
import software.amazon.lambda.powertools.parameters.cache.CacheManager;
import software.amazon.lambda.powertools.parameters.transform.TransformationManager;
import java.util.HashMap;
import java.util.Map;
-import static software.amazon.lambda.powertools.core.internal.LambdaConstants.AWS_LAMBDA_INITIALIZATION_TYPE;
-
/**
* Implements a {@link ParamProvider} on top of the AppConfig service. AppConfig provides
* a mechanism to retrieve and update configuration of applications over time.
@@ -144,19 +139,10 @@ public AppConfigProvider build() {
// Create a AppConfigDataClient if we haven't been given one
if (client == null) {
- AppConfigDataClientBuilder appConfigDataClientBuilder = AppConfigDataClient.builder()
+ client = AppConfigDataClient.builder()
.httpClientBuilder(UrlConnectionHttpClient.builder())
- .region(Region.of(System.getenv(SdkSystemSetting.AWS_REGION.environmentVariable())));
-
- // AWS_LAMBDA_INITIALIZATION_TYPE has two values on-demand and snap-start
- // when using snap-start mode, the env var creds provider isn't used and causes a fatal error if set
- // fall back to the default provider chain if the mode is anything other than on-demand.
- String initializationType = System.getenv().get(AWS_LAMBDA_INITIALIZATION_TYPE);
- if (initializationType != null && initializationType.equals(LambdaConstants.ON_DEMAND)) {
- appConfigDataClientBuilder.credentialsProvider(EnvironmentVariableCredentialsProvider.create());
- }
-
- client = appConfigDataClientBuilder.build();
+ .region(Region.of(System.getenv(SdkSystemSetting.AWS_REGION.environmentVariable())))
+ .build();
}
AppConfigProvider provider = new AppConfigProvider(cacheManager, client, environment, application);
diff --git a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/DynamoDbProvider.java b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/DynamoDbProvider.java
index 1b77aed88..e09f23348 100644
--- a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/DynamoDbProvider.java
+++ b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/DynamoDbProvider.java
@@ -1,17 +1,14 @@
package software.amazon.lambda.powertools.parameters;
-import software.amazon.awssdk.auth.credentials.EnvironmentVariableCredentialsProvider;
import software.amazon.awssdk.core.SdkSystemSetting;
import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
-import software.amazon.awssdk.services.dynamodb.DynamoDbClientBuilder;
import software.amazon.awssdk.services.dynamodb.model.AttributeValue;
import software.amazon.awssdk.services.dynamodb.model.GetItemRequest;
import software.amazon.awssdk.services.dynamodb.model.GetItemResponse;
import software.amazon.awssdk.services.dynamodb.model.QueryRequest;
import software.amazon.awssdk.services.dynamodb.model.QueryResponse;
-import software.amazon.lambda.powertools.core.internal.LambdaConstants;
import software.amazon.lambda.powertools.parameters.cache.CacheManager;
import software.amazon.lambda.powertools.parameters.exception.DynamoDbProviderSchemaException;
import software.amazon.lambda.powertools.parameters.transform.TransformationManager;
@@ -20,8 +17,6 @@
import java.util.Map;
import java.util.stream.Collectors;
-import static software.amazon.lambda.powertools.core.internal.LambdaConstants.AWS_LAMBDA_INITIALIZATION_TYPE;
-
/**
* Implements a {@link ParamProvider} on top of DynamoDB. The schema of the table
* is described in the Powertools for AWS Lambda (Java) documentation.
@@ -190,19 +185,10 @@ public DynamoDbProvider.Builder withTransformationManager(TransformationManager
}
private static DynamoDbClient createClient() {
- DynamoDbClientBuilder dynamoDbClientBuilder = DynamoDbClient.builder()
+ return DynamoDbClient.builder()
.httpClientBuilder(UrlConnectionHttpClient.builder())
- .region(Region.of(System.getenv(SdkSystemSetting.AWS_REGION.environmentVariable())));
-
- // AWS_LAMBDA_INITIALIZATION_TYPE has two values on-demand and snap-start
- // when using snap-start mode, the env var creds provider isn't used and causes a fatal error if set
- // fall back to the default provider chain if the mode is anything other than on-demand.
- String initializationType = System.getenv().get(AWS_LAMBDA_INITIALIZATION_TYPE);
- if (initializationType != null && initializationType.equals(LambdaConstants.ON_DEMAND)) {
- dynamoDbClientBuilder.credentialsProvider(EnvironmentVariableCredentialsProvider.create());
- }
-
- return dynamoDbClientBuilder.build();
+ .region(Region.of(System.getenv(SdkSystemSetting.AWS_REGION.environmentVariable())))
+ .build();
}
}
}
diff --git a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/SSMProvider.java b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/SSMProvider.java
index 2eb2d4199..1fa4dbaab 100644
--- a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/SSMProvider.java
+++ b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/SSMProvider.java
@@ -13,17 +13,14 @@
*/
package software.amazon.lambda.powertools.parameters;
-import software.amazon.awssdk.auth.credentials.EnvironmentVariableCredentialsProvider;
import software.amazon.awssdk.core.SdkSystemSetting;
import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.ssm.SsmClient;
-import software.amazon.awssdk.services.ssm.SsmClientBuilder;
import software.amazon.awssdk.services.ssm.model.GetParameterRequest;
import software.amazon.awssdk.services.ssm.model.GetParametersByPathRequest;
import software.amazon.awssdk.services.ssm.model.GetParametersByPathResponse;
import software.amazon.awssdk.utils.StringUtils;
-import software.amazon.lambda.powertools.core.internal.LambdaConstants;
import software.amazon.lambda.powertools.parameters.cache.CacheManager;
import software.amazon.lambda.powertools.parameters.transform.TransformationManager;
import software.amazon.lambda.powertools.parameters.transform.Transformer;
@@ -32,8 +29,6 @@
import java.util.HashMap;
import java.util.Map;
-import static software.amazon.lambda.powertools.core.internal.LambdaConstants.AWS_LAMBDA_INITIALIZATION_TYPE;
-
/**
* AWS System Manager Parameter Store Provider
*
@@ -283,19 +278,10 @@ public SSMProvider.Builder withClient(SsmClient client) {
}
private static SsmClient createClient() {
- SsmClientBuilder ssmClientBuilder = SsmClient.builder()
+ return SsmClient.builder()
.httpClientBuilder(UrlConnectionHttpClient.builder())
- .region(Region.of(System.getenv(SdkSystemSetting.AWS_REGION.environmentVariable())));
-
- // AWS_LAMBDA_INITIALIZATION_TYPE has two values on-demand and snap-start
- // when using snap-start mode, the env var creds provider isn't used and causes a fatal error if set
- // fall back to the default provider chain if the mode is anything other than on-demand.
- String initializationType = System.getenv().get(AWS_LAMBDA_INITIALIZATION_TYPE);
- if (initializationType != null && initializationType.equals(LambdaConstants.ON_DEMAND)) {
- ssmClientBuilder.credentialsProvider(EnvironmentVariableCredentialsProvider.create());
- }
-
- return ssmClientBuilder.build();
+ .region(Region.of(System.getenv(SdkSystemSetting.AWS_REGION.environmentVariable())))
+ .build();
}
/**
diff --git a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/SecretsProvider.java b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/SecretsProvider.java
index ea8b5a9d0..fd45da881 100644
--- a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/SecretsProvider.java
+++ b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/SecretsProvider.java
@@ -13,14 +13,11 @@
*/
package software.amazon.lambda.powertools.parameters;
-import software.amazon.awssdk.auth.credentials.EnvironmentVariableCredentialsProvider;
import software.amazon.awssdk.core.SdkSystemSetting;
import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient;
-import software.amazon.awssdk.services.secretsmanager.SecretsManagerClientBuilder;
import software.amazon.awssdk.services.secretsmanager.model.GetSecretValueRequest;
-import software.amazon.lambda.powertools.core.internal.LambdaConstants;
import software.amazon.lambda.powertools.parameters.cache.CacheManager;
import software.amazon.lambda.powertools.parameters.transform.TransformationManager;
import software.amazon.lambda.powertools.parameters.transform.Transformer;
@@ -30,7 +27,6 @@
import java.util.Map;
import static java.nio.charset.StandardCharsets.UTF_8;
-import static software.amazon.lambda.powertools.core.internal.LambdaConstants.AWS_LAMBDA_INITIALIZATION_TYPE;
/**
* AWS Secrets Manager Parameter Provider
@@ -191,19 +187,10 @@ public Builder withClient(SecretsManagerClient client) {
}
private static SecretsManagerClient createClient() {
- SecretsManagerClientBuilder secretsManagerClientBuilder = SecretsManagerClient.builder()
+ return SecretsManagerClient.builder()
.httpClientBuilder(UrlConnectionHttpClient.builder())
- .region(Region.of(System.getenv(SdkSystemSetting.AWS_REGION.environmentVariable())));
-
- // AWS_LAMBDA_INITIALIZATION_TYPE has two values on-demand and snap-start
- // when using snap-start mode, the env var creds provider isn't used and causes a fatal error if set
- // fall back to the default provider chain if the mode is anything other than on-demand.
- String initializationType = System.getenv().get(AWS_LAMBDA_INITIALIZATION_TYPE);
- if (initializationType != null && initializationType.equals(LambdaConstants.ON_DEMAND)) {
- secretsManagerClientBuilder.credentialsProvider(EnvironmentVariableCredentialsProvider.create());
- }
-
- return secretsManagerClientBuilder.build();
+ .region(Region.of(System.getenv(SdkSystemSetting.AWS_REGION.environmentVariable())))
+ .build();
}
/**
From 4bc526c39b58ed2b591598c1854dbe8c5342f08f Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 24 Jul 2023 13:45:45 +0200
Subject: [PATCH 047/666] build(deps): bump aws.sdk.version from 2.20.108 to
2.20.109 (#1308)
Bumps `aws.sdk.version` from 2.20.108 to 2.20.109.
Updates `software.amazon.awssdk:bom` from 2.20.108 to 2.20.109
Updates `software.amazon.awssdk:http-client-spi` from 2.20.108 to 2.20.109
Updates `software.amazon.awssdk:url-connection-client` from 2.20.108 to 2.20.109
Updates `software.amazon.awssdk:s3` from 2.20.108 to 2.20.109
Updates `software.amazon.awssdk:lambda` from 2.20.108 to 2.20.109
Updates `software.amazon.awssdk:cloudwatch` from 2.20.108 to 2.20.109
Updates `software.amazon.awssdk:xray` from 2.20.108 to 2.20.109
Updates `software.amazon.awssdk:cloudformation` from 2.20.108 to 2.20.109
Updates `software.amazon.awssdk:sts` from 2.20.108 to 2.20.109
---
updated-dependencies:
- dependency-name: software.amazon.awssdk:bom
dependency-type: direct:production
update-type: version-update:semver-patch
- dependency-name: software.amazon.awssdk:http-client-spi
dependency-type: direct:production
update-type: version-update:semver-patch
- dependency-name: software.amazon.awssdk:url-connection-client
dependency-type: direct:development
update-type: version-update:semver-patch
- dependency-name: software.amazon.awssdk:s3
dependency-type: direct:development
update-type: version-update:semver-patch
- dependency-name: software.amazon.awssdk:lambda
dependency-type: direct:development
update-type: version-update:semver-patch
- dependency-name: software.amazon.awssdk:cloudwatch
dependency-type: direct:development
update-type: version-update:semver-patch
- dependency-name: software.amazon.awssdk:xray
dependency-type: direct:development
update-type: version-update:semver-patch
- dependency-name: software.amazon.awssdk:cloudformation
dependency-type: direct:development
update-type: version-update:semver-patch
- dependency-name: software.amazon.awssdk:sts
dependency-type: direct:development
update-type: version-update:semver-patch
...
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
examples/powertools-examples-cloudformation/pom.xml | 2 +-
examples/powertools-examples-sqs/pom.xml | 2 +-
pom.xml | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml
index c7e35c8d8..c93a0c845 100644
--- a/examples/powertools-examples-cloudformation/pom.xml
+++ b/examples/powertools-examples-cloudformation/pom.xml
@@ -16,7 +16,7 @@
true1.2.23.11.2
- 2.20.108
+ 2.20.109
diff --git a/examples/powertools-examples-sqs/pom.xml b/examples/powertools-examples-sqs/pom.xml
index 71c0eb131..99a6d29f3 100644
--- a/examples/powertools-examples-sqs/pom.xml
+++ b/examples/powertools-examples-sqs/pom.xml
@@ -28,7 +28,7 @@
software.amazon.awssdkurl-connection-client
- 2.20.108
+ 2.20.109com.amazonaws
diff --git a/pom.xml b/pom.xml
index 197e84a91..b4134d1bc 100644
--- a/pom.xml
+++ b/pom.xml
@@ -60,7 +60,7 @@
2.20.02.15.21.9.7
- 2.20.108
+ 2.20.1092.14.02.1.3UTF-8
From 530968fc87d25d37e4b46e3313dc01a768eda6c9 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Tue, 25 Jul 2023 13:55:58 +0200
Subject: [PATCH 048/666] build(deps): bump aws.sdk.version from 2.20.109 to
2.20.110 (#1312)
Bumps `aws.sdk.version` from 2.20.109 to 2.20.110.
Updates `software.amazon.awssdk:bom` from 2.20.109 to 2.20.110
Updates `software.amazon.awssdk:http-client-spi` from 2.20.109 to 2.20.110
Updates `software.amazon.awssdk:url-connection-client` from 2.20.109 to 2.20.110
Updates `software.amazon.awssdk:s3` from 2.20.109 to 2.20.110
Updates `software.amazon.awssdk:lambda` from 2.20.109 to 2.20.110
Updates `software.amazon.awssdk:cloudwatch` from 2.20.109 to 2.20.110
Updates `software.amazon.awssdk:xray` from 2.20.109 to 2.20.110
Updates `software.amazon.awssdk:cloudformation` from 2.20.109 to 2.20.110
Updates `software.amazon.awssdk:sts` from 2.20.109 to 2.20.110
---
updated-dependencies:
- dependency-name: software.amazon.awssdk:bom
dependency-type: direct:production
update-type: version-update:semver-patch
- dependency-name: software.amazon.awssdk:http-client-spi
dependency-type: direct:production
update-type: version-update:semver-patch
- dependency-name: software.amazon.awssdk:url-connection-client
dependency-type: direct:development
update-type: version-update:semver-patch
- dependency-name: software.amazon.awssdk:s3
dependency-type: direct:development
update-type: version-update:semver-patch
- dependency-name: software.amazon.awssdk:lambda
dependency-type: direct:development
update-type: version-update:semver-patch
- dependency-name: software.amazon.awssdk:cloudwatch
dependency-type: direct:development
update-type: version-update:semver-patch
- dependency-name: software.amazon.awssdk:xray
dependency-type: direct:development
update-type: version-update:semver-patch
- dependency-name: software.amazon.awssdk:cloudformation
dependency-type: direct:development
update-type: version-update:semver-patch
- dependency-name: software.amazon.awssdk:sts
dependency-type: direct:development
update-type: version-update:semver-patch
...
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
examples/powertools-examples-cloudformation/pom.xml | 2 +-
examples/powertools-examples-sqs/pom.xml | 2 +-
pom.xml | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml
index c93a0c845..45857eee2 100644
--- a/examples/powertools-examples-cloudformation/pom.xml
+++ b/examples/powertools-examples-cloudformation/pom.xml
@@ -16,7 +16,7 @@
true1.2.23.11.2
- 2.20.109
+ 2.20.110
diff --git a/examples/powertools-examples-sqs/pom.xml b/examples/powertools-examples-sqs/pom.xml
index 99a6d29f3..d1b0c102b 100644
--- a/examples/powertools-examples-sqs/pom.xml
+++ b/examples/powertools-examples-sqs/pom.xml
@@ -28,7 +28,7 @@
software.amazon.awssdkurl-connection-client
- 2.20.109
+ 2.20.110com.amazonaws
diff --git a/pom.xml b/pom.xml
index b4134d1bc..cbd588c96 100644
--- a/pom.xml
+++ b/pom.xml
@@ -60,7 +60,7 @@
2.20.02.15.21.9.7
- 2.20.109
+ 2.20.1102.14.02.1.3UTF-8
From b1c688d56b5949d05b1118238914a0ad355fff15 Mon Sep 17 00:00:00 2001
From: Scott Gerring
Date: Tue, 25 Jul 2023 14:04:22 +0200
Subject: [PATCH 049/666] Update README.md (#1311)
---
README.md | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/README.md b/README.md
index a841e7df7..70cfab314 100644
--- a/README.md
+++ b/README.md
@@ -197,6 +197,15 @@ The following companies, among others, use Powertools:
* [MkDocs](https://www.mkdocs.org/)
* [Material for MkDocs](https://squidfunk.github.io/mkdocs-material/)
+## Connect
+
+* **Powertools for AWS Lambda on Discord**: `#java` - **[Invite link](https://discord.gg/B8zZKbbyET)**
+* **Email**:
+
+## Security disclosures
+
+If you think you’ve found a potential security issue, please do not post it in the Issues. Instead, please follow the instructions [here](https://aws.amazon.com/security/vulnerability-reporting/) or [email AWS security directly](mailto:aws-security@amazon.com).
+
## License
This library is licensed under the Apache License, Version 2.0. See the LICENSE file.
From 48533f73ab939df2f259875a26c29ee82eba224b Mon Sep 17 00:00:00 2001
From: Jeroen Reijn
Date: Wed, 26 Jul 2023 11:25:58 +0200
Subject: [PATCH 050/666] Make request for Logger explicit on current class
(#1307)
---
docs/core/logging.md | 18 +++++++++---------
.../demo/parameters/ParametersFunction.java | 2 +-
.../handlers/IdempotencyFunction.java | 2 +-
3 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/docs/core/logging.md b/docs/core/logging.md
index bf5fb6767..09714a512 100644
--- a/docs/core/logging.md
+++ b/docs/core/logging.md
@@ -239,7 +239,7 @@ to customise what is logged.
*/
public class App implements RequestHandler {
- Logger log = LogManager.getLogger();
+ Logger log = LogManager.getLogger(App.class);
@Logging
public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) {
@@ -256,7 +256,7 @@ to customise what is logged.
*/
public class AppLogEvent implements RequestHandler {
- Logger log = LogManager.getLogger();
+ Logger log = LogManager.getLogger(AppLogEvent.class);
@Logging(logEvent = true)
public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) {
@@ -315,7 +315,7 @@ You can set a Correlation ID using `correlationIdPath` attribute by passing a [J
*/
public class App implements RequestHandler {
- Logger log = LogManager.getLogger();
+ Logger log = LogManager.getLogger(App.class);
@Logging(correlationIdPath = "/headers/my_request_id_header")
public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) {
@@ -364,7 +364,7 @@ for known event sources, where either a request ID or X-Ray Trace ID are present
*/
public class App implements RequestHandler {
- Logger log = LogManager.getLogger();
+ Logger log = LogManager.getLogger(App.class);
@Logging(correlationIdPath = CorrelationIdPathConstants.API_GATEWAY_REST)
public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) {
@@ -417,7 +417,7 @@ You can append your own keys to your existing logs via `appendKey`.
*/
public class App implements RequestHandler {
- Logger log = LogManager.getLogger();
+ Logger log = LogManager.getLogger(App.class);
@Logging(logEvent = true)
public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) {
@@ -449,7 +449,7 @@ You can remove any additional key from entry using `LoggingUtils.removeKeys()`.
*/
public class App implements RequestHandler {
- Logger log = LogManager.getLogger();
+ Logger log = LogManager.getLogger(App.class);
@Logging(logEvent = true)
public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) {
@@ -484,7 +484,7 @@ this means that custom keys can be persisted across invocations. If you want all
*/
public class App implements RequestHandler {
- Logger log = LogManager.getLogger();
+ Logger log = LogManager.getLogger(App.class);
@Logging(clearState = true)
public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) {
@@ -545,7 +545,7 @@ specific fields from received event due to security.
*/
public class App implements RequestHandler {
- Logger log = LogManager.getLogger();
+ Logger log = LogManager.getLogger(App.class);
static {
ObjectMapper objectMapper = new ObjectMapper();
@@ -575,7 +575,7 @@ via `samplingRate` attribute on annotation.
*/
public class App implements RequestHandler {
- Logger log = LogManager.getLogger();
+ Logger log = LogManager.getLogger(App.class);
@Logging(samplingRate = 0.5)
public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) {
diff --git a/examples/powertools-examples-parameters/src/main/java/org/demo/parameters/ParametersFunction.java b/examples/powertools-examples-parameters/src/main/java/org/demo/parameters/ParametersFunction.java
index 7f41e020e..f96352e86 100644
--- a/examples/powertools-examples-parameters/src/main/java/org/demo/parameters/ParametersFunction.java
+++ b/examples/powertools-examples-parameters/src/main/java/org/demo/parameters/ParametersFunction.java
@@ -23,7 +23,7 @@
import static software.amazon.lambda.powertools.parameters.transform.Transformer.json;
public class ParametersFunction implements RequestHandler {
- private final static Logger log = LogManager.getLogger();
+ private final static Logger log = LogManager.getLogger(ParametersFunction.class);
SSMProvider ssmProvider = ParamManager.getSsmProvider();
SecretsProvider secretsProvider = ParamManager.getSecretsProvider();
diff --git a/powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/handlers/IdempotencyFunction.java b/powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/handlers/IdempotencyFunction.java
index c60336b81..0423bd90a 100644
--- a/powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/handlers/IdempotencyFunction.java
+++ b/powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/handlers/IdempotencyFunction.java
@@ -22,7 +22,7 @@
import java.util.stream.Collectors;
public class IdempotencyFunction implements RequestHandler {
- private final static Logger LOG = LogManager.getLogger();
+ private final static Logger LOG = LogManager.getLogger(IdempotencyFunction.class);
public boolean handlerExecuted = false;
From baa3592f12f81c13f8d076bef3fb947fc1f889d3 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Wed, 26 Jul 2023 14:19:05 +0200
Subject: [PATCH 051/666] build(deps): bump aws.sdk.version from 2.20.110 to
2.20.111 (#1315)
Bumps `aws.sdk.version` from 2.20.110 to 2.20.111.
Updates `software.amazon.awssdk:bom` from 2.20.110 to 2.20.111
Updates `software.amazon.awssdk:http-client-spi` from 2.20.110 to 2.20.111
Updates `software.amazon.awssdk:url-connection-client` from 2.20.110 to 2.20.111
Updates `software.amazon.awssdk:s3` from 2.20.110 to 2.20.111
Updates `software.amazon.awssdk:lambda` from 2.20.110 to 2.20.111
Updates `software.amazon.awssdk:cloudwatch` from 2.20.110 to 2.20.111
Updates `software.amazon.awssdk:xray` from 2.20.110 to 2.20.111
Updates `software.amazon.awssdk:cloudformation` from 2.20.110 to 2.20.111
Updates `software.amazon.awssdk:sts` from 2.20.110 to 2.20.111
---
updated-dependencies:
- dependency-name: software.amazon.awssdk:bom
dependency-type: direct:production
update-type: version-update:semver-patch
- dependency-name: software.amazon.awssdk:http-client-spi
dependency-type: direct:production
update-type: version-update:semver-patch
- dependency-name: software.amazon.awssdk:url-connection-client
dependency-type: direct:development
update-type: version-update:semver-patch
- dependency-name: software.amazon.awssdk:s3
dependency-type: direct:development
update-type: version-update:semver-patch
- dependency-name: software.amazon.awssdk:lambda
dependency-type: direct:development
update-type: version-update:semver-patch
- dependency-name: software.amazon.awssdk:cloudwatch
dependency-type: direct:development
update-type: version-update:semver-patch
- dependency-name: software.amazon.awssdk:xray
dependency-type: direct:development
update-type: version-update:semver-patch
- dependency-name: software.amazon.awssdk:cloudformation
dependency-type: direct:development
update-type: version-update:semver-patch
- dependency-name: software.amazon.awssdk:sts
dependency-type: direct:development
update-type: version-update:semver-patch
...
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
examples/powertools-examples-cloudformation/pom.xml | 2 +-
examples/powertools-examples-sqs/pom.xml | 2 +-
pom.xml | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml
index 45857eee2..843d8b5e8 100644
--- a/examples/powertools-examples-cloudformation/pom.xml
+++ b/examples/powertools-examples-cloudformation/pom.xml
@@ -16,7 +16,7 @@
true1.2.23.11.2
- 2.20.110
+ 2.20.111
diff --git a/examples/powertools-examples-sqs/pom.xml b/examples/powertools-examples-sqs/pom.xml
index d1b0c102b..78e4b0904 100644
--- a/examples/powertools-examples-sqs/pom.xml
+++ b/examples/powertools-examples-sqs/pom.xml
@@ -28,7 +28,7 @@
software.amazon.awssdkurl-connection-client
- 2.20.110
+ 2.20.111com.amazonaws
diff --git a/pom.xml b/pom.xml
index cbd588c96..ccc27b64c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -60,7 +60,7 @@
2.20.02.15.21.9.7
- 2.20.110
+ 2.20.1112.14.02.1.3UTF-8
From 0e76f04f1946dc3cabb842fe4303ac122b67b563 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Van=20Der=20Linden?=
<117538+jeromevdl@users.noreply.github.com>
Date: Thu, 27 Jul 2023 10:31:19 +0200
Subject: [PATCH 052/666] chore: checkstyle formater & linter (#1316)
* add checkstyle to the project
* apply checkstyle and add copyright headers when missing
* only check style on JDK 11 (fix jdk 8 build)
* notice in the contribution guide
---
CONTRIBUTING.md | 9 +-
checkstyle.xml | 427 ++++++++++++++++++
examples/pom.xml | 14 +
...owertoolsExamplesCloudformationCdkApp.java | 5 +-
.../src/main/java/helloworld/App.java | 15 +-
.../src/main/java/helloworld/App.java | 70 +--
.../src/main/java/helloworld/AppStream.java | 21 +-
.../src/test/java/helloworld/AppTest.java | 70 +--
.../powertools-examples-idempotency/pom.xml | 14 +
.../src/main/java/helloworld/App.java | 37 +-
.../src/test/java/helloworld/AppTest.java | 35 +-
.../java/org/demo/parameters/MyObject.java | 14 +
.../demo/parameters/ParametersFunction.java | 43 +-
...GatewayRequestDeserializationFunction.java | 32 +-
.../java/org/demo/serialization/Product.java | 14 +
.../SQSEventDeserializationFunction.java | 21 +-
...wayRequestDeserializationFunctionTest.java | 18 +-
.../SQSEventDeserializationFunctionTest.java | 24 +-
.../java/org/demo/sqs/SqsMessageSender.java | 63 ++-
.../src/main/java/org/demo/sqs/SqsPoller.java | 37 +-
.../powertools-examples-validation/pom.xml | 14 +
.../demo/validation/InboundValidation.java | 20 +-
.../validation/InboundValidationTest.java | 20 +-
license-header | 13 +
pom.xml | 53 +++
powertools-cloudformation/pom.xml | 22 +
.../AbstractCustomResourceHandler.java | 19 +-
.../CloudFormationResponse.java | 231 +++++-----
.../CustomResourceResponseException.java | 14 +
.../powertools/cloudformation/Response.java | 271 +++++------
.../AbstractCustomResourceHandlerTest.java | 209 +++++----
.../CloudFormationIntegrationTest.java | 99 ++--
.../CloudFormationResponseTest.java | 71 +--
.../cloudformation/ResponseTest.java | 47 +-
.../NoPhysicalResourceIdSetHandler.java | 14 +
.../PhysicalResourceIdSetHandler.java | 20 +-
.../RuntimeExceptionThrownHandler.java | 14 +
powertools-core/pom.xml | 23 +
.../core/internal/LambdaConstants.java | 3 +-
.../core/internal/LambdaHandlerProcessor.java | 14 +-
.../core/internal/SystemWrapper.java | 14 +
.../internal/LambdaHandlerProcessorTest.java | 40 +-
.../lambda/powertools/e2e/Function.java | 27 +-
.../amazon/lambda/powertools/e2e/Input.java | 14 +
.../lambda/powertools/e2e/Function.java | 14 +
.../amazon/lambda/powertools/e2e/Input.java | 14 +
.../lambda/powertools/e2e/Function.java | 14 +
.../amazon/lambda/powertools/e2e/Input.java | 21 +-
.../lambda/powertools/e2e/Function.java | 14 +
.../amazon/lambda/powertools/e2e/Input.java | 39 +-
.../lambda/powertools/e2e/Function.java | 29 +-
.../amazon/lambda/powertools/e2e/Input.java | 14 +
powertools-e2e-tests/pom.xml | 18 +
.../lambda/powertools/IdempotencyE2ET.java | 30 +-
.../amazon/lambda/powertools/LoggingE2ET.java | 38 +-
.../amazon/lambda/powertools/MetricsE2ET.java | 73 ++-
.../lambda/powertools/ParametersE2ET.java | 43 +-
.../amazon/lambda/powertools/TracingE2ET.java | 38 +-
.../powertools/testutils/AppConfig.java | 17 +-
.../powertools/testutils/Infrastructure.java | 304 +++++++------
.../powertools/testutils/JavaRuntime.java | 14 +
.../testutils/lambda/InvocationResult.java | 18 +-
.../testutils/lambda/LambdaInvoker.java | 27 +-
.../testutils/logging/InvocationLogs.java | 18 +-
.../testutils/metrics/MetricsFetcher.java | 105 +++--
.../testutils/tracing/SegmentDocument.java | 17 +-
.../powertools/testutils/tracing/Trace.java | 17 +-
.../testutils/tracing/TraceFetcher.java | 150 +++---
powertools-idempotency/pom.xml | 18 +
.../powertools/idempotency/Constants.java | 3 +-
.../powertools/idempotency/Idempotency.java | 52 ++-
.../idempotency/IdempotencyConfig.java | 49 +-
.../idempotency/IdempotencyKey.java | 3 +-
.../powertools/idempotency/Idempotent.java | 4 +-
...IdempotencyAlreadyInProgressException.java | 3 +-
.../IdempotencyConfigurationException.java | 3 +-
...IdempotencyInconsistentStateException.java | 3 +-
...IdempotencyItemAlreadyExistsException.java | 3 +-
.../IdempotencyItemNotFoundException.java | 7 +-
.../exceptions/IdempotencyKeyException.java | 3 +-
.../IdempotencyPersistenceLayerException.java | 3 +-
.../IdempotencyValidationException.java | 3 +-
.../internal/IdempotencyHandler.java | 56 ++-
.../internal/IdempotentAspect.java | 25 +-
.../idempotency/internal/cache/LRUCache.java | 4 +-
.../persistence/BasePersistenceStore.java | 63 +--
.../idempotency/persistence/DataRecord.java | 29 +-
.../persistence/DynamoDBPersistenceStore.java | 84 ++--
.../persistence/PersistenceStore.java | 10 +-
.../idempotency/DynamoDBConfig.java | 35 +-
.../idempotency/IdempotencyTest.java | 24 +-
.../handlers/IdempotencyEnabledFunction.java | 3 +-
.../handlers/IdempotencyFunction.java | 29 +-
.../handlers/IdempotencyInternalFunction.java | 7 +-
...dempotencyInternalFunctionInternalKey.java | 3 +-
.../IdempotencyInternalFunctionInvalid.java | 5 +-
.../IdempotencyInternalFunctionVoid.java | 5 +-
.../handlers/IdempotencyStringFunction.java | 14 +
.../IdempotencyWithErrorFunction.java | 3 +-
.../internal/IdempotencyAspectTest.java | 71 ++-
.../internal/cache/LRUCacheTest.java | 7 +-
.../powertools/idempotency/model/Basket.java | 25 +-
.../powertools/idempotency/model/Product.java | 11 +-
.../persistence/BasePersistenceStoreTest.java | 71 +--
.../DynamoDBPersistenceStoreTest.java | 66 ++-
powertools-logging/pom.xml | 22 +
.../logging/CorrelationIdPathConstants.java | 18 +-
.../lambda/powertools/logging/Logging.java | 6 +-
.../powertools/logging/LoggingUtils.java | 19 +-
.../internal/AbstractJacksonLayoutCopy.java | 381 ++++++++--------
.../logging/internal/DefaultLambdaFields.java | 12 +-
.../logging/internal/JacksonFactoryCopy.java | 108 +++--
.../logging/internal/LambdaJsonLayout.java | 175 +++----
.../logging/internal/LambdaLoggingAspect.java | 71 +--
.../logging/internal/PowertoolsResolver.java | 19 +-
.../internal/PowertoolsResolverFactory.java | 17 +-
.../core/layout/LambdaJsonLayoutTest.java | 84 ++--
.../powertools/logging/LoggingUtilsTest.java | 12 +-
...LogToolApiGatewayHttpApiCorrelationId.java | 7 +-
...LogToolApiGatewayRestApiCorrelationId.java | 7 +-
.../logging/handlers/PowerLogToolEnabled.java | 3 +-
.../PowerLogToolEnabledForStream.java | 6 +-
.../handlers/PowerLogToolSamplingEnabled.java | 3 +-
.../logging/handlers/PowerToolDisabled.java | 3 +-
.../handlers/PowerToolDisabledForStream.java | 4 +-
.../handlers/PowerToolLogEventEnabled.java | 3 +-
.../PowerToolLogEventEnabledForStream.java | 6 +-
...erToolLogEventEnabledWithCustomMapper.java | 20 +-
.../PowertoolsLogAlbCorrelationId.java | 7 +-
.../PowertoolsLogEnabledWithClearState.java | 5 +-
...PowertoolsLogEventBridgeCorrelationId.java | 12 +-
.../internal/LambdaLoggingAspectTest.java | 125 ++---
powertools-metrics/pom.xml | 22 +
.../emf/model/MetricsLoggerHelper.java | 18 +-
.../lambda/powertools/metrics/Metrics.java | 17 +
.../powertools/metrics/MetricsUtils.java | 65 ++-
.../metrics/ValidationException.java | 14 +
.../metrics/internal/LambdaMetricsAspect.java | 100 ++--
.../powertools/metrics/MetricsLoggerTest.java | 182 ++++----
...ertoolsMetricsColdStartEnabledHandler.java | 18 +-
...MetricsEnabledDefaultDimensionHandler.java | 26 +-
...tricsEnabledDefaultNoDimensionHandler.java | 24 +-
.../PowertoolsMetricsEnabledHandler.java | 20 +-
...PowertoolsMetricsEnabledStreamHandler.java | 21 +-
...sMetricsExceptionWhenNoMetricsHandler.java | 18 +-
.../PowertoolsMetricsNoDimensionsHandler.java | 18 +-
...etricsNoExceptionWhenNoMetricsHandler.java | 18 +-
...rtoolsMetricsTooManyDimensionsHandler.java | 19 +-
...wertoolsMetricsWithExceptionInHandler.java | 18 +-
.../internal/LambdaMetricsAspectTest.java | 362 ++++++++-------
powertools-parameters/pom.xml | 19 +-
.../parameters/AppConfigProvider.java | 85 ++--
.../powertools/parameters/BaseProvider.java | 78 ++--
.../parameters/DynamoDbProvider.java | 69 +--
.../lambda/powertools/parameters/Param.java | 19 +-
.../powertools/parameters/ParamManager.java | 31 +-
.../powertools/parameters/ParamProvider.java | 3 +-
.../powertools/parameters/SSMProvider.java | 63 +--
.../parameters/SecretsProvider.java | 56 +--
.../parameters/cache/CacheManager.java | 7 +-
.../parameters/cache/DataStore.java | 29 +-
.../DynamoDbProviderSchemaException.java | 14 +
.../exception/TransformationException.java | 6 +-
.../internal/LambdaParametersAspect.java | 18 +-
.../transform/Base64Transformer.java | 8 +-
.../transform/BasicTransformer.java | 3 +-
.../parameters/transform/JsonTransformer.java | 3 +-
.../transform/TransformationManager.java | 23 +-
.../parameters/transform/Transformer.java | 6 +-
.../parameters/AppConfigProviderTest.java | 54 ++-
.../parameters/BaseProviderTest.java | 87 ++--
.../parameters/DynamoDbProviderE2ETest.java | 29 +-
.../parameters/DynamoDbProviderTest.java | 62 ++-
.../ParamManagerIntegrationTest.java | 37 +-
.../parameters/ParamManagerTest.java | 11 +-
.../parameters/SSMProviderTest.java | 44 +-
.../parameters/SecretsProviderTest.java | 27 +-
.../parameters/cache/CacheManagerTest.java | 14 +-
.../parameters/cache/DataStoreTest.java | 14 +-
.../parameters/internal/AnotherObject.java | 18 +-
.../parameters/internal/CustomProvider.java | 19 +-
.../internal/LambdaParametersAspectTest.java | 39 +-
.../transform/Base64TransformerTest.java | 12 +-
.../transform/JsonTransformerTest.java | 26 +-
.../transform/ObjectToDeserialize.java | 8 +-
.../transform/TransformationManagerTest.java | 18 +-
powertools-serialization/pom.xml | 18 +
.../EventDeserializationException.java | 3 +-
.../utilities/EventDeserializer.java | 54 ++-
.../powertools/utilities/JsonConfig.java | 27 +-
.../utilities/jmespath/Base64Function.java | 28 +-
.../jmespath/Base64GZipFunction.java | 42 +-
.../utilities/jmespath/JsonFunction.java | 4 +-
.../utilities/EventDeserializerTest.java | 27 +-
.../jmespath/Base64FunctionTest.java | 16 +-
.../jmespath/Base64GZipFunctionTest.java | 31 +-
.../utilities/jmespath/JsonFunctionTest.java | 27 +-
.../powertools/utilities/model/Basket.java | 25 +-
.../powertools/utilities/model/Order.java | 1 +
.../powertools/utilities/model/Product.java | 11 +-
powertools-sqs/pom.xml | 23 +
.../sqs/SQSBatchProcessingException.java | 29 +-
.../lambda/powertools/sqs/SqsBatch.java | 30 +-
.../powertools/sqs/SqsLargeMessage.java | 15 +-
.../powertools/sqs/SqsMessageHandler.java | 19 +-
.../lambda/powertools/sqs/SqsUtils.java | 109 ++---
...ippedMessageDueToFailedBatchException.java | 14 +
.../powertools/sqs/internal/BatchContext.java | 194 ++++----
.../sqs/internal/SqsLargeMessageAspect.java | 146 +++---
.../SqsMessageBatchProcessorAspect.java | 22 +-
.../powertools/sqs/SampleSqsHandler.java | 14 +
.../sqs/SqsUtilsBatchProcessorTest.java | 298 ++++++------
.../sqs/SqsUtilsFifoBatchProcessorTest.java | 138 +++---
.../sqs/SqsUtilsLargeMessageTest.java | 164 ++++---
.../sqs/handlers/LambdaHandlerApiGateway.java | 16 +-
.../PartialBatchFailureSuppressedHandler.java | 20 +-
.../PartialBatchPartialFailureHandler.java | 20 +-
.../handlers/PartialBatchSuccessHandler.java | 20 +-
.../sqs/handlers/SqsMessageHandler.java | 14 +
...MessageHandlerWithNonRetryableHandler.java | 27 +-
...dlerWithNonRetryableHandlerWithDelete.java | 24 +-
.../handlers/SqsNoDeleteMessageHandler.java | 14 +
.../internal/SqsLargeMessageAspectTest.java | 121 +++--
.../SqsMessageBatchProcessorAspectTest.java | 214 +++++----
powertools-test-suite/pom.xml | 14 +
.../testsuite/LoggingOrderTest.java | 114 +++--
.../handler/LoggingOrderMessageHandler.java | 14 +
.../TracingLoggingStreamMessageHandler.java | 21 +-
powertools-tracing/pom.xml | 23 +
.../powertools/tracing/CaptureMode.java | 14 +
.../lambda/powertools/tracing/Tracing.java | 9 +-
.../powertools/tracing/TracingUtils.java | 55 +--
.../tracing/internal/LambdaTracingAspect.java | 35 +-
.../tracing/internal/SystemWrapper.java | 14 +
.../powertools/tracing/TracingUtilsTest.java | 160 ++++---
.../tracing/handlers/PowerToolDisabled.java | 3 +-
.../handlers/PowerToolDisabledForStream.java | 8 +-
.../handlers/PowerTracerToolEnabled.java | 3 +-
...lEnabledExplicitlyForResponseAndError.java | 7 +-
.../PowerTracerToolEnabledForError.java | 7 +-
.../PowerTracerToolEnabledForResponse.java | 7 +-
...oolEnabledForResponseWithCustomMapper.java | 48 +-
.../PowerTracerToolEnabledForStream.java | 6 +-
...cerToolEnabledForStreamWithNoMetaData.java | 10 +-
.../PowerTracerToolEnabledWithException.java | 3 +-
.../PowerTracerToolEnabledWithNoMetaData.java | 7 +-
...erToolEnabledWithNoMetaDataDeprecated.java | 5 +-
.../internal/LambdaTracingAspectTest.java | 278 ++++++------
.../nonhandler/PowerToolNonHandler.java | 14 +
powertools-validation/pom.xml | 23 +
.../powertools/validation/Validation.java | 8 +-
.../validation/ValidationConfig.java | 7 +-
.../validation/ValidationException.java | 3 +-
.../validation/ValidationUtils.java | 24 +-
.../validation/internal/ValidationAspect.java | 43 +-
.../validation/ValidationUtilsTest.java | 92 ++--
.../handlers/GenericSchemaV7Handler.java | 3 +-
.../handlers/MyCustomEventHandler.java | 3 +-
.../SQSWithCustomEnvelopeHandler.java | 3 +-
.../handlers/SQSWithWrongEnvelopeHandler.java | 3 +-
.../ValidationInboundStringHandler.java | 3 +-
.../ResponseEventsArgumentsProvider.java | 14 +-
.../internal/ValidationAspectTest.java | 40 +-
.../powertools/validation/model/Basket.java | 3 +-
.../validation/model/MyCustomEvent.java | 3 +-
.../powertools/validation/model/Product.java | 3 +-
266 files changed, 6810 insertions(+), 3722 deletions(-)
create mode 100644 checkstyle.xml
create mode 100644 license-header
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 08aeddcfe..46fab27cf 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -31,10 +31,11 @@ To send us a pull request, please:
1. Fork the repository.
2. Modify the source; please focus on the specific change you are contributing. If you also reformat all the code, it will be hard for us to focus on your change.
-3. Ensure local tests pass.
-4. Commit to your fork using clear commit messages.
-5. Send us a pull request, answering any default questions in the pull request interface.
-6. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation.
+3. Ensure local tests pass: `mvn clean test`
+4. Ensure your code is formatted with the provided [checkstyle.xml](https://github.com/aws-powertools/powertools-lambda-java/blob/main/checkstyle.xml): `mvn clean verify`
+5. Commit to your fork using clear commit messages.
+6. Send us a pull request, answering any default questions in the pull request interface.
+7. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation.
GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and
[creating a pull request](https://help.github.com/articles/creating-a-pull-request/).
diff --git a/checkstyle.xml b/checkstyle.xml
new file mode 100644
index 000000000..34ef98ef2
--- /dev/null
+++ b/checkstyle.xml
@@ -0,0 +1,427 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/examples/pom.xml b/examples/pom.xml
index c9b8ea8ae..72f1dc03b 100644
--- a/examples/pom.xml
+++ b/examples/pom.xml
@@ -1,4 +1,18 @@
+
+
diff --git a/examples/powertools-examples-cloudformation/infra/cdk/src/main/java/com/myorg/PowertoolsExamplesCloudformationCdkApp.java b/examples/powertools-examples-cloudformation/infra/cdk/src/main/java/com/myorg/PowertoolsExamplesCloudformationCdkApp.java
index 84060171b..f4a4d06d7 100644
--- a/examples/powertools-examples-cloudformation/infra/cdk/src/main/java/com/myorg/PowertoolsExamplesCloudformationCdkApp.java
+++ b/examples/powertools-examples-cloudformation/infra/cdk/src/main/java/com/myorg/PowertoolsExamplesCloudformationCdkApp.java
@@ -7,8 +7,9 @@ public class PowertoolsExamplesCloudformationCdkApp {
public static void main(final String[] args) {
App app = new App();
- new PowertoolsExamplesCloudformationCdkStack(app, "PowertoolsExamplesCloudformationCdkStack", StackProps.builder()
- .build());
+ new PowertoolsExamplesCloudformationCdkStack(app, "PowertoolsExamplesCloudformationCdkStack",
+ StackProps.builder()
+ .build());
app.synth();
}
diff --git a/examples/powertools-examples-cloudformation/src/main/java/helloworld/App.java b/examples/powertools-examples-cloudformation/src/main/java/helloworld/App.java
index c7744cd5a..ca3cb0ab7 100644
--- a/examples/powertools-examples-cloudformation/src/main/java/helloworld/App.java
+++ b/examples/powertools-examples-cloudformation/src/main/java/helloworld/App.java
@@ -41,7 +41,8 @@ public App() {
protected Response create(CloudFormationCustomResourceEvent cloudFormationCustomResourceEvent, Context context) {
// Validate the CloudFormation Custom Resource event
Objects.requireNonNull(cloudFormationCustomResourceEvent, "cloudFormationCustomResourceEvent cannot be null.");
- Objects.requireNonNull(cloudFormationCustomResourceEvent.getResourceProperties().get("BucketName"), "BucketName cannot be null.");
+ Objects.requireNonNull(cloudFormationCustomResourceEvent.getResourceProperties().get("BucketName"),
+ "BucketName cannot be null.");
log.info(cloudFormationCustomResourceEvent);
String bucketName = (String) cloudFormationCustomResourceEvent.getResourceProperties().get("BucketName");
@@ -70,7 +71,8 @@ protected Response create(CloudFormationCustomResourceEvent cloudFormationCustom
protected Response update(CloudFormationCustomResourceEvent cloudFormationCustomResourceEvent, Context context) {
// Validate the CloudFormation Custom Resource event
Objects.requireNonNull(cloudFormationCustomResourceEvent, "cloudFormationCustomResourceEvent cannot be null.");
- Objects.requireNonNull(cloudFormationCustomResourceEvent.getResourceProperties().get("BucketName"), "BucketName cannot be null.");
+ Objects.requireNonNull(cloudFormationCustomResourceEvent.getResourceProperties().get("BucketName"),
+ "BucketName cannot be null.");
log.info(cloudFormationCustomResourceEvent);
// Get the physicalResourceId. physicalResourceId is the value returned to CloudFormation in the Create request, and passed in on subsequent requests (e.g. UPDATE or DELETE)
@@ -112,7 +114,8 @@ protected Response update(CloudFormationCustomResourceEvent cloudFormationCustom
protected Response delete(CloudFormationCustomResourceEvent cloudFormationCustomResourceEvent, Context context) {
// Validate the CloudFormation Custom Resource event
Objects.requireNonNull(cloudFormationCustomResourceEvent, "cloudFormationCustomResourceEvent cannot be null.");
- Objects.requireNonNull(cloudFormationCustomResourceEvent.getPhysicalResourceId(), "PhysicalResourceId cannot be null.");
+ Objects.requireNonNull(cloudFormationCustomResourceEvent.getPhysicalResourceId(),
+ "PhysicalResourceId cannot be null.");
log.info(cloudFormationCustomResourceEvent);
// Get the physicalResourceId. physicalResourceId is the value provided to CloudFormation in the Create request.
@@ -142,7 +145,8 @@ protected Response delete(CloudFormationCustomResourceEvent cloudFormationCustom
private boolean bucketExists(String bucketName) {
try {
- HeadBucketResponse headBucketResponse = s3Client.headBucket(HeadBucketRequest.builder().bucket(bucketName).build());
+ HeadBucketResponse headBucketResponse =
+ s3Client.headBucket(HeadBucketRequest.builder().bucket(bucketName).build());
if (headBucketResponse.sdkHttpResponse().isSuccessful()) {
return true;
}
@@ -157,7 +161,8 @@ private void createBucket(String bucketName) {
S3Waiter waiter = s3Client.waiter();
CreateBucketRequest createBucketRequest = CreateBucketRequest.builder().bucket(bucketName).build();
s3Client.createBucket(createBucketRequest);
- WaiterResponse waiterResponse = waiter.waitUntilBucketExists(HeadBucketRequest.builder().bucket(bucketName).build());
+ WaiterResponse waiterResponse =
+ waiter.waitUntilBucketExists(HeadBucketRequest.builder().bucket(bucketName).build());
waiterResponse.matched().response().ifPresent(log::info);
log.info("Bucket Created {}", bucketName);
}
diff --git a/examples/powertools-examples-core/src/main/java/helloworld/App.java b/examples/powertools-examples-core/src/main/java/helloworld/App.java
index b45440114..94360cf59 100644
--- a/examples/powertools-examples-core/src/main/java/helloworld/App.java
+++ b/examples/powertools-examples-core/src/main/java/helloworld/App.java
@@ -1,12 +1,23 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package helloworld;
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.net.URL;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.stream.Collectors;
+import static software.amazon.lambda.powertools.metrics.MetricsUtils.metricsLogger;
+import static software.amazon.lambda.powertools.metrics.MetricsUtils.withSingleMetric;
+import static software.amazon.lambda.powertools.tracing.TracingUtils.putMetadata;
+import static software.amazon.lambda.powertools.tracing.TracingUtils.withEntitySubsegment;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
@@ -14,21 +25,23 @@
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent;
import com.amazonaws.xray.AWSXRay;
import com.amazonaws.xray.entities.Entity;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.stream.Collectors;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import software.amazon.cloudwatchlogs.emf.model.DimensionSet;
import software.amazon.cloudwatchlogs.emf.model.Unit;
-import software.amazon.lambda.powertools.logging.LoggingUtils;
import software.amazon.lambda.powertools.logging.Logging;
+import software.amazon.lambda.powertools.logging.LoggingUtils;
import software.amazon.lambda.powertools.metrics.Metrics;
import software.amazon.lambda.powertools.tracing.CaptureMode;
-import software.amazon.lambda.powertools.tracing.TracingUtils;
import software.amazon.lambda.powertools.tracing.Tracing;
-
-import static software.amazon.lambda.powertools.metrics.MetricsUtils.metricsLogger;
-import static software.amazon.lambda.powertools.metrics.MetricsUtils.withSingleMetric;
-import static software.amazon.lambda.powertools.tracing.TracingUtils.putMetadata;
-import static software.amazon.lambda.powertools.tracing.TracingUtils.withEntitySubsegment;
+import software.amazon.lambda.powertools.tracing.TracingUtils;
/**
* Handler for requests to Lambda function.
@@ -47,10 +60,11 @@ public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEv
metricsLogger().putMetric("CustomMetric1", 1, Unit.COUNT);
- withSingleMetric("CustomMetrics2", 1, Unit.COUNT, "Another", (metric) -> {
- metric.setDimensions(DimensionSet.of("AnotherService", "CustomService"));
- metric.setDimensions(DimensionSet.of("AnotherService1", "CustomService1"));
- });
+ withSingleMetric("CustomMetrics2", 1, Unit.COUNT, "Another", (metric) ->
+ {
+ metric.setDimensions(DimensionSet.of("AnotherService", "CustomService"));
+ metric.setDimensions(DimensionSet.of("AnotherService1", "CustomService1"));
+ });
LoggingUtils.appendKey("test", "willBeLogged");
@@ -62,11 +76,12 @@ public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEv
TracingUtils.putAnnotation("Test", "New");
String output = String.format("{ \"message\": \"hello world\", \"location\": \"%s\" }", pageContents);
- TracingUtils.withSubsegment("loggingResponse", subsegment -> {
- String sampled = "log something out";
- log.info(sampled);
- log.info(output);
- });
+ TracingUtils.withSubsegment("loggingResponse", subsegment ->
+ {
+ String sampled = "log something out";
+ log.info(sampled);
+ log.info(output);
+ });
threadOption1();
@@ -91,10 +106,11 @@ private void threadOption1() throws InterruptedException {
private void threadOption2() throws InterruptedException {
Entity traceEntity = AWSXRay.getTraceEntity();
- Thread anotherThread = new Thread(() -> withEntitySubsegment("inlineLog", traceEntity, subsegment -> {
- String var = "somethingToProcess";
- log.info("inside threaded logging inline {}", var);
- }));
+ Thread anotherThread = new Thread(() -> withEntitySubsegment("inlineLog", traceEntity, subsegment ->
+ {
+ String var = "somethingToProcess";
+ log.info("inside threaded logging inline {}", var);
+ }));
anotherThread.start();
anotherThread.join();
}
diff --git a/examples/powertools-examples-core/src/main/java/helloworld/AppStream.java b/examples/powertools-examples-core/src/main/java/helloworld/AppStream.java
index aed048eef..401ef8c48 100644
--- a/examples/powertools-examples-core/src/main/java/helloworld/AppStream.java
+++ b/examples/powertools-examples-core/src/main/java/helloworld/AppStream.java
@@ -1,13 +1,26 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package helloworld;
+import com.amazonaws.services.lambda.runtime.Context;
+import com.amazonaws.services.lambda.runtime.RequestStreamHandler;
+import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Map;
-
-import com.amazonaws.services.lambda.runtime.Context;
-import com.amazonaws.services.lambda.runtime.RequestStreamHandler;
-import com.fasterxml.jackson.databind.ObjectMapper;
import software.amazon.lambda.powertools.logging.Logging;
import software.amazon.lambda.powertools.metrics.Metrics;
diff --git a/examples/powertools-examples-core/src/test/java/helloworld/AppTest.java b/examples/powertools-examples-core/src/test/java/helloworld/AppTest.java
index b584ee944..70dad8d71 100644
--- a/examples/powertools-examples-core/src/test/java/helloworld/AppTest.java
+++ b/examples/powertools-examples-core/src/test/java/helloworld/AppTest.java
@@ -1,43 +1,59 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package helloworld;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent;
import com.amazonaws.xray.AWSXRay;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
-import static org.junit.Assert.*;
-
public class AppTest {
- @Before
- public void setup() {
- if(null == System.getenv("LAMBDA_TASK_ROOT")) {
- AWSXRay.beginSegment("test");
+ @Before
+ public void setup() {
+ if (null == System.getenv("LAMBDA_TASK_ROOT")) {
+ AWSXRay.beginSegment("test");
+ }
}
- }
- @After
- public void tearDown() {
- if (AWSXRay.getCurrentSubsegmentOptional().isPresent()) {
- AWSXRay.endSubsegment();
+ @After
+ public void tearDown() {
+ if (AWSXRay.getCurrentSubsegmentOptional().isPresent()) {
+ AWSXRay.endSubsegment();
+ }
+
+ if (null == System.getenv("LAMBDA_TASK_ROOT")) {
+ AWSXRay.endSegment();
+ }
}
- if(null == System.getenv("LAMBDA_TASK_ROOT")) {
- AWSXRay.endSegment();
+ @Test
+ public void successfulResponse() {
+ App app = new App();
+ APIGatewayProxyResponseEvent result = app.handleRequest(null, null);
+ assertEquals(result.getStatusCode().intValue(), 200);
+ assertEquals(result.getHeaders().get("Content-Type"), "application/json");
+ String content = result.getBody();
+ assertNotNull(content);
+ assertTrue(content.contains("\"message\""));
+ assertTrue(content.contains("\"hello world\""));
+ assertTrue(content.contains("\"location\""));
}
- }
-
- @Test
- public void successfulResponse() {
- App app = new App();
- APIGatewayProxyResponseEvent result = app.handleRequest(null, null);
- assertEquals(result.getStatusCode().intValue(), 200);
- assertEquals(result.getHeaders().get("Content-Type"), "application/json");
- String content = result.getBody();
- assertNotNull(content);
- assertTrue(content.contains("\"message\""));
- assertTrue(content.contains("\"hello world\""));
- assertTrue(content.contains("\"location\""));
- }
}
diff --git a/examples/powertools-examples-idempotency/pom.xml b/examples/powertools-examples-idempotency/pom.xml
index 0607fdd14..f24b2ffc4 100644
--- a/examples/powertools-examples-idempotency/pom.xml
+++ b/examples/powertools-examples-idempotency/pom.xml
@@ -1,3 +1,17 @@
+
+
4.0.0
diff --git a/examples/powertools-examples-idempotency/src/main/java/helloworld/App.java b/examples/powertools-examples-idempotency/src/main/java/helloworld/App.java
index 0a20aa3a4..ac2c7ef1b 100644
--- a/examples/powertools-examples-idempotency/src/main/java/helloworld/App.java
+++ b/examples/powertools-examples-idempotency/src/main/java/helloworld/App.java
@@ -1,9 +1,30 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package helloworld;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.stream.Collectors;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
@@ -14,14 +35,6 @@
import software.amazon.lambda.powertools.logging.Logging;
import software.amazon.lambda.powertools.utilities.JsonConfig;
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.net.URL;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.stream.Collectors;
-
public class App implements RequestHandler {
private final static Logger log = LogManager.getLogger(App.class);
@@ -32,7 +45,8 @@ public App() {
public App(DynamoDbClient client) {
Idempotency.config().withConfig(
IdempotencyConfig.builder()
- .withEventKeyJMESPath("powertools_json(body).address") // will retrieve the address field in the body which is a string transformed to json with `powertools_json`
+ .withEventKeyJMESPath(
+ "powertools_json(body).address") // will retrieve the address field in the body which is a string transformed to json with `powertools_json`
.build())
.withPersistenceStore(
DynamoDBPersistenceStore.builder()
@@ -45,7 +59,7 @@ public App(DynamoDbClient client) {
/**
* This is our Lambda event handler. It accepts HTTP POST requests from API gateway and returns the contents of the given URL. Requests are made idempotent
* by the idempotency library, and results are cached for the default 1h expiry time.
- *
+ *
* You can test the endpoint like this:
*
*
@@ -89,13 +103,12 @@ public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEv
/**
* Helper to retrieve the contents of the given URL and return them as a string.
- *
+ *
* We could also put the @Idempotent annotation here if we only wanted this sub-operation to be idempotent. Putting
* it on the handler, however, reduces total execution time and saves us time!
*
* @param address The URL to fetch
* @return The contents of the given URL
- *
* @throws IOException
*/
private String getPageContents(String address) throws IOException {
diff --git a/examples/powertools-examples-idempotency/src/test/java/helloworld/AppTest.java b/examples/powertools-examples-idempotency/src/test/java/helloworld/AppTest.java
index 7a5304e36..7f097906a 100644
--- a/examples/powertools-examples-idempotency/src/test/java/helloworld/AppTest.java
+++ b/examples/powertools-examples-idempotency/src/test/java/helloworld/AppTest.java
@@ -1,3 +1,17 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package helloworld;
import com.amazonaws.services.dynamodbv2.local.main.ServerRunner;
@@ -5,6 +19,9 @@
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent;
import com.amazonaws.services.lambda.runtime.tests.EventLoader;
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.net.URI;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
@@ -16,23 +33,24 @@
import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
-import software.amazon.awssdk.services.dynamodb.model.*;
-
-import java.io.IOException;
-import java.net.ServerSocket;
-import java.net.URI;
+import software.amazon.awssdk.services.dynamodb.model.AttributeDefinition;
+import software.amazon.awssdk.services.dynamodb.model.BillingMode;
+import software.amazon.awssdk.services.dynamodb.model.CreateTableRequest;
+import software.amazon.awssdk.services.dynamodb.model.KeySchemaElement;
+import software.amazon.awssdk.services.dynamodb.model.KeyType;
+import software.amazon.awssdk.services.dynamodb.model.ScalarAttributeType;
public class AppTest {
+ private static DynamoDbClient client;
@Mock
private Context context;
private App app;
- private static DynamoDbClient client;
@BeforeAll
public static void setupDynamoLocal() {
int port = getFreePort();
try {
- DynamoDBProxyServer dynamoProxy = ServerRunner.createServerFromCommandLineArgs(new String[]{
+ DynamoDBProxyServer dynamoProxy = ServerRunner.createServerFromCommandLineArgs(new String[] {
"-inMemory",
"-port",
Integer.toString(port)
@@ -79,7 +97,8 @@ void setUp() {
@Test
public void testApp() {
- APIGatewayProxyResponseEvent response = app.handleRequest(EventLoader.loadApiGatewayRestEvent("event.json"), context);
+ APIGatewayProxyResponseEvent response =
+ app.handleRequest(EventLoader.loadApiGatewayRestEvent("event.json"), context);
Assertions.assertNotNull(response);
Assertions.assertTrue(response.getBody().contains("hello world"));
}
diff --git a/examples/powertools-examples-parameters/src/main/java/org/demo/parameters/MyObject.java b/examples/powertools-examples-parameters/src/main/java/org/demo/parameters/MyObject.java
index 2cf145284..d406ae3df 100644
--- a/examples/powertools-examples-parameters/src/main/java/org/demo/parameters/MyObject.java
+++ b/examples/powertools-examples-parameters/src/main/java/org/demo/parameters/MyObject.java
@@ -1,3 +1,17 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package org.demo.parameters;
public class MyObject {
diff --git a/examples/powertools-examples-parameters/src/main/java/org/demo/parameters/ParametersFunction.java b/examples/powertools-examples-parameters/src/main/java/org/demo/parameters/ParametersFunction.java
index f96352e86..5b691cfd9 100644
--- a/examples/powertools-examples-parameters/src/main/java/org/demo/parameters/ParametersFunction.java
+++ b/examples/powertools-examples-parameters/src/main/java/org/demo/parameters/ParametersFunction.java
@@ -1,15 +1,27 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package org.demo.parameters;
+import static java.time.temporal.ChronoUnit.SECONDS;
+import static software.amazon.lambda.powertools.parameters.transform.Transformer.base64;
+import static software.amazon.lambda.powertools.parameters.transform.Transformer.json;
+
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent;
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
-import software.amazon.lambda.powertools.parameters.ParamManager;
-import software.amazon.lambda.powertools.parameters.SSMProvider;
-import software.amazon.lambda.powertools.parameters.SecretsProvider;
-
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
@@ -17,10 +29,11 @@
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
-
-import static java.time.temporal.ChronoUnit.SECONDS;
-import static software.amazon.lambda.powertools.parameters.transform.Transformer.base64;
-import static software.amazon.lambda.powertools.parameters.transform.Transformer.json;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import software.amazon.lambda.powertools.parameters.ParamManager;
+import software.amazon.lambda.powertools.parameters.SSMProvider;
+import software.amazon.lambda.powertools.parameters.SecretsProvider;
public class ParametersFunction implements RequestHandler {
private final static Logger log = LogManager.getLogger(ParametersFunction.class);
@@ -34,8 +47,10 @@ public class ParametersFunction implements RequestHandler allValues = ssmProvider.getMultiple("/powertools-java/sample");
String b64value = ssmProvider.withTransformation(base64).get("/powertools-java/sample/keybase64");
- Map secretJson = secretsProvider.withTransformation(json).get("/powertools-java/userpwd", Map.class);
- MyObject secretJsonObj = secretsProvider.withMaxAge(42, SECONDS).withTransformation(json).get("/powertools-java/secretcode", MyObject.class);
+ Map secretJson =
+ secretsProvider.withTransformation(json).get("/powertools-java/userpwd", Map.class);
+ MyObject secretJsonObj = secretsProvider.withMaxAge(42, SECONDS).withTransformation(json)
+ .get("/powertools-java/secretcode", MyObject.class);
@Override
public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent input, Context context) {
@@ -72,9 +87,9 @@ public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent in
}
}
- private String getPageContents(String address) throws IOException{
+ private String getPageContents(String address) throws IOException {
URL url = new URL(address);
- try(BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream(), "UTF-8"))) {
+ try (BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream(), "UTF-8"))) {
return br.lines().collect(Collectors.joining(System.lineSeparator()));
}
}
diff --git a/examples/powertools-examples-serialization/src/main/java/org/demo/serialization/APIGatewayRequestDeserializationFunction.java b/examples/powertools-examples-serialization/src/main/java/org/demo/serialization/APIGatewayRequestDeserializationFunction.java
index 8c33baed9..e70b37959 100644
--- a/examples/powertools-examples-serialization/src/main/java/org/demo/serialization/APIGatewayRequestDeserializationFunction.java
+++ b/examples/powertools-examples-serialization/src/main/java/org/demo/serialization/APIGatewayRequestDeserializationFunction.java
@@ -1,19 +1,33 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package org.demo.serialization;
+import static software.amazon.lambda.powertools.utilities.EventDeserializer.extractDataFrom;
+
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent;
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
-
import java.util.HashMap;
import java.util.Map;
-
-import static software.amazon.lambda.powertools.utilities.EventDeserializer.extractDataFrom;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
-public class APIGatewayRequestDeserializationFunction implements RequestHandler {
+public class APIGatewayRequestDeserializationFunction
+ implements RequestHandler {
private final static Logger LOGGER = LogManager.getLogger(APIGatewayRequestDeserializationFunction.class);
private static final Map HEADERS = new HashMap() {{
@@ -28,9 +42,9 @@ public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent ev
LOGGER.info("product={}\n", product);
return new APIGatewayProxyResponseEvent()
- .withHeaders(HEADERS)
- .withStatusCode(200)
- .withBody("Received request for productId: " + product.getId());
+ .withHeaders(HEADERS)
+ .withStatusCode(200)
+ .withBody("Received request for productId: " + product.getId());
}
}
diff --git a/examples/powertools-examples-serialization/src/main/java/org/demo/serialization/Product.java b/examples/powertools-examples-serialization/src/main/java/org/demo/serialization/Product.java
index fb94a99f8..25bae34f6 100644
--- a/examples/powertools-examples-serialization/src/main/java/org/demo/serialization/Product.java
+++ b/examples/powertools-examples-serialization/src/main/java/org/demo/serialization/Product.java
@@ -1,3 +1,17 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package org.demo.serialization;
public class Product {
diff --git a/examples/powertools-examples-serialization/src/main/java/org/demo/serialization/SQSEventDeserializationFunction.java b/examples/powertools-examples-serialization/src/main/java/org/demo/serialization/SQSEventDeserializationFunction.java
index 129fe0243..36dbed074 100644
--- a/examples/powertools-examples-serialization/src/main/java/org/demo/serialization/SQSEventDeserializationFunction.java
+++ b/examples/powertools-examples-serialization/src/main/java/org/demo/serialization/SQSEventDeserializationFunction.java
@@ -1,15 +1,28 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package org.demo.serialization;
+import static software.amazon.lambda.powertools.utilities.EventDeserializer.extractDataFrom;
+
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.lambda.runtime.events.SQSEvent;
+import java.util.List;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
-import java.util.List;
-
-import static software.amazon.lambda.powertools.utilities.EventDeserializer.extractDataFrom;
-
public class SQSEventDeserializationFunction implements RequestHandler {
diff --git a/examples/powertools-examples-serialization/src/test/java/org/demo/serialization/APIGatewayRequestDeserializationFunctionTest.java b/examples/powertools-examples-serialization/src/test/java/org/demo/serialization/APIGatewayRequestDeserializationFunctionTest.java
index 5d5da7ecc..ec8cdbd33 100644
--- a/examples/powertools-examples-serialization/src/test/java/org/demo/serialization/APIGatewayRequestDeserializationFunctionTest.java
+++ b/examples/powertools-examples-serialization/src/test/java/org/demo/serialization/APIGatewayRequestDeserializationFunctionTest.java
@@ -1,5 +1,21 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package org.demo.serialization;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent;
@@ -8,8 +24,6 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
class APIGatewayRequestDeserializationFunctionTest {
@Mock
diff --git a/examples/powertools-examples-serialization/src/test/java/org/demo/serialization/SQSEventDeserializationFunctionTest.java b/examples/powertools-examples-serialization/src/test/java/org/demo/serialization/SQSEventDeserializationFunctionTest.java
index 6979a6868..b46af3052 100644
--- a/examples/powertools-examples-serialization/src/test/java/org/demo/serialization/SQSEventDeserializationFunctionTest.java
+++ b/examples/powertools-examples-serialization/src/test/java/org/demo/serialization/SQSEventDeserializationFunctionTest.java
@@ -1,17 +1,29 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package org.demo.serialization;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.events.SQSEvent;
+import java.util.ArrayList;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import java.util.List;
-import java.util.ArrayList;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
class SQSEventDeserializationFunctionTest {
@Mock
@@ -29,7 +41,7 @@ public void shouldReturnNumberOfReceivedMessages() {
SQSEvent.SQSMessage message1 = messageWithBody("{ \"id\": 1234, \"name\": \"product\", \"price\": 42}");
SQSEvent.SQSMessage message2 = messageWithBody("{ \"id\": 12345, \"name\": \"product5\", \"price\": 45}");
SQSEvent event = new SQSEvent();
- event.setRecords(new ArrayList(){{
+ event.setRecords(new ArrayList() {{
add(message1);
add(message2);
}});
diff --git a/examples/powertools-examples-sqs/src/main/java/org/demo/sqs/SqsMessageSender.java b/examples/powertools-examples-sqs/src/main/java/org/demo/sqs/SqsMessageSender.java
index b90c50654..45856d198 100644
--- a/examples/powertools-examples-sqs/src/main/java/org/demo/sqs/SqsMessageSender.java
+++ b/examples/powertools-examples-sqs/src/main/java/org/demo/sqs/SqsMessageSender.java
@@ -1,11 +1,32 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
package org.demo.sqs;
+import static java.util.stream.Collectors.toList;
+
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.lambda.runtime.events.ScheduledEvent;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.joda.JodaModule;
+import java.security.SecureRandom;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+import java.util.stream.IntStream;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient;
@@ -17,15 +38,6 @@
import software.amazon.lambda.powertools.logging.Logging;
import software.amazon.lambda.powertools.logging.LoggingUtils;
-import java.security.SecureRandom;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Random;
-import java.util.stream.IntStream;
-
-import static java.util.stream.Collectors.toList;
-
public class SqsMessageSender implements RequestHandler {
private static final Logger log = LogManager.getLogger(SqsMessageSender.class);
@@ -50,22 +62,23 @@ public String handleRequest(final ScheduledEvent input, final Context context) {
// Push 5 messages on each invoke.
List batchRequestEntries = IntStream.range(0, 5)
- .mapToObj(value -> {
- Map attributeValueHashMap = new HashMap<>();
- attributeValueHashMap.put("Key" + value, MessageAttributeValue.builder()
- .dataType("String")
- .stringValue("Value" + value)
- .build());
-
- byte[] array = new byte[7];
- random.nextBytes(array);
-
- return SendMessageBatchRequestEntry.builder()
- .messageAttributes(attributeValueHashMap)
- .id(input.getId() + value)
- .messageBody("Sample Message " + value)
- .build();
- }).collect(toList());
+ .mapToObj(value ->
+ {
+ Map attributeValueHashMap = new HashMap<>();
+ attributeValueHashMap.put("Key" + value, MessageAttributeValue.builder()
+ .dataType("String")
+ .stringValue("Value" + value)
+ .build());
+
+ byte[] array = new byte[7];
+ random.nextBytes(array);
+
+ return SendMessageBatchRequestEntry.builder()
+ .messageAttributes(attributeValueHashMap)
+ .id(input.getId() + value)
+ .messageBody("Sample Message " + value)
+ .build();
+ }).collect(toList());
SendMessageBatchResponse sendMessageBatchResponse = sqsClient.sendMessageBatch(SendMessageBatchRequest.builder()
.queueUrl(queueUrl)
diff --git a/examples/powertools-examples-sqs/src/main/java/org/demo/sqs/SqsPoller.java b/examples/powertools-examples-sqs/src/main/java/org/demo/sqs/SqsPoller.java
index bf2b7bdfe..9ad5c7868 100644
--- a/examples/powertools-examples-sqs/src/main/java/org/demo/sqs/SqsPoller.java
+++ b/examples/powertools-examples-sqs/src/main/java/org/demo/sqs/SqsPoller.java
@@ -1,10 +1,26 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package org.demo.sqs;
-import java.util.Random;
+import static com.amazonaws.services.lambda.runtime.events.SQSEvent.SQSMessage;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.lambda.runtime.events.SQSEvent;
+import java.security.SecureRandom;
+import java.util.Random;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient;
@@ -13,18 +29,12 @@
import software.amazon.lambda.powertools.sqs.SqsBatch;
import software.amazon.lambda.powertools.sqs.SqsMessageHandler;
import software.amazon.lambda.powertools.sqs.SqsUtils;
-import java.security.SecureRandom;
-
-import static com.amazonaws.services.lambda.runtime.events.SQSEvent.SQSMessage;
/**
* Handler for requests to Lambda function.
*/
public class SqsPoller implements RequestHandler {
- Logger log = LogManager.getLogger(SqsPoller.class);
- Random random = new SecureRandom();
-
static {
// https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/lambda-optimize-starttime.html
SqsUtils.overrideSqsClient(SqsClient.builder()
@@ -32,6 +42,9 @@ public class SqsPoller implements RequestHandler {
.build());
}
+ Logger log = LogManager.getLogger(SqsPoller.class);
+ Random random = new SecureRandom();
+
@SqsBatch(value = BatchProcessor.class, nonRetryableExceptions = {IllegalArgumentException.class})
@Logging(logEvent = true)
public String handleRequest(final SQSEvent input, final Context context) {
@@ -45,14 +58,16 @@ public String process(SQSMessage message) {
int nextInt = random.nextInt(100);
- if(nextInt <= 10) {
+ if (nextInt <= 10) {
log.info("Randomly picked message with id {} as business validation failure.", message.getMessageId());
- throw new IllegalArgumentException("Failed business validation. No point of retrying. Move me to DLQ." + message.getMessageId());
+ throw new IllegalArgumentException(
+ "Failed business validation. No point of retrying. Move me to DLQ." + message.getMessageId());
}
- if(nextInt > 90) {
+ if (nextInt > 90) {
log.info("Randomly picked message with id {} as intermittent failure.", message.getMessageId());
- throw new RuntimeException("Failed due to intermittent issue. Will be sent back for retry." + message.getMessageId());
+ throw new RuntimeException(
+ "Failed due to intermittent issue. Will be sent back for retry." + message.getMessageId());
}
return "Success";
diff --git a/examples/powertools-examples-validation/pom.xml b/examples/powertools-examples-validation/pom.xml
index 455fd66b8..1c7e33de0 100644
--- a/examples/powertools-examples-validation/pom.xml
+++ b/examples/powertools-examples-validation/pom.xml
@@ -1,3 +1,17 @@
+
+
4.0.0
diff --git a/examples/powertools-examples-validation/src/main/java/org/demo/validation/InboundValidation.java b/examples/powertools-examples-validation/src/main/java/org/demo/validation/InboundValidation.java
index 89ec538c9..d3b8e51e4 100644
--- a/examples/powertools-examples-validation/src/main/java/org/demo/validation/InboundValidation.java
+++ b/examples/powertools-examples-validation/src/main/java/org/demo/validation/InboundValidation.java
@@ -1,11 +1,23 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package org.demo.validation;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent;
-import software.amazon.lambda.powertools.validation.Validation;
-
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
@@ -13,6 +25,7 @@
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
+import software.amazon.lambda.powertools.validation.Validation;
/**
* Request handler for Lambda function which demonstrates validation of request message.
@@ -20,7 +33,8 @@
public class InboundValidation implements RequestHandler {
@Validation(inboundSchema = "classpath:/schema.json")
- public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent apiGatewayProxyRequestEvent, Context context) {
+ public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent apiGatewayProxyRequestEvent,
+ Context context) {
Map headers = new HashMap<>();
headers.put("Content-Type", "application/json");
diff --git a/examples/powertools-examples-validation/src/test/java/org/demo/validation/InboundValidationTest.java b/examples/powertools-examples-validation/src/test/java/org/demo/validation/InboundValidationTest.java
index af47d3d87..d5e6de313 100644
--- a/examples/powertools-examples-validation/src/test/java/org/demo/validation/InboundValidationTest.java
+++ b/examples/powertools-examples-validation/src/test/java/org/demo/validation/InboundValidationTest.java
@@ -1,5 +1,22 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package org.demo.validation;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent;
@@ -9,9 +26,6 @@
import org.mockito.MockitoAnnotations;
import software.amazon.lambda.powertools.validation.ValidationException;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertThrows;
-
public class InboundValidationTest {
@Mock
diff --git a/license-header b/license-header
new file mode 100644
index 000000000..5669f143f
--- /dev/null
+++ b/license-header
@@ -0,0 +1,13 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
diff --git a/pom.xml b/pom.xml
index ccc27b64c..7744913fd 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,4 +1,18 @@
+
+
@@ -525,6 +539,45 @@
+
+ jdk11
+
+ 11
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-checkstyle-plugin
+ 3.3.0
+
+ checkstyle.xml
+ UTF-8
+ true
+ true
+ false
+
+
+
+
+
+ com.puppycrawl.tools
+ checkstyle
+ 10.9.1
+
+
+
+
+
+ check
+
+
+
+
+
+
+
diff --git a/powertools-cloudformation/pom.xml b/powertools-cloudformation/pom.xml
index 3a846c378..a122e7ac8 100644
--- a/powertools-cloudformation/pom.xml
+++ b/powertools-cloudformation/pom.xml
@@ -1,4 +1,18 @@
+
+
@@ -100,4 +114,12 @@
+
+
+
+ org.apache.maven.plugins
+ maven-checkstyle-plugin
+
+
+
\ No newline at end of file
diff --git a/powertools-cloudformation/src/main/java/software/amazon/lambda/powertools/cloudformation/AbstractCustomResourceHandler.java b/powertools-cloudformation/src/main/java/software/amazon/lambda/powertools/cloudformation/AbstractCustomResourceHandler.java
index 7d3a43069..7f5b6bb24 100644
--- a/powertools-cloudformation/src/main/java/software/amazon/lambda/powertools/cloudformation/AbstractCustomResourceHandler.java
+++ b/powertools-cloudformation/src/main/java/software/amazon/lambda/powertools/cloudformation/AbstractCustomResourceHandler.java
@@ -1,16 +1,29 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.cloudformation;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.lambda.runtime.events.CloudFormationCustomResourceEvent;
+import java.io.IOException;
+import java.util.Objects;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import software.amazon.awssdk.http.SdkHttpClient;
import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient;
-import java.io.IOException;
-import java.util.Objects;
-
/**
* Handler base class providing core functionality for sending responses to custom CloudFormation resources after
* receiving some event. Depending on the type of event, this class either invokes the crete, update, or delete method
diff --git a/powertools-cloudformation/src/main/java/software/amazon/lambda/powertools/cloudformation/CloudFormationResponse.java b/powertools-cloudformation/src/main/java/software/amazon/lambda/powertools/cloudformation/CloudFormationResponse.java
index 39a86293b..2f020aa25 100644
--- a/powertools-cloudformation/src/main/java/software/amazon/lambda/powertools/cloudformation/CloudFormationResponse.java
+++ b/powertools-cloudformation/src/main/java/software/amazon/lambda/powertools/cloudformation/CloudFormationResponse.java
@@ -1,3 +1,17 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.cloudformation;
import com.amazonaws.services.lambda.runtime.Context;
@@ -6,6 +20,13 @@
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.databind.node.ObjectNode;
+import java.io.IOException;
+import java.net.URI;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import software.amazon.awssdk.http.Header;
@@ -16,14 +37,6 @@
import software.amazon.awssdk.http.SdkHttpRequest;
import software.amazon.awssdk.utils.StringInputStream;
-import java.io.IOException;
-import java.net.URI;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-
/**
* Client for sending responses to AWS CloudFormation custom resources by way of a response URL, which is an Amazon S3
* pre-signed URL.
@@ -35,102 +48,6 @@
class CloudFormationResponse {
private static final Logger LOG = LoggerFactory.getLogger(CloudFormationResponse.class);
-
- /**
- * Internal representation of the payload to be sent to the event target URL. Retains all properties of the payload
- * except for "Data". This is done so that the serialization of the non-"Data" properties and the serialization of
- * the value of "Data" can be handled by separate ObjectMappers, if need be. The former properties are dictated by
- * the custom resource but the latter is dictated by the implementor of the custom resource handler.
- */
- @SuppressWarnings("unused")
- static class ResponseBody {
- static final ObjectMapper MAPPER = new ObjectMapper()
- .setPropertyNamingStrategy(PropertyNamingStrategies.UPPER_CAMEL_CASE);
- private static final String DATA_PROPERTY_NAME = "Data";
-
- private final String status;
- private final String reason;
- private final String physicalResourceId;
- private final String stackId;
- private final String requestId;
- private final String logicalResourceId;
- private final boolean noEcho;
-
- ResponseBody(CloudFormationCustomResourceEvent event,
- Response.Status responseStatus,
- String physicalResourceId,
- boolean noEcho,
- String reason) {
- Objects.requireNonNull(event, "CloudFormationCustomResourceEvent cannot be null");
-
- this.physicalResourceId = physicalResourceId;
- this.reason = reason;
- this.status = responseStatus == null ? Response.Status.SUCCESS.name() : responseStatus.name();
- this.stackId = event.getStackId();
- this.requestId = event.getRequestId();
- this.logicalResourceId = event.getLogicalResourceId();
- this.noEcho = noEcho;
- }
-
- public String getStatus() {
- return status;
- }
-
- public String getReason() {
- return reason;
- }
-
- public String getPhysicalResourceId() {
- return physicalResourceId;
- }
-
- public String getStackId() {
- return stackId;
- }
-
- public String getRequestId() {
- return requestId;
- }
-
- public String getLogicalResourceId() {
- return logicalResourceId;
- }
-
- public boolean isNoEcho() {
- return noEcho;
- }
-
- /**
- * Returns this ResponseBody as an ObjectNode with the provided JsonNode as the value of its "Data" property.
- *
- * @param dataNode the value of the "Data" property for the returned node; may be null
- * @return an ObjectNode representation of this ResponseBody and the provided dataNode
- */
- ObjectNode toObjectNode(JsonNode dataNode) {
- ObjectNode node = MAPPER.valueToTree(this);
- if (dataNode == null) {
- node.putNull(DATA_PROPERTY_NAME);
- } else {
- node.set(DATA_PROPERTY_NAME, dataNode);
- }
- return node;
- }
-
- @Override
- public String toString() {
- final StringBuffer sb = new StringBuffer("ResponseBody{");
- sb.append("status='").append(status).append('\'');
- sb.append(", reason='").append(reason).append('\'');
- sb.append(", physicalResourceId='").append(physicalResourceId).append('\'');
- sb.append(", stackId='").append(stackId).append('\'');
- sb.append(", requestId='").append(requestId).append('\'');
- sb.append(", logicalResourceId='").append(logicalResourceId).append('\'');
- sb.append(", noEcho=").append(noEcho);
- sb.append('}');
- return sb.toString();
- }
- }
-
private final SdkHttpClient client;
/**
@@ -212,7 +129,7 @@ protected Map> headers(int contentLength) {
/**
* Returns the response body as an input stream, for supplying with the HTTP request to the custom resource.
- *
+ *
* If PhysicalResourceId is null at this point it will be replaced with the Lambda LogStreamName.
*
* @throws CustomResourceResponseException if unable to generate the response stream
@@ -223,7 +140,8 @@ StringInputStream responseBodyStream(CloudFormationCustomResourceEvent event,
try {
String reason = "See the details in CloudWatch Log Stream: " + context.getLogStreamName();
if (resp == null) {
- String physicalResourceId = event.getPhysicalResourceId() != null? event.getPhysicalResourceId() : context.getLogStreamName();
+ String physicalResourceId = event.getPhysicalResourceId() != null ? event.getPhysicalResourceId() :
+ context.getLogStreamName();
ResponseBody body = new ResponseBody(event, Response.Status.SUCCESS, physicalResourceId, false, reason);
LOG.debug("ResponseBody: {}", body);
@@ -232,9 +150,11 @@ StringInputStream responseBodyStream(CloudFormationCustomResourceEvent event,
} else {
String physicalResourceId = resp.getPhysicalResourceId() != null ? resp.getPhysicalResourceId() :
- event.getPhysicalResourceId() != null? event.getPhysicalResourceId() : context.getLogStreamName();
+ event.getPhysicalResourceId() != null ? event.getPhysicalResourceId() :
+ context.getLogStreamName();
- ResponseBody body = new ResponseBody(event, resp.getStatus(), physicalResourceId, resp.isNoEcho(), reason);
+ ResponseBody body =
+ new ResponseBody(event, resp.getStatus(), physicalResourceId, resp.isNoEcho(), reason);
LOG.debug("ResponseBody: {}", body);
ObjectNode node = body.toObjectNode(resp.getJsonNode());
return new StringInputStream(node.toString());
@@ -244,4 +164,99 @@ StringInputStream responseBodyStream(CloudFormationCustomResourceEvent event,
throw new CustomResourceResponseException("Unable to generate response body.", e);
}
}
+
+ /**
+ * Internal representation of the payload to be sent to the event target URL. Retains all properties of the payload
+ * except for "Data". This is done so that the serialization of the non-"Data" properties and the serialization of
+ * the value of "Data" can be handled by separate ObjectMappers, if need be. The former properties are dictated by
+ * the custom resource but the latter is dictated by the implementor of the custom resource handler.
+ */
+ @SuppressWarnings("unused")
+ static class ResponseBody {
+ static final ObjectMapper MAPPER = new ObjectMapper()
+ .setPropertyNamingStrategy(PropertyNamingStrategies.UPPER_CAMEL_CASE);
+ private static final String DATA_PROPERTY_NAME = "Data";
+
+ private final String status;
+ private final String reason;
+ private final String physicalResourceId;
+ private final String stackId;
+ private final String requestId;
+ private final String logicalResourceId;
+ private final boolean noEcho;
+
+ ResponseBody(CloudFormationCustomResourceEvent event,
+ Response.Status responseStatus,
+ String physicalResourceId,
+ boolean noEcho,
+ String reason) {
+ Objects.requireNonNull(event, "CloudFormationCustomResourceEvent cannot be null");
+
+ this.physicalResourceId = physicalResourceId;
+ this.reason = reason;
+ this.status = responseStatus == null ? Response.Status.SUCCESS.name() : responseStatus.name();
+ this.stackId = event.getStackId();
+ this.requestId = event.getRequestId();
+ this.logicalResourceId = event.getLogicalResourceId();
+ this.noEcho = noEcho;
+ }
+
+ public String getStatus() {
+ return status;
+ }
+
+ public String getReason() {
+ return reason;
+ }
+
+ public String getPhysicalResourceId() {
+ return physicalResourceId;
+ }
+
+ public String getStackId() {
+ return stackId;
+ }
+
+ public String getRequestId() {
+ return requestId;
+ }
+
+ public String getLogicalResourceId() {
+ return logicalResourceId;
+ }
+
+ public boolean isNoEcho() {
+ return noEcho;
+ }
+
+ /**
+ * Returns this ResponseBody as an ObjectNode with the provided JsonNode as the value of its "Data" property.
+ *
+ * @param dataNode the value of the "Data" property for the returned node; may be null
+ * @return an ObjectNode representation of this ResponseBody and the provided dataNode
+ */
+ ObjectNode toObjectNode(JsonNode dataNode) {
+ ObjectNode node = MAPPER.valueToTree(this);
+ if (dataNode == null) {
+ node.putNull(DATA_PROPERTY_NAME);
+ } else {
+ node.set(DATA_PROPERTY_NAME, dataNode);
+ }
+ return node;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuffer sb = new StringBuffer("ResponseBody{");
+ sb.append("status='").append(status).append('\'');
+ sb.append(", reason='").append(reason).append('\'');
+ sb.append(", physicalResourceId='").append(physicalResourceId).append('\'');
+ sb.append(", stackId='").append(stackId).append('\'');
+ sb.append(", requestId='").append(requestId).append('\'');
+ sb.append(", logicalResourceId='").append(logicalResourceId).append('\'');
+ sb.append(", noEcho=").append(noEcho);
+ sb.append('}');
+ return sb.toString();
+ }
+ }
}
diff --git a/powertools-cloudformation/src/main/java/software/amazon/lambda/powertools/cloudformation/CustomResourceResponseException.java b/powertools-cloudformation/src/main/java/software/amazon/lambda/powertools/cloudformation/CustomResourceResponseException.java
index ead912392..904ae9c3f 100644
--- a/powertools-cloudformation/src/main/java/software/amazon/lambda/powertools/cloudformation/CustomResourceResponseException.java
+++ b/powertools-cloudformation/src/main/java/software/amazon/lambda/powertools/cloudformation/CustomResourceResponseException.java
@@ -1,3 +1,17 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.cloudformation;
/**
diff --git a/powertools-cloudformation/src/main/java/software/amazon/lambda/powertools/cloudformation/Response.java b/powertools-cloudformation/src/main/java/software/amazon/lambda/powertools/cloudformation/Response.java
index f388f6384..fe18000d4 100644
--- a/powertools-cloudformation/src/main/java/software/amazon/lambda/powertools/cloudformation/Response.java
+++ b/powertools-cloudformation/src/main/java/software/amazon/lambda/powertools/cloudformation/Response.java
@@ -1,8 +1,21 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.cloudformation;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
-
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
@@ -13,119 +26,16 @@
*/
public class Response {
- /**
- * Indicates whether a response is a success or failure.
- */
- public enum Status {
- SUCCESS, FAILED
- }
-
- /**
- * For building Response instances.
- */
- public static class Builder {
- private Object value;
- private ObjectMapper objectMapper;
- private Status status;
- private String physicalResourceId;
- private boolean noEcho;
-
- private Builder() {
- }
-
- /**
- * Configures the value of this Response, typically a Map of name/value pairs.
- *
- * @param value if null, the Response will be empty
- * @return a reference to this builder
- */
- public Builder value(Object value) {
- this.value = value;
- return this;
- }
-
- /**
- * Configures a custom ObjectMapper for serializing the value object. Creates a copy of the mapper provided;
- * future mutations of the ObjectMapper made using the provided reference will not affect Response
- * serialization.
- *
- * @param objectMapper if null, a default mapper will be used
- * @return a reference to this builder
- */
- public Builder objectMapper(ObjectMapper objectMapper) {
- this.objectMapper = objectMapper == null ? null : objectMapper.copy();
- return this;
- }
-
- /**
- * Configures the status of this response.
- *
- * @param status if null, SUCCESS will be assumed
- * @return a reference to this builder
- */
- public Builder status(Status status) {
- this.status = status;
- return this;
- }
-
- /**
- * A unique identifier for the custom resource being responded to. By default, the identifier is the name of the
- * Amazon CloudWatch Logs log stream associated with the Lambda function.
- *
- * @param physicalResourceId if null, the default resource ID will be used
- * @return a reference to this builder
- */
- public Builder physicalResourceId(String physicalResourceId) {
- this.physicalResourceId = physicalResourceId;
- return this;
- }
-
- /**
- * Indicates whether to mask the output of the custom resource when it's retrieved by using the Fn::GetAtt
- * function. If set to true, values will be masked with asterisks (*****), except for information stored in the
- * these locations:
- *
- *
The Metadata template section. CloudFormation does not transform, modify, or redact any information
- * included in the Metadata section. See
- * https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/metadata-section-structure.html
- *
The Outputs template section. See
- * https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/outputs-section-structure.html
- *
The Metadata attribute of a resource definition. See
- * https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-metadata.html
- *
- *
- * We strongly recommend not using these mechanisms to include sensitive information, such as passwords or
- * secrets.
- *
- * For more information about using noEcho to mask sensitive information, see
- * https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/best-practices.html#creds
- *
- * By default, this value is false.
- *
- * @param noEcho when true, masks certain output
- * @return a reference to this builder
- */
- public Builder noEcho(boolean noEcho) {
- this.noEcho = noEcho;
- return this;
- }
+ private final JsonNode jsonNode;
+ private final Status status;
+ private final String physicalResourceId;
+ private final boolean noEcho;
- /**
- * Builds a Response object for the value.
- *
- * @return a Response object wrapping the initially provided value.
- */
- public Response build() {
- JsonNode node;
- if (value == null) {
- node = null;
- } else {
- ObjectMapper mapper = objectMapper != null ? objectMapper : CloudFormationResponse.ResponseBody.MAPPER;
- node = mapper.valueToTree(value);
- }
- Status responseStatus = this.status != null ? this.status : Status.SUCCESS;
- return new Response(node, responseStatus, physicalResourceId, noEcho);
- }
+ private Response(JsonNode jsonNode, Status status, String physicalResourceId, boolean noEcho) {
+ this.jsonNode = jsonNode;
+ this.status = status;
+ this.physicalResourceId = physicalResourceId;
+ this.noEcho = noEcho;
}
/**
@@ -140,14 +50,14 @@ public static Builder builder() {
/**
* Creates a failed Response with no physicalResourceId set. Powertools for AWS Lambda (Java) will set the physicalResourceId to the
* Lambda LogStreamName
- *
+ *
* The value returned for a PhysicalResourceId can change custom resource update operations. If the value returned
* is the same, it is considered a normal update. If the value returned is different, AWS CloudFormation recognizes
* the update as a replacement and sends a delete request to the old resource. For more information,
* see AWS::CloudFormation::CustomResource.
*
- * @deprecated this method is not safe. Provide a physicalResourceId.
* @return a failed Response with no value.
+ * @deprecated this method is not safe. Provide a physicalResourceId.
*/
@Deprecated
public static Response failed() {
@@ -173,14 +83,14 @@ public static Response failed(String physicalResourceId) {
/**
* Creates a successful Response with no physicalResourceId set. Powertools for AWS Lambda (Java) will set the physicalResourceId to the
* Lambda LogStreamName
- *
+ *
* The value returned for a PhysicalResourceId can change custom resource update operations. If the value returned
* is the same, it is considered a normal update. If the value returned is different, AWS CloudFormation recognizes
* the update as a replacement and sends a delete request to the old resource. For more information,
* see AWS::CloudFormation::CustomResource.
*
- * @deprecated this method is not safe. Provide a physicalResourceId.
* @return a success Response with no physicalResourceId value.
+ * @deprecated this method is not safe. Provide a physicalResourceId.
*/
@Deprecated
public static Response success() {
@@ -203,18 +113,6 @@ public static Response success(String physicalResourceId) {
return new Response(null, Status.SUCCESS, physicalResourceId, false);
}
- private final JsonNode jsonNode;
- private final Status status;
- private final String physicalResourceId;
- private final boolean noEcho;
-
- private Response(JsonNode jsonNode, Status status, String physicalResourceId, boolean noEcho) {
- this.jsonNode = jsonNode;
- this.status = status;
- this.physicalResourceId = physicalResourceId;
- this.noEcho = noEcho;
- }
-
/**
* Returns a JsonNode representation of the Response.
*
@@ -267,4 +165,119 @@ public String toString() {
.map(entry -> entry.getKey() + " = " + entry.getValue())
.collect(Collectors.joining(",", "[", "]"));
}
+
+ /**
+ * Indicates whether a response is a success or failure.
+ */
+ public enum Status {
+ SUCCESS, FAILED
+ }
+
+ /**
+ * For building Response instances.
+ */
+ public static class Builder {
+ private Object value;
+ private ObjectMapper objectMapper;
+ private Status status;
+ private String physicalResourceId;
+ private boolean noEcho;
+
+ private Builder() {
+ }
+
+ /**
+ * Configures the value of this Response, typically a Map of name/value pairs.
+ *
+ * @param value if null, the Response will be empty
+ * @return a reference to this builder
+ */
+ public Builder value(Object value) {
+ this.value = value;
+ return this;
+ }
+
+ /**
+ * Configures a custom ObjectMapper for serializing the value object. Creates a copy of the mapper provided;
+ * future mutations of the ObjectMapper made using the provided reference will not affect Response
+ * serialization.
+ *
+ * @param objectMapper if null, a default mapper will be used
+ * @return a reference to this builder
+ */
+ public Builder objectMapper(ObjectMapper objectMapper) {
+ this.objectMapper = objectMapper == null ? null : objectMapper.copy();
+ return this;
+ }
+
+ /**
+ * Configures the status of this response.
+ *
+ * @param status if null, SUCCESS will be assumed
+ * @return a reference to this builder
+ */
+ public Builder status(Status status) {
+ this.status = status;
+ return this;
+ }
+
+ /**
+ * A unique identifier for the custom resource being responded to. By default, the identifier is the name of the
+ * Amazon CloudWatch Logs log stream associated with the Lambda function.
+ *
+ * @param physicalResourceId if null, the default resource ID will be used
+ * @return a reference to this builder
+ */
+ public Builder physicalResourceId(String physicalResourceId) {
+ this.physicalResourceId = physicalResourceId;
+ return this;
+ }
+
+ /**
+ * Indicates whether to mask the output of the custom resource when it's retrieved by using the Fn::GetAtt
+ * function. If set to true, values will be masked with asterisks (*****), except for information stored in the
+ * these locations:
+ *
+ *
The Metadata template section. CloudFormation does not transform, modify, or redact any information
+ * included in the Metadata section. See
+ * https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/metadata-section-structure.html
+ *
The Outputs template section. See
+ * https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/outputs-section-structure.html
+ *
The Metadata attribute of a resource definition. See
+ * https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-metadata.html
+ *
+ *
+ * We strongly recommend not using these mechanisms to include sensitive information, such as passwords or
+ * secrets.
+ *
+ * For more information about using noEcho to mask sensitive information, see
+ * https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/best-practices.html#creds
+ *
+ * By default, this value is false.
+ *
+ * @param noEcho when true, masks certain output
+ * @return a reference to this builder
+ */
+ public Builder noEcho(boolean noEcho) {
+ this.noEcho = noEcho;
+ return this;
+ }
+
+ /**
+ * Builds a Response object for the value.
+ *
+ * @return a Response object wrapping the initially provided value.
+ */
+ public Response build() {
+ JsonNode node;
+ if (value == null) {
+ node = null;
+ } else {
+ ObjectMapper mapper = objectMapper != null ? objectMapper : CloudFormationResponse.ResponseBody.MAPPER;
+ node = mapper.valueToTree(value);
+ }
+ Status responseStatus = this.status != null ? this.status : Status.SUCCESS;
+ return new Response(node, responseStatus, physicalResourceId, noEcho);
+ }
+ }
}
diff --git a/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/AbstractCustomResourceHandlerTest.java b/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/AbstractCustomResourceHandlerTest.java
index d68b434d6..1e399ef6f 100644
--- a/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/AbstractCustomResourceHandlerTest.java
+++ b/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/AbstractCustomResourceHandlerTest.java
@@ -1,14 +1,18 @@
-package software.amazon.lambda.powertools.cloudformation;
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
-import com.amazonaws.services.lambda.runtime.Context;
-import com.amazonaws.services.lambda.runtime.events.CloudFormationCustomResourceEvent;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.params.ParameterizedTest;
-import org.junit.jupiter.params.provider.CsvSource;
-import software.amazon.awssdk.http.SdkHttpClient;
-import software.amazon.lambda.powertools.cloudformation.Response.Status;
-
-import java.io.IOException;
+package software.amazon.lambda.powertools.cloudformation;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
@@ -21,95 +25,16 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-public class AbstractCustomResourceHandlerTest {
-
- /**
- * Bare-bones implementation that returns null for abstract methods.
- */
- static class NullCustomResourceHandler extends AbstractCustomResourceHandler {
- NullCustomResourceHandler() {
- }
-
- NullCustomResourceHandler(SdkHttpClient client) {
- super(client);
- }
-
- @Override
- protected Response create(CloudFormationCustomResourceEvent event, Context context) {
- return null;
- }
-
- @Override
- protected Response update(CloudFormationCustomResourceEvent event, Context context) {
- return null;
- }
-
- @Override
- protected Response delete(CloudFormationCustomResourceEvent event, Context context) {
- return null;
- }
- }
-
- /**
- * Uses a mocked CloudFormationResponse to avoid sending actual HTTP requests.
- */
- static class NoOpCustomResourceHandler extends NullCustomResourceHandler {
-
- NoOpCustomResourceHandler() {
- super(mock(SdkHttpClient.class));
- }
-
- @Override
- protected CloudFormationResponse buildResponseClient() {
- return mock(CloudFormationResponse.class);
- }
- }
-
- /**
- * Creates a handler that will expect the Response to be sent with an expected status. Will throw an AssertionError
- * if the method is sent with an unexpected status.
- */
- static class ExpectedStatusResourceHandler extends NoOpCustomResourceHandler {
- private final Status expectedStatus;
-
- ExpectedStatusResourceHandler(Status expectedStatus) {
- this.expectedStatus = expectedStatus;
- }
-
- @Override
- protected CloudFormationResponse buildResponseClient() {
- // create a CloudFormationResponse that fails if invoked with unexpected status
- CloudFormationResponse cfnResponse = mock(CloudFormationResponse.class);
- try {
- when(cfnResponse.send(any(), any(), argThat(resp -> resp.getStatus() != expectedStatus)))
- .thenThrow(new AssertionError("Expected response's status to be " + expectedStatus));
- } catch (IOException | CustomResourceResponseException e) {
- // this should never happen
- throw new RuntimeException("Unexpected mocking exception", e);
- }
- return cfnResponse;
- }
- }
+import com.amazonaws.services.lambda.runtime.Context;
+import com.amazonaws.services.lambda.runtime.events.CloudFormationCustomResourceEvent;
+import java.io.IOException;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.CsvSource;
+import software.amazon.awssdk.http.SdkHttpClient;
+import software.amazon.lambda.powertools.cloudformation.Response.Status;
- /**
- * Always fails to send the response
- */
- static class FailToSendResponseHandler extends NoOpCustomResourceHandler {
- @Override
- protected CloudFormationResponse buildResponseClient() {
- CloudFormationResponse cfnResponse = mock(CloudFormationResponse.class);
- try {
- when(cfnResponse.send(any(), any()))
- .thenThrow(new IOException("Intentional send failure"));
- when(cfnResponse.send(any(), any(), any()))
- .thenThrow(new IOException("Intentional send failure"));
- } catch (IOException | CustomResourceResponseException e) {
- // this should never happen
- throw new RuntimeException("Unexpected mocking exception", e);
- }
- return cfnResponse;
- }
- }
+public class AbstractCustomResourceHandlerTest {
/**
* Builds a valid Event with the provide request type.
@@ -288,4 +213,92 @@ protected Response create(CloudFormationCustomResourceEvent event, Context conte
verify(handler, times(1))
.onSendFailure(eq(event), eq(context), isNull(), any(IOException.class));
}
+
+ /**
+ * Bare-bones implementation that returns null for abstract methods.
+ */
+ static class NullCustomResourceHandler extends AbstractCustomResourceHandler {
+ NullCustomResourceHandler() {
+ }
+
+ NullCustomResourceHandler(SdkHttpClient client) {
+ super(client);
+ }
+
+ @Override
+ protected Response create(CloudFormationCustomResourceEvent event, Context context) {
+ return null;
+ }
+
+ @Override
+ protected Response update(CloudFormationCustomResourceEvent event, Context context) {
+ return null;
+ }
+
+ @Override
+ protected Response delete(CloudFormationCustomResourceEvent event, Context context) {
+ return null;
+ }
+ }
+
+ /**
+ * Uses a mocked CloudFormationResponse to avoid sending actual HTTP requests.
+ */
+ static class NoOpCustomResourceHandler extends NullCustomResourceHandler {
+
+ NoOpCustomResourceHandler() {
+ super(mock(SdkHttpClient.class));
+ }
+
+ @Override
+ protected CloudFormationResponse buildResponseClient() {
+ return mock(CloudFormationResponse.class);
+ }
+ }
+
+ /**
+ * Creates a handler that will expect the Response to be sent with an expected status. Will throw an AssertionError
+ * if the method is sent with an unexpected status.
+ */
+ static class ExpectedStatusResourceHandler extends NoOpCustomResourceHandler {
+ private final Status expectedStatus;
+
+ ExpectedStatusResourceHandler(Status expectedStatus) {
+ this.expectedStatus = expectedStatus;
+ }
+
+ @Override
+ protected CloudFormationResponse buildResponseClient() {
+ // create a CloudFormationResponse that fails if invoked with unexpected status
+ CloudFormationResponse cfnResponse = mock(CloudFormationResponse.class);
+ try {
+ when(cfnResponse.send(any(), any(), argThat(resp -> resp.getStatus() != expectedStatus)))
+ .thenThrow(new AssertionError("Expected response's status to be " + expectedStatus));
+ } catch (IOException | CustomResourceResponseException e) {
+ // this should never happen
+ throw new RuntimeException("Unexpected mocking exception", e);
+ }
+ return cfnResponse;
+ }
+ }
+
+ /**
+ * Always fails to send the response
+ */
+ static class FailToSendResponseHandler extends NoOpCustomResourceHandler {
+ @Override
+ protected CloudFormationResponse buildResponseClient() {
+ CloudFormationResponse cfnResponse = mock(CloudFormationResponse.class);
+ try {
+ when(cfnResponse.send(any(), any()))
+ .thenThrow(new IOException("Intentional send failure"));
+ when(cfnResponse.send(any(), any(), any()))
+ .thenThrow(new IOException("Intentional send failure"));
+ } catch (IOException | CustomResourceResponseException e) {
+ // this should never happen
+ throw new RuntimeException("Unexpected mocking exception", e);
+ }
+ return cfnResponse;
+ }
+ }
}
diff --git a/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/CloudFormationIntegrationTest.java b/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/CloudFormationIntegrationTest.java
index 06463308c..ce45d3afc 100644
--- a/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/CloudFormationIntegrationTest.java
+++ b/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/CloudFormationIntegrationTest.java
@@ -1,5 +1,28 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.cloudformation;
+import static com.github.tomakehurst.wiremock.client.WireMock.matchingJsonPath;
+import static com.github.tomakehurst.wiremock.client.WireMock.ok;
+import static com.github.tomakehurst.wiremock.client.WireMock.put;
+import static com.github.tomakehurst.wiremock.client.WireMock.putRequestedFor;
+import static com.github.tomakehurst.wiremock.client.WireMock.stubFor;
+import static com.github.tomakehurst.wiremock.client.WireMock.urlPathMatching;
+import static com.github.tomakehurst.wiremock.client.WireMock.verify;
+import static org.assertj.core.api.Assertions.assertThat;
+
import com.amazonaws.services.lambda.runtime.ClientContext;
import com.amazonaws.services.lambda.runtime.CognitoIdentity;
import com.amazonaws.services.lambda.runtime.Context;
@@ -7,6 +30,7 @@
import com.amazonaws.services.lambda.runtime.events.CloudFormationCustomResourceEvent;
import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo;
import com.github.tomakehurst.wiremock.junit5.WireMockTest;
+import java.util.UUID;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
@@ -14,20 +38,47 @@
import software.amazon.lambda.powertools.cloudformation.handlers.PhysicalResourceIdSetHandler;
import software.amazon.lambda.powertools.cloudformation.handlers.RuntimeExceptionThrownHandler;
-import java.util.UUID;
-
-import static com.github.tomakehurst.wiremock.client.WireMock.*;
-import static org.assertj.core.api.Assertions.assertThat;
-
@WireMockTest
public class CloudFormationIntegrationTest {
public static final String PHYSICAL_RESOURCE_ID = UUID.randomUUID().toString();
public static final String LOG_STREAM_NAME = "FakeLogStreamName";
+ private static CloudFormationCustomResourceEvent updateEventWithPhysicalResourceId(int httpPort,
+ String physicalResourceId) {
+ CloudFormationCustomResourceEvent.CloudFormationCustomResourceEventBuilder builder = baseEvent(httpPort);
+
+ builder.withPhysicalResourceId(physicalResourceId);
+ builder.withRequestType("Update");
+
+ return builder.build();
+ }
+
+ private static CloudFormationCustomResourceEvent deleteEventWithPhysicalResourceId(int httpPort,
+ String physicalResourceId) {
+ CloudFormationCustomResourceEvent.CloudFormationCustomResourceEventBuilder builder = baseEvent(httpPort);
+
+ builder.withPhysicalResourceId(physicalResourceId);
+ builder.withRequestType("Delete");
+
+ return builder.build();
+ }
+
+ private static CloudFormationCustomResourceEvent.CloudFormationCustomResourceEventBuilder baseEvent(int httpPort) {
+ CloudFormationCustomResourceEvent.CloudFormationCustomResourceEventBuilder builder =
+ CloudFormationCustomResourceEvent.builder()
+ .withResponseUrl("http://localhost:" + httpPort + "/")
+ .withStackId("123")
+ .withRequestId("234")
+ .withLogicalResourceId("345");
+
+ return builder;
+ }
+
@ParameterizedTest
@ValueSource(strings = {"Update", "Delete"})
- void physicalResourceIdTakenFromRequestForUpdateOrDeleteWhenUserSpecifiesNull(String requestType, WireMockRuntimeInfo wmRuntimeInfo) {
+ void physicalResourceIdTakenFromRequestForUpdateOrDeleteWhenUserSpecifiesNull(String requestType,
+ WireMockRuntimeInfo wmRuntimeInfo) {
stubFor(put("/").willReturn(ok()));
NoPhysicalResourceIdSetHandler handler = new NoPhysicalResourceIdSetHandler();
@@ -48,7 +99,8 @@ void physicalResourceIdTakenFromRequestForUpdateOrDeleteWhenUserSpecifiesNull(St
@ParameterizedTest
@ValueSource(strings = {"Update", "Delete"})
- void physicalResourceIdDoesNotChangeWhenRuntimeExceptionThrownWhenUpdatingOrDeleting(String requestType, WireMockRuntimeInfo wmRuntimeInfo) {
+ void physicalResourceIdDoesNotChangeWhenRuntimeExceptionThrownWhenUpdatingOrDeleting(String requestType,
+ WireMockRuntimeInfo wmRuntimeInfo) {
stubFor(put("/").willReturn(ok()));
RuntimeExceptionThrownHandler handler = new RuntimeExceptionThrownHandler();
@@ -68,7 +120,7 @@ void physicalResourceIdDoesNotChangeWhenRuntimeExceptionThrownWhenUpdatingOrDele
}
@Test
- void runtimeExceptionThrownOnCreateSendsLogStreamNameAsPhysicalResourceId(WireMockRuntimeInfo wmRuntimeInfo) {
+ void runtimeExceptionThrownOnCreateSendsLogStreamNameAsPhysicalResourceId(WireMockRuntimeInfo wmRuntimeInfo) {
stubFor(put("/").willReturn(ok()));
RuntimeExceptionThrownHandler handler = new RuntimeExceptionThrownHandler();
@@ -85,7 +137,8 @@ void runtimeExceptionThrownOnCreateSendsLogStreamNameAsPhysicalResourceId(WireMo
@ParameterizedTest
@ValueSource(strings = {"Update", "Delete"})
- void physicalResourceIdSetFromRequestOnUpdateOrDeleteWhenCustomerDoesntProvideAPhysicalResourceId(String requestType, WireMockRuntimeInfo wmRuntimeInfo) {
+ void physicalResourceIdSetFromRequestOnUpdateOrDeleteWhenCustomerDoesntProvideAPhysicalResourceId(
+ String requestType, WireMockRuntimeInfo wmRuntimeInfo) {
stubFor(put("/").willReturn(ok()));
NoPhysicalResourceIdSetHandler handler = new NoPhysicalResourceIdSetHandler();
@@ -160,34 +213,6 @@ void physicalResourceIdReturnedFromFailedToCloudformation(String requestType, Wi
);
}
- private static CloudFormationCustomResourceEvent updateEventWithPhysicalResourceId(int httpPort, String physicalResourceId) {
- CloudFormationCustomResourceEvent.CloudFormationCustomResourceEventBuilder builder = baseEvent(httpPort);
-
- builder.withPhysicalResourceId(physicalResourceId);
- builder.withRequestType("Update");
-
- return builder.build();
- }
-
- private static CloudFormationCustomResourceEvent deleteEventWithPhysicalResourceId(int httpPort, String physicalResourceId) {
- CloudFormationCustomResourceEvent.CloudFormationCustomResourceEventBuilder builder = baseEvent(httpPort);
-
- builder.withPhysicalResourceId(physicalResourceId);
- builder.withRequestType("Delete");
-
- return builder.build();
- }
-
- private static CloudFormationCustomResourceEvent.CloudFormationCustomResourceEventBuilder baseEvent(int httpPort) {
- CloudFormationCustomResourceEvent.CloudFormationCustomResourceEventBuilder builder = CloudFormationCustomResourceEvent.builder()
- .withResponseUrl("http://localhost:" + httpPort + "/")
- .withStackId("123")
- .withRequestId("234")
- .withLogicalResourceId("345");
-
- return builder;
- }
-
private static class FakeContext implements Context {
@Override
public String getAwsRequestId() {
diff --git a/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/CloudFormationResponseTest.java b/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/CloudFormationResponseTest.java
index 64c313695..2e7fbcc0c 100644
--- a/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/CloudFormationResponseTest.java
+++ b/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/CloudFormationResponseTest.java
@@ -1,8 +1,33 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.cloudformation;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.events.CloudFormationCustomResourceEvent;
import com.fasterxml.jackson.databind.node.ObjectNode;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Optional;
import org.junit.jupiter.api.Test;
import software.amazon.awssdk.http.AbortableInputStream;
import software.amazon.awssdk.http.ExecutableHttpRequest;
@@ -13,18 +38,6 @@
import software.amazon.awssdk.utils.StringInputStream;
import software.amazon.lambda.powertools.cloudformation.CloudFormationResponse.ResponseBody;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.Optional;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatThrownBy;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
public class CloudFormationResponseTest {
/**
@@ -44,16 +57,17 @@ static CloudFormationResponse testableCloudFormationResponse() {
SdkHttpClient client = mock(SdkHttpClient.class);
ExecutableHttpRequest executableRequest = mock(ExecutableHttpRequest.class);
- when(client.prepareRequest(any(HttpExecuteRequest.class))).thenAnswer(args -> {
- HttpExecuteRequest request = args.getArgument(0, HttpExecuteRequest.class);
- assertThat(request.contentStreamProvider()).isPresent();
+ when(client.prepareRequest(any(HttpExecuteRequest.class))).thenAnswer(args ->
+ {
+ HttpExecuteRequest request = args.getArgument(0, HttpExecuteRequest.class);
+ assertThat(request.contentStreamProvider()).isPresent();
- InputStream inputStream = request.contentStreamProvider().get().newStream();
- HttpExecuteResponse response = mock(HttpExecuteResponse.class);
- when(response.responseBody()).thenReturn(Optional.of(AbortableInputStream.create(inputStream)));
- when(executableRequest.call()).thenReturn(response);
- return executableRequest;
- });
+ InputStream inputStream = request.contentStreamProvider().get().newStream();
+ HttpExecuteResponse response = mock(HttpExecuteResponse.class);
+ when(response.responseBody()).thenReturn(Optional.of(AbortableInputStream.create(inputStream)));
+ when(executableRequest.call()).thenReturn(response);
+ return executableRequest;
+ });
return new CloudFormationResponse(client);
}
@@ -113,7 +127,8 @@ void customPhysicalResponseId() {
String customPhysicalResourceId = "Custom-Physical-Resource-ID";
ResponseBody body = new ResponseBody(
- event, Response.Status.SUCCESS, customPhysicalResourceId, false, "See the details in CloudWatch Log Stream: " + context.getLogStreamName());
+ event, Response.Status.SUCCESS, customPhysicalResourceId, false,
+ "See the details in CloudWatch Log Stream: " + context.getLogStreamName());
assertThat(body.getPhysicalResourceId()).isEqualTo(customPhysicalResourceId);
}
@@ -122,7 +137,8 @@ void responseBodyWithNullDataNode() {
CloudFormationCustomResourceEvent event = mockCloudFormationCustomResourceEvent();
Context context = mock(Context.class);
- ResponseBody responseBody = new ResponseBody(event, Response.Status.FAILED, null, true, "See the details in CloudWatch Log Stream: " + context.getLogStreamName());
+ ResponseBody responseBody = new ResponseBody(event, Response.Status.FAILED, null, true,
+ "See the details in CloudWatch Log Stream: " + context.getLogStreamName());
String actualJson = responseBody.toObjectNode(null).toString();
String expectedJson = "{" +
@@ -146,7 +162,8 @@ void responseBodyWithNonNullDataNode() {
dataNode.put("foo", "bar");
dataNode.put("baz", 10);
- ResponseBody responseBody = new ResponseBody(event, Response.Status.FAILED, null, true, "See the details in CloudWatch Log Stream: " + context.getLogStreamName());
+ ResponseBody responseBody = new ResponseBody(event, Response.Status.FAILED, null, true,
+ "See the details in CloudWatch Log Stream: " + context.getLogStreamName());
String actualJson = responseBody.toObjectNode(dataNode).toString();
String expectedJson = "{" +
@@ -178,7 +195,8 @@ void customStatus() {
Context context = mock(Context.class);
ResponseBody body = new ResponseBody(
- event, Response.Status.FAILED, null, false, "See the details in CloudWatch Log Stream: " + context.getLogStreamName());
+ event, Response.Status.FAILED, null, false,
+ "See the details in CloudWatch Log Stream: " + context.getLogStreamName());
assertThat(body.getStatus()).isEqualTo("FAILED");
}
@@ -191,7 +209,8 @@ void reasonIncludesLogStreamName() {
when(context.getLogStreamName()).thenReturn(logStreamName);
ResponseBody body = new ResponseBody(
- event, Response.Status.SUCCESS, null, false, "See the details in CloudWatch Log Stream: " + context.getLogStreamName());
+ event, Response.Status.SUCCESS, null, false,
+ "See the details in CloudWatch Log Stream: " + context.getLogStreamName());
assertThat(body.getReason()).contains(logStreamName);
}
diff --git a/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/ResponseTest.java b/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/ResponseTest.java
index e97a1a5ba..37fe73d0f 100644
--- a/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/ResponseTest.java
+++ b/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/ResponseTest.java
@@ -1,29 +1,29 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.cloudformation;
+import static org.assertj.core.api.Assertions.assertThat;
+
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
-import org.junit.jupiter.api.Test;
-
import java.util.HashMap;
import java.util.Map;
-
-import static org.assertj.core.api.Assertions.assertThat;
+import org.junit.jupiter.api.Test;
public class ResponseTest {
- static class DummyBean {
- private final Object propertyWithLongName;
-
- DummyBean(Object propertyWithLongName) {
- this.propertyWithLongName = propertyWithLongName;
- }
-
- @SuppressWarnings("unused")
- public Object getPropertyWithLongName() {
- return propertyWithLongName;
- }
- }
-
@Test
void defaultValues() {
Response response = Response.builder().build();
@@ -173,4 +173,17 @@ void failedFactoryMethod() {
assertThat(response).isNotNull();
assertThat(response.getStatus()).isEqualTo(Response.Status.FAILED);
}
+
+ static class DummyBean {
+ private final Object propertyWithLongName;
+
+ DummyBean(Object propertyWithLongName) {
+ this.propertyWithLongName = propertyWithLongName;
+ }
+
+ @SuppressWarnings("unused")
+ public Object getPropertyWithLongName() {
+ return propertyWithLongName;
+ }
+ }
}
diff --git a/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/handlers/NoPhysicalResourceIdSetHandler.java b/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/handlers/NoPhysicalResourceIdSetHandler.java
index 68d057b54..2bbda309f 100644
--- a/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/handlers/NoPhysicalResourceIdSetHandler.java
+++ b/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/handlers/NoPhysicalResourceIdSetHandler.java
@@ -1,3 +1,17 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.cloudformation.handlers;
import com.amazonaws.services.lambda.runtime.Context;
diff --git a/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/handlers/PhysicalResourceIdSetHandler.java b/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/handlers/PhysicalResourceIdSetHandler.java
index 51f520a3d..c6bd56b76 100644
--- a/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/handlers/PhysicalResourceIdSetHandler.java
+++ b/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/handlers/PhysicalResourceIdSetHandler.java
@@ -1,3 +1,17 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.cloudformation.handlers;
import com.amazonaws.services.lambda.runtime.Context;
@@ -17,16 +31,16 @@ public PhysicalResourceIdSetHandler(String physicalResourceId, boolean callsSucc
@Override
protected Response create(CloudFormationCustomResourceEvent event, Context context) {
- return callsSucceed? Response.success(physicalResourceId) : Response.failed(physicalResourceId);
+ return callsSucceed ? Response.success(physicalResourceId) : Response.failed(physicalResourceId);
}
@Override
protected Response update(CloudFormationCustomResourceEvent event, Context context) {
- return callsSucceed? Response.success(physicalResourceId) : Response.failed(physicalResourceId);
+ return callsSucceed ? Response.success(physicalResourceId) : Response.failed(physicalResourceId);
}
@Override
protected Response delete(CloudFormationCustomResourceEvent event, Context context) {
- return callsSucceed? Response.success(physicalResourceId) : Response.failed(physicalResourceId);
+ return callsSucceed ? Response.success(physicalResourceId) : Response.failed(physicalResourceId);
}
}
diff --git a/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/handlers/RuntimeExceptionThrownHandler.java b/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/handlers/RuntimeExceptionThrownHandler.java
index ee5be77b8..d5a11e895 100644
--- a/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/handlers/RuntimeExceptionThrownHandler.java
+++ b/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/handlers/RuntimeExceptionThrownHandler.java
@@ -1,3 +1,17 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.cloudformation.handlers;
import com.amazonaws.services.lambda.runtime.Context;
diff --git a/powertools-core/pom.xml b/powertools-core/pom.xml
index cf9ad45d1..1adb64af8 100644
--- a/powertools-core/pom.xml
+++ b/powertools-core/pom.xml
@@ -1,4 +1,18 @@
+
+
@@ -89,4 +103,13 @@
+
+
+
+ org.apache.maven.plugins
+ maven-checkstyle-plugin
+
+
+
+
\ No newline at end of file
diff --git a/powertools-core/src/main/java/software/amazon/lambda/powertools/core/internal/LambdaConstants.java b/powertools-core/src/main/java/software/amazon/lambda/powertools/core/internal/LambdaConstants.java
index ea6a6ff44..d0f94260b 100644
--- a/powertools-core/src/main/java/software/amazon/lambda/powertools/core/internal/LambdaConstants.java
+++ b/powertools-core/src/main/java/software/amazon/lambda/powertools/core/internal/LambdaConstants.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2022 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,6 +11,7 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.core.internal;
public class LambdaConstants {
diff --git a/powertools-core/src/main/java/software/amazon/lambda/powertools/core/internal/LambdaHandlerProcessor.java b/powertools-core/src/main/java/software/amazon/lambda/powertools/core/internal/LambdaHandlerProcessor.java
index c7f8b119f..e9e220e41 100644
--- a/powertools-core/src/main/java/software/amazon/lambda/powertools/core/internal/LambdaHandlerProcessor.java
+++ b/powertools-core/src/main/java/software/amazon/lambda/powertools/core/internal/LambdaHandlerProcessor.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,20 +11,20 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.core.internal;
+import static java.util.Optional.empty;
+import static java.util.Optional.of;
+import static software.amazon.lambda.powertools.core.internal.SystemWrapper.getenv;
+
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.lambda.runtime.RequestStreamHandler;
-import org.aspectj.lang.ProceedingJoinPoint;
-
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Optional;
-
-import static java.util.Optional.empty;
-import static java.util.Optional.of;
-import static software.amazon.lambda.powertools.core.internal.SystemWrapper.getenv;
+import org.aspectj.lang.ProceedingJoinPoint;
public final class LambdaHandlerProcessor {
diff --git a/powertools-core/src/main/java/software/amazon/lambda/powertools/core/internal/SystemWrapper.java b/powertools-core/src/main/java/software/amazon/lambda/powertools/core/internal/SystemWrapper.java
index aef64378f..30f72232f 100644
--- a/powertools-core/src/main/java/software/amazon/lambda/powertools/core/internal/SystemWrapper.java
+++ b/powertools-core/src/main/java/software/amazon/lambda/powertools/core/internal/SystemWrapper.java
@@ -1,3 +1,17 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.core.internal;
public class SystemWrapper {
diff --git a/powertools-core/src/test/java/software/amazon/lambda/powertools/core/internal/LambdaHandlerProcessorTest.java b/powertools-core/src/test/java/software/amazon/lambda/powertools/core/internal/LambdaHandlerProcessorTest.java
index 94ad97506..dc8f49580 100644
--- a/powertools-core/src/test/java/software/amazon/lambda/powertools/core/internal/LambdaHandlerProcessorTest.java
+++ b/powertools-core/src/test/java/software/amazon/lambda/powertools/core/internal/LambdaHandlerProcessorTest.java
@@ -1,24 +1,37 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.core.internal;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.mockStatic;
+import static org.mockito.Mockito.when;
+import static software.amazon.lambda.powertools.core.internal.SystemWrapper.getenv;
+
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.lambda.runtime.RequestStreamHandler;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Optional;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.junit.jupiter.api.Test;
import org.mockito.MockedStatic;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.Optional;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.mockStatic;
-import static org.mockito.Mockito.when;
-import static software.amazon.lambda.powertools.core.internal.SystemWrapper.getenv;
-
class LambdaHandlerProcessorTest {
private Signature signature = mock(Signature.class);
@@ -42,7 +55,7 @@ void isHandlerMethod_shouldRecognizeRequestStreamHandler() {
@Test
void isHandlerMethod_shouldReturnFalse() {
- ProceedingJoinPoint pjpMock = mockRequestHandlerPjp(Object.class, new Object[]{});
+ ProceedingJoinPoint pjpMock = mockRequestHandlerPjp(Object.class, new Object[] {});
boolean isHandlerMethod = LambdaHandlerProcessor.isHandlerMethod(pjpMock);
@@ -210,7 +223,8 @@ void isSamLocal() {
void serviceName() {
try (MockedStatic mockedSystemWrapper = mockStatic(SystemWrapper.class)) {
String expectedServiceName = "MyService";
- mockedSystemWrapper.when(() -> getenv(LambdaConstants.POWERTOOLS_SERVICE_NAME)).thenReturn(expectedServiceName);
+ mockedSystemWrapper.when(() -> getenv(LambdaConstants.POWERTOOLS_SERVICE_NAME))
+ .thenReturn(expectedServiceName);
String actualServiceName = LambdaHandlerProcessor.serviceName();
diff --git a/powertools-e2e-tests/handlers/idempotency/src/main/java/software/amazon/lambda/powertools/e2e/Function.java b/powertools-e2e-tests/handlers/idempotency/src/main/java/software/amazon/lambda/powertools/e2e/Function.java
index cc6eec4fa..8c2b5fc58 100644
--- a/powertools-e2e-tests/handlers/idempotency/src/main/java/software/amazon/lambda/powertools/e2e/Function.java
+++ b/powertools-e2e-tests/handlers/idempotency/src/main/java/software/amazon/lambda/powertools/e2e/Function.java
@@ -1,7 +1,26 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.e2e;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
+import java.time.Duration;
+import java.time.Instant;
+import java.time.format.DateTimeFormatter;
+import java.time.temporal.ChronoUnit;
+import java.util.TimeZone;
import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
@@ -10,12 +29,6 @@
import software.amazon.lambda.powertools.idempotency.Idempotent;
import software.amazon.lambda.powertools.idempotency.persistence.DynamoDBPersistenceStore;
-import java.time.Duration;
-import java.time.Instant;
-import java.time.format.DateTimeFormatter;
-import java.time.temporal.ChronoUnit;
-import java.util.TimeZone;
-
public class Function implements RequestHandler {
@@ -42,7 +55,7 @@ public Function(DynamoDbClient client) {
@Idempotent
public String handleRequest(Input input, Context context) {
- DateTimeFormatter dtf = DateTimeFormatter.ISO_DATE_TIME.withZone(TimeZone.getTimeZone("UTC").toZoneId());
+ DateTimeFormatter dtf = DateTimeFormatter.ISO_DATE_TIME.withZone(TimeZone.getTimeZone("UTC").toZoneId());
return dtf.format(Instant.now());
}
}
\ No newline at end of file
diff --git a/powertools-e2e-tests/handlers/idempotency/src/main/java/software/amazon/lambda/powertools/e2e/Input.java b/powertools-e2e-tests/handlers/idempotency/src/main/java/software/amazon/lambda/powertools/e2e/Input.java
index c5c2a121e..e0e4c27c9 100644
--- a/powertools-e2e-tests/handlers/idempotency/src/main/java/software/amazon/lambda/powertools/e2e/Input.java
+++ b/powertools-e2e-tests/handlers/idempotency/src/main/java/software/amazon/lambda/powertools/e2e/Input.java
@@ -1,3 +1,17 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.e2e;
public class Input {
diff --git a/powertools-e2e-tests/handlers/logging/src/main/java/software/amazon/lambda/powertools/e2e/Function.java b/powertools-e2e-tests/handlers/logging/src/main/java/software/amazon/lambda/powertools/e2e/Function.java
index 5a9a87109..62ebabc6e 100644
--- a/powertools-e2e-tests/handlers/logging/src/main/java/software/amazon/lambda/powertools/e2e/Function.java
+++ b/powertools-e2e-tests/handlers/logging/src/main/java/software/amazon/lambda/powertools/e2e/Function.java
@@ -1,3 +1,17 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.e2e;
import com.amazonaws.services.lambda.runtime.Context;
diff --git a/powertools-e2e-tests/handlers/logging/src/main/java/software/amazon/lambda/powertools/e2e/Input.java b/powertools-e2e-tests/handlers/logging/src/main/java/software/amazon/lambda/powertools/e2e/Input.java
index 83afbbd5a..cc449922e 100644
--- a/powertools-e2e-tests/handlers/logging/src/main/java/software/amazon/lambda/powertools/e2e/Input.java
+++ b/powertools-e2e-tests/handlers/logging/src/main/java/software/amazon/lambda/powertools/e2e/Input.java
@@ -1,3 +1,17 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.e2e;
import java.util.Map;
diff --git a/powertools-e2e-tests/handlers/metrics/src/main/java/software/amazon/lambda/powertools/e2e/Function.java b/powertools-e2e-tests/handlers/metrics/src/main/java/software/amazon/lambda/powertools/e2e/Function.java
index e643de9d5..d9cf575c3 100644
--- a/powertools-e2e-tests/handlers/metrics/src/main/java/software/amazon/lambda/powertools/e2e/Function.java
+++ b/powertools-e2e-tests/handlers/metrics/src/main/java/software/amazon/lambda/powertools/e2e/Function.java
@@ -1,3 +1,17 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.e2e;
import com.amazonaws.services.lambda.runtime.Context;
diff --git a/powertools-e2e-tests/handlers/metrics/src/main/java/software/amazon/lambda/powertools/e2e/Input.java b/powertools-e2e-tests/handlers/metrics/src/main/java/software/amazon/lambda/powertools/e2e/Input.java
index 5ff8a7125..18c4eb747 100644
--- a/powertools-e2e-tests/handlers/metrics/src/main/java/software/amazon/lambda/powertools/e2e/Input.java
+++ b/powertools-e2e-tests/handlers/metrics/src/main/java/software/amazon/lambda/powertools/e2e/Input.java
@@ -1,3 +1,17 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.e2e;
import java.util.Map;
@@ -7,6 +21,9 @@ public class Input {
private Map dimensions;
+ public Input() {
+ }
+
public Map getMetrics() {
return metrics;
}
@@ -15,10 +32,6 @@ public void setMetrics(Map metrics) {
this.metrics = metrics;
}
- public Input() {
- }
-
-
public Map getDimensions() {
return dimensions;
}
diff --git a/powertools-e2e-tests/handlers/parameters/src/main/java/software/amazon/lambda/powertools/e2e/Function.java b/powertools-e2e-tests/handlers/parameters/src/main/java/software/amazon/lambda/powertools/e2e/Function.java
index a2d6a1ba6..3a83a1b05 100644
--- a/powertools-e2e-tests/handlers/parameters/src/main/java/software/amazon/lambda/powertools/e2e/Function.java
+++ b/powertools-e2e-tests/handlers/parameters/src/main/java/software/amazon/lambda/powertools/e2e/Function.java
@@ -1,3 +1,17 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.e2e;
import com.amazonaws.services.lambda.runtime.Context;
diff --git a/powertools-e2e-tests/handlers/parameters/src/main/java/software/amazon/lambda/powertools/e2e/Input.java b/powertools-e2e-tests/handlers/parameters/src/main/java/software/amazon/lambda/powertools/e2e/Input.java
index 7ea22143f..b481d25e1 100644
--- a/powertools-e2e-tests/handlers/parameters/src/main/java/software/amazon/lambda/powertools/e2e/Input.java
+++ b/powertools-e2e-tests/handlers/parameters/src/main/java/software/amazon/lambda/powertools/e2e/Input.java
@@ -1,34 +1,47 @@
-package software.amazon.lambda.powertools.e2e;
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
-import java.util.Map;
+package software.amazon.lambda.powertools.e2e;
public class Input {
private String app;
private String environment;
private String key;
- public void setApp(String app) {
- this.app = app;
- }
-
- public void setEnvironment(String environment) {
- this.environment = environment;
- }
-
- public void setKey(String key) {
- this.key = key;
- }
public String getApp() {
return app;
}
+ public void setApp(String app) {
+ this.app = app;
+ }
+
public String getEnvironment() {
return environment;
}
+ public void setEnvironment(String environment) {
+ this.environment = environment;
+ }
+
public String getKey() {
return key;
}
+ public void setKey(String key) {
+ this.key = key;
+ }
+
}
diff --git a/powertools-e2e-tests/handlers/tracing/src/main/java/software/amazon/lambda/powertools/e2e/Function.java b/powertools-e2e-tests/handlers/tracing/src/main/java/software/amazon/lambda/powertools/e2e/Function.java
index f7b2c5e5d..462b7c71d 100644
--- a/powertools-e2e-tests/handlers/tracing/src/main/java/software/amazon/lambda/powertools/e2e/Function.java
+++ b/powertools-e2e-tests/handlers/tracing/src/main/java/software/amazon/lambda/powertools/e2e/Function.java
@@ -1,3 +1,17 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.e2e;
import com.amazonaws.services.lambda.runtime.Context;
@@ -16,13 +30,14 @@ public String handleRequest(Input input, Context context) {
}
String message = buildMessage(input.getMessage(), context.getFunctionName());
- TracingUtils.withSubsegment("internal_stuff", subsegment -> {
- try {
- Thread.sleep(100); // simulate stuff
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- }
- });
+ TracingUtils.withSubsegment("internal_stuff", subsegment ->
+ {
+ try {
+ Thread.sleep(100); // simulate stuff
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ });
return message;
}
diff --git a/powertools-e2e-tests/handlers/tracing/src/main/java/software/amazon/lambda/powertools/e2e/Input.java b/powertools-e2e-tests/handlers/tracing/src/main/java/software/amazon/lambda/powertools/e2e/Input.java
index 29cf618ba..92078d0b3 100644
--- a/powertools-e2e-tests/handlers/tracing/src/main/java/software/amazon/lambda/powertools/e2e/Input.java
+++ b/powertools-e2e-tests/handlers/tracing/src/main/java/software/amazon/lambda/powertools/e2e/Input.java
@@ -1,3 +1,17 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.e2e;
public class Input {
diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml
index 5b6b50511..3e7f0f460 100644
--- a/powertools-e2e-tests/pom.xml
+++ b/powertools-e2e-tests/pom.xml
@@ -1,4 +1,18 @@
+
+
@@ -133,6 +147,10 @@
+
+ org.apache.maven.plugins
+ maven-checkstyle-plugin
+ org.apache.maven.pluginsmaven-compiler-plugin
diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/IdempotencyE2ET.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/IdempotencyE2ET.java
index 6923c3caa..fed823299 100644
--- a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/IdempotencyE2ET.java
+++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/IdempotencyE2ET.java
@@ -1,5 +1,25 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools;
+import static software.amazon.lambda.powertools.testutils.lambda.LambdaInvoker.invokeFunction;
+
+import java.time.Year;
+import java.util.Collections;
+import java.util.UUID;
+import java.util.concurrent.TimeUnit;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
@@ -8,13 +28,6 @@
import software.amazon.lambda.powertools.testutils.Infrastructure;
import software.amazon.lambda.powertools.testutils.lambda.InvocationResult;
-import java.time.Year;
-import java.util.Collections;
-import java.util.UUID;
-import java.util.concurrent.TimeUnit;
-
-import static software.amazon.lambda.powertools.testutils.lambda.LambdaInvoker.invokeFunction;
-
public class IdempotencyE2ET {
private static Infrastructure infrastructure;
private static String functionName;
@@ -34,8 +47,9 @@ public static void setup() {
@AfterAll
public static void tearDown() {
- if (infrastructure != null)
+ if (infrastructure != null) {
infrastructure.destroy();
+ }
}
@Test
diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/LoggingE2ET.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/LoggingE2ET.java
index 15c5eb935..e4b8dccd2 100644
--- a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/LoggingE2ET.java
+++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/LoggingE2ET.java
@@ -1,8 +1,30 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools;
+import static org.assertj.core.api.Assertions.assertThat;
+import static software.amazon.lambda.powertools.testutils.lambda.LambdaInvoker.invokeFunction;
+import static software.amazon.lambda.powertools.testutils.logging.InvocationLogs.Level.INFO;
+
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
+import java.util.UUID;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
@@ -10,15 +32,6 @@
import software.amazon.lambda.powertools.testutils.Infrastructure;
import software.amazon.lambda.powertools.testutils.lambda.InvocationResult;
-import java.util.UUID;
-import java.util.concurrent.TimeUnit;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static software.amazon.lambda.powertools.testutils.lambda.LambdaInvoker.invokeFunction;
-import static software.amazon.lambda.powertools.testutils.logging.InvocationLogs.Level.INFO;
-
public class LoggingE2ET {
private static final ObjectMapper objectMapper = new ObjectMapper();
@@ -33,7 +46,7 @@ public static void setup() {
.testName(LoggingE2ET.class.getSimpleName())
.pathToFunction("logging")
.environmentVariables(
- Stream.of(new String[][]{
+ Stream.of(new String[][] {
{"POWERTOOLS_LOG_LEVEL", "INFO"},
{"POWERTOOLS_SERVICE_NAME", LoggingE2ET.class.getSimpleName()}
})
@@ -44,15 +57,16 @@ public static void setup() {
@AfterAll
public static void tearDown() {
- if (infrastructure != null)
+ if (infrastructure != null) {
infrastructure.destroy();
+ }
}
@Test
public void test_logInfoWithAdditionalKeys() throws JsonProcessingException {
// GIVEN
String orderId = UUID.randomUUID().toString();
- String event = "{\"message\":\"New Order\", \"keys\":{\"orderId\":\"" + orderId +"\"}}";
+ String event = "{\"message\":\"New Order\", \"keys\":{\"orderId\":\"" + orderId + "\"}}";
// WHEN
InvocationResult invocationResult1 = invokeFunction(functionName, event);
diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/MetricsE2ET.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/MetricsE2ET.java
index 4b8d7ea5a..32965b3be 100644
--- a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/MetricsE2ET.java
+++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/MetricsE2ET.java
@@ -1,12 +1,21 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools;
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.Timeout;
-import software.amazon.lambda.powertools.testutils.Infrastructure;
-import software.amazon.lambda.powertools.testutils.lambda.InvocationResult;
-import software.amazon.lambda.powertools.testutils.metrics.MetricsFetcher;
+import static org.assertj.core.api.Assertions.assertThat;
+import static software.amazon.lambda.powertools.testutils.lambda.LambdaInvoker.invokeFunction;
import java.util.Collections;
import java.util.List;
@@ -14,13 +23,17 @@
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.Stream;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static software.amazon.lambda.powertools.testutils.lambda.LambdaInvoker.invokeFunction;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.Timeout;
+import software.amazon.lambda.powertools.testutils.Infrastructure;
+import software.amazon.lambda.powertools.testutils.lambda.InvocationResult;
+import software.amazon.lambda.powertools.testutils.metrics.MetricsFetcher;
public class MetricsE2ET {
- private static final String namespace = "MetricsE2ENamespace_"+UUID.randomUUID();
- private static final String service = "MetricsE2EService_"+UUID.randomUUID();
+ private static final String namespace = "MetricsE2ENamespace_" + UUID.randomUUID();
+ private static final String service = "MetricsE2EService_" + UUID.randomUUID();
private static Infrastructure infrastructure;
private static String functionName;
@@ -31,7 +44,7 @@ public static void setup() {
.testName(MetricsE2ET.class.getSimpleName())
.pathToFunction("metrics")
.environmentVariables(
- Stream.of(new String[][]{
+ Stream.of(new String[][] {
{"POWERTOOLS_METRICS_NAMESPACE", namespace},
{"POWERTOOLS_SERVICE_NAME", service}
})
@@ -42,32 +55,44 @@ public static void setup() {
@AfterAll
public static void tearDown() {
- if (infrastructure != null)
+ if (infrastructure != null) {
infrastructure.destroy();
+ }
}
@Test
- public void test_recordMetrics() {
+ public void test_recordMetrics() {
// GIVEN
- String event1 = "{ \"metrics\": {\"orders\": 1, \"products\": 4}, \"dimensions\": { \"Environment\": \"test\"} }";
+ String event1 =
+ "{ \"metrics\": {\"orders\": 1, \"products\": 4}, \"dimensions\": { \"Environment\": \"test\"} }";
// WHEN
InvocationResult invocationResult = invokeFunction(functionName, event1);
// THEN
MetricsFetcher metricsFetcher = new MetricsFetcher();
- List coldStart = metricsFetcher.fetchMetrics(invocationResult.getStart(), invocationResult.getEnd(), 60, namespace, "ColdStart", Stream.of(new String[][]{
- {"FunctionName", functionName},
- {"Service", service}}
- ).collect(Collectors.toMap(data -> data[0], data -> data[1])));
+ List coldStart =
+ metricsFetcher.fetchMetrics(invocationResult.getStart(), invocationResult.getEnd(), 60, namespace,
+ "ColdStart", Stream.of(new String[][] {
+ {"FunctionName", functionName},
+ {"Service", service}}
+ ).collect(Collectors.toMap(data -> data[0], data -> data[1])));
assertThat(coldStart.get(0)).isEqualTo(1);
- List orderMetrics = metricsFetcher.fetchMetrics(invocationResult.getStart(), invocationResult.getEnd(), 60, namespace, "orders", Collections.singletonMap("Environment", "test"));
+ List orderMetrics =
+ metricsFetcher.fetchMetrics(invocationResult.getStart(), invocationResult.getEnd(), 60, namespace,
+ "orders", Collections.singletonMap("Environment", "test"));
assertThat(orderMetrics.get(0)).isEqualTo(1);
- List productMetrics = metricsFetcher.fetchMetrics(invocationResult.getStart(), invocationResult.getEnd(), 60, namespace, "products", Collections.singletonMap("Environment", "test"));
+ List productMetrics =
+ metricsFetcher.fetchMetrics(invocationResult.getStart(), invocationResult.getEnd(), 60, namespace,
+ "products", Collections.singletonMap("Environment", "test"));
assertThat(productMetrics.get(0)).isEqualTo(4);
- orderMetrics = metricsFetcher.fetchMetrics(invocationResult.getStart(), invocationResult.getEnd(), 60, namespace, "orders", Collections.singletonMap("Service", service));
+ orderMetrics =
+ metricsFetcher.fetchMetrics(invocationResult.getStart(), invocationResult.getEnd(), 60, namespace,
+ "orders", Collections.singletonMap("Service", service));
assertThat(orderMetrics.get(0)).isEqualTo(1);
- productMetrics = metricsFetcher.fetchMetrics(invocationResult.getStart(), invocationResult.getEnd(), 60, namespace, "products", Collections.singletonMap("Service", service));
+ productMetrics =
+ metricsFetcher.fetchMetrics(invocationResult.getStart(), invocationResult.getEnd(), 60, namespace,
+ "products", Collections.singletonMap("Service", service));
assertThat(productMetrics.get(0)).isEqualTo(4);
}
}
diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/ParametersE2ET.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/ParametersE2ET.java
index dbebe721f..678321a99 100644
--- a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/ParametersE2ET.java
+++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/ParametersE2ET.java
@@ -1,9 +1,21 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools;
-import org.junit.jupiter.api.*;
-import software.amazon.lambda.powertools.testutils.AppConfig;
-import software.amazon.lambda.powertools.testutils.Infrastructure;
-import software.amazon.lambda.powertools.testutils.lambda.InvocationResult;
+import static org.assertj.core.api.Assertions.assertThat;
+import static software.amazon.lambda.powertools.testutils.lambda.LambdaInvoker.invokeFunction;
import java.util.HashMap;
import java.util.Map;
@@ -11,23 +23,29 @@
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.Stream;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static software.amazon.lambda.powertools.testutils.lambda.LambdaInvoker.invokeFunction;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestInstance;
+import org.junit.jupiter.api.Timeout;
+import software.amazon.lambda.powertools.testutils.AppConfig;
+import software.amazon.lambda.powertools.testutils.Infrastructure;
+import software.amazon.lambda.powertools.testutils.lambda.InvocationResult;
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class ParametersE2ET {
+ private final AppConfig appConfig;
private Infrastructure infrastructure;
private String functionName;
- private final AppConfig appConfig;
public ParametersE2ET() {
String appName = UUID.randomUUID().toString();
- Map params = new HashMap<>();
+ Map params = new HashMap<>();
params.put("key1", "value1");
params.put("key2", "value2");
appConfig = new AppConfig(appName, "e2etest", params);
}
+
@BeforeAll
@Timeout(value = 5, unit = TimeUnit.MINUTES)
public void setup() {
@@ -36,7 +54,7 @@ public void setup() {
.pathToFunction("parameters")
.appConfig(appConfig)
.environmentVariables(
- Stream.of(new String[][]{
+ Stream.of(new String[][] {
{"POWERTOOLS_LOG_LEVEL", "INFO"},
{"POWERTOOLS_SERVICE_NAME", ParametersE2ET.class.getSimpleName()}
})
@@ -47,13 +65,14 @@ public void setup() {
@AfterAll
public void tearDown() {
- if (infrastructure != null)
+ if (infrastructure != null) {
infrastructure.destroy();
+ }
}
@Test
public void test_getAppConfigValue() {
- for (Map.EntryconfigKey: appConfig.getConfigurationValues().entrySet()) {
+ for (Map.Entry configKey : appConfig.getConfigurationValues().entrySet()) {
// Arrange
String event1 = "{" +
diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/TracingE2ET.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/TracingE2ET.java
index 1f002fe60..cd4a21df4 100644
--- a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/TracingE2ET.java
+++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/TracingE2ET.java
@@ -1,5 +1,26 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools;
+import static org.assertj.core.api.Assertions.assertThat;
+import static software.amazon.lambda.powertools.testutils.lambda.LambdaInvoker.invokeFunction;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.TimeUnit;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
@@ -10,16 +31,9 @@
import software.amazon.lambda.powertools.testutils.tracing.Trace;
import software.amazon.lambda.powertools.testutils.tracing.TraceFetcher;
-import java.util.Collections;
-import java.util.Map;
-import java.util.UUID;
-import java.util.concurrent.TimeUnit;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static software.amazon.lambda.powertools.testutils.lambda.LambdaInvoker.invokeFunction;
-
public class TracingE2ET {
- private static final String service = "TracingE2EService_" + UUID.randomUUID(); // "TracingE2EService_e479fb27-422b-4107-9f8c-086c62e1cd12";
+ private static final String service = "TracingE2EService_" + UUID.randomUUID();
+ // "TracingE2EService_e479fb27-422b-4107-9f8c-086c62e1cd12";
private static Infrastructure infrastructure;
private static String functionName;
@@ -38,8 +52,9 @@ public static void setup() {
@AfterAll
public static void tearDown() {
- if (infrastructure != null)
+ if (infrastructure != null) {
infrastructure.destroy();
+ }
}
@Test
@@ -77,7 +92,8 @@ public void test_tracing() {
sub = handleRequest.getSubsegments().get(1);
assertThat(sub.getName()).isIn("## internal_stuff", "## buildMessage");
- SubSegment buildMessage = handleRequest.getSubsegments().stream().filter(subSegment -> subSegment.getName().equals("## buildMessage")).findFirst().orElse(null);
+ SubSegment buildMessage = handleRequest.getSubsegments().stream()
+ .filter(subSegment -> subSegment.getName().equals("## buildMessage")).findFirst().orElse(null);
assertThat(buildMessage).isNotNull();
assertThat(buildMessage.getAnnotations()).hasSize(1);
assertThat(buildMessage.getAnnotations().get("message")).isEqualTo(message);
diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/AppConfig.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/AppConfig.java
index c87f4ac48..4229af040 100644
--- a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/AppConfig.java
+++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/AppConfig.java
@@ -1,12 +1,25 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.testutils;
-import java.util.HashMap;
import java.util.Map;
/**
* Defines configuration used to setup an AppConfig
* deployment when the infrastructure is rolled out.
- *
+ *
* All fields are non-nullable.
*/
public class AppConfig {
diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/Infrastructure.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/Infrastructure.java
index 59035af7c..62bb018f4 100644
--- a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/Infrastructure.java
+++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/Infrastructure.java
@@ -1,23 +1,56 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.testutils;
+import static java.util.Collections.singletonList;
+
import com.fasterxml.jackson.databind.JsonNode;
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.UUID;
+import java.util.stream.Collectors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.yaml.snakeyaml.Yaml;
+import software.amazon.awscdk.App;
+import software.amazon.awscdk.BundlingOptions;
+import software.amazon.awscdk.BundlingOutput;
+import software.amazon.awscdk.DockerVolume;
+import software.amazon.awscdk.Duration;
+import software.amazon.awscdk.RemovalPolicy;
import software.amazon.awscdk.Stack;
-import software.amazon.awscdk.*;
import software.amazon.awscdk.cxapi.CloudAssembly;
-import software.amazon.awscdk.services.appconfig.*;
+import software.amazon.awscdk.services.appconfig.CfnApplication;
+import software.amazon.awscdk.services.appconfig.CfnConfigurationProfile;
+import software.amazon.awscdk.services.appconfig.CfnDeployment;
+import software.amazon.awscdk.services.appconfig.CfnDeploymentStrategy;
+import software.amazon.awscdk.services.appconfig.CfnEnvironment;
+import software.amazon.awscdk.services.appconfig.CfnHostedConfigurationVersion;
import software.amazon.awscdk.services.dynamodb.Attribute;
import software.amazon.awscdk.services.dynamodb.AttributeType;
import software.amazon.awscdk.services.dynamodb.BillingMode;
import software.amazon.awscdk.services.dynamodb.Table;
-import software.amazon.awscdk.services.groundstation.CfnConfig;
import software.amazon.awscdk.services.iam.PolicyStatement;
-import software.amazon.awscdk.services.iam.ServicePrincipal;
import software.amazon.awscdk.services.lambda.Code;
import software.amazon.awscdk.services.lambda.Function;
-import software.amazon.awscdk.services.lambda.Permission;
import software.amazon.awscdk.services.lambda.Tracing;
import software.amazon.awscdk.services.logs.LogGroup;
import software.amazon.awscdk.services.logs.RetentionDays;
@@ -27,7 +60,12 @@
import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.cloudformation.CloudFormationClient;
-import software.amazon.awssdk.services.cloudformation.model.*;
+import software.amazon.awssdk.services.cloudformation.model.Capability;
+import software.amazon.awssdk.services.cloudformation.model.CreateStackRequest;
+import software.amazon.awssdk.services.cloudformation.model.DeleteStackRequest;
+import software.amazon.awssdk.services.cloudformation.model.DescribeStacksRequest;
+import software.amazon.awssdk.services.cloudformation.model.DescribeStacksResponse;
+import software.amazon.awssdk.services.cloudformation.model.OnFailure;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.ListObjectsV2Request;
import software.amazon.awssdk.services.s3.model.ListObjectsV2Response;
@@ -36,14 +74,6 @@
import software.amazon.awssdk.utils.StringUtils;
import software.amazon.lambda.powertools.utilities.JsonConfig;
-import java.io.File;
-import java.io.IOException;
-import java.nio.file.Paths;
-import java.util.*;
-import java.util.stream.Collectors;
-
-import static java.util.Collections.singletonList;
-
/**
* This class is in charge of bootstrapping the infrastructure for the tests.
*
@@ -71,12 +101,10 @@ public class Infrastructure {
private final String account;
private final String idempotencyTable;
private final AppConfig appConfig;
-
-
+ private final SdkHttpClient httpClient;
private String functionName;
private Object cfnTemplate;
private String cfnAssetDirectory;
- private final SdkHttpClient httpClient;
private Infrastructure(Builder builder) {
this.stackName = builder.stackName;
@@ -110,8 +138,13 @@ private Infrastructure(Builder builder) {
.build();
}
+ public static Builder builder() {
+ return new Builder();
+ }
+
/**
* Use the CloudFormation SDK to create the stack
+ *
* @return the name of the function deployed part of the stack
*/
public String deploy() {
@@ -124,9 +157,11 @@ public String deploy() {
.onFailure(OnFailure.ROLLBACK)
.capabilities(Capability.CAPABILITY_IAM)
.build());
- WaiterResponse waiterResponse = cfn.waiter().waitUntilStackCreateComplete(DescribeStacksRequest.builder().stackName(stackName).build());
+ WaiterResponse waiterResponse =
+ cfn.waiter().waitUntilStackCreateComplete(DescribeStacksRequest.builder().stackName(stackName).build());
if (waiterResponse.matched().response().isPresent()) {
- LOG.info("Stack " + waiterResponse.matched().response().get().stacks().get(0).stackName() + " successfully deployed");
+ LOG.info("Stack " + waiterResponse.matched().response().get().stacks().get(0).stackName() +
+ " successfully deployed");
} else {
throw new RuntimeException("Failed to create stack");
}
@@ -141,93 +176,9 @@ public void destroy() {
cfn.deleteStack(DeleteStackRequest.builder().stackName(stackName).build());
}
- public static Builder builder() {
- return new Builder();
- }
-
- public static class Builder {
- public long timeoutInSeconds = 30;
- public String pathToFunction;
- public String testName;
- public AppConfig appConfig;
- private String stackName;
- private boolean tracing = false;
- private JavaRuntime runtime;
- private Map environmentVariables = new HashMap<>();
- private String idemPotencyTable;
-
- private Builder() {
- getJavaRuntime();
- }
-
- /**
- * Retrieve the java runtime to use for the lambda function.
- */
- private void getJavaRuntime() {
- String javaVersion = System.getenv("JAVA_VERSION"); // must be set in GitHub actions
- if (javaVersion == null) {
- throw new IllegalArgumentException("JAVA_VERSION is not set");
- }
- if (javaVersion.startsWith("8")) {
- runtime = JavaRuntime.JAVA8AL2;
- } else if (javaVersion.startsWith("11")) {
- runtime = JavaRuntime.JAVA11;
- } else if (javaVersion.startsWith("17")) {
- runtime = JavaRuntime.JAVA17;
- } else {
- throw new IllegalArgumentException("Unsupported Java version " + javaVersion);
- }
- LOG.debug("Java Version set to {}, using runtime {}", javaVersion, runtime.getRuntime());
- }
-
- public Infrastructure build() {
- Objects.requireNonNull(testName, "testName must not be null");
-
- String uuid = UUID.randomUUID().toString().replace("-", "").substring(0, 12);
- stackName = testName + "-" + uuid;
-
- Objects.requireNonNull(pathToFunction, "pathToFunction must not be null");
- return new Infrastructure(this);
- }
-
- public Builder testName(String testName) {
- this.testName = testName;
- return this;
- }
-
- public Builder pathToFunction(String pathToFunction) {
- this.pathToFunction = pathToFunction;
- return this;
- }
-
- public Builder tracing(boolean tracing) {
- this.tracing = tracing;
- return this;
- }
-
- public Builder idempotencyTable(String tableName) {
- this.idemPotencyTable = tableName;
- return this;
- }
-
- public Builder appConfig(AppConfig app) {
- this.appConfig = app;
- return this;
- }
-
- public Builder environmentVariables(Map environmentVariables) {
- this.environmentVariables = environmentVariables;
- return this;
- }
-
- public Builder timeoutInSeconds(long timeoutInSeconds) {
- this.timeoutInSeconds = timeoutInSeconds;
- return this;
- }
- }
-
/**
* Build the CDK Stack containing the required resources (Lambda function, LogGroup, DDB Table)
+ *
* @return the CDK stack
*/
private Stack createStackWithLambda() {
@@ -259,7 +210,8 @@ private Stack createStackWithLambda() {
functionName = stackName + "-function";
- LOG.debug("Building Lambda function with command "+ packagingInstruction.stream().collect(Collectors.joining(" ", "[", "]")));
+ LOG.debug("Building Lambda function with command " +
+ packagingInstruction.stream().collect(Collectors.joining(" ", "[", "]")));
Function function = Function.Builder
.create(stack, functionName)
.code(Code.fromAsset("handlers/", AssetOptions.builder()
@@ -297,10 +249,10 @@ private Stack createStackWithLambda() {
}
if (appConfig != null) {
- CfnApplication app = CfnApplication.Builder
- .create(stack, "AppConfigApp")
- .name(appConfig.getApplication())
- .build();
+ CfnApplication app = CfnApplication.Builder
+ .create(stack, "AppConfigApp")
+ .name(appConfig.getApplication())
+ .build();
CfnEnvironment environment = CfnEnvironment.Builder
.create(stack, "AppConfigEnvironment")
@@ -327,7 +279,7 @@ private Stack createStackWithLambda() {
);
CfnDeployment previousDeployment = null;
- for (Map.Entry entry : appConfig.getConfigurationValues().entrySet()) {
+ for (Map.Entry entry : appConfig.getConfigurationValues().entrySet()) {
CfnConfigurationProfile configProfile = CfnConfigurationProfile.Builder
.create(stack, "AppConfigProfileFor" + entry.getKey())
.applicationId(app.getRef())
@@ -376,43 +328,133 @@ private void synthesize() {
*/
private void uploadAssets() {
Map assets = findAssets();
- assets.forEach((objectKey, asset) -> {
- if (!asset.assetPath.endsWith(".jar")) {
- return;
- }
- ListObjectsV2Response objects = s3.listObjectsV2(ListObjectsV2Request.builder().bucket(asset.bucketName).build());
- if (objects.contents().stream().anyMatch(o -> o.key().equals(objectKey))) {
- LOG.debug("Asset already exists, skipping");
- return;
- }
- LOG.info("Uploading asset " + objectKey + " to " + asset.bucketName);
- s3.putObject(PutObjectRequest.builder().bucket(asset.bucketName).key(objectKey).build(), Paths.get(cfnAssetDirectory, asset.assetPath));
- });
+ assets.forEach((objectKey, asset) ->
+ {
+ if (!asset.assetPath.endsWith(".jar")) {
+ return;
+ }
+ ListObjectsV2Response objects =
+ s3.listObjectsV2(ListObjectsV2Request.builder().bucket(asset.bucketName).build());
+ if (objects.contents().stream().anyMatch(o -> o.key().equals(objectKey))) {
+ LOG.debug("Asset already exists, skipping");
+ return;
+ }
+ LOG.info("Uploading asset " + objectKey + " to " + asset.bucketName);
+ s3.putObject(PutObjectRequest.builder().bucket(asset.bucketName).key(objectKey).build(),
+ Paths.get(cfnAssetDirectory, asset.assetPath));
+ });
}
/**
* Reading the cdk assets.json file to retrieve the list of assets to push to S3
+ *
* @return a map of assets
*/
private Map findAssets() {
Map assets = new HashMap<>();
try {
- JsonNode jsonNode = JsonConfig.get().getObjectMapper().readTree(new File(cfnAssetDirectory, stackName + ".assets.json"));
+ JsonNode jsonNode = JsonConfig.get().getObjectMapper()
+ .readTree(new File(cfnAssetDirectory, stackName + ".assets.json"));
JsonNode files = jsonNode.get("files");
- files.iterator().forEachRemaining(file -> {
- String assetPath = file.get("source").get("path").asText();
- String assetPackaging = file.get("source").get("packaging").asText();
- String bucketName = file.get("destinations").get("current_account-current_region").get("bucketName").asText();
- String objectKey = file.get("destinations").get("current_account-current_region").get("objectKey").asText();
- Asset asset = new Asset(assetPath, assetPackaging, bucketName.replace("${AWS::AccountId}", account).replace("${AWS::Region}", region.toString()));
- assets.put(objectKey, asset);
- });
+ files.iterator().forEachRemaining(file ->
+ {
+ String assetPath = file.get("source").get("path").asText();
+ String assetPackaging = file.get("source").get("packaging").asText();
+ String bucketName =
+ file.get("destinations").get("current_account-current_region").get("bucketName").asText();
+ String objectKey =
+ file.get("destinations").get("current_account-current_region").get("objectKey").asText();
+ Asset asset = new Asset(assetPath, assetPackaging, bucketName.replace("${AWS::AccountId}", account)
+ .replace("${AWS::Region}", region.toString()));
+ assets.put(objectKey, asset);
+ });
} catch (IOException e) {
throw new RuntimeException(e);
}
return assets;
}
+ public static class Builder {
+ public long timeoutInSeconds = 30;
+ public String pathToFunction;
+ public String testName;
+ public AppConfig appConfig;
+ private String stackName;
+ private boolean tracing = false;
+ private JavaRuntime runtime;
+ private Map environmentVariables = new HashMap<>();
+ private String idemPotencyTable;
+
+ private Builder() {
+ getJavaRuntime();
+ }
+
+ /**
+ * Retrieve the java runtime to use for the lambda function.
+ */
+ private void getJavaRuntime() {
+ String javaVersion = System.getenv("JAVA_VERSION"); // must be set in GitHub actions
+ if (javaVersion == null) {
+ throw new IllegalArgumentException("JAVA_VERSION is not set");
+ }
+ if (javaVersion.startsWith("8")) {
+ runtime = JavaRuntime.JAVA8AL2;
+ } else if (javaVersion.startsWith("11")) {
+ runtime = JavaRuntime.JAVA11;
+ } else if (javaVersion.startsWith("17")) {
+ runtime = JavaRuntime.JAVA17;
+ } else {
+ throw new IllegalArgumentException("Unsupported Java version " + javaVersion);
+ }
+ LOG.debug("Java Version set to {}, using runtime {}", javaVersion, runtime.getRuntime());
+ }
+
+ public Infrastructure build() {
+ Objects.requireNonNull(testName, "testName must not be null");
+
+ String uuid = UUID.randomUUID().toString().replace("-", "").substring(0, 12);
+ stackName = testName + "-" + uuid;
+
+ Objects.requireNonNull(pathToFunction, "pathToFunction must not be null");
+ return new Infrastructure(this);
+ }
+
+ public Builder testName(String testName) {
+ this.testName = testName;
+ return this;
+ }
+
+ public Builder pathToFunction(String pathToFunction) {
+ this.pathToFunction = pathToFunction;
+ return this;
+ }
+
+ public Builder tracing(boolean tracing) {
+ this.tracing = tracing;
+ return this;
+ }
+
+ public Builder idempotencyTable(String tableName) {
+ this.idemPotencyTable = tableName;
+ return this;
+ }
+
+ public Builder appConfig(AppConfig app) {
+ this.appConfig = app;
+ return this;
+ }
+
+ public Builder environmentVariables(Map environmentVariables) {
+ this.environmentVariables = environmentVariables;
+ return this;
+ }
+
+ public Builder timeoutInSeconds(long timeoutInSeconds) {
+ this.timeoutInSeconds = timeoutInSeconds;
+ return this;
+ }
+ }
+
private static class Asset {
private final String assetPath;
private final String assetPackaging;
diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/JavaRuntime.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/JavaRuntime.java
index dce97538f..c50fcab84 100644
--- a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/JavaRuntime.java
+++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/JavaRuntime.java
@@ -1,3 +1,17 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.testutils;
import software.amazon.awscdk.services.lambda.Runtime;
diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/lambda/InvocationResult.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/lambda/InvocationResult.java
index 168fec71b..b91840b8e 100644
--- a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/lambda/InvocationResult.java
+++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/lambda/InvocationResult.java
@@ -1,10 +1,23 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.testutils.lambda;
+import java.time.Instant;
import software.amazon.awssdk.services.lambda.model.InvokeResponse;
import software.amazon.lambda.powertools.testutils.logging.InvocationLogs;
-import java.time.Instant;
-
public class InvocationResult {
private final InvocationLogs logs;
@@ -21,6 +34,7 @@ public InvocationResult(InvokeResponse response, Instant start, Instant end) {
this.start = start;
this.end = end;
}
+
public InvocationLogs getLogs() {
return logs;
}
diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/lambda/LambdaInvoker.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/lambda/LambdaInvoker.java
index ecde1042e..cf45076bf 100644
--- a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/lambda/LambdaInvoker.java
+++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/lambda/LambdaInvoker.java
@@ -1,5 +1,23 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.testutils.lambda;
+import static java.time.temporal.ChronoUnit.MINUTES;
+
+import java.time.Clock;
+import java.time.Instant;
import software.amazon.awssdk.core.SdkBytes;
import software.amazon.awssdk.http.SdkHttpClient;
import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient;
@@ -9,18 +27,13 @@
import software.amazon.awssdk.services.lambda.model.InvokeResponse;
import software.amazon.awssdk.services.lambda.model.LogType;
-import java.time.Clock;
-import java.time.Instant;
-
-import static java.time.temporal.ChronoUnit.MINUTES;
-
public class LambdaInvoker {
private static final SdkHttpClient httpClient = UrlConnectionHttpClient.builder().build();
private static final Region region = Region.of(System.getProperty("AWS_DEFAULT_REGION", "eu-west-1"));
private static final LambdaClient lambda = LambdaClient.builder()
.httpClient(httpClient)
- .region(region)
- .build();
+ .region(region)
+ .build();
public static InvocationResult invokeFunction(String functionName, String input) {
SdkBytes payload = SdkBytes.fromUtf8String(input);
diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/logging/InvocationLogs.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/logging/InvocationLogs.java
index 1ae1cfad7..cd63d308a 100644
--- a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/logging/InvocationLogs.java
+++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/logging/InvocationLogs.java
@@ -1,3 +1,17 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.testutils.logging;
import java.nio.charset.StandardCharsets;
@@ -35,6 +49,7 @@ public String[] getAllLogs() {
/**
* Return only logs from function, exclude START, END, and REPORT and other elements generated by Lambda service
+ *
* @return only logs generated by the function
*/
public String[] getFunctionLogs() {
@@ -44,7 +59,8 @@ public String[] getFunctionLogs() {
public String[] getFunctionLogs(Level level) {
String[] filtered = getFunctionLogs();
- return Arrays.stream(filtered).filter(log -> log.contains("\"level\":\""+level.getLevel()+"\"")).toArray(String[]::new);
+ return Arrays.stream(filtered).filter(log -> log.contains("\"level\":\"" + level.getLevel() + "\""))
+ .toArray(String[]::new);
}
public enum Level {
diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/metrics/MetricsFetcher.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/metrics/MetricsFetcher.java
index eb3cd63a4..349a9acc1 100644
--- a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/metrics/MetricsFetcher.java
+++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/metrics/MetricsFetcher.java
@@ -1,25 +1,44 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.testutils.metrics;
+import static java.time.Duration.ofSeconds;
+
import com.evanlennick.retry4j.CallExecutor;
import com.evanlennick.retry4j.CallExecutorBuilder;
import com.evanlennick.retry4j.Status;
import com.evanlennick.retry4j.config.RetryConfig;
import com.evanlennick.retry4j.config.RetryConfigBuilder;
+import java.time.Instant;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Callable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import software.amazon.awssdk.http.SdkHttpClient;
import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.cloudwatch.CloudWatchClient;
-import software.amazon.awssdk.services.cloudwatch.model.*;
-
-import java.time.Instant;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.Callable;
-
-import static java.time.Duration.ofSeconds;
+import software.amazon.awssdk.services.cloudwatch.model.Dimension;
+import software.amazon.awssdk.services.cloudwatch.model.GetMetricDataRequest;
+import software.amazon.awssdk.services.cloudwatch.model.GetMetricDataResponse;
+import software.amazon.awssdk.services.cloudwatch.model.Metric;
+import software.amazon.awssdk.services.cloudwatch.model.MetricDataQuery;
+import software.amazon.awssdk.services.cloudwatch.model.MetricStat;
+import software.amazon.awssdk.services.cloudwatch.model.StandardUnit;
/**
* Class in charge of retrieving the actual metrics of a Lambda execution on CloudWatch
@@ -37,6 +56,7 @@ public class MetricsFetcher {
/**
* Retrieve the metric values from start to end. Different parameters are required (see {@link CloudWatchClient#getMetricData} for more info).
* Use a retry mechanism as metrics may not be available instantaneously after a function runs.
+ *
* @param start
* @param end
* @param period
@@ -45,37 +65,41 @@ public class MetricsFetcher {
* @param dimensions
* @return
*/
- public List fetchMetrics(Instant start, Instant end, int period, String namespace, String metricName, Map dimensions) {
+ public List fetchMetrics(Instant start, Instant end, int period, String namespace, String metricName,
+ Map dimensions) {
List dimensionsList = new ArrayList<>();
- if (dimensions != null)
+ if (dimensions != null) {
dimensions.forEach((key, value) -> dimensionsList.add(Dimension.builder().name(key).value(value).build()));
+ }
- Callable> callable = () -> {
- LOG.debug("Get Metrics for namespace {}, start {}, end {}, metric {}, dimensions {}", namespace, start, end, metricName, dimensionsList);
- GetMetricDataResponse metricData = cloudwatch.getMetricData(GetMetricDataRequest.builder()
- .startTime(start)
- .endTime(end)
- .metricDataQueries(MetricDataQuery.builder()
- .id(metricName.toLowerCase())
- .metricStat(MetricStat.builder()
- .unit(StandardUnit.COUNT)
- .metric(Metric.builder()
- .namespace(namespace)
- .metricName(metricName)
- .dimensions(dimensionsList)
- .build())
- .period(period)
- .stat("Sum")
- .build())
- .returnData(true)
- .build())
- .build());
- List values = metricData.metricDataResults().get(0).values();
- if (values == null || values.isEmpty()) {
- throw new Exception("No data found for metric " + metricName);
- }
- return values;
- };
+ Callable> callable = () ->
+ {
+ LOG.debug("Get Metrics for namespace {}, start {}, end {}, metric {}, dimensions {}", namespace, start,
+ end, metricName, dimensionsList);
+ GetMetricDataResponse metricData = cloudwatch.getMetricData(GetMetricDataRequest.builder()
+ .startTime(start)
+ .endTime(end)
+ .metricDataQueries(MetricDataQuery.builder()
+ .id(metricName.toLowerCase())
+ .metricStat(MetricStat.builder()
+ .unit(StandardUnit.COUNT)
+ .metric(Metric.builder()
+ .namespace(namespace)
+ .metricName(metricName)
+ .dimensions(dimensionsList)
+ .build())
+ .period(period)
+ .stat("Sum")
+ .build())
+ .returnData(true)
+ .build())
+ .build());
+ List values = metricData.metricDataResults().get(0).values();
+ if (values == null || values.isEmpty()) {
+ throw new Exception("No data found for metric " + metricName);
+ }
+ return values;
+ };
RetryConfig retryConfig = new RetryConfigBuilder()
.withMaxNumberOfTries(10)
@@ -85,9 +109,10 @@ public List fetchMetrics(Instant start, Instant end, int period, String
.build();
CallExecutor> callExecutor = new CallExecutorBuilder>()
.config(retryConfig)
- .afterFailedTryListener(s -> {
- LOG.warn(s.getLastExceptionThatCausedRetry().getMessage() + ", attempts: " + s.getTotalTries());
- })
+ .afterFailedTryListener(s ->
+ {
+ LOG.warn(s.getLastExceptionThatCausedRetry().getMessage() + ", attempts: " + s.getTotalTries());
+ })
.build();
Status> status = callExecutor.execute(callable);
return status.getResult();
diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/tracing/SegmentDocument.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/tracing/SegmentDocument.java
index 08f4bf7d8..5654b9876 100644
--- a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/tracing/SegmentDocument.java
+++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/tracing/SegmentDocument.java
@@ -1,7 +1,20 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.testutils.tracing;
import com.fasterxml.jackson.annotation.JsonSetter;
-
import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
@@ -92,7 +105,7 @@ public boolean hasSubsegments() {
return !subsegments.isEmpty();
}
- public static class SubSegment{
+ public static class SubSegment {
private String id;
private String name;
diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/tracing/Trace.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/tracing/Trace.java
index 15026a9d1..7298957aa 100644
--- a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/tracing/Trace.java
+++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/tracing/Trace.java
@@ -1,9 +1,22 @@
-package software.amazon.lambda.powertools.testutils.tracing;
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
-import software.amazon.lambda.powertools.testutils.tracing.SegmentDocument.SubSegment;
+package software.amazon.lambda.powertools.testutils.tracing;
import java.util.ArrayList;
import java.util.List;
+import software.amazon.lambda.powertools.testutils.tracing.SegmentDocument.SubSegment;
public class Trace {
private final List subsegments = new ArrayList<>();
diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/tracing/TraceFetcher.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/tracing/TraceFetcher.java
index e7cd13640..dc63987fd 100644
--- a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/tracing/TraceFetcher.java
+++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/tracing/TraceFetcher.java
@@ -1,5 +1,21 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.testutils.tracing;
+import static java.time.Duration.ofSeconds;
+
import com.evanlennick.retry4j.CallExecutor;
import com.evanlennick.retry4j.CallExecutorBuilder;
import com.evanlennick.retry4j.Status;
@@ -8,15 +24,6 @@
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import software.amazon.awssdk.http.SdkHttpClient;
-import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient;
-import software.amazon.awssdk.regions.Region;
-import software.amazon.awssdk.services.xray.XRayClient;
-import software.amazon.awssdk.services.xray.model.*;
-import software.amazon.lambda.powertools.testutils.tracing.SegmentDocument.SubSegment;
-
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.Arrays;
@@ -24,25 +31,42 @@
import java.util.List;
import java.util.concurrent.Callable;
import java.util.stream.Collectors;
-
-import static java.time.Duration.ofSeconds;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import software.amazon.awssdk.http.SdkHttpClient;
+import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.services.xray.XRayClient;
+import software.amazon.awssdk.services.xray.model.BatchGetTracesRequest;
+import software.amazon.awssdk.services.xray.model.BatchGetTracesResponse;
+import software.amazon.awssdk.services.xray.model.GetTraceSummariesRequest;
+import software.amazon.awssdk.services.xray.model.GetTraceSummariesResponse;
+import software.amazon.awssdk.services.xray.model.TimeRangeType;
+import software.amazon.awssdk.services.xray.model.TraceSummary;
+import software.amazon.lambda.powertools.testutils.tracing.SegmentDocument.SubSegment;
/**
* Class in charge of retrieving the actual traces of a Lambda execution on X-Ray
*/
public class TraceFetcher {
- private static final ObjectMapper MAPPER = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+ private static final ObjectMapper MAPPER =
+ new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
private static final Logger LOG = LoggerFactory.getLogger(TraceFetcher.class);
-
+ private static final SdkHttpClient httpClient = UrlConnectionHttpClient.builder().build();
+ private static final Region region = Region.of(System.getProperty("AWS_DEFAULT_REGION", "eu-west-1"));
+ private static final XRayClient xray = XRayClient.builder()
+ .httpClient(httpClient)
+ .region(region)
+ .build();
private final Instant start;
private final Instant end;
private final String filterExpression;
private final List excludedSegments;
/**
- * @param start beginning of the time slot to search in
- * @param end end of the time slot to search in
+ * @param start beginning of the time slot to search in
+ * @param end end of the time slot to search in
* @param filterExpression eventual filter for the search
* @param excludedSegments list of segment to exclude from the search
*/
@@ -64,10 +88,11 @@ public static Builder builder() {
* @return traces
*/
public Trace fetchTrace() {
- Callable callable = () -> {
- List traceIds = getTraceIds();
- return getTrace(traceIds);
- };
+ Callable callable = () ->
+ {
+ List traceIds = getTraceIds();
+ return getTrace(traceIds);
+ };
RetryConfig retryConfig = new RetryConfigBuilder()
.withMaxNumberOfTries(10)
@@ -77,7 +102,10 @@ public Trace fetchTrace() {
.build();
CallExecutor callExecutor = new CallExecutorBuilder()
.config(retryConfig)
- .afterFailedTryListener(s -> {LOG.warn(s.getLastExceptionThatCausedRetry().getMessage() + ", attempts: " + s.getTotalTries());})
+ .afterFailedTryListener(s ->
+ {
+ LOG.warn(s.getLastExceptionThatCausedRetry().getMessage() + ", attempts: " + s.getTotalTries());
+ })
.build();
Status status = callExecutor.execute(callable);
return status.getResult();
@@ -85,6 +113,7 @@ public Trace fetchTrace() {
/**
* Retrieve traces from trace ids.
+ *
* @param traceIds
* @return
*/
@@ -96,43 +125,49 @@ private Trace getTrace(List traceIds) {
throw new RuntimeException("No trace found");
}
Trace traceRes = new Trace();
- tracesResponse.traces().forEach(trace -> {
- if (trace.hasSegments()) {
- trace.segments().forEach(segment -> {
- try {
- SegmentDocument document = MAPPER.readValue(segment.document(), SegmentDocument.class);
- if (document.getOrigin().equals("AWS::Lambda::Function")) {
- if (document.hasSubsegments()) {
- getNestedSubSegments(document.getSubsegments(), traceRes, Collections.emptyList());
+ tracesResponse.traces().forEach(trace ->
+ {
+ if (trace.hasSegments()) {
+ trace.segments().forEach(segment ->
+ {
+ try {
+ SegmentDocument document = MAPPER.readValue(segment.document(), SegmentDocument.class);
+ if (document.getOrigin().equals("AWS::Lambda::Function")) {
+ if (document.hasSubsegments()) {
+ getNestedSubSegments(document.getSubsegments(), traceRes,
+ Collections.emptyList());
+ }
+ }
+ } catch (JsonProcessingException e) {
+ LOG.error("Failed to parse segment document: " + e.getMessage());
+ throw new RuntimeException(e);
}
- }
- } catch (JsonProcessingException e) {
- LOG.error("Failed to parse segment document: " + e.getMessage());
- throw new RuntimeException(e);
- }
- });
- }
- });
+ });
+ }
+ });
return traceRes;
}
private void getNestedSubSegments(List subsegments, Trace traceRes, List idsToIgnore) {
- subsegments.forEach(subsegment -> {
- List subSegmentIdsToIgnore = Collections.emptyList();
- if (!excludedSegments.contains(subsegment.getName()) && !idsToIgnore.contains(subsegment.getId())) {
- traceRes.addSubSegment(subsegment);
+ subsegments.forEach(subsegment ->
+ {
+ List subSegmentIdsToIgnore = Collections.emptyList();
+ if (!excludedSegments.contains(subsegment.getName()) && !idsToIgnore.contains(subsegment.getId())) {
+ traceRes.addSubSegment(subsegment);
+ if (subsegment.hasSubsegments()) {
+ subSegmentIdsToIgnore = subsegment.getSubsegments().stream().map(SubSegment::getId)
+ .collect(Collectors.toList());
+ }
+ }
if (subsegment.hasSubsegments()) {
- subSegmentIdsToIgnore = subsegment.getSubsegments().stream().map(SubSegment::getId).collect(Collectors.toList());
+ getNestedSubSegments(subsegment.getSubsegments(), traceRes, subSegmentIdsToIgnore);
}
- }
- if (subsegment.hasSubsegments()) {
- getNestedSubSegments(subsegment.getSubsegments(), traceRes, subSegmentIdsToIgnore);
- }
- });
+ });
}
/**
* Use the X-Ray SDK to retrieve the trace ids corresponding to a specific function during a specific time slot
+ *
* @return a list of trace ids
*/
private List getTraceIds() {
@@ -146,20 +181,14 @@ private List getTraceIds() {
if (!traceSummaries.hasTraceSummaries()) {
throw new RuntimeException("No trace id found");
}
- List traceIds = traceSummaries.traceSummaries().stream().map(TraceSummary::id).collect(Collectors.toList());
+ List traceIds =
+ traceSummaries.traceSummaries().stream().map(TraceSummary::id).collect(Collectors.toList());
if (traceIds.isEmpty()) {
throw new RuntimeException("No trace id found");
}
return traceIds;
}
- private static final SdkHttpClient httpClient = UrlConnectionHttpClient.builder().build();
- private static final Region region = Region.of(System.getProperty("AWS_DEFAULT_REGION", "eu-west-1"));
- private static final XRayClient xray = XRayClient.builder()
- .httpClient(httpClient)
- .region(region)
- .build();
-
public static class Builder {
private Instant start;
private Instant end;
@@ -167,12 +196,15 @@ public static class Builder {
private List excludedSegments = Arrays.asList("Initialization", "Invocation", "Overhead");
public TraceFetcher build() {
- if (filterExpression == null)
+ if (filterExpression == null) {
throw new IllegalArgumentException("filterExpression or functionName is required");
- if (start == null)
+ }
+ if (start == null) {
throw new IllegalArgumentException("start is required");
- if (end == null)
+ }
+ if (end == null) {
end = start.plus(1, ChronoUnit.MINUTES);
+ }
LOG.debug("Looking for traces from {} to {} with filter {}", start, end, filterExpression);
return new TraceFetcher(start, end, filterExpression, excludedSegments);
}
@@ -194,6 +226,7 @@ public Builder filterExpression(String filterExpression) {
/**
* "Initialization", "Invocation", "Overhead" are excluded by default
+ *
* @param excludedSegments
* @return
*/
@@ -203,7 +236,8 @@ public Builder excludeSegments(List excludedSegments) {
}
public Builder functionName(String functionName) {
- this.filterExpression = String.format("service(id(name: \"%s\", type: \"AWS::Lambda::Function\"))", functionName);
+ this.filterExpression =
+ String.format("service(id(name: \"%s\", type: \"AWS::Lambda::Function\"))", functionName);
return this;
}
}
diff --git a/powertools-idempotency/pom.xml b/powertools-idempotency/pom.xml
index cb4d9b802..ba4b147ae 100644
--- a/powertools-idempotency/pom.xml
+++ b/powertools-idempotency/pom.xml
@@ -1,4 +1,18 @@
+
+
@@ -180,6 +194,10 @@
+
+ org.apache.maven.plugins
+ maven-checkstyle-plugin
+
diff --git a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/Constants.java b/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/Constants.java
index 28c6f58aa..0d19fa7a9 100644
--- a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/Constants.java
+++ b/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/Constants.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2022 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,6 +11,7 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.idempotency;
public class Constants {
diff --git a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/Idempotency.java b/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/Idempotency.java
index ce652791b..6da826c45 100644
--- a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/Idempotency.java
+++ b/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/Idempotency.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2022 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,6 +11,7 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.idempotency;
import com.amazonaws.services.lambda.runtime.Context;
@@ -38,29 +39,6 @@ public class Idempotency {
private Idempotency() {
}
- public IdempotencyConfig getConfig() {
- return config;
- }
-
- public BasePersistenceStore getPersistenceStore() {
- if (persistenceStore == null) {
- throw new IllegalStateException("Persistence Store is null, did you call 'configure()'?");
- }
- return persistenceStore;
- }
-
- private void setConfig(IdempotencyConfig config) {
- this.config = config;
- }
-
- private void setPersistenceStore(BasePersistenceStore persistenceStore) {
- this.persistenceStore = persistenceStore;
- }
-
- private static class Holder {
- private final static Idempotency instance = new Idempotency();
- }
-
public static Idempotency getInstance() {
return Holder.instance;
}
@@ -84,6 +62,29 @@ public static Config config() {
return new Config();
}
+ public IdempotencyConfig getConfig() {
+ return config;
+ }
+
+ private void setConfig(IdempotencyConfig config) {
+ this.config = config;
+ }
+
+ public BasePersistenceStore getPersistenceStore() {
+ if (persistenceStore == null) {
+ throw new IllegalStateException("Persistence Store is null, did you call 'configure()'?");
+ }
+ return persistenceStore;
+ }
+
+ private void setPersistenceStore(BasePersistenceStore persistenceStore) {
+ this.persistenceStore = persistenceStore;
+ }
+
+ private static class Holder {
+ private final static Idempotency instance = new Idempotency();
+ }
+
public static class Config {
private IdempotencyConfig config;
@@ -94,7 +95,8 @@ public static class Config {
*/
public void configure() {
if (store == null) {
- throw new IllegalStateException("Persistence Layer is null, configure one with 'withPersistenceStore()'");
+ throw new IllegalStateException(
+ "Persistence Layer is null, configure one with 'withPersistenceStore()'");
}
if (config == null) {
config = IdempotencyConfig.builder().build();
diff --git a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/IdempotencyConfig.java b/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/IdempotencyConfig.java
index 28f20ffa9..58d0a7f5b 100644
--- a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/IdempotencyConfig.java
+++ b/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/IdempotencyConfig.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2022 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,12 +11,12 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.idempotency;
import com.amazonaws.services.lambda.runtime.Context;
-import software.amazon.lambda.powertools.idempotency.internal.cache.LRUCache;
-
import java.time.Duration;
+import software.amazon.lambda.powertools.idempotency.internal.cache.LRUCache;
/**
* Configuration of the idempotency feature. Use the {@link Builder} to create an instance.
@@ -31,7 +31,9 @@ public class IdempotencyConfig {
private final String hashFunction;
private Context lambdaContext;
- private IdempotencyConfig(String eventKeyJMESPath, String payloadValidationJMESPath, boolean throwOnNoIdempotencyKey, boolean useLocalCache, int localCacheMaxItems, long expirationInSeconds, String hashFunction) {
+ private IdempotencyConfig(String eventKeyJMESPath, String payloadValidationJMESPath,
+ boolean throwOnNoIdempotencyKey, boolean useLocalCache, int localCacheMaxItems,
+ long expirationInSeconds, String hashFunction) {
this.localCacheMaxItems = localCacheMaxItems;
this.useLocalCache = useLocalCache;
this.expirationInSeconds = expirationInSeconds;
@@ -41,6 +43,15 @@ private IdempotencyConfig(String eventKeyJMESPath, String payloadValidationJMESP
this.hashFunction = hashFunction;
}
+ /**
+ * Create a builder that can be used to configure and create a {@link IdempotencyConfig}.
+ *
+ * @return a new instance of {@link Builder}
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
public int getLocalCacheMaxItems() {
return localCacheMaxItems;
}
@@ -69,24 +80,14 @@ public String getHashFunction() {
return hashFunction;
}
-
- /**
- * Create a builder that can be used to configure and create a {@link IdempotencyConfig}.
- *
- * @return a new instance of {@link Builder}
- */
- public static Builder builder() {
- return new Builder();
+ public Context getLambdaContext() {
+ return lambdaContext;
}
public void setLambdaContext(Context lambdaContext) {
this.lambdaContext = lambdaContext;
}
- public Context getLambdaContext() {
- return lambdaContext;
- }
-
public static class Builder {
private int localCacheMaxItems = 256;
@@ -107,6 +108,7 @@ public static class Builder {
*
+ *
* @return an instance of {@link IdempotencyConfig}.
*/
public IdempotencyConfig build() {
@@ -124,16 +126,15 @@ public IdempotencyConfig build() {
* A JMESPath expression to extract the idempotency key from the event record.
* See https://jmespath.org/ for more details.
* Common paths are:
- *
powertools_json(body) for APIGatewayProxyRequestEvent and APIGatewayV2HTTPEvent
- *
Records[*].powertools_json(body) for SQSEvent
- *
Records[0].Sns.Message | powertools_json(@) for SNSEvent
- *
detail for ScheduledEvent (EventBridge / CloudWatch events)
- *
Records[*].kinesis.powertools_json(powertools_base64(data)) for KinesisEvent
- *
Records[*].powertools_json(powertools_base64(data)) for KinesisFirehoseEvent
- *
...
+ *
powertools_json(body) for APIGatewayProxyRequestEvent and APIGatewayV2HTTPEvent
+ *
Records[*].powertools_json(body) for SQSEvent
+ *
Records[0].Sns.Message | powertools_json(@) for SNSEvent
+ *
detail for ScheduledEvent (EventBridge / CloudWatch events)
+ *
Records[*].kinesis.powertools_json(powertools_base64(data)) for KinesisEvent
+ *
Records[*].powertools_json(powertools_base64(data)) for KinesisFirehoseEvent
+ *
...
*
*
- *
* @param eventKeyJMESPath path of the key in the Lambda event
* @return the instance of the builder (to chain operations)
*/
diff --git a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/IdempotencyKey.java b/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/IdempotencyKey.java
index 92a0a3d49..4f63b10f5 100644
--- a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/IdempotencyKey.java
+++ b/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/IdempotencyKey.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2022 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,6 +11,7 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.idempotency;
import java.lang.annotation.ElementType;
diff --git a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/Idempotent.java b/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/Idempotent.java
index e7cace1fb..6ca40a0e1 100644
--- a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/Idempotent.java
+++ b/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/Idempotent.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2022 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,10 +11,10 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.idempotency;
import com.amazonaws.services.lambda.runtime.Context;
-
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
diff --git a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyAlreadyInProgressException.java b/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyAlreadyInProgressException.java
index 3d5ee93c5..dc87f422b 100644
--- a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyAlreadyInProgressException.java
+++ b/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyAlreadyInProgressException.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2022 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,6 +11,7 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.idempotency.exceptions;
/**
diff --git a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyConfigurationException.java b/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyConfigurationException.java
index 0d3844641..9e85f4b5f 100644
--- a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyConfigurationException.java
+++ b/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyConfigurationException.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2022 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,6 +11,7 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.idempotency.exceptions;
/**
diff --git a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyInconsistentStateException.java b/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyInconsistentStateException.java
index 40c90dcab..e41e30e84 100644
--- a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyInconsistentStateException.java
+++ b/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyInconsistentStateException.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2022 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,6 +11,7 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.idempotency.exceptions;
/**
diff --git a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyItemAlreadyExistsException.java b/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyItemAlreadyExistsException.java
index 088db59c0..ba7da69bf 100644
--- a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyItemAlreadyExistsException.java
+++ b/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyItemAlreadyExistsException.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2022 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,6 +11,7 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.idempotency.exceptions;
/**
diff --git a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyItemNotFoundException.java b/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyItemNotFoundException.java
index afae2554e..420829363 100644
--- a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyItemNotFoundException.java
+++ b/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyItemNotFoundException.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2022 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,15 +11,16 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.idempotency.exceptions;
/**
* Exception thrown when the item was not found in the persistence store.
*/
-public class IdempotencyItemNotFoundException extends RuntimeException{
+public class IdempotencyItemNotFoundException extends RuntimeException {
private static final long serialVersionUID = 4818288566747993032L;
public IdempotencyItemNotFoundException(String idempotencyKey) {
- super("Item with idempotency key "+ idempotencyKey + " not found");
+ super("Item with idempotency key " + idempotencyKey + " not found");
}
}
diff --git a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyKeyException.java b/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyKeyException.java
index 7259dff0f..29b8bd2ec 100644
--- a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyKeyException.java
+++ b/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyKeyException.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2022 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,6 +11,7 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.idempotency.exceptions;
/**
diff --git a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyPersistenceLayerException.java b/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyPersistenceLayerException.java
index fa49b746c..bfdd2d792 100644
--- a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyPersistenceLayerException.java
+++ b/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyPersistenceLayerException.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2022 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,6 +11,7 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.idempotency.exceptions;
/**
diff --git a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyValidationException.java b/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyValidationException.java
index 5aee228eb..cdb2bb6a7 100644
--- a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyValidationException.java
+++ b/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyValidationException.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2022 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,6 +11,7 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.idempotency.exceptions;
import software.amazon.lambda.powertools.idempotency.IdempotencyConfig;
diff --git a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/internal/IdempotencyHandler.java b/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/internal/IdempotencyHandler.java
index 5ce723f04..2875ab3d1 100644
--- a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/internal/IdempotencyHandler.java
+++ b/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/internal/IdempotencyHandler.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2022 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,26 +11,32 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.idempotency.internal;
+import static software.amazon.lambda.powertools.idempotency.persistence.DataRecord.Status.EXPIRED;
+import static software.amazon.lambda.powertools.idempotency.persistence.DataRecord.Status.INPROGRESS;
+
import com.amazonaws.services.lambda.runtime.Context;
import com.fasterxml.jackson.databind.JsonNode;
+import java.time.Instant;
+import java.util.OptionalInt;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import software.amazon.lambda.powertools.idempotency.Idempotency;
-import software.amazon.lambda.powertools.idempotency.exceptions.*;
+import software.amazon.lambda.powertools.idempotency.exceptions.IdempotencyAlreadyInProgressException;
+import software.amazon.lambda.powertools.idempotency.exceptions.IdempotencyInconsistentStateException;
+import software.amazon.lambda.powertools.idempotency.exceptions.IdempotencyItemAlreadyExistsException;
+import software.amazon.lambda.powertools.idempotency.exceptions.IdempotencyItemNotFoundException;
+import software.amazon.lambda.powertools.idempotency.exceptions.IdempotencyKeyException;
+import software.amazon.lambda.powertools.idempotency.exceptions.IdempotencyPersistenceLayerException;
+import software.amazon.lambda.powertools.idempotency.exceptions.IdempotencyValidationException;
import software.amazon.lambda.powertools.idempotency.persistence.BasePersistenceStore;
import software.amazon.lambda.powertools.idempotency.persistence.DataRecord;
import software.amazon.lambda.powertools.utilities.JsonConfig;
-import java.time.Instant;
-import java.util.OptionalInt;
-
-import static software.amazon.lambda.powertools.idempotency.persistence.DataRecord.Status.EXPIRED;
-import static software.amazon.lambda.powertools.idempotency.persistence.DataRecord.Status.INPROGRESS;
-
/**
* Internal class that will handle the Idempotency, and use the {@link software.amazon.lambda.powertools.idempotency.persistence.PersistenceStore}
* to store the result of previous calls.
@@ -90,7 +96,9 @@ private Object processIdempotency() throws Throwable {
} catch (IdempotencyKeyException ike) {
throw ike;
} catch (Exception e) {
- throw new IdempotencyPersistenceLayerException("Failed to save in progress record to idempotency store. If you believe this is a Powertools for AWS Lambda (Java) bug, please open an issue.", e);
+ throw new IdempotencyPersistenceLayerException(
+ "Failed to save in progress record to idempotency store. If you believe this is a Powertools for AWS Lambda (Java) bug, please open an issue.",
+ e);
}
return getFunctionResponse();
}
@@ -121,11 +129,14 @@ private DataRecord getIdempotencyRecord() {
} catch (IdempotencyItemNotFoundException e) {
// This code path will only be triggered if the record is removed between saveInProgress and getRecord
LOG.debug("An existing idempotency record was deleted before we could fetch it");
- throw new IdempotencyInconsistentStateException("saveInProgress and getRecord return inconsistent results", e);
+ throw new IdempotencyInconsistentStateException("saveInProgress and getRecord return inconsistent results",
+ e);
} catch (IdempotencyValidationException | IdempotencyKeyException vke) {
throw vke;
} catch (Exception e) {
- throw new IdempotencyPersistenceLayerException("Failed to get record from idempotency store. If you believe this is a Powertools for AWS Lambda (Java) bug, please open an issue.", e);
+ throw new IdempotencyPersistenceLayerException(
+ "Failed to get record from idempotency store. If you believe this is a Powertools for AWS Lambda (Java) bug, please open an issue.",
+ e);
}
}
@@ -144,19 +155,24 @@ private Object handleForStatus(DataRecord record) {
if (INPROGRESS.equals(record.getStatus())) {
if (record.getInProgressExpiryTimestamp().isPresent()
&& record.getInProgressExpiryTimestamp().getAsLong() < Instant.now().toEpochMilli()) {
- throw new IdempotencyInconsistentStateException("Item should have been expired in-progress because it already time-outed.");
+ throw new IdempotencyInconsistentStateException(
+ "Item should have been expired in-progress because it already time-outed.");
}
- throw new IdempotencyAlreadyInProgressException("Execution already in progress with idempotency key: " + record.getIdempotencyKey());
+ throw new IdempotencyAlreadyInProgressException(
+ "Execution already in progress with idempotency key: " + record.getIdempotencyKey());
}
Class> returnType = ((MethodSignature) pjp.getSignature()).getReturnType();
try {
- LOG.debug("Response for key '{}' retrieved from idempotency store, skipping the function", record.getIdempotencyKey());
- if (returnType.equals(String.class))
+ LOG.debug("Response for key '{}' retrieved from idempotency store, skipping the function",
+ record.getIdempotencyKey());
+ if (returnType.equals(String.class)) {
return record.getResponseData();
+ }
return JsonConfig.get().getObjectMapper().reader().readValue(record.getResponseData(), returnType);
} catch (Exception e) {
- throw new IdempotencyPersistenceLayerException("Unable to get function response as " + returnType.getSimpleName(), e);
+ throw new IdempotencyPersistenceLayerException(
+ "Unable to get function response as " + returnType.getSimpleName(), e);
}
}
@@ -172,7 +188,9 @@ private Object getFunctionResponse() throws Throwable {
} catch (IdempotencyKeyException ke) {
throw ke;
} catch (Exception e) {
- throw new IdempotencyPersistenceLayerException("Failed to delete record from idempotency store. If you believe this is a Powertools for AWS Lambda (Java) bug, please open an issue.", e);
+ throw new IdempotencyPersistenceLayerException(
+ "Failed to delete record from idempotency store. If you believe this is a Powertools for AWS Lambda (Java) bug, please open an issue.",
+ e);
}
throw handlerException;
}
@@ -180,7 +198,9 @@ private Object getFunctionResponse() throws Throwable {
try {
persistenceStore.saveSuccess(data, response, Instant.now());
} catch (Exception e) {
- throw new IdempotencyPersistenceLayerException("Failed to update record state to success in idempotency store. If you believe this is a Powertools for AWS Lambda (Java) bug, please open an issue.", e);
+ throw new IdempotencyPersistenceLayerException(
+ "Failed to update record state to success in idempotency store. If you believe this is a Powertools for AWS Lambda (Java) bug, please open an issue.",
+ e);
}
return response;
}
diff --git a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/internal/IdempotentAspect.java b/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/internal/IdempotentAspect.java
index dc2703e64..d34dd72dd 100644
--- a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/internal/IdempotentAspect.java
+++ b/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/internal/IdempotentAspect.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2022 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,15 +11,20 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.idempotency.internal;
+import static software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor.placedOnRequestHandler;
+
+import com.amazonaws.services.lambda.runtime.Context;
import com.fasterxml.jackson.databind.JsonNode;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
-import com.amazonaws.services.lambda.runtime.Context;
import software.amazon.lambda.powertools.idempotency.Constants;
import software.amazon.lambda.powertools.idempotency.Idempotency;
import software.amazon.lambda.powertools.idempotency.IdempotencyKey;
@@ -27,11 +32,6 @@
import software.amazon.lambda.powertools.idempotency.exceptions.IdempotencyConfigurationException;
import software.amazon.lambda.powertools.utilities.JsonConfig;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Method;
-
-import static software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor.placedOnRequestHandler;
-
/**
* Aspect that handles the {@link Idempotent} annotation.
* It uses the {@link IdempotencyHandler} to actually do the job.
@@ -48,19 +48,21 @@ public Object around(ProceedingJoinPoint pjp,
Idempotent idempotent) throws Throwable {
String idempotencyDisabledEnv = System.getenv().get(Constants.IDEMPOTENCY_DISABLED_ENV);
- if (idempotencyDisabledEnv != null && !idempotencyDisabledEnv.equalsIgnoreCase("false")) {
+ if (idempotencyDisabledEnv != null && !"false".equalsIgnoreCase(idempotencyDisabledEnv)) {
return pjp.proceed(pjp.getArgs());
}
Method method = ((MethodSignature) pjp.getSignature()).getMethod();
if (method.getReturnType().equals(void.class)) {
- throw new IdempotencyConfigurationException("The annotated method doesn't return anything. Unable to perform idempotency on void return type");
+ throw new IdempotencyConfigurationException(
+ "The annotated method doesn't return anything. Unable to perform idempotency on void return type");
}
boolean isHandler = placedOnRequestHandler(pjp);
JsonNode payload = getPayload(pjp, method, isHandler);
if (payload == null) {
- throw new IdempotencyConfigurationException("Unable to get payload from the method. Ensure there is at least one parameter or that you use @IdempotencyKey");
+ throw new IdempotencyConfigurationException(
+ "Unable to get payload from the method. Ensure there is at least one parameter or that you use @IdempotencyKey");
}
Context lambdaContext;
@@ -76,7 +78,8 @@ public Object around(ProceedingJoinPoint pjp,
/**
* Retrieve the payload from the annotated method parameters
- * @param pjp joinPoint
+ *
+ * @param pjp joinPoint
* @param method the annotated method
* @return the payload used for idempotency
*/
diff --git a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/internal/cache/LRUCache.java b/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/internal/cache/LRUCache.java
index a017c211a..b57ad2977 100644
--- a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/internal/cache/LRUCache.java
+++ b/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/internal/cache/LRUCache.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2022 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,6 +11,7 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.idempotency.internal.cache;
import java.util.LinkedHashMap;
@@ -19,6 +20,7 @@
/**
* Implementation of a simple LRU Cache based on a {@link LinkedHashMap}
* See here.
+ *
* @param Type of the keys
* @param Types of the values
*/
diff --git a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/BasePersistenceStore.java b/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/BasePersistenceStore.java
index c79068d1a..f58b276fd 100644
--- a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/BasePersistenceStore.java
+++ b/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/BasePersistenceStore.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2022 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,23 +11,15 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.idempotency.persistence;
+import static software.amazon.lambda.powertools.core.internal.LambdaConstants.LAMBDA_FUNCTION_NAME_ENV;
+
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectWriter;
import io.burt.jmespath.Expression;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import software.amazon.awssdk.utils.StringUtils;
-import software.amazon.lambda.powertools.idempotency.IdempotencyConfig;
-import software.amazon.lambda.powertools.idempotency.exceptions.IdempotencyItemAlreadyExistsException;
-import software.amazon.lambda.powertools.idempotency.exceptions.IdempotencyItemNotFoundException;
-import software.amazon.lambda.powertools.idempotency.exceptions.IdempotencyKeyException;
-import software.amazon.lambda.powertools.idempotency.exceptions.IdempotencyValidationException;
-import software.amazon.lambda.powertools.idempotency.internal.cache.LRUCache;
-import software.amazon.lambda.powertools.utilities.JsonConfig;
-
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
@@ -42,8 +34,16 @@
import java.util.Spliterators;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
-
-import static software.amazon.lambda.powertools.core.internal.LambdaConstants.LAMBDA_FUNCTION_NAME_ENV;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import software.amazon.awssdk.utils.StringUtils;
+import software.amazon.lambda.powertools.idempotency.IdempotencyConfig;
+import software.amazon.lambda.powertools.idempotency.exceptions.IdempotencyItemAlreadyExistsException;
+import software.amazon.lambda.powertools.idempotency.exceptions.IdempotencyItemNotFoundException;
+import software.amazon.lambda.powertools.idempotency.exceptions.IdempotencyKeyException;
+import software.amazon.lambda.powertools.idempotency.exceptions.IdempotencyValidationException;
+import software.amazon.lambda.powertools.idempotency.internal.cache.LRUCache;
+import software.amazon.lambda.powertools.utilities.JsonConfig;
/**
* Persistence layer that will store the idempotency result.
@@ -53,7 +53,7 @@
public abstract class BasePersistenceStore implements PersistenceStore {
private static final Logger LOG = LoggerFactory.getLogger(BasePersistenceStore.class);
-
+ protected boolean payloadValidationEnabled = false;
private String functionName = "";
private boolean configured = false;
private long expirationInSeconds = 60 * 60; // 1 hour default
@@ -61,7 +61,6 @@ public abstract class BasePersistenceStore implements PersistenceStore {
private LRUCache cache;
private String eventKeyJMESPath;
private Expression eventKeyCompiledJMESPath;
- protected boolean payloadValidationEnabled = false;
private Expression validationKeyJMESPath;
private boolean throwOnNoIdempotencyKey = false;
private String hashFunctionName;
@@ -130,7 +129,8 @@ public void saveSuccess(JsonNode data, Object result, Instant now) {
responseJson,
getHashedPayload(data)
);
- LOG.debug("Function successfully executed. Saving record to persistence store with idempotency key: {}", record.getIdempotencyKey());
+ LOG.debug("Function successfully executed. Saving record to persistence store with idempotency key: {}",
+ record.getIdempotencyKey());
updateRecord(record);
saveToCache(record);
} catch (JsonProcessingException e) {
@@ -145,7 +145,8 @@ public void saveSuccess(JsonNode data, Object result, Instant now) {
* @param data Payload
* @param now
*/
- public void saveInProgress(JsonNode data, Instant now, OptionalInt remainingTimeInMs) throws IdempotencyItemAlreadyExistsException {
+ public void saveInProgress(JsonNode data, Instant now, OptionalInt remainingTimeInMs)
+ throws IdempotencyItemAlreadyExistsException {
Optional hashedIdempotencyKey = getHashedIdempotencyKey(data);
if (!hashedIdempotencyKey.isPresent()) {
// missing idempotency key => non-idempotent transaction, we do not store the data, simply return
@@ -159,7 +160,8 @@ public void saveInProgress(JsonNode data, Instant now, OptionalInt remainingTime
OptionalLong inProgressExpirationMsTimestamp = OptionalLong.empty();
if (remainingTimeInMs.isPresent()) {
- inProgressExpirationMsTimestamp = OptionalLong.of(now.plus(remainingTimeInMs.getAsInt(), ChronoUnit.MILLIS).toEpochMilli());
+ inProgressExpirationMsTimestamp =
+ OptionalLong.of(now.plus(remainingTimeInMs.getAsInt(), ChronoUnit.MILLIS).toEpochMilli());
}
DataRecord record = new DataRecord(
@@ -205,7 +207,8 @@ public void deleteRecord(JsonNode data, Throwable throwable) {
* @throws IdempotencyValidationException Payload doesn't match the stored record for the given idempotency key
* @throws IdempotencyItemNotFoundException Exception thrown if no record exists in persistence store with the idempotency key
*/
- public DataRecord getRecord(JsonNode data, Instant now) throws IdempotencyValidationException, IdempotencyItemNotFoundException {
+ public DataRecord getRecord(JsonNode data, Instant now)
+ throws IdempotencyValidationException, IdempotencyItemNotFoundException {
Optional hashedIdempotencyKey = getHashedIdempotencyKey(data);
if (!hashedIdempotencyKey.isPresent()) {
// missing idempotency key => non-idempotent transaction, we do not get the data, simply return nothing
@@ -255,7 +258,9 @@ private Optional getHashedIdempotencyKey(JsonNode data) {
private boolean isMissingIdemPotencyKey(JsonNode data) {
if (data.isContainerNode()) {
- Stream> stream = StreamSupport.stream(Spliterators.spliteratorUnknownSize(data.fields(), Spliterator.ORDERED), false);
+ Stream> stream =
+ StreamSupport.stream(Spliterators.spliteratorUnknownSize(data.fields(), Spliterator.ORDERED),
+ false);
return stream.allMatch(e -> e.getValue().isNull());
}
return data.isNull();
@@ -302,7 +307,9 @@ String generateHash(JsonNode data) {
node = data.decimalValue();
} else if (data.isBoolean()) {
node = data.asBoolean();
- } else node = data; // anything else
+ } else {
+ node = data; // anything else
+ }
MessageDigest hashAlgorithm = getHashAlgorithm();
byte[] digest = hashAlgorithm.digest(node.toString().getBytes(StandardCharsets.UTF_8));
@@ -356,17 +363,20 @@ private long getExpiryEpochSecond(Instant now) {
* @param dataRecord DataRecord to save in cache
*/
private void saveToCache(DataRecord dataRecord) {
- if (!useLocalCache)
+ if (!useLocalCache) {
return;
- if (dataRecord.getStatus().equals(DataRecord.Status.INPROGRESS))
+ }
+ if (dataRecord.getStatus().equals(DataRecord.Status.INPROGRESS)) {
return;
+ }
cache.put(dataRecord.getIdempotencyKey(), dataRecord);
}
private DataRecord retrieveFromCache(String idempotencyKey, Instant now) {
- if (!useLocalCache)
+ if (!useLocalCache) {
return null;
+ }
DataRecord record = cache.get(idempotencyKey);
if (record != null) {
@@ -380,8 +390,9 @@ private DataRecord retrieveFromCache(String idempotencyKey, Instant now) {
}
private void deleteFromCache(String idempotencyKey) {
- if (!useLocalCache)
+ if (!useLocalCache) {
return;
+ }
cache.remove(idempotencyKey);
}
diff --git a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/DataRecord.java b/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/DataRecord.java
index 54001c449..9af7c6a53 100644
--- a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/DataRecord.java
+++ b/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/DataRecord.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2022 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,14 +11,13 @@
* limitations under the License.
*
*/
-package software.amazon.lambda.powertools.idempotency.persistence;
-import software.amazon.lambda.powertools.idempotency.IdempotencyConfig;
+package software.amazon.lambda.powertools.idempotency.persistence;
import java.time.Instant;
import java.util.Objects;
-import java.util.OptionalInt;
import java.util.OptionalLong;
+import software.amazon.lambda.powertools.idempotency.IdempotencyConfig;
/**
* Data Class for idempotency records. This is actually the item that will be stored in the persistence layer.
@@ -30,7 +29,7 @@ public class DataRecord {
/**
* This field is controlling how long the result of the idempotent
* event is cached. It is stored in _seconds since epoch_.
- *
+ *
* DynamoDB's TTL mechanism is used to remove the record once the
* expiry has been reached, and subsequent execution of the request
* will be permitted. The user must configure this on their table.
@@ -43,16 +42,17 @@ public class DataRecord {
* The in-progress field is set to the remaining lambda execution time
* when the record is created.
* This field is stored in _milliseconds since epoch_.
- *
+ *
* This ensures that:
- *
+ *
* 1/ other concurrently executing requests are blocked from starting
* 2/ if a lambda times out, subsequent requests will be allowed again, despite
- * the fact that the idempotency record is already in the table
+ * the fact that the idempotency record is already in the table
*/
private final OptionalLong inProgressExpiryTimestamp;
- public DataRecord(String idempotencyKey, Status status, long expiryTimestamp, String responseData, String payloadHash) {
+ public DataRecord(String idempotencyKey, Status status, long expiryTimestamp, String responseData,
+ String payloadHash) {
this.idempotencyKey = idempotencyKey;
this.status = status.toString();
this.expiryTimestamp = expiryTimestamp;
@@ -61,7 +61,8 @@ public DataRecord(String idempotencyKey, Status status, long expiryTimestamp, St
this.inProgressExpiryTimestamp = OptionalLong.empty();
}
- public DataRecord(String idempotencyKey, Status status, long expiryTimestamp, String responseData, String payloadHash, OptionalLong inProgressExpiryTimestamp) {
+ public DataRecord(String idempotencyKey, Status status, long expiryTimestamp, String responseData,
+ String payloadHash, OptionalLong inProgressExpiryTimestamp) {
this.idempotencyKey = idempotencyKey;
this.status = status.toString();
this.expiryTimestamp = expiryTimestamp;
@@ -110,8 +111,12 @@ public String getPayloadHash() {
@Override
public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
DataRecord record = (DataRecord) o;
return expiryTimestamp == record.expiryTimestamp
&& idempotencyKey.equals(record.idempotencyKey)
diff --git a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/DynamoDBPersistenceStore.java b/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/DynamoDBPersistenceStore.java
index 783b029bb..7a023b4de 100644
--- a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/DynamoDBPersistenceStore.java
+++ b/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/DynamoDBPersistenceStore.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2022 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,31 +11,37 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.idempotency.persistence;
+import static software.amazon.lambda.powertools.core.internal.LambdaConstants.AWS_REGION_ENV;
+import static software.amazon.lambda.powertools.core.internal.LambdaConstants.LAMBDA_FUNCTION_NAME_ENV;
+import static software.amazon.lambda.powertools.idempotency.persistence.DataRecord.Status.INPROGRESS;
+
+import java.time.Instant;
+import java.util.AbstractMap;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.OptionalLong;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
-import software.amazon.awssdk.services.dynamodb.model.*;
+import software.amazon.awssdk.services.dynamodb.model.AttributeValue;
+import software.amazon.awssdk.services.dynamodb.model.ConditionalCheckFailedException;
+import software.amazon.awssdk.services.dynamodb.model.DeleteItemRequest;
+import software.amazon.awssdk.services.dynamodb.model.GetItemRequest;
+import software.amazon.awssdk.services.dynamodb.model.GetItemResponse;
+import software.amazon.awssdk.services.dynamodb.model.PutItemRequest;
+import software.amazon.awssdk.services.dynamodb.model.UpdateItemRequest;
import software.amazon.awssdk.utils.StringUtils;
import software.amazon.lambda.powertools.idempotency.Constants;
import software.amazon.lambda.powertools.idempotency.exceptions.IdempotencyItemAlreadyExistsException;
import software.amazon.lambda.powertools.idempotency.exceptions.IdempotencyItemNotFoundException;
-import java.time.Instant;
-import java.util.AbstractMap;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.OptionalLong;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-import static software.amazon.lambda.powertools.core.internal.LambdaConstants.AWS_REGION_ENV;
-import static software.amazon.lambda.powertools.core.internal.LambdaConstants.LAMBDA_FUNCTION_NAME_ENV;
-import static software.amazon.lambda.powertools.idempotency.persistence.DataRecord.Status.INPROGRESS;
-
/**
* DynamoDB version of the {@link PersistenceStore}. Will store idempotency data in DynamoDB.
* Use the {@link Builder} to create a new instance.
@@ -83,7 +89,7 @@ private DynamoDBPersistenceStore(String tableName,
this.dynamoDbClient = client;
} else {
String idempotencyDisabledEnv = System.getenv().get(Constants.IDEMPOTENCY_DISABLED_ENV);
- if (idempotencyDisabledEnv == null || idempotencyDisabledEnv.equalsIgnoreCase("false")) {
+ if (idempotencyDisabledEnv == null || "false".equalsIgnoreCase(idempotencyDisabledEnv)) {
this.dynamoDbClient = DynamoDbClient.builder()
.httpClient(UrlConnectionHttpClient.builder().build())
.region(Region.of(System.getenv(AWS_REGION_ENV)))
@@ -96,6 +102,10 @@ private DynamoDBPersistenceStore(String tableName,
}
}
+ public static Builder builder() {
+ return new Builder();
+ }
+
@Override
public DataRecord getRecord(String idempotencyKey) throws IdempotencyItemNotFoundException {
GetItemResponse response = dynamoDbClient.getItem(
@@ -133,7 +143,9 @@ public void putRecord(DataRecord record, Instant now) throws IdempotencyItemAlre
item.put(this.statusAttr, AttributeValue.builder().s(record.getStatus().toString()).build());
if (record.getInProgressExpiryTimestamp().isPresent()) {
- item.put(this.inProgressExpiryAttr, AttributeValue.builder().n(String.valueOf(record.getInProgressExpiryTimestamp().getAsLong())).build());
+ item.put(this.inProgressExpiryAttr,
+ AttributeValue.builder().n(String.valueOf(record.getInProgressExpiryTimestamp().getAsLong()))
+ .build());
}
if (this.payloadValidationEnabled) {
@@ -151,9 +163,12 @@ public void putRecord(DataRecord record, Instant now) throws IdempotencyItemAlre
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
Map expressionAttributeValues = Stream.of(
- new AbstractMap.SimpleEntry<>(":now", AttributeValue.builder().n(String.valueOf(now.getEpochSecond())).build()),
- new AbstractMap.SimpleEntry<>(":now_milliseconds", AttributeValue.builder().n(String.valueOf(now.toEpochMilli())).build()),
- new AbstractMap.SimpleEntry<>(":inprogress", AttributeValue.builder().s(INPROGRESS.toString()).build())
+ new AbstractMap.SimpleEntry<>(":now",
+ AttributeValue.builder().n(String.valueOf(now.getEpochSecond())).build()),
+ new AbstractMap.SimpleEntry<>(":now_milliseconds",
+ AttributeValue.builder().n(String.valueOf(now.toEpochMilli())).build()),
+ new AbstractMap.SimpleEntry<>(":inprogress",
+ AttributeValue.builder().s(INPROGRESS.toString()).build())
).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
@@ -161,14 +176,16 @@ public void putRecord(DataRecord record, Instant now) throws IdempotencyItemAlre
PutItemRequest.builder()
.tableName(tableName)
.item(item)
- .conditionExpression("attribute_not_exists(#id) OR #expiry < :now OR (attribute_exists(#in_progress_expiry) AND #in_progress_expiry < :now_milliseconds AND #status = :inprogress)")
+ .conditionExpression(
+ "attribute_not_exists(#id) OR #expiry < :now OR (attribute_exists(#in_progress_expiry) AND #in_progress_expiry < :now_milliseconds AND #status = :inprogress)")
.expressionAttributeNames(expressionAttributeNames)
.expressionAttributeValues(expressionAttributeValues)
.build()
);
} catch (ConditionalCheckFailedException e) {
LOG.debug("Failed to put record for already existing idempotency key: {}", record.getIdempotencyKey());
- throw new IdempotencyItemAlreadyExistsException("Failed to put record for already existing idempotency key: " + record.getIdempotencyKey(), e);
+ throw new IdempotencyItemAlreadyExistsException(
+ "Failed to put record for already existing idempotency key: " + record.getIdempotencyKey(), e);
}
}
@@ -184,15 +201,19 @@ public void updateRecord(DataRecord record) {
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
Map expressionAttributeValues = Stream.of(
- new AbstractMap.SimpleEntry<>(":response_data", AttributeValue.builder().s(record.getResponseData()).build()),
- new AbstractMap.SimpleEntry<>(":expiry", AttributeValue.builder().n(String.valueOf(record.getExpiryTimestamp())).build()),
- new AbstractMap.SimpleEntry<>(":status", AttributeValue.builder().s(record.getStatus().toString()).build()))
+ new AbstractMap.SimpleEntry<>(":response_data",
+ AttributeValue.builder().s(record.getResponseData()).build()),
+ new AbstractMap.SimpleEntry<>(":expiry",
+ AttributeValue.builder().n(String.valueOf(record.getExpiryTimestamp())).build()),
+ new AbstractMap.SimpleEntry<>(":status",
+ AttributeValue.builder().s(record.getStatus().toString()).build()))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
if (payloadValidationEnabled) {
updateExpression += ", #validation_key = :validation_key";
expressionAttributeNames.put("#validation_key", this.validationAttr);
- expressionAttributeValues.put(":validation_key", AttributeValue.builder().s(record.getPayloadHash()).build());
+ expressionAttributeValues.put(":validation_key",
+ AttributeValue.builder().s(record.getPayloadHash()).build());
}
dynamoDbClient.updateItem(UpdateItemRequest.builder()
@@ -242,16 +263,14 @@ private DataRecord itemToRecord(Map item) {
// data and validation payload may be null
AttributeValue data = item.get(this.dataAttr);
AttributeValue validation = item.get(this.validationAttr);
- return new DataRecord(item.get(sortKeyAttr != null ? sortKeyAttr: keyAttr).s(),
+ return new DataRecord(item.get(sortKeyAttr != null ? sortKeyAttr : keyAttr).s(),
DataRecord.Status.valueOf(item.get(this.statusAttr).s()),
Long.parseLong(item.get(this.expiryAttr).n()),
data != null ? data.s() : null,
validation != null ? validation.s() : null,
- item.get(this.inProgressExpiryAttr) != null ? OptionalLong.of(Long.parseLong(item.get(this.inProgressExpiryAttr).n())) : OptionalLong.empty());
- }
-
- public static Builder builder() {
- return new Builder();
+ item.get(this.inProgressExpiryAttr) != null ?
+ OptionalLong.of(Long.parseLong(item.get(this.inProgressExpiryAttr).n())) :
+ OptionalLong.empty());
}
/**
@@ -288,7 +307,8 @@ public DynamoDBPersistenceStore build() {
if (StringUtils.isEmpty(tableName)) {
throw new IllegalArgumentException("Table name is not specified");
}
- return new DynamoDBPersistenceStore(tableName, keyAttr, staticPkValue, sortKeyAttr, expiryAttr, inProgressExpiryAttr, statusAttr, dataAttr, validationAttr, dynamoDbClient);
+ return new DynamoDBPersistenceStore(tableName, keyAttr, staticPkValue, sortKeyAttr, expiryAttr,
+ inProgressExpiryAttr, statusAttr, dataAttr, validationAttr, dynamoDbClient);
}
/**
diff --git a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/PersistenceStore.java b/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/PersistenceStore.java
index d199c99b5..c058b592e 100644
--- a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/PersistenceStore.java
+++ b/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/PersistenceStore.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2022 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,13 +11,13 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.idempotency.persistence;
+import java.time.Instant;
import software.amazon.lambda.powertools.idempotency.exceptions.IdempotencyItemAlreadyExistsException;
import software.amazon.lambda.powertools.idempotency.exceptions.IdempotencyItemNotFoundException;
-import java.time.Instant;
-
/**
* Persistence layer that will store the idempotency result.
* In order to provide another implementation, extends {@link BasePersistenceStore}.
@@ -26,6 +26,7 @@ public interface PersistenceStore {
/**
* Retrieve item from persistence store using idempotency key and return it as a DataRecord instance.
+ *
* @param idempotencyKey the key of the record
* @return DataRecord representation of existing record found in persistence store
* @throws IdempotencyItemNotFoundException Exception thrown if no record exists in persistence store with the idempotency key
@@ -34,6 +35,7 @@ public interface PersistenceStore {
/**
* Add a DataRecord to persistence store if it does not already exist with that key
+ *
* @param record DataRecord instance
* @param now
* @throws IdempotencyItemAlreadyExistsException if a non-expired entry already exists.
@@ -42,12 +44,14 @@ public interface PersistenceStore {
/**
* Update item in persistence store
+ *
* @param record DataRecord instance
*/
void updateRecord(DataRecord record);
/**
* Remove item from persistence store
+ *
* @param idempotencyKey the key of the record
*/
void deleteRecord(String idempotencyKey);
diff --git a/powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/DynamoDBConfig.java b/powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/DynamoDBConfig.java
index 38678322c..66ddb53ac 100644
--- a/powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/DynamoDBConfig.java
+++ b/powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/DynamoDBConfig.java
@@ -1,7 +1,24 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.idempotency;
import com.amazonaws.services.dynamodbv2.local.main.ServerRunner;
import com.amazonaws.services.dynamodbv2.local.server.DynamoDBProxyServer;
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.net.URI;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
@@ -9,11 +26,14 @@
import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
-import software.amazon.awssdk.services.dynamodb.model.*;
-
-import java.io.IOException;
-import java.net.ServerSocket;
-import java.net.URI;
+import software.amazon.awssdk.services.dynamodb.model.AttributeDefinition;
+import software.amazon.awssdk.services.dynamodb.model.BillingMode;
+import software.amazon.awssdk.services.dynamodb.model.CreateTableRequest;
+import software.amazon.awssdk.services.dynamodb.model.DescribeTableRequest;
+import software.amazon.awssdk.services.dynamodb.model.DescribeTableResponse;
+import software.amazon.awssdk.services.dynamodb.model.KeySchemaElement;
+import software.amazon.awssdk.services.dynamodb.model.KeyType;
+import software.amazon.awssdk.services.dynamodb.model.ScalarAttributeType;
public class DynamoDBConfig {
protected static final String TABLE_NAME = "idempotency_table";
@@ -24,7 +44,7 @@ public class DynamoDBConfig {
public static void setupDynamo() {
int port = getFreePort();
try {
- dynamoProxy = ServerRunner.createServerFromCommandLineArgs(new String[]{
+ dynamoProxy = ServerRunner.createServerFromCommandLineArgs(new String[] {
"-inMemory",
"-port",
Integer.toString(port)
@@ -51,7 +71,8 @@ public static void setupDynamo() {
.billingMode(BillingMode.PAY_PER_REQUEST)
.build());
- DescribeTableResponse response = client.describeTable(DescribeTableRequest.builder().tableName(TABLE_NAME).build());
+ DescribeTableResponse response =
+ client.describeTable(DescribeTableRequest.builder().tableName(TABLE_NAME).build());
if (response == null) {
throw new RuntimeException("Table was not created within expected time");
}
diff --git a/powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/IdempotencyTest.java b/powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/IdempotencyTest.java
index a782d9613..c94fec3db 100644
--- a/powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/IdempotencyTest.java
+++ b/powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/IdempotencyTest.java
@@ -1,6 +1,22 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.idempotency;
+import static org.assertj.core.api.Assertions.assertThat;
+
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent;
import com.amazonaws.services.lambda.runtime.tests.EventLoader;
@@ -11,8 +27,6 @@
import software.amazon.awssdk.services.dynamodb.model.ScanRequest;
import software.amazon.lambda.powertools.idempotency.handlers.IdempotencyFunction;
-import static org.assertj.core.api.Assertions.assertThat;
-
public class IdempotencyTest extends DynamoDBConfig {
@Mock
@@ -27,12 +41,14 @@ void setUp() {
public void endToEndTest() {
IdempotencyFunction function = new IdempotencyFunction(client);
- APIGatewayProxyResponseEvent response = function.handleRequest(EventLoader.loadApiGatewayRestEvent("apigw_event2.json"), context);
+ APIGatewayProxyResponseEvent response =
+ function.handleRequest(EventLoader.loadApiGatewayRestEvent("apigw_event2.json"), context);
assertThat(function.handlerExecuted).isTrue();
function.handlerExecuted = false;
- APIGatewayProxyResponseEvent response2 = function.handleRequest(EventLoader.loadApiGatewayRestEvent("apigw_event2.json"), context);
+ APIGatewayProxyResponseEvent response2 =
+ function.handleRequest(EventLoader.loadApiGatewayRestEvent("apigw_event2.json"), context);
assertThat(function.handlerExecuted).isFalse();
assertThat(response).isEqualTo(response2);
diff --git a/powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/handlers/IdempotencyEnabledFunction.java b/powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/handlers/IdempotencyEnabledFunction.java
index 6c39dc6de..f12edc87e 100644
--- a/powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/handlers/IdempotencyEnabledFunction.java
+++ b/powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/handlers/IdempotencyEnabledFunction.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,6 +11,7 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.idempotency.handlers;
import com.amazonaws.services.lambda.runtime.Context;
diff --git a/powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/handlers/IdempotencyFunction.java b/powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/handlers/IdempotencyFunction.java
index 0423bd90a..76c36ae9f 100644
--- a/powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/handlers/IdempotencyFunction.java
+++ b/powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/handlers/IdempotencyFunction.java
@@ -1,9 +1,30 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.idempotency.handlers;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.stream.Collectors;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
@@ -13,14 +34,6 @@
import software.amazon.lambda.powertools.idempotency.persistence.DynamoDBPersistenceStore;
import software.amazon.lambda.powertools.utilities.JsonConfig;
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.net.URL;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.stream.Collectors;
-
public class IdempotencyFunction implements RequestHandler {
private final static Logger LOG = LogManager.getLogger(IdempotencyFunction.class);
diff --git a/powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/handlers/IdempotencyInternalFunction.java b/powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/handlers/IdempotencyInternalFunction.java
index f3c1bdbc9..34e3eb319 100644
--- a/powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/handlers/IdempotencyInternalFunction.java
+++ b/powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/handlers/IdempotencyInternalFunction.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,6 +11,7 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.idempotency.handlers;
import com.amazonaws.services.lambda.runtime.Context;
@@ -38,14 +39,14 @@ public Basket handleRequest(Product input, Context context) {
if (registerContext) {
Idempotency.registerLambdaContext(context);
}
-
+
return createBasket("fake", input);
}
@Idempotent
private Basket createBasket(@IdempotencyKey String magicProduct, Product p) {
called = true;
- Basket b = new Basket(p);
+ Basket b = new Basket(p);
b.add(new Product(0, magicProduct, 0));
return b;
}
diff --git a/powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/handlers/IdempotencyInternalFunctionInternalKey.java b/powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/handlers/IdempotencyInternalFunctionInternalKey.java
index 566db6727..3ae500341 100644
--- a/powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/handlers/IdempotencyInternalFunctionInternalKey.java
+++ b/powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/handlers/IdempotencyInternalFunctionInternalKey.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,6 +11,7 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.idempotency.handlers;
import com.amazonaws.services.lambda.runtime.Context;
diff --git a/powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/handlers/IdempotencyInternalFunctionInvalid.java b/powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/handlers/IdempotencyInternalFunctionInvalid.java
index 4c82bff15..42e438798 100644
--- a/powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/handlers/IdempotencyInternalFunctionInvalid.java
+++ b/powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/handlers/IdempotencyInternalFunctionInvalid.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,6 +11,7 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.idempotency.handlers;
import com.amazonaws.services.lambda.runtime.Context;
@@ -33,7 +34,7 @@ public Basket handleRequest(Product input, Context context) {
@Idempotent
private Basket createBasket(String magicProduct, Product p) {
- Basket b = new Basket(p);
+ Basket b = new Basket(p);
b.add(new Product(0, magicProduct, 0));
return b;
}
diff --git a/powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/handlers/IdempotencyInternalFunctionVoid.java b/powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/handlers/IdempotencyInternalFunctionVoid.java
index a6b89fc8d..384ed5e86 100644
--- a/powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/handlers/IdempotencyInternalFunctionVoid.java
+++ b/powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/handlers/IdempotencyInternalFunctionVoid.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,6 +11,7 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.idempotency.handlers;
import com.amazonaws.services.lambda.runtime.Context;
@@ -28,7 +29,7 @@ public class IdempotencyInternalFunctionVoid implements RequestHandler function.handleRequest(p, context)).isInstanceOf(IdempotencyAlreadyInProgressException.class);
+ assertThatThrownBy(() -> function.handleRequest(p, context)).isInstanceOf(
+ IdempotencyAlreadyInProgressException.class);
}
@Test
- public void secondCall_inProgress_lambdaTimeout_timeoutExpired_shouldThrowInconsistentState() throws JsonProcessingException {
+ public void secondCall_inProgress_lambdaTimeout_timeoutExpired_shouldThrowInconsistentState()
+ throws JsonProcessingException {
// GIVEN
Idempotency.config()
.withPersistenceStore(store)
@@ -195,7 +210,8 @@ public void secondCall_inProgress_lambdaTimeout_timeoutExpired_shouldThrowIncons
Product p = new Product(42, "fake product", 12);
Basket b = new Basket(p);
- OptionalLong timestampInThePast = OptionalLong.of(Instant.now().toEpochMilli() - 100); // timeout expired 100ms ago
+ OptionalLong timestampInThePast =
+ OptionalLong.of(Instant.now().toEpochMilli() - 100); // timeout expired 100ms ago
DataRecord record = new DataRecord(
"42",
DataRecord.Status.INPROGRESS,
@@ -207,7 +223,8 @@ public void secondCall_inProgress_lambdaTimeout_timeoutExpired_shouldThrowIncons
// THEN
IdempotencyEnabledFunction function = new IdempotencyEnabledFunction();
- assertThatThrownBy(() -> function.handleRequest(p, context)).isInstanceOf(IdempotencyInconsistentStateException.class);
+ assertThatThrownBy(() -> function.handleRequest(p, context)).isInstanceOf(
+ IdempotencyInconsistentStateException.class);
}
@Test
@@ -278,7 +295,8 @@ public void idempotencyOnSubMethodAnnotated_firstCall_shouldPutInStore() {
ArgumentCaptor resultCaptor = ArgumentCaptor.forClass(Basket.class);
verify(store).saveSuccess(any(), resultCaptor.capture(), any());
- assertThat(resultCaptor.getValue().getProducts()).contains(basket.getProducts().get(0), new Product(0, "fake", 0));
+ assertThat(resultCaptor.getValue().getProducts()).contains(basket.getProducts().get(0),
+ new Product(0, "fake", 0));
}
@Test
@@ -305,11 +323,13 @@ public void idempotencyOnSubMethodAnnotated_firstCall_contextNotRegistered_shoul
ArgumentCaptor resultCaptor = ArgumentCaptor.forClass(Basket.class);
verify(store).saveSuccess(any(), resultCaptor.capture(), any());
- assertThat(resultCaptor.getValue().getProducts()).contains(basket.getProducts().get(0), new Product(0, "fake", 0));
+ assertThat(resultCaptor.getValue().getProducts()).contains(basket.getProducts().get(0),
+ new Product(0, "fake", 0));
}
@Test
- public void idempotencyOnSubMethodAnnotated_secondCall_notExpired_shouldGetFromStore() throws JsonProcessingException {
+ public void idempotencyOnSubMethodAnnotated_secondCall_notExpired_shouldGetFromStore()
+ throws JsonProcessingException {
// GIVEN
Idempotency.config()
.withPersistenceStore(store)
@@ -354,7 +374,8 @@ public void idempotencyOnSubMethodAnnotated_keyJMESPath_shouldPutInStoreWithKey(
ArgumentCaptor recordCaptor = ArgumentCaptor.forClass(DataRecord.class);
verify(persistenceStore).putRecord(recordCaptor.capture(), any());
// a1d0c6e83f027327d8461063f4ac58a6 = MD5(42)
- assertThat(recordCaptor.getValue().getIdempotencyKey()).isEqualTo("testFunction.createBasket#a1d0c6e83f027327d8461063f4ac58a6");
+ assertThat(recordCaptor.getValue().getIdempotencyKey()).isEqualTo(
+ "testFunction.createBasket#a1d0c6e83f027327d8461063f4ac58a6");
}
@Test
@@ -369,7 +390,8 @@ public void idempotencyOnSubMethodNotAnnotated_shouldThrowException() {
Product p = new Product(42, "fake product", 12);
// THEN
- assertThatThrownBy(() -> function.handleRequest(p, context)).isInstanceOf(IdempotencyConfigurationException.class);
+ assertThatThrownBy(() -> function.handleRequest(p, context)).isInstanceOf(
+ IdempotencyConfigurationException.class);
}
@Test
@@ -384,7 +406,8 @@ public void idempotencyOnSubMethodVoid_shouldThrowException() {
Product p = new Product(42, "fake product", 12);
// THEN
- assertThatThrownBy(() -> function.handleRequest(p, context)).isInstanceOf(IdempotencyConfigurationException.class);
+ assertThatThrownBy(() -> function.handleRequest(p, context)).isInstanceOf(
+ IdempotencyConfigurationException.class);
}
}
diff --git a/powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/internal/cache/LRUCacheTest.java b/powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/internal/cache/LRUCacheTest.java
index 3d2f7c7e3..8854be1f2 100644
--- a/powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/internal/cache/LRUCacheTest.java
+++ b/powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/internal/cache/LRUCacheTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2022 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,12 +11,13 @@
* limitations under the License.
*
*/
-package software.amazon.lambda.powertools.idempotency.internal.cache;
-import org.junit.jupiter.api.Test;
+package software.amazon.lambda.powertools.idempotency.internal.cache;
import static org.assertj.core.api.Assertions.assertThat;
+import org.junit.jupiter.api.Test;
+
public class LRUCacheTest {
@Test
diff --git a/powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/model/Basket.java b/powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/model/Basket.java
index 304fd3810..a17bb8abf 100644
--- a/powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/model/Basket.java
+++ b/powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/model/Basket.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2022 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,6 +11,7 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.idempotency.model;
import java.util.ArrayList;
@@ -21,19 +22,19 @@
public class Basket {
private List products = new ArrayList<>();
- public List getProducts() {
- return products;
+ public Basket() {
}
- public void setProducts(List products) {
- this.products = products;
+ public Basket(Product... p) {
+ products.addAll(Arrays.asList(p));
}
- public Basket() {
+ public List getProducts() {
+ return products;
}
- public Basket( Product ...p){
- products.addAll(Arrays.asList(p));
+ public void setProducts(List products) {
+ this.products = products;
}
public void add(Product product) {
@@ -42,8 +43,12 @@ public void add(Product product) {
@Override
public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
Basket basket = (Basket) o;
return products.equals(basket.products);
}
diff --git a/powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/model/Product.java b/powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/model/Product.java
index 1c66c584d..7fa191d82 100644
--- a/powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/model/Product.java
+++ b/powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/model/Product.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2022 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,6 +11,7 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.idempotency.model;
import java.util.Objects;
@@ -57,8 +58,12 @@ public void setPrice(double price) {
@Override
public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
Product product = (Product) o;
return id == product.id && Double.compare(product.price, price) == 0 && Objects.equals(name, product.name);
}
diff --git a/powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/persistence/BasePersistenceStoreTest.java b/powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/persistence/BasePersistenceStoreTest.java
index 6b58fa8a5..67bc5aa22 100644
--- a/powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/persistence/BasePersistenceStoreTest.java
+++ b/powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/persistence/BasePersistenceStoreTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2022 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,13 +11,21 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.idempotency.persistence;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent;
import com.amazonaws.services.lambda.runtime.tests.EventLoader;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.node.DoubleNode;
import com.fasterxml.jackson.databind.node.TextNode;
+import java.time.Duration;
+import java.time.Instant;
+import java.time.temporal.ChronoUnit;
+import java.util.OptionalInt;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import software.amazon.lambda.powertools.idempotency.IdempotencyConfig;
@@ -29,14 +37,6 @@
import software.amazon.lambda.powertools.idempotency.model.Product;
import software.amazon.lambda.powertools.utilities.JsonConfig;
-import java.time.Duration;
-import java.time.Instant;
-import java.time.temporal.ChronoUnit;
-import java.util.OptionalInt;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatThrownBy;
-
public class BasePersistenceStoreTest {
private DataRecord dr;
@@ -53,7 +53,8 @@ public void setup() {
@Override
public DataRecord getRecord(String idempotencyKey) throws IdempotencyItemNotFoundException {
status = 0;
- return new DataRecord(idempotencyKey, DataRecord.Status.INPROGRESS, Instant.now().plus(3600, ChronoUnit.SECONDS).getEpochSecond(), "Response", validationHash);
+ return new DataRecord(idempotencyKey, DataRecord.Status.INPROGRESS,
+ Instant.now().plus(3600, ChronoUnit.SECONDS).getEpochSecond(), "Response", validationHash);
}
@Override
@@ -84,7 +85,8 @@ public void saveInProgress_defaultConfig() {
persistenceStore.configure(IdempotencyConfig.builder().build(), null);
Instant now = Instant.now();
- persistenceStore.saveInProgress(JsonConfig.get().getObjectMapper().valueToTree(event), now, OptionalInt.empty());
+ persistenceStore.saveInProgress(JsonConfig.get().getObjectMapper().valueToTree(event), now,
+ OptionalInt.empty());
assertThat(dr.getStatus()).isEqualTo(DataRecord.Status.INPROGRESS);
assertThat(dr.getExpiryTimestamp()).isEqualTo(now.plus(3600, ChronoUnit.SECONDS).getEpochSecond());
assertThat(dr.getResponseData()).isNull();
@@ -101,13 +103,15 @@ public void saveInProgress_withRemainingTime() {
int lambdaTimeoutMs = 30000;
Instant now = Instant.now();
- persistenceStore.saveInProgress(JsonConfig.get().getObjectMapper().valueToTree(event), now, OptionalInt.of(lambdaTimeoutMs));
+ persistenceStore.saveInProgress(JsonConfig.get().getObjectMapper().valueToTree(event), now,
+ OptionalInt.of(lambdaTimeoutMs));
assertThat(dr.getStatus()).isEqualTo(DataRecord.Status.INPROGRESS);
assertThat(dr.getExpiryTimestamp()).isEqualTo(now.plus(3600, ChronoUnit.SECONDS).getEpochSecond());
assertThat(dr.getResponseData()).isNull();
assertThat(dr.getIdempotencyKey()).isEqualTo("testFunction#7b40f56c086de5aa91dc467456329ed2");
assertThat(dr.getPayloadHash()).isEqualTo("");
- assertThat(dr.getInProgressExpiryTimestamp().orElse(-1)).isEqualTo(now.plus(lambdaTimeoutMs, ChronoUnit.MILLIS).toEpochMilli());
+ assertThat(dr.getInProgressExpiryTimestamp().orElse(-1)).isEqualTo(
+ now.plus(lambdaTimeoutMs, ChronoUnit.MILLIS).toEpochMilli());
assertThat(status).isEqualTo(1);
}
@@ -119,7 +123,8 @@ public void saveInProgress_jmespath() {
.build(), "myfunc");
Instant now = Instant.now();
- persistenceStore.saveInProgress(JsonConfig.get().getObjectMapper().valueToTree(event), now, OptionalInt.empty());
+ persistenceStore.saveInProgress(JsonConfig.get().getObjectMapper().valueToTree(event), now,
+ OptionalInt.empty());
assertThat(dr.getStatus()).isEqualTo(DataRecord.Status.INPROGRESS);
assertThat(dr.getExpiryTimestamp()).isEqualTo(now.plus(3600, ChronoUnit.SECONDS).getEpochSecond());
assertThat(dr.getResponseData()).isNull();
@@ -136,7 +141,9 @@ public void saveInProgress_jmespath_NotFound_shouldThrowException() {
.withThrowOnNoIdempotencyKey(true) // should throw
.build(), "");
Instant now = Instant.now();
- assertThatThrownBy(() -> persistenceStore.saveInProgress(JsonConfig.get().getObjectMapper().valueToTree(event), now, OptionalInt.empty()))
+ assertThatThrownBy(
+ () -> persistenceStore.saveInProgress(JsonConfig.get().getObjectMapper().valueToTree(event), now,
+ OptionalInt.empty()))
.isInstanceOf(IdempotencyKeyException.class)
.hasMessageContaining("No data found to create a hashed idempotency key");
assertThat(status).isEqualTo(-1);
@@ -149,7 +156,8 @@ public void saveInProgress_jmespath_NotFound_shouldNotPersist() {
.withEventKeyJMESPath("unavailable")
.build(), "");
Instant now = Instant.now();
- persistenceStore.saveInProgress(JsonConfig.get().getObjectMapper().valueToTree(event), now, OptionalInt.empty());
+ persistenceStore.saveInProgress(JsonConfig.get().getObjectMapper().valueToTree(event), now,
+ OptionalInt.empty());
assertThat(dr).isNull();
assertThat(status).isEqualTo(-1);
}
@@ -170,7 +178,9 @@ public void saveInProgress_withLocalCache_NotExpired_ShouldThrowException() {
now.plus(3600, ChronoUnit.SECONDS).getEpochSecond(),
null, null)
);
- assertThatThrownBy(() -> persistenceStore.saveInProgress(JsonConfig.get().getObjectMapper().valueToTree(event), now, OptionalInt.empty()))
+ assertThatThrownBy(
+ () -> persistenceStore.saveInProgress(JsonConfig.get().getObjectMapper().valueToTree(event), now,
+ OptionalInt.empty()))
.isInstanceOf(IdempotencyItemAlreadyExistsException.class);
assertThat(status).isEqualTo(-1);
}
@@ -192,7 +202,8 @@ public void saveInProgress_withLocalCache_Expired_ShouldRemoveFromCache() {
now.minus(3, ChronoUnit.SECONDS).getEpochSecond(),
null, null)
);
- persistenceStore.saveInProgress(JsonConfig.get().getObjectMapper().valueToTree(event), now, OptionalInt.empty());
+ persistenceStore.saveInProgress(JsonConfig.get().getObjectMapper().valueToTree(event), now,
+ OptionalInt.empty());
assertThat(dr.getStatus()).isEqualTo(DataRecord.Status.INPROGRESS);
assertThat(cache).isEmpty();
assertThat(status).isEqualTo(1);
@@ -250,7 +261,8 @@ public void saveSuccess_withCacheEnabled_shouldSaveInCache() throws JsonProcessi
//
@Test
- public void getRecord_shouldReturnRecordFromPersistence() throws IdempotencyItemNotFoundException, IdempotencyValidationException {
+ public void getRecord_shouldReturnRecordFromPersistence()
+ throws IdempotencyItemNotFoundException, IdempotencyValidationException {
APIGatewayProxyRequestEvent event = EventLoader.loadApiGatewayRestEvent("apigw_event.json");
LRUCache cache = new LRUCache<>(2);
persistenceStore.configure(IdempotencyConfig.builder().build(), "myfunc", cache);
@@ -264,7 +276,8 @@ public void getRecord_shouldReturnRecordFromPersistence() throws IdempotencyItem
}
@Test
- public void getRecord_cacheEnabledNotExpired_shouldReturnRecordFromCache() throws IdempotencyItemNotFoundException, IdempotencyValidationException {
+ public void getRecord_cacheEnabledNotExpired_shouldReturnRecordFromCache()
+ throws IdempotencyItemNotFoundException, IdempotencyValidationException {
APIGatewayProxyRequestEvent event = EventLoader.loadApiGatewayRestEvent("apigw_event.json");
LRUCache cache = new LRUCache<>(2);
persistenceStore.configure(IdempotencyConfig.builder()
@@ -287,7 +300,8 @@ public void getRecord_cacheEnabledNotExpired_shouldReturnRecordFromCache() throw
}
@Test
- public void getRecord_cacheEnabledExpired_shouldReturnRecordFromPersistence() throws IdempotencyItemNotFoundException, IdempotencyValidationException {
+ public void getRecord_cacheEnabledExpired_shouldReturnRecordFromPersistence()
+ throws IdempotencyItemNotFoundException, IdempotencyValidationException {
APIGatewayProxyRequestEvent event = EventLoader.loadApiGatewayRestEvent("apigw_event.json");
LRUCache cache = new LRUCache<>(2);
persistenceStore.configure(IdempotencyConfig.builder()
@@ -314,14 +328,15 @@ public void getRecord_cacheEnabledExpired_shouldReturnRecordFromPersistence() th
public void getRecord_invalidPayload_shouldThrowValidationException() {
APIGatewayProxyRequestEvent event = EventLoader.loadApiGatewayRestEvent("apigw_event.json");
persistenceStore.configure(IdempotencyConfig.builder()
- .withEventKeyJMESPath("powertools_json(body).id")
- .withPayloadValidationJMESPath("powertools_json(body).message")
- .build(),
+ .withEventKeyJMESPath("powertools_json(body).id")
+ .withPayloadValidationJMESPath("powertools_json(body).message")
+ .build(),
"myfunc");
this.validationHash = "different hash"; // "Lambda rocks" ==> 70c24d88041893f7fbab4105b76fd9e1
- assertThatThrownBy(() -> persistenceStore.getRecord(JsonConfig.get().getObjectMapper().valueToTree(event), Instant.now()))
+ assertThatThrownBy(
+ () -> persistenceStore.getRecord(JsonConfig.get().getObjectMapper().valueToTree(event), Instant.now()))
.isInstanceOf(IdempotencyValidationException.class);
}
@@ -348,7 +363,8 @@ public void deleteRecord_cacheEnabled_shouldDeleteRecordFromCache() {
.withUseLocalCache(true).build(), null, cache);
cache.put("testFunction#7b40f56c086de5aa91dc467456329ed2",
- new DataRecord("testFunction#7b40f56c086de5aa91dc467456329ed2", DataRecord.Status.COMPLETED, 123, null, null));
+ new DataRecord("testFunction#7b40f56c086de5aa91dc467456329ed2", DataRecord.Status.COMPLETED, 123, null,
+ null));
persistenceStore.deleteRecord(JsonConfig.get().getObjectMapper().valueToTree(event), new ArithmeticException());
assertThat(status).isEqualTo(3);
assertThat(cache).isEmpty();
@@ -385,7 +401,8 @@ public void generateHashDouble_shouldGenerateMd5ofDouble() {
@Test
public void generateHashString_withSha256Algorithm_shouldGenerateSha256ofString() {
persistenceStore.configure(IdempotencyConfig.builder().withHashFunction("SHA-256").build(), null);
- String expectedHash = "e6139efa88ef3337e901e826e6f327337f414860fb499d9f26eefcff21d719af"; // SHA-256(Lambda rocks)
+ String expectedHash =
+ "e6139efa88ef3337e901e826e6f327337f414860fb499d9f26eefcff21d719af"; // SHA-256(Lambda rocks)
String generatedHash = persistenceStore.generateHash(new TextNode("Lambda rocks"));
assertThat(generatedHash).isEqualTo(expectedHash);
}
diff --git a/powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/persistence/DynamoDBPersistenceStoreTest.java b/powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/persistence/DynamoDBPersistenceStoreTest.java
index 768da2eaa..b19cebfe1 100644
--- a/powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/persistence/DynamoDBPersistenceStoreTest.java
+++ b/powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/persistence/DynamoDBPersistenceStoreTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2022 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,28 +11,39 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.idempotency.persistence;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import java.time.Instant;
+import java.time.temporal.ChronoUnit;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junitpioneer.jupiter.SetEnvironmentVariable;
-import software.amazon.awssdk.services.dynamodb.model.*;
+import software.amazon.awssdk.services.dynamodb.model.AttributeDefinition;
+import software.amazon.awssdk.services.dynamodb.model.AttributeValue;
+import software.amazon.awssdk.services.dynamodb.model.BillingMode;
+import software.amazon.awssdk.services.dynamodb.model.CreateTableRequest;
+import software.amazon.awssdk.services.dynamodb.model.DeleteItemRequest;
+import software.amazon.awssdk.services.dynamodb.model.DeleteTableRequest;
+import software.amazon.awssdk.services.dynamodb.model.GetItemRequest;
+import software.amazon.awssdk.services.dynamodb.model.KeySchemaElement;
+import software.amazon.awssdk.services.dynamodb.model.KeyType;
+import software.amazon.awssdk.services.dynamodb.model.PutItemRequest;
+import software.amazon.awssdk.services.dynamodb.model.ScalarAttributeType;
+import software.amazon.awssdk.services.dynamodb.model.ScanRequest;
import software.amazon.lambda.powertools.idempotency.Constants;
import software.amazon.lambda.powertools.idempotency.DynamoDBConfig;
import software.amazon.lambda.powertools.idempotency.IdempotencyConfig;
import software.amazon.lambda.powertools.idempotency.exceptions.IdempotencyItemAlreadyExistsException;
import software.amazon.lambda.powertools.idempotency.exceptions.IdempotencyItemNotFoundException;
-import java.time.Instant;
-import java.time.temporal.ChronoUnit;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatThrownBy;
-
/**
* These test are using DynamoDBLocal and sqlite, see https://nickolasfisher.com/blog/Configuring-an-In-Memory-DynamoDB-instance-with-Java-for-Integration-Testing
* NOTE: on a Mac with Apple Chipset, you need to use the Oracle JDK x86 64-bit
@@ -51,7 +62,8 @@ public void putRecord_shouldCreateRecordInDynamoDB() throws IdempotencyItemAlrea
dynamoDBPersistenceStore.putRecord(new DataRecord("key", DataRecord.Status.COMPLETED, expiry, null, null), now);
key = Collections.singletonMap("id", AttributeValue.builder().s("key").build());
- Map item = client.getItem(GetItemRequest.builder().tableName(TABLE_NAME).key(key).build()).item();
+ Map item =
+ client.getItem(GetItemRequest.builder().tableName(TABLE_NAME).key(key).build()).item();
assertThat(item).isNotNull();
assertThat(item.get("status").s()).isEqualTo("COMPLETED");
assertThat(item.get("expiration").n()).isEqualTo(String.valueOf(expiry));
@@ -81,7 +93,8 @@ public void putRecord_shouldCreateRecordInDynamoDB_IfPreviousExpired() {
), now);
// THEN: an item is inserted
- Map itemInDb = client.getItem(GetItemRequest.builder().tableName(TABLE_NAME).key(key).build()).item();
+ Map itemInDb =
+ client.getItem(GetItemRequest.builder().tableName(TABLE_NAME).key(key).build()).item();
assertThat(itemInDb).isNotNull();
assertThat(itemInDb.get("status").s()).isEqualTo("INPROGRESS");
assertThat(itemInDb.get("expiration").n()).isEqualTo(String.valueOf(expiry2));
@@ -113,7 +126,8 @@ public void putRecord_shouldCreateRecordInDynamoDB_IfLambdaWasInProgressAndTimed
), now);
// THEN: an item is inserted
- Map itemInDb = client.getItem(GetItemRequest.builder().tableName(TABLE_NAME).key(key).build()).item();
+ Map itemInDb =
+ client.getItem(GetItemRequest.builder().tableName(TABLE_NAME).key(key).build()).item();
assertThat(itemInDb).isNotNull();
assertThat(itemInDb.get("status").s()).isEqualTo("INPROGRESS");
assertThat(itemInDb.get("expiration").n()).isEqualTo(String.valueOf(expiry2));
@@ -144,7 +158,8 @@ public void putRecord_shouldThrowIdempotencyItemAlreadyExistsException_IfRecordA
).isInstanceOf(IdempotencyItemAlreadyExistsException.class);
// THEN: item was not updated, retrieve the initial one
- Map itemInDb = client.getItem(GetItemRequest.builder().tableName(TABLE_NAME).key(key).build()).item();
+ Map itemInDb =
+ client.getItem(GetItemRequest.builder().tableName(TABLE_NAME).key(key).build()).item();
assertThat(itemInDb).isNotNull();
assertThat(itemInDb.get("status").s()).isEqualTo("COMPLETED");
assertThat(itemInDb.get("expiration").n()).isEqualTo(String.valueOf(expiry));
@@ -178,7 +193,8 @@ public void putRecord_shouldBlockUpdate_IfRecordAlreadyExistAndProgressNotExpire
.isInstanceOf(IdempotencyItemAlreadyExistsException.class);
// THEN: item was not updated, retrieve the initial one
- Map itemInDb = client.getItem(GetItemRequest.builder().tableName(TABLE_NAME).key(key).build()).item();
+ Map itemInDb =
+ client.getItem(GetItemRequest.builder().tableName(TABLE_NAME).key(key).build()).item();
assertThat(itemInDb).isNotNull();
assertThat(itemInDb.get("status").s()).isEqualTo("INPROGRESS");
assertThat(itemInDb.get("expiration").n()).isEqualTo(String.valueOf(expiry));
@@ -217,7 +233,8 @@ public void getRecord_shouldReturnExistingRecord() throws IdempotencyItemNotFoun
@Test
public void getRecord_shouldThrowException_whenRecordIsAbsent() {
- assertThatThrownBy(() -> dynamoDBPersistenceStore.getRecord("key")).isInstanceOf(IdempotencyItemNotFoundException.class);
+ assertThatThrownBy(() -> dynamoDBPersistenceStore.getRecord("key")).isInstanceOf(
+ IdempotencyItemNotFoundException.class);
}
//
@@ -237,7 +254,8 @@ public void updateRecord_shouldUpdateRecord() {
item.put("status", AttributeValue.builder().s(DataRecord.Status.INPROGRESS.toString()).build());
client.putItem(PutItemRequest.builder().tableName(TABLE_NAME).item(item).build());
// enable payload validation
- dynamoDBPersistenceStore.configure(IdempotencyConfig.builder().withPayloadValidationJMESPath("path").build(), null);
+ dynamoDBPersistenceStore.configure(IdempotencyConfig.builder().withPayloadValidationJMESPath("path").build(),
+ null);
// WHEN
expiry = now.plus(3600, ChronoUnit.SECONDS).getEpochSecond();
@@ -245,7 +263,8 @@ public void updateRecord_shouldUpdateRecord() {
dynamoDBPersistenceStore.updateRecord(record);
// THEN
- Map itemInDb = client.getItem(GetItemRequest.builder().tableName(TABLE_NAME).key(key).build()).item();
+ Map itemInDb =
+ client.getItem(GetItemRequest.builder().tableName(TABLE_NAME).key(key).build()).item();
assertThat(itemInDb.get("status").s()).isEqualTo("COMPLETED");
assertThat(itemInDb.get("expiration").n()).isEqualTo(String.valueOf(expiry));
assertThat(itemInDb.get("data").s()).isEqualTo("Fake result");
@@ -290,8 +309,10 @@ public void endToEndWithCustomAttrNamesAndSortKey() throws IdempotencyItemNotFou
KeySchemaElement.builder().keyType(KeyType.RANGE).attributeName("sortkey").build()
)
.attributeDefinitions(
- AttributeDefinition.builder().attributeName("key").attributeType(ScalarAttributeType.S).build(),
- AttributeDefinition.builder().attributeName("sortkey").attributeType(ScalarAttributeType.S).build()
+ AttributeDefinition.builder().attributeName("key").attributeType(ScalarAttributeType.S)
+ .build(),
+ AttributeDefinition.builder().attributeName("sortkey").attributeType(ScalarAttributeType.S)
+ .build()
)
.billingMode(BillingMode.PAY_PER_REQUEST)
.build());
@@ -323,7 +344,8 @@ public void endToEndWithCustomAttrNamesAndSortKey() throws IdempotencyItemNotFou
customKey.put("key", AttributeValue.builder().s("pk").build());
customKey.put("sortkey", AttributeValue.builder().s("mykey").build());
- Map itemInDb = client.getItem(GetItemRequest.builder().tableName(TABLE_NAME_CUSTOM).key(customKey).build()).item();
+ Map itemInDb =
+ client.getItem(GetItemRequest.builder().tableName(TABLE_NAME_CUSTOM).key(customKey).build()).item();
// GET
DataRecord recordInDb = persistenceStore.getRecord("mykey");
diff --git a/powertools-logging/pom.xml b/powertools-logging/pom.xml
index 767fbd3ee..83650fcde 100644
--- a/powertools-logging/pom.xml
+++ b/powertools-logging/pom.xml
@@ -1,4 +1,18 @@
+
+
@@ -127,4 +141,12 @@
+
+
+
+ org.apache.maven.plugins
+ maven-checkstyle-plugin
+
+
+
\ No newline at end of file
diff --git a/powertools-metrics/src/main/java/software/amazon/cloudwatchlogs/emf/model/MetricsLoggerHelper.java b/powertools-metrics/src/main/java/software/amazon/cloudwatchlogs/emf/model/MetricsLoggerHelper.java
index f59658e9c..e2d886fe5 100644
--- a/powertools-metrics/src/main/java/software/amazon/cloudwatchlogs/emf/model/MetricsLoggerHelper.java
+++ b/powertools-metrics/src/main/java/software/amazon/cloudwatchlogs/emf/model/MetricsLoggerHelper.java
@@ -1,9 +1,23 @@
-package software.amazon.cloudwatchlogs.emf.model;
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
-import java.lang.reflect.Field;
+package software.amazon.cloudwatchlogs.emf.model;
import static software.amazon.lambda.powertools.metrics.MetricsUtils.metricsLogger;
+import java.lang.reflect.Field;
+
public final class MetricsLoggerHelper {
private MetricsLoggerHelper() {
}
diff --git a/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/Metrics.java b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/Metrics.java
index 2a4f4d472..fb92c900d 100644
--- a/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/Metrics.java
+++ b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/Metrics.java
@@ -1,3 +1,17 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.metrics;
import java.lang.annotation.ElementType;
@@ -44,7 +58,10 @@
@Target(ElementType.METHOD)
public @interface Metrics {
String namespace() default "";
+
String service() default "";
+
boolean captureColdStart() default false;
+
boolean raiseOnEmptyMetrics() default false;
}
diff --git a/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/MetricsUtils.java b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/MetricsUtils.java
index 8705c2da4..1da100f26 100644
--- a/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/MetricsUtils.java
+++ b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/MetricsUtils.java
@@ -1,9 +1,28 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.metrics;
+import static java.util.Objects.requireNonNull;
+import static java.util.Optional.ofNullable;
+import static software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor.getXrayTraceId;
+import static software.amazon.lambda.powertools.metrics.internal.LambdaMetricsAspect.REQUEST_ID_PROPERTY;
+import static software.amazon.lambda.powertools.metrics.internal.LambdaMetricsAspect.TRACE_ID_PROPERTY;
+
import java.util.Arrays;
import java.util.Optional;
import java.util.function.Consumer;
-
import software.amazon.cloudwatchlogs.emf.config.SystemWrapper;
import software.amazon.cloudwatchlogs.emf.environment.EnvironmentProvider;
import software.amazon.cloudwatchlogs.emf.logger.MetricsLogger;
@@ -12,16 +31,10 @@
import software.amazon.cloudwatchlogs.emf.model.MetricsLoggerHelper;
import software.amazon.cloudwatchlogs.emf.model.Unit;
-import static java.util.Objects.requireNonNull;
-import static java.util.Optional.ofNullable;
-import static software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor.getXrayTraceId;
-import static software.amazon.lambda.powertools.metrics.internal.LambdaMetricsAspect.REQUEST_ID_PROPERTY;
-import static software.amazon.lambda.powertools.metrics.internal.LambdaMetricsAspect.TRACE_ID_PROPERTY;
-
/**
* A class used to retrieve the instance of the {@code MetricsLogger} used by
* {@code Metrics}.
- *
+ *
* {@see Metrics}
*/
public final class MetricsUtils {
@@ -43,6 +56,7 @@ public static MetricsLogger metricsLogger() {
/**
* Configure default dimension to be used by logger.
* By default, @{@link Metrics} annotation captures configured service as a dimension Service
+ *
* @param dimensionSets Default value of dimensions set for logger
*/
public static void defaultDimensions(final DimensionSet... dimensionSets) {
@@ -52,15 +66,15 @@ public static void defaultDimensions(final DimensionSet... dimensionSets) {
/**
* Configure default dimension to be used by logger.
* By default, @{@link Metrics} annotation captures configured service as a dimension Service
+ *
* @param dimensionSet Default value of dimension set for logger
* @deprecated use {@link #defaultDimensions(DimensionSet...)} instead
- *
*/
@Deprecated
public static void defaultDimensionSet(final DimensionSet dimensionSet) {
requireNonNull(dimensionSet, "Null dimension set not allowed");
- if(dimensionSet.getDimensionKeys().size() > 0) {
+ if (dimensionSet.getDimensionKeys().size() > 0) {
defaultDimensions(dimensionSet);
}
}
@@ -81,10 +95,11 @@ public static void withSingleMetric(final String name,
final double value,
final Unit unit,
final Consumer logger) {
- withMetricsLogger(metricsLogger -> {
- metricsLogger.putMetric(name, value, unit);
- logger.accept(metricsLogger);
- });
+ withMetricsLogger(metricsLogger ->
+ {
+ metricsLogger.putMetric(name, value, unit);
+ logger.accept(metricsLogger);
+ });
}
/**
@@ -92,22 +107,23 @@ public static void withSingleMetric(final String name,
* It by default captures function_request_id as property if used together with {@link Metrics} annotation. It will also
* capture xray_trace_id as property if tracing is enabled.
*
- * @param name the name of the metric
- * @param value the value of the metric
- * @param unit the unit type of the metric
+ * @param name the name of the metric
+ * @param value the value of the metric
+ * @param unit the unit type of the metric
* @param namespace the namespace associated with the metric
- * @param logger the MetricsLogger
+ * @param logger the MetricsLogger
*/
public static void withSingleMetric(final String name,
final double value,
final Unit unit,
final String namespace,
final Consumer logger) {
- withMetricsLogger(metricsLogger -> {
- metricsLogger.setNamespace(namespace);
- metricsLogger.putMetric(name, value, unit);
- logger.accept(metricsLogger);
- });
+ withMetricsLogger(metricsLogger ->
+ {
+ metricsLogger.setNamespace(namespace);
+ metricsLogger.putMetric(name, value, unit);
+ logger.accept(metricsLogger);
+ });
}
/**
@@ -137,7 +153,6 @@ public static void withMetricsLogger(final Consumer logger) {
* capture xray_trace_id as property if tracing is enabled.
*
* @param logger the MetricsLogger
- *
* @deprecated use {@link MetricsUtils#withMetricsLogger} instead
*/
@Deprecated
@@ -164,7 +179,7 @@ private static void captureRequestAndTraceId(MetricsLogger metricsLogger) {
private static String defaultNameSpace() {
MetricsContext context = MetricsLoggerHelper.metricsContext();
return "aws-embedded-metrics".equals(context.getNamespace()) ?
- SystemWrapper.getenv("POWERTOOLS_METRICS_NAMESPACE"): context.getNamespace();
+ SystemWrapper.getenv("POWERTOOLS_METRICS_NAMESPACE") : context.getNamespace();
}
private static Optional awsRequestId() {
diff --git a/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/ValidationException.java b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/ValidationException.java
index 2da9a539c..a553abbbd 100644
--- a/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/ValidationException.java
+++ b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/ValidationException.java
@@ -1,3 +1,17 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.metrics;
public class ValidationException extends RuntimeException {
diff --git a/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/LambdaMetricsAspect.java b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/LambdaMetricsAspect.java
index 927359fc5..8ca069b01 100644
--- a/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/LambdaMetricsAspect.java
+++ b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/LambdaMetricsAspect.java
@@ -1,8 +1,31 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.metrics.internal;
-import java.lang.reflect.Field;
+import static software.amazon.cloudwatchlogs.emf.model.MetricsLoggerHelper.dimensionsCount;
+import static software.amazon.cloudwatchlogs.emf.model.MetricsLoggerHelper.hasNoMetrics;
+import static software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor.coldStartDone;
+import static software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor.extractContext;
+import static software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor.isColdStart;
+import static software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor.isHandlerMethod;
+import static software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor.serviceName;
+import static software.amazon.lambda.powertools.metrics.MetricsUtils.hasDefaultDimension;
+import static software.amazon.lambda.powertools.metrics.MetricsUtils.metricsLogger;
import com.amazonaws.services.lambda.runtime.Context;
+import java.lang.reflect.Field;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
@@ -16,21 +39,33 @@
import software.amazon.lambda.powertools.metrics.MetricsUtils;
import software.amazon.lambda.powertools.metrics.ValidationException;
-import static software.amazon.cloudwatchlogs.emf.model.MetricsLoggerHelper.dimensionsCount;
-import static software.amazon.cloudwatchlogs.emf.model.MetricsLoggerHelper.hasNoMetrics;
-import static software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor.coldStartDone;
-import static software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor.extractContext;
-import static software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor.isColdStart;
-import static software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor.isHandlerMethod;
-import static software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor.serviceName;
-import static software.amazon.lambda.powertools.metrics.MetricsUtils.hasDefaultDimension;
-import static software.amazon.lambda.powertools.metrics.MetricsUtils.metricsLogger;
-
@Aspect
public class LambdaMetricsAspect {
- private static final String NAMESPACE = System.getenv("POWERTOOLS_METRICS_NAMESPACE");
public static final String TRACE_ID_PROPERTY = "xray_trace_id";
public static final String REQUEST_ID_PROPERTY = "function_request_id";
+ private static final String NAMESPACE = System.getenv("POWERTOOLS_METRICS_NAMESPACE");
+
+ private static String service(Metrics metrics) {
+ return !"".equals(metrics.service()) ? metrics.service() : serviceName();
+ }
+
+ // This can be simplified after this issues https://github.com/awslabs/aws-embedded-metrics-java/issues/35 is fixed
+ public static void refreshMetricsContext(Metrics metrics) {
+ try {
+ Field f = metricsLogger().getClass().getDeclaredField("context");
+ f.setAccessible(true);
+ MetricsContext context = new MetricsContext();
+
+ DimensionSet[] defaultDimensions = hasDefaultDimension() ? MetricsUtils.getDefaultDimensions()
+ : new DimensionSet[] {DimensionSet.of("Service", service(metrics))};
+
+ context.setDimensions(defaultDimensions);
+
+ f.set(metricsLogger(), context);
+ } catch (NoSuchFieldException | IllegalAccessException e) {
+ throw new RuntimeException(e);
+ }
+ }
@SuppressWarnings({"EmptyMethod"})
@Pointcut("@annotation(metrics)")
@@ -52,8 +87,9 @@ public Object around(ProceedingJoinPoint pjp,
Context extractedContext = extractContext(pjp);
- if( null != extractedContext) {
- coldStartSingleMetricIfApplicable(extractedContext.getAwsRequestId(), extractedContext.getFunctionName(), metrics);
+ if (null != extractedContext) {
+ coldStartSingleMetricIfApplicable(extractedContext.getAwsRequestId(),
+ extractedContext.getFunctionName(), metrics);
logger.putProperty(REQUEST_ID_PROPERTY, extractedContext.getAwsRequestId());
}
@@ -79,12 +115,12 @@ private void coldStartSingleMetricIfApplicable(final String awsRequestId,
final Metrics metrics) {
if (metrics.captureColdStart()
&& isColdStart()) {
- MetricsLogger metricsLogger = new MetricsLogger();
- metricsLogger.setNamespace(namespace(metrics));
- metricsLogger.putMetric("ColdStart", 1, Unit.COUNT);
- metricsLogger.setDimensions(DimensionSet.of("Service", service(metrics), "FunctionName", functionName));
- metricsLogger.putProperty(REQUEST_ID_PROPERTY, awsRequestId);
- metricsLogger.flush();
+ MetricsLogger metricsLogger = new MetricsLogger();
+ metricsLogger.setNamespace(namespace(metrics));
+ metricsLogger.putMetric("ColdStart", 1, Unit.COUNT);
+ metricsLogger.setDimensions(DimensionSet.of("Service", service(metrics), "FunctionName", functionName));
+ metricsLogger.putProperty(REQUEST_ID_PROPERTY, awsRequestId);
+ metricsLogger.flush();
}
}
@@ -104,34 +140,12 @@ private String namespace(Metrics metrics) {
return !"".equals(metrics.namespace()) ? metrics.namespace() : NAMESPACE;
}
- private static String service(Metrics metrics) {
- return !"".equals(metrics.service()) ? metrics.service() : serviceName();
- }
-
private void validateMetricsAndRefreshOnFailure(Metrics metrics) {
try {
validateBeforeFlushingMetrics(metrics);
- } catch (ValidationException e){
+ } catch (ValidationException e) {
refreshMetricsContext(metrics);
throw e;
}
}
-
- // This can be simplified after this issues https://github.com/awslabs/aws-embedded-metrics-java/issues/35 is fixed
- public static void refreshMetricsContext(Metrics metrics) {
- try {
- Field f = metricsLogger().getClass().getDeclaredField("context");
- f.setAccessible(true);
- MetricsContext context = new MetricsContext();
-
- DimensionSet[] defaultDimensions = hasDefaultDimension() ? MetricsUtils.getDefaultDimensions()
- : new DimensionSet[]{DimensionSet.of("Service", service(metrics))};
-
- context.setDimensions(defaultDimensions);
-
- f.set(metricsLogger(), context);
- } catch (NoSuchFieldException | IllegalAccessException e) {
- throw new RuntimeException(e);
- }
- }
}
diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/MetricsLoggerTest.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/MetricsLoggerTest.java
index 6ebf30e04..da4162ea0 100644
--- a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/MetricsLoggerTest.java
+++ b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/MetricsLoggerTest.java
@@ -1,12 +1,31 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.metrics;
+import static java.util.Collections.emptyMap;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatNullPointerException;
+import static org.mockito.Mockito.mockStatic;
+import static software.amazon.lambda.powertools.core.internal.SystemWrapper.getenv;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.util.Map;
import java.util.function.Consumer;
-
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
@@ -17,18 +36,19 @@
import software.amazon.cloudwatchlogs.emf.model.DimensionSet;
import software.amazon.cloudwatchlogs.emf.model.Unit;
-import static java.util.Collections.emptyMap;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatNullPointerException;
-import static org.mockito.Mockito.mockStatic;
-import static software.amazon.lambda.powertools.core.internal.SystemWrapper.getenv;
-
class MetricsLoggerTest {
private final ByteArrayOutputStream out = new ByteArrayOutputStream();
private final PrintStream originalOut = System.out;
private final ObjectMapper mapper = new ObjectMapper();
+ @BeforeAll
+ static void beforeAll() {
+ try (MockedStatic mocked = mockStatic(SystemWrapper.class)) {
+ mocked.when(() -> SystemWrapper.getenv("AWS_EMF_ENVIRONMENT")).thenReturn("Lambda");
+ }
+ }
+
@BeforeEach
void setUp() {
System.setOut(new PrintStream(out));
@@ -39,88 +59,92 @@ void tearDown() {
System.setOut(originalOut);
}
- @BeforeAll
- static void beforeAll() {
- try (MockedStatic mocked = mockStatic(SystemWrapper.class)) {
- mocked.when(() -> SystemWrapper.getenv("AWS_EMF_ENVIRONMENT")).thenReturn("Lambda");
- }
- }
-
@Test
void singleMetricsCaptureUtilityWithDefaultDimension() {
try (MockedStatic mocked = mockStatic(SystemWrapper.class);
- MockedStatic internalWrapper = mockStatic(software.amazon.lambda.powertools.core.internal.SystemWrapper.class)) {
+ MockedStatic internalWrapper = mockStatic(
+ software.amazon.lambda.powertools.core.internal.SystemWrapper.class)) {
mocked.when(() -> SystemWrapper.getenv("AWS_EMF_ENVIRONMENT")).thenReturn("Lambda");
- internalWrapper.when(() -> getenv("_X_AMZN_TRACE_ID")).thenReturn("Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1\"");
+ internalWrapper.when(() -> getenv("_X_AMZN_TRACE_ID"))
+ .thenReturn("Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1\"");
MetricsUtils.defaultDimensions(DimensionSet.of("Service", "Booking"));
MetricsUtils.withSingleMetric("Metric1", 1, Unit.COUNT, "test",
- metricsLogger -> {});
+ metricsLogger ->
+ {
+ });
assertThat(out.toString())
- .satisfies(s -> {
- Map logAsJson = readAsJson(s);
-
- assertThat(logAsJson)
- .containsEntry("Metric1", 1.0)
- .containsEntry("Service", "Booking")
- .containsKey("_aws")
- .containsEntry("xray_trace_id", "1-5759e988-bd862e3fe1be46a994272793");
- });
+ .satisfies(s ->
+ {
+ Map logAsJson = readAsJson(s);
+
+ assertThat(logAsJson)
+ .containsEntry("Metric1", 1.0)
+ .containsEntry("Service", "Booking")
+ .containsKey("_aws")
+ .containsEntry("xray_trace_id", "1-5759e988-bd862e3fe1be46a994272793");
+ });
}
}
@Test
void singleMetricsCaptureUtility() {
try (MockedStatic mocked = mockStatic(SystemWrapper.class);
- MockedStatic internalWrapper = mockStatic(software.amazon.lambda.powertools.core.internal.SystemWrapper.class)) {
+ MockedStatic internalWrapper = mockStatic(
+ software.amazon.lambda.powertools.core.internal.SystemWrapper.class)) {
mocked.when(() -> SystemWrapper.getenv("AWS_EMF_ENVIRONMENT")).thenReturn("Lambda");
- internalWrapper.when(() -> getenv("_X_AMZN_TRACE_ID")).thenReturn("Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1\"");
+ internalWrapper.when(() -> getenv("_X_AMZN_TRACE_ID"))
+ .thenReturn("Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1\"");
MetricsUtils.withSingleMetric("Metric1", 1, Unit.COUNT, "test",
metricsLogger -> metricsLogger.setDimensions(DimensionSet.of("Dimension1", "Value1")));
assertThat(out.toString())
- .satisfies(s -> {
- Map logAsJson = readAsJson(s);
-
- assertThat(logAsJson)
- .containsEntry("Metric1", 1.0)
- .containsEntry("Dimension1", "Value1")
- .containsKey("_aws")
- .containsEntry("xray_trace_id", "1-5759e988-bd862e3fe1be46a994272793");
- });
+ .satisfies(s ->
+ {
+ Map logAsJson = readAsJson(s);
+
+ assertThat(logAsJson)
+ .containsEntry("Metric1", 1.0)
+ .containsEntry("Dimension1", "Value1")
+ .containsKey("_aws")
+ .containsEntry("xray_trace_id", "1-5759e988-bd862e3fe1be46a994272793");
+ });
}
}
@Test
void singleMetricsCaptureUtilityWithDefaultNameSpace() {
try (MockedStatic mocked = mockStatic(SystemWrapper.class);
- MockedStatic internalWrapper = mockStatic(software.amazon.lambda.powertools.core.internal.SystemWrapper.class)) {
+ MockedStatic internalWrapper = mockStatic(
+ software.amazon.lambda.powertools.core.internal.SystemWrapper.class)) {
mocked.when(() -> SystemWrapper.getenv("AWS_EMF_ENVIRONMENT")).thenReturn("Lambda");
mocked.when(() -> SystemWrapper.getenv("POWERTOOLS_METRICS_NAMESPACE")).thenReturn("GlobalName");
- internalWrapper.when(() -> getenv("_X_AMZN_TRACE_ID")).thenReturn("Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1\"");
+ internalWrapper.when(() -> getenv("_X_AMZN_TRACE_ID"))
+ .thenReturn("Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1\"");
MetricsUtils.withSingleMetric("Metric1", 1, Unit.COUNT,
metricsLogger -> metricsLogger.setDimensions(DimensionSet.of("Dimension1", "Value1")));
assertThat(out.toString())
- .satisfies(s -> {
- Map logAsJson = readAsJson(s);
-
- assertThat(logAsJson)
- .containsEntry("Metric1", 1.0)
- .containsEntry("Dimension1", "Value1")
- .containsKey("_aws")
- .containsEntry("xray_trace_id", "1-5759e988-bd862e3fe1be46a994272793");
-
- Map aws = (Map) logAsJson.get("_aws");
-
- assertThat(aws.get("CloudWatchMetrics"))
- .asString()
- .contains("Namespace=GlobalName");
- });
+ .satisfies(s ->
+ {
+ Map logAsJson = readAsJson(s);
+
+ assertThat(logAsJson)
+ .containsEntry("Metric1", 1.0)
+ .containsEntry("Dimension1", "Value1")
+ .containsKey("_aws")
+ .containsEntry("xray_trace_id", "1-5759e988-bd862e3fe1be46a994272793");
+
+ Map aws = (Map) logAsJson.get("_aws");
+
+ assertThat(aws.get("CloudWatchMetrics"))
+ .asString()
+ .contains("Namespace=GlobalName");
+ });
}
}
@@ -143,32 +167,36 @@ void shouldThrowExceptionWhenDefaultDimensionIsNull() {
private void testLogger(Consumer> methodToTest) {
try (MockedStatic mocked = mockStatic(SystemWrapper.class);
- MockedStatic internalWrapper = mockStatic(software.amazon.lambda.powertools.core.internal.SystemWrapper.class)) {
+ MockedStatic internalWrapper = mockStatic(
+ software.amazon.lambda.powertools.core.internal.SystemWrapper.class)) {
mocked.when(() -> SystemWrapper.getenv("AWS_EMF_ENVIRONMENT")).thenReturn("Lambda");
mocked.when(() -> SystemWrapper.getenv("POWERTOOLS_METRICS_NAMESPACE")).thenReturn("GlobalName");
- internalWrapper.when(() -> getenv("_X_AMZN_TRACE_ID")).thenReturn("Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1\"");
+ internalWrapper.when(() -> getenv("_X_AMZN_TRACE_ID"))
+ .thenReturn("Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1\"");
- methodToTest.accept(metricsLogger -> {
- metricsLogger.setDimensions(DimensionSet.of("Dimension1", "Value1"));
- metricsLogger.putMetric("Metric1", 1, Unit.COUNT);
- });
+ methodToTest.accept(metricsLogger ->
+ {
+ metricsLogger.setDimensions(DimensionSet.of("Dimension1", "Value1"));
+ metricsLogger.putMetric("Metric1", 1, Unit.COUNT);
+ });
assertThat(out.toString())
- .satisfies(s -> {
- Map logAsJson = readAsJson(s);
-
- assertThat(logAsJson)
- .containsEntry("Metric1", 1.0)
- .containsEntry("Dimension1", "Value1")
- .containsKey("_aws")
- .containsEntry("xray_trace_id", "1-5759e988-bd862e3fe1be46a994272793");
-
- Map aws = (Map) logAsJson.get("_aws");
-
- assertThat(aws.get("CloudWatchMetrics"))
- .asString()
- .contains("Namespace=GlobalName");
- });
+ .satisfies(s ->
+ {
+ Map logAsJson = readAsJson(s);
+
+ assertThat(logAsJson)
+ .containsEntry("Metric1", 1.0)
+ .containsEntry("Dimension1", "Value1")
+ .containsKey("_aws")
+ .containsEntry("xray_trace_id", "1-5759e988-bd862e3fe1be46a994272793");
+
+ Map aws = (Map) logAsJson.get("_aws");
+
+ assertThat(aws.get("CloudWatchMetrics"))
+ .asString()
+ .contains("Namespace=GlobalName");
+ });
}
}
diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsColdStartEnabledHandler.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsColdStartEnabledHandler.java
index a722bd689..e3a0fa22e 100644
--- a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsColdStartEnabledHandler.java
+++ b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsColdStartEnabledHandler.java
@@ -1,13 +1,27 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.metrics.handlers;
+import static software.amazon.lambda.powertools.metrics.MetricsUtils.metricsLogger;
+
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import software.amazon.cloudwatchlogs.emf.logger.MetricsLogger;
import software.amazon.cloudwatchlogs.emf.model.Unit;
import software.amazon.lambda.powertools.metrics.Metrics;
-import static software.amazon.lambda.powertools.metrics.MetricsUtils.metricsLogger;
-
public class PowertoolsMetricsColdStartEnabledHandler implements RequestHandler {
@Override
diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsEnabledDefaultDimensionHandler.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsEnabledDefaultDimensionHandler.java
index f66269546..5d7fb7120 100644
--- a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsEnabledDefaultDimensionHandler.java
+++ b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsEnabledDefaultDimensionHandler.java
@@ -1,5 +1,23 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.metrics.handlers;
+import static software.amazon.lambda.powertools.metrics.MetricsUtils.defaultDimensions;
+import static software.amazon.lambda.powertools.metrics.MetricsUtils.metricsLogger;
+import static software.amazon.lambda.powertools.metrics.MetricsUtils.withSingleMetric;
+
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import software.amazon.cloudwatchlogs.emf.logger.MetricsLogger;
@@ -7,10 +25,6 @@
import software.amazon.cloudwatchlogs.emf.model.Unit;
import software.amazon.lambda.powertools.metrics.Metrics;
-import static software.amazon.lambda.powertools.metrics.MetricsUtils.defaultDimensions;
-import static software.amazon.lambda.powertools.metrics.MetricsUtils.metricsLogger;
-import static software.amazon.lambda.powertools.metrics.MetricsUtils.withSingleMetric;
-
public class PowertoolsMetricsEnabledDefaultDimensionHandler implements RequestHandler {
static {
@@ -23,7 +37,9 @@ public Object handleRequest(Object input, Context context) {
MetricsLogger metricsLogger = metricsLogger();
metricsLogger.putMetric("Metric1", 1, Unit.BYTES);
- withSingleMetric("Metric2", 1, Unit.COUNT, log -> {});
+ withSingleMetric("Metric2", 1, Unit.COUNT, log ->
+ {
+ });
return null;
}
diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsEnabledDefaultNoDimensionHandler.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsEnabledDefaultNoDimensionHandler.java
index 761362f43..0a0079b80 100644
--- a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsEnabledDefaultNoDimensionHandler.java
+++ b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsEnabledDefaultNoDimensionHandler.java
@@ -1,5 +1,22 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.metrics.handlers;
+import static software.amazon.lambda.powertools.metrics.MetricsUtils.metricsLogger;
+import static software.amazon.lambda.powertools.metrics.MetricsUtils.withSingleMetric;
+
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import software.amazon.cloudwatchlogs.emf.logger.MetricsLogger;
@@ -7,9 +24,6 @@
import software.amazon.lambda.powertools.metrics.Metrics;
import software.amazon.lambda.powertools.metrics.MetricsUtils;
-import static software.amazon.lambda.powertools.metrics.MetricsUtils.metricsLogger;
-import static software.amazon.lambda.powertools.metrics.MetricsUtils.withSingleMetric;
-
public class PowertoolsMetricsEnabledDefaultNoDimensionHandler implements RequestHandler {
static {
@@ -22,7 +36,9 @@ public Object handleRequest(Object input, Context context) {
MetricsLogger metricsLogger = metricsLogger();
metricsLogger.putMetric("Metric1", 1, Unit.BYTES);
- withSingleMetric("Metric2", 1, Unit.COUNT, log -> {});
+ withSingleMetric("Metric2", 1, Unit.COUNT, log ->
+ {
+ });
return null;
}
diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsEnabledHandler.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsEnabledHandler.java
index 160109787..7cfee533d 100644
--- a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsEnabledHandler.java
+++ b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsEnabledHandler.java
@@ -1,5 +1,22 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.metrics.handlers;
+import static software.amazon.lambda.powertools.metrics.MetricsUtils.metricsLogger;
+import static software.amazon.lambda.powertools.metrics.MetricsUtils.withSingleMetric;
+
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import software.amazon.cloudwatchlogs.emf.logger.MetricsLogger;
@@ -7,9 +24,6 @@
import software.amazon.cloudwatchlogs.emf.model.Unit;
import software.amazon.lambda.powertools.metrics.Metrics;
-import static software.amazon.lambda.powertools.metrics.MetricsUtils.metricsLogger;
-import static software.amazon.lambda.powertools.metrics.MetricsUtils.withSingleMetric;
-
public class PowertoolsMetricsEnabledHandler implements RequestHandler {
@Override
diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsEnabledStreamHandler.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsEnabledStreamHandler.java
index 2eb877dc3..1600f4a64 100644
--- a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsEnabledStreamHandler.java
+++ b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsEnabledStreamHandler.java
@@ -1,16 +1,29 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.metrics.handlers;
-import java.io.InputStream;
-import java.io.OutputStream;
+import static software.amazon.lambda.powertools.metrics.MetricsUtils.metricsLogger;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestStreamHandler;
+import java.io.InputStream;
+import java.io.OutputStream;
import software.amazon.cloudwatchlogs.emf.logger.MetricsLogger;
import software.amazon.cloudwatchlogs.emf.model.Unit;
import software.amazon.lambda.powertools.metrics.Metrics;
-import static software.amazon.lambda.powertools.metrics.MetricsUtils.metricsLogger;
-
public class PowertoolsMetricsEnabledStreamHandler implements RequestStreamHandler {
@Override
diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsExceptionWhenNoMetricsHandler.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsExceptionWhenNoMetricsHandler.java
index 8ada044ee..42e0b3ad4 100644
--- a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsExceptionWhenNoMetricsHandler.java
+++ b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsExceptionWhenNoMetricsHandler.java
@@ -1,12 +1,26 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.metrics.handlers;
+import static software.amazon.lambda.powertools.metrics.MetricsUtils.metricsLogger;
+
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import software.amazon.cloudwatchlogs.emf.logger.MetricsLogger;
import software.amazon.lambda.powertools.metrics.Metrics;
-import static software.amazon.lambda.powertools.metrics.MetricsUtils.metricsLogger;
-
public class PowertoolsMetricsExceptionWhenNoMetricsHandler implements RequestHandler {
@Override
diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsNoDimensionsHandler.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsNoDimensionsHandler.java
index 1c4cc3f77..04b02e166 100644
--- a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsNoDimensionsHandler.java
+++ b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsNoDimensionsHandler.java
@@ -1,13 +1,27 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.metrics.handlers;
+import static software.amazon.lambda.powertools.metrics.MetricsUtils.metricsLogger;
+
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import software.amazon.cloudwatchlogs.emf.logger.MetricsLogger;
import software.amazon.cloudwatchlogs.emf.model.DimensionSet;
import software.amazon.lambda.powertools.metrics.Metrics;
-import static software.amazon.lambda.powertools.metrics.MetricsUtils.metricsLogger;
-
public class PowertoolsMetricsNoDimensionsHandler implements RequestHandler {
@Override
diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsNoExceptionWhenNoMetricsHandler.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsNoExceptionWhenNoMetricsHandler.java
index 3639542f8..c08ce2f86 100644
--- a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsNoExceptionWhenNoMetricsHandler.java
+++ b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsNoExceptionWhenNoMetricsHandler.java
@@ -1,12 +1,26 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.metrics.handlers;
+import static software.amazon.lambda.powertools.metrics.MetricsUtils.metricsLogger;
+
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import software.amazon.cloudwatchlogs.emf.logger.MetricsLogger;
import software.amazon.lambda.powertools.metrics.Metrics;
-import static software.amazon.lambda.powertools.metrics.MetricsUtils.metricsLogger;
-
public class PowertoolsMetricsNoExceptionWhenNoMetricsHandler implements RequestHandler {
@Override
diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsTooManyDimensionsHandler.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsTooManyDimensionsHandler.java
index ccec863f9..bc8a6e949 100644
--- a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsTooManyDimensionsHandler.java
+++ b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsTooManyDimensionsHandler.java
@@ -1,15 +1,28 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.metrics.handlers;
-import java.util.stream.IntStream;
+import static software.amazon.lambda.powertools.metrics.MetricsUtils.metricsLogger;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
+import java.util.stream.IntStream;
import software.amazon.cloudwatchlogs.emf.logger.MetricsLogger;
import software.amazon.cloudwatchlogs.emf.model.DimensionSet;
import software.amazon.lambda.powertools.metrics.Metrics;
-import static software.amazon.lambda.powertools.metrics.MetricsUtils.metricsLogger;
-
public class PowertoolsMetricsTooManyDimensionsHandler implements RequestHandler {
@Override
diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsWithExceptionInHandler.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsWithExceptionInHandler.java
index db75d9f95..da9028a70 100644
--- a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsWithExceptionInHandler.java
+++ b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsWithExceptionInHandler.java
@@ -1,12 +1,26 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.metrics.handlers;
+import static software.amazon.lambda.powertools.metrics.MetricsUtils.metricsLogger;
+
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import software.amazon.cloudwatchlogs.emf.logger.MetricsLogger;
import software.amazon.lambda.powertools.metrics.Metrics;
-import static software.amazon.lambda.powertools.metrics.MetricsUtils.metricsLogger;
-
public class PowertoolsMetricsWithExceptionInHandler implements RequestHandler {
@Override
diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/LambdaMetricsAspectTest.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/LambdaMetricsAspectTest.java
index 6c18d5d7a..44202b8b8 100644
--- a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/LambdaMetricsAspectTest.java
+++ b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/LambdaMetricsAspectTest.java
@@ -1,16 +1,38 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.metrics.internal;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.PrintStream;
-import java.util.Map;
+import static java.util.Collections.emptyMap;
+import static org.apache.commons.lang3.reflect.FieldUtils.writeStaticField;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
+import static org.mockito.Mockito.mockStatic;
+import static org.mockito.Mockito.when;
+import static org.mockito.MockitoAnnotations.openMocks;
+import static software.amazon.lambda.powertools.core.internal.SystemWrapper.getenv;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.lambda.runtime.RequestStreamHandler;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.util.Map;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
@@ -18,7 +40,6 @@
import org.mockito.Mock;
import org.mockito.MockedStatic;
import software.amazon.cloudwatchlogs.emf.config.SystemWrapper;
-import software.amazon.cloudwatchlogs.emf.model.DimensionSet;
import software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor;
import software.amazon.lambda.powertools.metrics.MetricsUtils;
import software.amazon.lambda.powertools.metrics.ValidationException;
@@ -33,22 +54,12 @@
import software.amazon.lambda.powertools.metrics.handlers.PowertoolsMetricsTooManyDimensionsHandler;
import software.amazon.lambda.powertools.metrics.handlers.PowertoolsMetricsWithExceptionInHandler;
-import static java.util.Collections.emptyMap;
-import static org.apache.commons.lang3.reflect.FieldUtils.writeStaticField;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
-import static org.mockito.Mockito.mockStatic;
-import static org.mockito.Mockito.when;
-import static org.mockito.MockitoAnnotations.openMocks;
-import static software.amazon.lambda.powertools.core.internal.SystemWrapper.getenv;
-
public class LambdaMetricsAspectTest {
- @Mock
- private Context context;
-
private final ByteArrayOutputStream out = new ByteArrayOutputStream();
private final PrintStream originalOut = System.out;
private final ObjectMapper mapper = new ObjectMapper();
+ @Mock
+ private Context context;
private RequestHandler requestHandler;
@@ -75,10 +86,12 @@ void tearDown() {
@Test
public void metricsWithoutColdStart() {
try (MockedStatic mocked = mockStatic(SystemWrapper.class);
- MockedStatic internalWrapper = mockStatic(software.amazon.lambda.powertools.core.internal.SystemWrapper.class)) {
+ MockedStatic internalWrapper = mockStatic(
+ software.amazon.lambda.powertools.core.internal.SystemWrapper.class)) {
mocked.when(() -> SystemWrapper.getenv("AWS_EMF_ENVIRONMENT")).thenReturn("Lambda");
- internalWrapper.when(() -> getenv("_X_AMZN_TRACE_ID")).thenReturn("Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1\"");
+ internalWrapper.when(() -> getenv("_X_AMZN_TRACE_ID"))
+ .thenReturn("Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1\"");
MetricsUtils.defaultDimensions(null);
requestHandler = new PowertoolsMetricsEnabledHandler();
@@ -86,40 +99,43 @@ public void metricsWithoutColdStart() {
assertThat(out.toString().split("\n"))
.hasSize(2)
- .satisfies(s -> {
- Map logAsJson = readAsJson(s[0]);
-
- assertThat(logAsJson)
- .containsEntry("Metric2", 1.0)
- .containsEntry("Dimension1", "Value1")
- .containsKey("_aws")
- .containsEntry("xray_trace_id", "1-5759e988-bd862e3fe1be46a994272793")
- .containsEntry("function_request_id", "123ABC");
-
- Map aws = (Map) logAsJson.get("_aws");
-
- assertThat(aws.get("CloudWatchMetrics"))
- .asString()
- .contains("Namespace=ExampleApplication");
-
- logAsJson = readAsJson(s[1]);
-
- assertThat(logAsJson)
- .containsEntry("Metric1", 1.0)
- .containsEntry("Service", "booking")
- .containsEntry("function_request_id", "123ABC")
- .containsKey("_aws");
- });
+ .satisfies(s ->
+ {
+ Map logAsJson = readAsJson(s[0]);
+
+ assertThat(logAsJson)
+ .containsEntry("Metric2", 1.0)
+ .containsEntry("Dimension1", "Value1")
+ .containsKey("_aws")
+ .containsEntry("xray_trace_id", "1-5759e988-bd862e3fe1be46a994272793")
+ .containsEntry("function_request_id", "123ABC");
+
+ Map aws = (Map) logAsJson.get("_aws");
+
+ assertThat(aws.get("CloudWatchMetrics"))
+ .asString()
+ .contains("Namespace=ExampleApplication");
+
+ logAsJson = readAsJson(s[1]);
+
+ assertThat(logAsJson)
+ .containsEntry("Metric1", 1.0)
+ .containsEntry("Service", "booking")
+ .containsEntry("function_request_id", "123ABC")
+ .containsKey("_aws");
+ });
}
}
@Test
public void metricsWithDefaultDimensionSpecified() {
try (MockedStatic mocked = mockStatic(SystemWrapper.class);
- MockedStatic internalWrapper = mockStatic(software.amazon.lambda.powertools.core.internal.SystemWrapper.class)) {
+ MockedStatic internalWrapper = mockStatic(
+ software.amazon.lambda.powertools.core.internal.SystemWrapper.class)) {
mocked.when(() -> SystemWrapper.getenv("AWS_EMF_ENVIRONMENT")).thenReturn("Lambda");
- internalWrapper.when(() -> getenv("_X_AMZN_TRACE_ID")).thenReturn("Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1\"");
+ internalWrapper.when(() -> getenv("_X_AMZN_TRACE_ID"))
+ .thenReturn("Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1\"");
requestHandler = new PowertoolsMetricsEnabledDefaultDimensionHandler();
@@ -127,40 +143,43 @@ public void metricsWithDefaultDimensionSpecified() {
assertThat(out.toString().split("\n"))
.hasSize(2)
- .satisfies(s -> {
- Map logAsJson = readAsJson(s[0]);
-
- assertThat(logAsJson)
- .containsEntry("Metric2", 1.0)
- .containsEntry("CustomDimension", "booking")
- .containsKey("_aws")
- .containsEntry("xray_trace_id", "1-5759e988-bd862e3fe1be46a994272793")
- .containsEntry("function_request_id", "123ABC");
-
- Map aws = (Map) logAsJson.get("_aws");
-
- assertThat(aws.get("CloudWatchMetrics"))
- .asString()
- .contains("Namespace=ExampleApplication");
-
- logAsJson = readAsJson(s[1]);
-
- assertThat(logAsJson)
- .containsEntry("Metric1", 1.0)
- .containsEntry("CustomDimension", "booking")
- .containsEntry("function_request_id", "123ABC")
- .containsKey("_aws");
- });
+ .satisfies(s ->
+ {
+ Map logAsJson = readAsJson(s[0]);
+
+ assertThat(logAsJson)
+ .containsEntry("Metric2", 1.0)
+ .containsEntry("CustomDimension", "booking")
+ .containsKey("_aws")
+ .containsEntry("xray_trace_id", "1-5759e988-bd862e3fe1be46a994272793")
+ .containsEntry("function_request_id", "123ABC");
+
+ Map aws = (Map) logAsJson.get("_aws");
+
+ assertThat(aws.get("CloudWatchMetrics"))
+ .asString()
+ .contains("Namespace=ExampleApplication");
+
+ logAsJson = readAsJson(s[1]);
+
+ assertThat(logAsJson)
+ .containsEntry("Metric1", 1.0)
+ .containsEntry("CustomDimension", "booking")
+ .containsEntry("function_request_id", "123ABC")
+ .containsKey("_aws");
+ });
}
}
@Test
public void metricsWithDefaultNoDimensionSpecified() {
try (MockedStatic mocked = mockStatic(SystemWrapper.class);
- MockedStatic internalWrapper = mockStatic(software.amazon.lambda.powertools.core.internal.SystemWrapper.class)) {
+ MockedStatic internalWrapper = mockStatic(
+ software.amazon.lambda.powertools.core.internal.SystemWrapper.class)) {
mocked.when(() -> SystemWrapper.getenv("AWS_EMF_ENVIRONMENT")).thenReturn("Lambda");
- internalWrapper.when(() -> getenv("_X_AMZN_TRACE_ID")).thenReturn("Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1\"");
+ internalWrapper.when(() -> getenv("_X_AMZN_TRACE_ID"))
+ .thenReturn("Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1\"");
requestHandler = new PowertoolsMetricsEnabledDefaultNoDimensionHandler();
@@ -168,28 +187,29 @@ public void metricsWithDefaultNoDimensionSpecified() {
assertThat(out.toString().split("\n"))
.hasSize(2)
- .satisfies(s -> {
- Map logAsJson = readAsJson(s[0]);
+ .satisfies(s ->
+ {
+ Map logAsJson = readAsJson(s[0]);
- assertThat(logAsJson)
- .containsEntry("Metric2", 1.0)
- .containsKey("_aws")
- .containsEntry("xray_trace_id", "1-5759e988-bd862e3fe1be46a994272793")
- .containsEntry("function_request_id", "123ABC");
+ assertThat(logAsJson)
+ .containsEntry("Metric2", 1.0)
+ .containsKey("_aws")
+ .containsEntry("xray_trace_id", "1-5759e988-bd862e3fe1be46a994272793")
+ .containsEntry("function_request_id", "123ABC");
- Map aws = (Map) logAsJson.get("_aws");
+ Map aws = (Map) logAsJson.get("_aws");
- assertThat(aws.get("CloudWatchMetrics"))
- .asString()
- .contains("Namespace=ExampleApplication");
+ assertThat(aws.get("CloudWatchMetrics"))
+ .asString()
+ .contains("Namespace=ExampleApplication");
- logAsJson = readAsJson(s[1]);
+ logAsJson = readAsJson(s[1]);
- assertThat(logAsJson)
- .containsEntry("Metric1", 1.0)
- .containsEntry("function_request_id", "123ABC")
- .containsKey("_aws");
- });
+ assertThat(logAsJson)
+ .containsEntry("Metric1", 1.0)
+ .containsEntry("function_request_id", "123ABC")
+ .containsKey("_aws");
+ });
}
}
@@ -207,25 +227,26 @@ public void metricsWithColdStart() {
assertThat(out.toString().split("\n"))
.hasSize(2)
- .satisfies(s -> {
- Map logAsJson = readAsJson(s[0]);
-
- assertThat(logAsJson)
- .doesNotContainKey("Metric1")
- .containsEntry("ColdStart", 1.0)
- .containsEntry("Service", "booking")
- .containsEntry("function_request_id", "123ABC")
- .containsKey("_aws");
-
- logAsJson = readAsJson(s[1]);
-
- assertThat(logAsJson)
- .doesNotContainKey("ColdStart")
- .containsEntry("Metric1", 1.0)
- .containsEntry("Service", "booking")
- .containsEntry("function_request_id", "123ABC")
- .containsKey("_aws");
- });
+ .satisfies(s ->
+ {
+ Map logAsJson = readAsJson(s[0]);
+
+ assertThat(logAsJson)
+ .doesNotContainKey("Metric1")
+ .containsEntry("ColdStart", 1.0)
+ .containsEntry("Service", "booking")
+ .containsEntry("function_request_id", "123ABC")
+ .containsKey("_aws");
+
+ logAsJson = readAsJson(s[1]);
+
+ assertThat(logAsJson)
+ .doesNotContainKey("ColdStart")
+ .containsEntry("Metric1", 1.0)
+ .containsEntry("Service", "booking")
+ .containsEntry("function_request_id", "123ABC")
+ .containsKey("_aws");
+ });
}
}
@@ -243,34 +264,35 @@ public void noColdStartMetricsWhenColdStartDone() {
assertThat(out.toString().split("\n"))
.hasSize(3)
- .satisfies(s -> {
- Map logAsJson = readAsJson(s[0]);
-
- assertThat(logAsJson)
- .doesNotContainKey("Metric1")
- .containsEntry("ColdStart", 1.0)
- .containsEntry("Service", "booking")
- .containsEntry("function_request_id", "123ABC")
- .containsKey("_aws");
-
- logAsJson = readAsJson(s[1]);
-
- assertThat(logAsJson)
- .doesNotContainKey("ColdStart")
- .containsEntry("Metric1", 1.0)
- .containsEntry("Service", "booking")
- .containsEntry("function_request_id", "123ABC")
- .containsKey("_aws");
-
- logAsJson = readAsJson(s[2]);
-
- assertThat(logAsJson)
- .doesNotContainKey("ColdStart")
- .containsEntry("Metric1", 1.0)
- .containsEntry("Service", "booking")
- .containsEntry("function_request_id", "123ABC")
- .containsKey("_aws");
- });
+ .satisfies(s ->
+ {
+ Map logAsJson = readAsJson(s[0]);
+
+ assertThat(logAsJson)
+ .doesNotContainKey("Metric1")
+ .containsEntry("ColdStart", 1.0)
+ .containsEntry("Service", "booking")
+ .containsEntry("function_request_id", "123ABC")
+ .containsKey("_aws");
+
+ logAsJson = readAsJson(s[1]);
+
+ assertThat(logAsJson)
+ .doesNotContainKey("ColdStart")
+ .containsEntry("Metric1", 1.0)
+ .containsEntry("Service", "booking")
+ .containsEntry("function_request_id", "123ABC")
+ .containsKey("_aws");
+
+ logAsJson = readAsJson(s[2]);
+
+ assertThat(logAsJson)
+ .doesNotContainKey("ColdStart")
+ .containsEntry("Metric1", 1.0)
+ .containsEntry("Service", "booking")
+ .containsEntry("function_request_id", "123ABC")
+ .containsKey("_aws");
+ });
}
}
@@ -283,18 +305,19 @@ public void metricsWithStreamHandler() throws IOException {
MetricsUtils.defaultDimensions(null);
RequestStreamHandler streamHandler = new PowertoolsMetricsEnabledStreamHandler();
- streamHandler.handleRequest(new ByteArrayInputStream(new byte[]{}), new ByteArrayOutputStream(), context);
+ streamHandler.handleRequest(new ByteArrayInputStream(new byte[] {}), new ByteArrayOutputStream(), context);
assertThat(out.toString())
- .satisfies(s -> {
- Map logAsJson = readAsJson(s);
-
- assertThat(logAsJson)
- .containsEntry("Metric1", 1.0)
- .containsEntry("Service", "booking")
- .containsEntry("function_request_id", "123ABC")
- .containsKey("_aws");
- });
+ .satisfies(s ->
+ {
+ Map logAsJson = readAsJson(s);
+
+ assertThat(logAsJson)
+ .containsEntry("Metric1", 1.0)
+ .containsEntry("Service", "booking")
+ .containsEntry("function_request_id", "123ABC")
+ .containsKey("_aws");
+ });
}
}
@@ -324,13 +347,14 @@ public void noExceptionWhenNoMetricsEmitted() {
requestHandler.handleRequest("input", context);
assertThat(out.toString())
- .satisfies(s -> {
- Map logAsJson = readAsJson(s);
-
- assertThat(logAsJson)
- .containsEntry("Service", "booking")
- .doesNotContainKey("_aws");
- });
+ .satisfies(s ->
+ {
+ Map logAsJson = readAsJson(s);
+
+ assertThat(logAsJson)
+ .containsEntry("Service", "booking")
+ .doesNotContainKey("_aws");
+ });
}
}
@@ -344,13 +368,14 @@ public void allowWhenNoDimensionsSet() {
requestHandler.handleRequest("input", context);
assertThat(out.toString())
- .satisfies(s -> {
- Map logAsJson = readAsJson(s);
- assertThat(logAsJson)
- .containsEntry("CoolMetric", 1.0)
- .containsEntry("function_request_id", "123ABC")
- .containsKey("_aws");
- });
+ .satisfies(s ->
+ {
+ Map logAsJson = readAsJson(s);
+ assertThat(logAsJson)
+ .containsEntry("CoolMetric", 1.0)
+ .containsEntry("function_request_id", "123ABC")
+ .containsKey("_aws");
+ });
}
}
@@ -383,14 +408,15 @@ public void metricsPublishedEvenHandlerThrowsException() {
.withMessage("Whoops, unexpected exception");
assertThat(out.toString())
- .satisfies(s -> {
- Map logAsJson = readAsJson(s);
- assertThat(logAsJson)
- .containsEntry("CoolMetric", 1.0)
- .containsEntry("Service", "booking")
- .containsEntry("function_request_id", "123ABC")
- .containsKey("_aws");
- });
+ .satisfies(s ->
+ {
+ Map logAsJson = readAsJson(s);
+ assertThat(logAsJson)
+ .containsEntry("CoolMetric", 1.0)
+ .containsEntry("Service", "booking")
+ .containsEntry("function_request_id", "123ABC")
+ .containsKey("_aws");
+ });
}
}
diff --git a/powertools-parameters/pom.xml b/powertools-parameters/pom.xml
index b50844d99..fab72a9b7 100644
--- a/powertools-parameters/pom.xml
+++ b/powertools-parameters/pom.xml
@@ -1,4 +1,18 @@
+
+
@@ -144,7 +158,10 @@
+
+ org.apache.maven.plugins
+ maven-checkstyle-plugin
+
-
diff --git a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/AppConfigProvider.java b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/AppConfigProvider.java
index c62d7a2e5..130be25a3 100644
--- a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/AppConfigProvider.java
+++ b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/AppConfigProvider.java
@@ -1,5 +1,21 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.parameters;
+import java.util.HashMap;
+import java.util.Map;
import software.amazon.awssdk.core.SdkSystemSetting;
import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient;
import software.amazon.awssdk.regions.Region;
@@ -10,15 +26,12 @@
import software.amazon.lambda.powertools.parameters.cache.CacheManager;
import software.amazon.lambda.powertools.parameters.transform.TransformationManager;
-import java.util.HashMap;
-import java.util.Map;
-
/**
* Implements a {@link ParamProvider} on top of the AppConfig service. AppConfig provides
* a mechanism to retrieve and update configuration of applications over time.
* AppConfig requires the user to create an application, environment, and configuration profile.
* The configuration profile's value can then be retrieved, by key name, through this provider.
- *
+ *
* Because AppConfig is designed to handle rollouts of configuration over time, we must first
* establish a session for each key we wish to retrieve, and then poll the session for the latest
* value when the user re-requests it. This means we must hold a keyed set of session tokens
@@ -27,24 +40,11 @@
* @see Parameters provider documentation
* @see AppConfig documentation
*/
-public class AppConfigProvider extends BaseProvider{
-
- private static class EstablishedSession {
- private final String nextSessionToken;
- private final String lastConfigurationValue;
-
- private EstablishedSession(String nextSessionToken, String value) {
- this.nextSessionToken = nextSessionToken;
- this.lastConfigurationValue = value;
- }
- }
+public class AppConfigProvider extends BaseProvider {
private final AppConfigDataClient client;
-
private final String application;
-
private final String environment;
-
private final HashMap establishedSessions = new HashMap<>();
AppConfigProvider(CacheManager cacheManager, AppConfigDataClient client, String environment, String application) {
@@ -54,6 +54,14 @@ private EstablishedSession(String nextSessionToken, String value) {
this.environment = environment;
}
+ /**
+ * Create a builder that can be used to configure and create a {@link AppConfigProvider}.
+ *
+ * @return a new instance of {@link AppConfigProvider.Builder}
+ */
+ public static AppConfigProvider.Builder builder() {
+ return new AppConfigProvider.Builder();
+ }
/**
* Retrieve the parameter value from the AppConfig parameter store.
@@ -67,18 +75,18 @@ protected String getValue(String key) {
// so that we can the initial token. If we already have a session, we can take
// the next request token from there.
EstablishedSession establishedSession = establishedSessions.getOrDefault(key, null);
- String sessionToken = establishedSession != null?
+ String sessionToken = establishedSession != null ?
establishedSession.nextSessionToken :
client.startConfigurationSession(StartConfigurationSessionRequest.builder()
- .applicationIdentifier(this.application)
- .environmentIdentifier(this.environment)
- .configurationProfileIdentifier(key)
- .build())
- .initialConfigurationToken();
+ .applicationIdentifier(this.application)
+ .environmentIdentifier(this.environment)
+ .configurationProfileIdentifier(key)
+ .build())
+ .initialConfigurationToken();
// Get the configuration using the token
GetLatestConfigurationResponse response = client.getLatestConfiguration(GetLatestConfigurationRequest.builder()
- .configurationToken(sessionToken)
+ .configurationToken(sessionToken)
.build());
// Get the next session token we'll use next time we are asked for this key
@@ -87,11 +95,12 @@ protected String getValue(String key) {
// Get the value of the key. Note that AppConfig will return null if the value
// has not changed since we last asked for it in this session - in this case
// we return the value we stashed at last request.
- String value = response.configuration() != null?
+ String value = response.configuration() != null ?
response.configuration().asUtf8String() : // if we have a new value, use it
- establishedSession != null?
- establishedSession.lastConfigurationValue : // if we don't but we have a previous value, use that
- null; // otherwise we've got no value
+ establishedSession != null ?
+ establishedSession.lastConfigurationValue :
+ // if we don't but we have a previous value, use that
+ null; // otherwise we've got no value
// Update the cache so we can get the next value later
establishedSessions.put(key, new EstablishedSession(nextSessionToken, value));
@@ -102,16 +111,18 @@ protected String getValue(String key) {
@Override
protected Map getMultipleValues(String path) {
// Retrieving multiple values is not supported with the AppConfig provider.
- throw new RuntimeException("Retrieving multiple parameter values is not supported with the AWS App Config Provider");
+ throw new RuntimeException(
+ "Retrieving multiple parameter values is not supported with the AWS App Config Provider");
}
- /**
- * Create a builder that can be used to configure and create a {@link AppConfigProvider}.
- *
- * @return a new instance of {@link AppConfigProvider.Builder}
- */
- public static AppConfigProvider.Builder builder() {
- return new AppConfigProvider.Builder();
+ private static class EstablishedSession {
+ private final String nextSessionToken;
+ private final String lastConfigurationValue;
+
+ private EstablishedSession(String nextSessionToken, String value) {
+ this.nextSessionToken = nextSessionToken;
+ this.lastConfigurationValue = value;
+ }
}
static class Builder {
diff --git a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/BaseProvider.java b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/BaseProvider.java
index fb539f850..e7bfdf835 100644
--- a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/BaseProvider.java
+++ b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/BaseProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,8 +11,14 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.parameters;
+import java.time.Clock;
+import java.time.Duration;
+import java.time.Instant;
+import java.time.temporal.ChronoUnit;
+import java.util.Map;
import software.amazon.awssdk.annotations.NotThreadSafe;
import software.amazon.lambda.powertools.parameters.cache.CacheManager;
import software.amazon.lambda.powertools.parameters.exception.TransformationException;
@@ -20,12 +26,6 @@
import software.amazon.lambda.powertools.parameters.transform.TransformationManager;
import software.amazon.lambda.powertools.parameters.transform.Transformer;
-import java.time.Clock;
-import java.time.Duration;
-import java.time.Instant;
-import java.time.temporal.ChronoUnit;
-import java.util.Map;
-
/**
* Base class for all parameter providers.
*/
@@ -106,7 +106,8 @@ public BaseProvider withMaxAge(int maxAge, ChronoUnit unit) {
*/
public BaseProvider withTransformation(Class extends Transformer> transformerClass) {
if (transformationManager == null) {
- throw new IllegalStateException("Trying to add transformation while no TransformationManager has been provided.");
+ throw new IllegalStateException(
+ "Trying to add transformation while no TransformationManager has been provided.");
}
transformationManager.setTransformer(transformerClass);
return this;
@@ -126,15 +127,16 @@ public Map getMultiple(String path) {
// remove trailing whitespace
String pathWithoutTrailingSlash = path.replaceAll("\\/+$", "");
try {
- return (Map) cacheManager.getIfNotExpired(pathWithoutTrailingSlash, now()).orElseGet(() -> {
- Map params = getMultipleValues(pathWithoutTrailingSlash);
+ return (Map) cacheManager.getIfNotExpired(pathWithoutTrailingSlash, now()).orElseGet(() ->
+ {
+ Map params = getMultipleValues(pathWithoutTrailingSlash);
- cacheManager.putInCache(pathWithoutTrailingSlash, params);
+ cacheManager.putInCache(pathWithoutTrailingSlash, params);
- params.forEach((k, v) -> cacheManager.putInCache(pathWithoutTrailingSlash + "/" + k, v));
+ params.forEach((k, v) -> cacheManager.putInCache(pathWithoutTrailingSlash + "/" + k, v));
- return params;
- });
+ return params;
+ });
} finally {
resetToDefaults();
}
@@ -148,24 +150,25 @@ public Map getMultiple(String path) {
*
* @param key key of the parameter
* @return the String value of the parameter
- * @throws IllegalStateException if a wrong transformer class is provided through {@link #withTransformation(Class)}. Needs to be a {@link BasicTransformer}.
- * @throws TransformationException if the transformation could not be done, because of a wrong format or an error during transformation.
+ * @throws IllegalStateException if a wrong transformer class is provided through {@link #withTransformation(Class)}. Needs to be a {@link BasicTransformer}.
+ * @throws TransformationException if the transformation could not be done, because of a wrong format or an error during transformation.
*/
@Override
public String get(final String key) {
try {
- return (String) cacheManager.getIfNotExpired(key, now()).orElseGet(() -> {
- String value = getValue(key);
+ return (String) cacheManager.getIfNotExpired(key, now()).orElseGet(() ->
+ {
+ String value = getValue(key);
- String transformedValue = value;
- if (transformationManager != null && transformationManager.shouldTransform()) {
- transformedValue = transformationManager.performBasicTransformation(value);
- }
+ String transformedValue = value;
+ if (transformationManager != null && transformationManager.shouldTransform()) {
+ transformedValue = transformationManager.performBasicTransformation(value);
+ }
- cacheManager.putInCache(key, transformedValue);
+ cacheManager.putInCache(key, transformedValue);
- return transformedValue;
- });
+ return transformedValue;
+ });
} finally {
// in all case, we reset options to default, for next call
resetToDefaults();
@@ -181,24 +184,26 @@ public String get(final String key) {
* @param key key of the parameter
* @param targetClass class of the target Object (after transformation)
* @return the Object (T) value of the parameter
- * @throws IllegalStateException if no transformation class was provided through {@link #withTransformation(Class)}
- * @throws TransformationException if the transformation could not be done, because of a wrong format or an error during transformation.
+ * @throws IllegalStateException if no transformation class was provided through {@link #withTransformation(Class)}
+ * @throws TransformationException if the transformation could not be done, because of a wrong format or an error during transformation.
*/
@Override
public T get(final String key, final Class targetClass) {
try {
- return (T) cacheManager.getIfNotExpired(key, now()).orElseGet(() -> {
- String value = getValue(key);
+ return (T) cacheManager.getIfNotExpired(key, now()).orElseGet(() ->
+ {
+ String value = getValue(key);
- if (transformationManager == null) {
- throw new IllegalStateException("Trying to transform value while no TransformationManager has been provided.");
- }
- T transformedValue = transformationManager.performComplexTransformation(value, targetClass);
+ if (transformationManager == null) {
+ throw new IllegalStateException(
+ "Trying to transform value while no TransformationManager has been provided.");
+ }
+ T transformedValue = transformationManager.performComplexTransformation(value, targetClass);
- cacheManager.putInCache(key, transformedValue);
+ cacheManager.putInCache(key, transformedValue);
- return transformedValue;
- });
+ return transformedValue;
+ });
} finally {
// in all case, we reset options to default, for next call
resetToDefaults();
@@ -225,6 +230,7 @@ protected void setTransformationManager(TransformationManager transformationMana
/**
* For test purpose
+ *
* @param clock
*/
void setClock(Clock clock) {
diff --git a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/DynamoDbProvider.java b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/DynamoDbProvider.java
index e09f23348..2b0694a5d 100644
--- a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/DynamoDbProvider.java
+++ b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/DynamoDbProvider.java
@@ -1,5 +1,22 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.parameters;
+import java.util.Collections;
+import java.util.Map;
+import java.util.stream.Collectors;
import software.amazon.awssdk.core.SdkSystemSetting;
import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient;
import software.amazon.awssdk.regions.Region;
@@ -13,16 +30,11 @@
import software.amazon.lambda.powertools.parameters.exception.DynamoDbProviderSchemaException;
import software.amazon.lambda.powertools.parameters.transform.TransformationManager;
-import java.util.Collections;
-import java.util.Map;
-import java.util.stream.Collectors;
-
/**
* Implements a {@link ParamProvider} on top of DynamoDB. The schema of the table
* is described in the Powertools for AWS Lambda (Java) documentation.
*
* @see Parameters provider documentation
- *
*/
public class DynamoDbProvider extends BaseProvider {
@@ -39,6 +51,15 @@ public class DynamoDbProvider extends BaseProvider {
this(cacheManager, Builder.createClient(), tableName);
}
+ /**
+ * Create a builder that can be used to configure and create a {@link DynamoDbProvider}.
+ *
+ * @return a new instance of {@link DynamoDbProvider.Builder}
+ */
+ public static DynamoDbProvider.Builder builder() {
+ return new DynamoDbProvider.Builder();
+ }
+
/**
* Return a single value from the DynamoDB parameter provider.
*
@@ -82,9 +103,10 @@ protected Map getMultipleValues(String path) {
.build());
return resp
- .items()
- .stream()
- .peek((i) -> {
+ .items()
+ .stream()
+ .peek((i) ->
+ {
if (!i.containsKey("sk")) {
throw new DynamoDbProviderSchemaException("Missing 'sk': " + i.toString());
}
@@ -92,29 +114,27 @@ protected Map getMultipleValues(String path) {
throw new DynamoDbProviderSchemaException("Missing 'value': " + i.toString());
}
})
- .collect(
- Collectors.toMap(
- (i) -> i.get("sk").s(),
- (i) -> i.get("value").s()));
+ .collect(
+ Collectors.toMap(
+ (i) -> i.get("sk").s(),
+ (i) -> i.get("value").s()));
}
- /**
- * Create a builder that can be used to configure and create a {@link DynamoDbProvider}.
- *
- * @return a new instance of {@link DynamoDbProvider.Builder}
- */
- public static DynamoDbProvider.Builder builder() {
- return new DynamoDbProvider.Builder();
- }
-
static class Builder {
private DynamoDbClient client;
private String table;
private CacheManager cacheManager;
private TransformationManager transformationManager;
+ private static DynamoDbClient createClient() {
+ return DynamoDbClient.builder()
+ .httpClientBuilder(UrlConnectionHttpClient.builder())
+ .region(Region.of(System.getenv(SdkSystemSetting.AWS_REGION.environmentVariable())))
+ .build();
+ }
+
/**
* Create a {@link DynamoDbProvider} instance.
*
@@ -183,12 +203,5 @@ public DynamoDbProvider.Builder withTransformationManager(TransformationManager
this.transformationManager = transformationManager;
return this;
}
-
- private static DynamoDbClient createClient() {
- return DynamoDbClient.builder()
- .httpClientBuilder(UrlConnectionHttpClient.builder())
- .region(Region.of(System.getenv(SdkSystemSetting.AWS_REGION.environmentVariable())))
- .build();
- }
}
}
diff --git a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/Param.java b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/Param.java
index ef3d08b72..7ffb0310c 100644
--- a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/Param.java
+++ b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/Param.java
@@ -1,11 +1,24 @@
-package software.amazon.lambda.powertools.parameters;
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
-import software.amazon.lambda.powertools.parameters.transform.Transformer;
+package software.amazon.lambda.powertools.parameters;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
+import software.amazon.lambda.powertools.parameters.transform.Transformer;
/**
* {@code Param} is used to signal that the annotated field should be
@@ -25,6 +38,8 @@
@Target(ElementType.FIELD)
public @interface Param {
String key();
+
Class extends BaseProvider> provider() default SSMProvider.class;
+
Class extends Transformer> transformer() default Transformer.class;
}
diff --git a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/ParamManager.java b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/ParamManager.java
index c8abedf06..6fee0f114 100644
--- a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/ParamManager.java
+++ b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/ParamManager.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,8 +11,11 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.parameters;
+import java.lang.reflect.Constructor;
+import java.util.concurrent.ConcurrentHashMap;
import software.amazon.awssdk.services.appconfigdata.AppConfigDataClient;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient;
@@ -20,9 +23,6 @@
import software.amazon.lambda.powertools.parameters.cache.CacheManager;
import software.amazon.lambda.powertools.parameters.transform.TransformationManager;
-import java.lang.reflect.Constructor;
-import java.util.concurrent.ConcurrentHashMap;
-
/**
* Utility class to retrieve instances of parameter providers.
* Each instance is unique (singleton).
@@ -39,8 +39,9 @@ public final class ParamManager {
* Get a concrete implementation of {@link BaseProvider}.
* You can specify {@link SecretsProvider}, {@link SSMProvider} or create your
* custom provider by extending {@link BaseProvider} if you need to integrate with a different parameter store.
- * @deprecated You should not use this method directly but a typed one (getSecretsProvider, getSsmProvider, getDynamoDbProvider, getAppConfigProvider), will be removed in v2
+ *
* @return a {@link SecretsProvider}
+ * @deprecated You should not use this method directly but a typed one (getSecretsProvider, getSsmProvider, getDynamoDbProvider, getAppConfigProvider), will be removed in v2
*/
// TODO in v2: remove public access to this and review how we get providers (it was not designed for DDB and AppConfig in mind initially)
public static T getProvider(Class providerClass) {
@@ -48,7 +49,8 @@ public static T getProvider(Class providerClass) {
throw new IllegalStateException("providerClass cannot be null.");
}
if (providerClass == DynamoDbProvider.class || providerClass == AppConfigProvider.class) {
- throw new IllegalArgumentException(providerClass + " cannot be instantiated like this, additional parameters are required");
+ throw new IllegalArgumentException(
+ providerClass + " cannot be instantiated like this, additional parameters are required");
}
return (T) providers.computeIfAbsent(providerClass, ParamManager::createProvider);
}
@@ -56,6 +58,7 @@ public static T getProvider(Class providerClass) {
/**
* Get a {@link SecretsProvider} with default {@link SecretsManagerClient}.
* If you need to customize the region, or other part of the client, use {@link ParamManager#getSecretsProvider(SecretsManagerClient)} instead.
+ *
* @return a {@link SecretsProvider}
*/
public static SecretsProvider getSecretsProvider() {
@@ -65,6 +68,7 @@ public static SecretsProvider getSecretsProvider() {
/**
* Get a {@link SSMProvider} with default {@link SsmClient}.
* If you need to customize the region, or other part of the client, use {@link ParamManager#getSsmProvider(SsmClient)} instead.
+ *
* @return a {@link SSMProvider}
*/
public static SSMProvider getSsmProvider() {
@@ -89,6 +93,7 @@ public static DynamoDbProvider getDynamoDbProvider(String tableName) {
/**
* Get a {@link AppConfigProvider} with default {@link AppConfigDataClient}.
* If you need to customize the region, or other part of the client, use {@link ParamManager#getAppConfigProvider(AppConfigDataClient, String, String)} instead.
+ *
* @return a {@link AppConfigProvider}
*/
public static AppConfigProvider getAppConfigProvider(String environment, String application) {
@@ -107,6 +112,7 @@ public static AppConfigProvider getAppConfigProvider(String environment, String
/**
* Get a {@link SecretsProvider} with your custom {@link SecretsManagerClient}.
* Use this to configure region or other part of the client. Use {@link ParamManager#getSsmProvider()} if you don't need this customization.
+ *
* @return a {@link SecretsProvider}
*/
public static SecretsProvider getSecretsProvider(SecretsManagerClient client) {
@@ -120,6 +126,7 @@ public static SecretsProvider getSecretsProvider(SecretsManagerClient client) {
/**
* Get a {@link SSMProvider} with your custom {@link SsmClient}.
* Use this to configure region or other part of the client. Use {@link ParamManager#getSsmProvider()} if you don't need this customization.
+ *
* @return a {@link SSMProvider}
*/
public static SSMProvider getSsmProvider(SsmClient client) {
@@ -133,6 +140,7 @@ public static SSMProvider getSsmProvider(SsmClient client) {
/**
* Get a {@link DynamoDbProvider} with your custom {@link DynamoDbClient}.
* Use this to configure region or other part of the client. Use {@link ParamManager#getDynamoDbProvider(String)} )} if you don't need this customization.
+ *
* @return a {@link DynamoDbProvider}
*/
public static DynamoDbProvider getDynamoDbProvider(DynamoDbClient client, String table) {
@@ -143,13 +151,15 @@ public static DynamoDbProvider getDynamoDbProvider(DynamoDbClient client, String
.withTransformationManager(transformationManager)
.build());
}
-
+
/**
* Get a {@link AppConfigProvider} with your custom {@link AppConfigDataClient}.
* Use this to configure region or other part of the client. Use {@link ParamManager#getAppConfigProvider(String, String)} if you don't need this customization.
+ *
* @return a {@link AppConfigProvider}
*/
- public static AppConfigProvider getAppConfigProvider(AppConfigDataClient client, String environment, String application) {
+ public static AppConfigProvider getAppConfigProvider(AppConfigDataClient client, String environment,
+ String application) {
return (AppConfigProvider) providers.computeIfAbsent(AppConfigProvider.class, (k) -> AppConfigProvider.builder()
.withClient(client)
.withCacheManager(cacheManager)
@@ -168,10 +178,11 @@ public static TransformationManager getTransformationManager() {
return transformationManager;
}
- static T createProvider(Class providerClass) {
+ static T createProvider(Class providerClass) {
try {
Constructor constructor = providerClass.getDeclaredConstructor(CacheManager.class);
- T provider = constructor.newInstance(cacheManager); // FIXME: avoid reflection here as we may have issues (#1280)
+ T provider =
+ constructor.newInstance(cacheManager); // FIXME: avoid reflection here as we may have issues (#1280)
provider.setTransformationManager(transformationManager);
return provider;
} catch (ReflectiveOperationException e) {
diff --git a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/ParamProvider.java b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/ParamProvider.java
index b496ed4f3..ba4232261 100644
--- a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/ParamProvider.java
+++ b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/ParamProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,6 +11,7 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.parameters;
import java.util.Map;
diff --git a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/SSMProvider.java b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/SSMProvider.java
index 1fa4dbaab..b24b1e319 100644
--- a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/SSMProvider.java
+++ b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/SSMProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,8 +11,12 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.parameters;
+import java.time.temporal.ChronoUnit;
+import java.util.HashMap;
+import java.util.Map;
import software.amazon.awssdk.core.SdkSystemSetting;
import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient;
import software.amazon.awssdk.regions.Region;
@@ -25,10 +29,6 @@
import software.amazon.lambda.powertools.parameters.transform.TransformationManager;
import software.amazon.lambda.powertools.parameters.transform.Transformer;
-import java.time.temporal.ChronoUnit;
-import java.util.HashMap;
-import java.util.Map;
-
/**
* AWS System Manager Parameter Store Provider
*
@@ -88,14 +88,24 @@ public class SSMProvider extends BaseProvider {
/**
* Constructor with only a CacheManager
- *
+ *
* Used in {@link ParamManager#createProvider(Class)}
+ *
* @param cacheManager handles the parameter caching
*/
SSMProvider(CacheManager cacheManager) {
this(cacheManager, Builder.createClient());
}
+ /**
+ * Create a builder that can be used to configure and create a {@link SSMProvider}.
+ *
+ * @return a new instance of {@link SSMProvider.Builder}
+ */
+ public static SSMProvider.Builder builder() {
+ return new SSMProvider.Builder();
+ }
+
/**
* Retrieve the parameter value from the AWS System Manager Parameter Store.
*
@@ -194,19 +204,20 @@ private Map getMultipleBis(String path, String nextToken) {
// not using the client.getParametersByPathPaginator() as hardly testable
GetParametersByPathResponse res = client.getParametersByPath(request);
if (res.hasParameters()) {
- res.parameters().forEach(parameter -> {
+ res.parameters().forEach(parameter ->
+ {
/* Standardize the parameter name
The parameter name returned by SSM will contained the full path.
However, for readability, we should return only the part after
the path.
*/
- String name = parameter.name();
- if (name.startsWith(path)) {
- name = name.replaceFirst(path, "");
- }
- name = name.replaceFirst("/", "");
- params.put(name, parameter.value());
- });
+ String name = parameter.name();
+ if (name.startsWith(path)) {
+ name = name.replaceFirst(path, "");
+ }
+ name = name.replaceFirst("/", "");
+ params.put(name, parameter.value());
+ });
}
if (!StringUtils.isEmpty(res.nextToken())) {
@@ -228,21 +239,18 @@ SsmClient getClient() {
return client;
}
- /**
- * Create a builder that can be used to configure and create a {@link SSMProvider}.
- *
- * @return a new instance of {@link SSMProvider.Builder}
- */
- public static SSMProvider.Builder builder() {
- return new SSMProvider.Builder();
- }
-
-
static class Builder {
private SsmClient client;
private CacheManager cacheManager;
private TransformationManager transformationManager;
+ private static SsmClient createClient() {
+ return SsmClient.builder()
+ .httpClientBuilder(UrlConnectionHttpClient.builder())
+ .region(Region.of(System.getenv(SdkSystemSetting.AWS_REGION.environmentVariable())))
+ .build();
+ }
+
/**
* Create a {@link SSMProvider} instance.
*
@@ -277,13 +285,6 @@ public SSMProvider.Builder withClient(SsmClient client) {
return this;
}
- private static SsmClient createClient() {
- return SsmClient.builder()
- .httpClientBuilder(UrlConnectionHttpClient.builder())
- .region(Region.of(System.getenv(SdkSystemSetting.AWS_REGION.environmentVariable())))
- .build();
- }
-
/**
* Mandatory. Provide a CacheManager to the {@link SSMProvider}
*
diff --git a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/SecretsProvider.java b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/SecretsProvider.java
index fd45da881..99b87f84b 100644
--- a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/SecretsProvider.java
+++ b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/SecretsProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,8 +11,14 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.parameters;
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+import java.time.temporal.ChronoUnit;
+import java.util.Base64;
+import java.util.Map;
import software.amazon.awssdk.core.SdkSystemSetting;
import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient;
import software.amazon.awssdk.regions.Region;
@@ -22,12 +28,6 @@
import software.amazon.lambda.powertools.parameters.transform.TransformationManager;
import software.amazon.lambda.powertools.parameters.transform.Transformer;
-import java.time.temporal.ChronoUnit;
-import java.util.Base64;
-import java.util.Map;
-
-import static java.nio.charset.StandardCharsets.UTF_8;
-
/**
* AWS Secrets Manager Parameter Provider
*
@@ -59,7 +59,7 @@ public class SecretsProvider extends BaseProvider {
/**
* Constructor with custom {@link SecretsManagerClient}.
* Use when you need to customize region or any other attribute of the client.
- *
+ *
* Use the {@link Builder} to create an instance of it.
*
* @param client custom client you would like to use.
@@ -71,14 +71,24 @@ public class SecretsProvider extends BaseProvider {
/**
* Constructor with only a CacheManager
- *
+ *
* Used in {@link ParamManager#createProvider(Class)}
+ *
* @param cacheManager handles the parameter caching
*/
SecretsProvider(CacheManager cacheManager) {
this(cacheManager, Builder.createClient());
}
+ /**
+ * Create a builder that can be used to configure and create a {@link SecretsProvider}.
+ *
+ * @return a new instance of {@link SecretsProvider.Builder}
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
/**
* Retrieve the parameter value from the AWS Secrets Manager.
*
@@ -91,13 +101,14 @@ protected String getValue(String key) {
String secretValue = client.getSecretValue(request).secretString();
if (secretValue == null) {
- secretValue = new String(Base64.getDecoder().decode(client.getSecretValue(request).secretBinary().asByteArray()), UTF_8);
+ secretValue =
+ new String(Base64.getDecoder().decode(client.getSecretValue(request).secretBinary().asByteArray()),
+ UTF_8);
}
return secretValue;
}
/**
- *
* @throws UnsupportedOperationException as it is not possible to get multiple values simultaneously from Secrets Manager
*/
@Override
@@ -137,21 +148,19 @@ SecretsManagerClient getClient() {
return client;
}
- /**
- * Create a builder that can be used to configure and create a {@link SecretsProvider}.
- *
- * @return a new instance of {@link SecretsProvider.Builder}
- */
- public static Builder builder() {
- return new Builder();
- }
-
static class Builder {
private SecretsManagerClient client;
private CacheManager cacheManager;
private TransformationManager transformationManager;
+ private static SecretsManagerClient createClient() {
+ return SecretsManagerClient.builder()
+ .httpClientBuilder(UrlConnectionHttpClient.builder())
+ .region(Region.of(System.getenv(SdkSystemSetting.AWS_REGION.environmentVariable())))
+ .build();
+ }
+
/**
* Create a {@link SecretsProvider} instance.
*
@@ -186,13 +195,6 @@ public Builder withClient(SecretsManagerClient client) {
return this;
}
- private static SecretsManagerClient createClient() {
- return SecretsManagerClient.builder()
- .httpClientBuilder(UrlConnectionHttpClient.builder())
- .region(Region.of(System.getenv(SdkSystemSetting.AWS_REGION.environmentVariable())))
- .build();
- }
-
/**
* Mandatory. Provide a CacheManager to the {@link SecretsProvider}
*
diff --git a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/cache/CacheManager.java b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/cache/CacheManager.java
index 687337a96..b868cb642 100644
--- a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/cache/CacheManager.java
+++ b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/cache/CacheManager.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,15 +11,16 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.parameters.cache;
+import static java.time.temporal.ChronoUnit.SECONDS;
+
import java.time.Clock;
import java.time.Duration;
import java.time.Instant;
import java.util.Optional;
-import static java.time.temporal.ChronoUnit.SECONDS;
-
public class CacheManager {
static final Duration DEFAULT_MAX_AGE_SECS = Duration.of(5, SECONDS);
diff --git a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/cache/DataStore.java b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/cache/DataStore.java
index 9ad8df12c..737faa353 100644
--- a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/cache/DataStore.java
+++ b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/cache/DataStore.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,6 +11,7 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.parameters.cache;
import java.time.Instant;
@@ -27,21 +28,11 @@ public DataStore() {
this.store = new ConcurrentHashMap<>();
}
- static class ValueNode {
- public final Object value;
- public final Instant time;
-
- public ValueNode(Object value, Instant time){
- this.value = value;
- this.time = time;
- }
- }
-
- public void put(String key, Object value, Instant time){
+ public void put(String key, Object value, Instant time) {
store.put(key, new ValueNode(value, time));
}
- public void remove(String Key){
+ public void remove(String Key) {
store.remove(Key);
}
@@ -51,11 +42,21 @@ public Object get(String key) {
}
public boolean hasExpired(String key, Instant now) {
- boolean hasExpired = !store.containsKey(key) || now.isAfter(store.get(key).time);
+ boolean hasExpired = !store.containsKey(key) || now.isAfter(store.get(key).time);
// Auto-clean if the parameter has expired
if (hasExpired) {
remove(key);
}
return hasExpired;
}
+
+ static class ValueNode {
+ public final Object value;
+ public final Instant time;
+
+ public ValueNode(Object value, Instant time) {
+ this.value = value;
+ this.time = time;
+ }
+ }
}
diff --git a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/exception/DynamoDbProviderSchemaException.java b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/exception/DynamoDbProviderSchemaException.java
index b7574e81d..77df6e3d3 100644
--- a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/exception/DynamoDbProviderSchemaException.java
+++ b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/exception/DynamoDbProviderSchemaException.java
@@ -1,3 +1,17 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.parameters.exception;
/**
diff --git a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/exception/TransformationException.java b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/exception/TransformationException.java
index 7d28d12d1..f071c8a6b 100644
--- a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/exception/TransformationException.java
+++ b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/exception/TransformationException.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,6 +11,7 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.parameters.exception;
public class TransformationException extends RuntimeException {
@@ -19,6 +20,7 @@ public TransformationException(Exception e) {
super(e);
}
- public TransformationException(String message) { super(message);
+ public TransformationException(String message) {
+ super(message);
}
}
diff --git a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/internal/LambdaParametersAspect.java b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/internal/LambdaParametersAspect.java
index 8de2f3f57..081af108d 100644
--- a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/internal/LambdaParametersAspect.java
+++ b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/internal/LambdaParametersAspect.java
@@ -1,3 +1,17 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.parameters.internal;
import org.aspectj.lang.ProceedingJoinPoint;
@@ -20,12 +34,12 @@ public void getParam(Param paramAnnotation) {
public Object injectParam(final ProceedingJoinPoint joinPoint, final Param paramAnnotation) {
BaseProvider provider = ParamManager.getProvider(paramAnnotation.provider());
- if(paramAnnotation.transformer().isInterface()) {
+ if (paramAnnotation.transformer().isInterface()) {
// No transformation
return provider.get(paramAnnotation.key());
} else {
FieldSignature s = (FieldSignature) joinPoint.getSignature();
- if(String.class.isAssignableFrom(s.getFieldType())) {
+ if (String.class.isAssignableFrom(s.getFieldType())) {
// Basic transformation
return provider
.withTransformation(paramAnnotation.transformer())
diff --git a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/transform/Base64Transformer.java b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/transform/Base64Transformer.java
index c666edce7..e8557ebfd 100644
--- a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/transform/Base64Transformer.java
+++ b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/transform/Base64Transformer.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,13 +11,13 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.parameters.transform;
-import software.amazon.lambda.powertools.parameters.exception.TransformationException;
+import static java.nio.charset.StandardCharsets.UTF_8;
import java.util.Base64;
-
-import static java.nio.charset.StandardCharsets.UTF_8;
+import software.amazon.lambda.powertools.parameters.exception.TransformationException;
/**
* Transformer that take a base64 encoded string and return a decoded string.
diff --git a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/transform/BasicTransformer.java b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/transform/BasicTransformer.java
index 5251d9f16..92e73d9b0 100644
--- a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/transform/BasicTransformer.java
+++ b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/transform/BasicTransformer.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,6 +11,7 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.parameters.transform;
import software.amazon.lambda.powertools.parameters.exception.TransformationException;
diff --git a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/transform/JsonTransformer.java b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/transform/JsonTransformer.java
index d84a1ab3a..0eff58ea8 100644
--- a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/transform/JsonTransformer.java
+++ b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/transform/JsonTransformer.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,6 +11,7 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.parameters.transform;
import com.fasterxml.jackson.core.JsonProcessingException;
diff --git a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/transform/TransformationManager.java b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/transform/TransformationManager.java
index 00e6f84a9..d3fbce14f 100644
--- a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/transform/TransformationManager.java
+++ b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/transform/TransformationManager.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,11 +11,11 @@
* limitations under the License.
*
*/
-package software.amazon.lambda.powertools.parameters.transform;
-import software.amazon.lambda.powertools.parameters.exception.TransformationException;
+package software.amazon.lambda.powertools.parameters.transform;
import java.lang.reflect.InvocationTargetException;
+import software.amazon.lambda.powertools.parameters.exception.TransformationException;
/**
* Manager in charge of transforming parameter values in another format.
@@ -50,15 +50,18 @@ public boolean shouldTransform() {
*/
public String performBasicTransformation(String value) {
if (transformer == null) {
- throw new IllegalStateException("You cannot perform a transformation without Transformer, use the provider.withTransformation() method to specify it.");
+ throw new IllegalStateException(
+ "You cannot perform a transformation without Transformer, use the provider.withTransformation() method to specify it.");
}
if (!BasicTransformer.class.isAssignableFrom(transformer)) {
throw new IllegalStateException("Wrong Transformer for a String, choose a BasicTransformer.");
}
try {
- BasicTransformer basicTransformer = (BasicTransformer) transformer.getDeclaredConstructor().newInstance(null);
+ BasicTransformer basicTransformer =
+ (BasicTransformer) transformer.getDeclaredConstructor().newInstance(null);
return basicTransformer.applyTransformation(value);
- } catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
+ } catch (InstantiationException | IllegalAccessException | NoSuchMethodException |
+ InvocationTargetException e) {
throw new TransformationException(e);
}
}
@@ -66,19 +69,21 @@ public String performBasicTransformation(String value) {
/**
* Transform a String in a Java Object.
*
- * @param value the value to transform
+ * @param value the value to transform
* @param targetClass the type of the target object.
* @return the value transformed in an object ot type T.
*/
public T performComplexTransformation(String value, Class targetClass) {
if (transformer == null) {
- throw new IllegalStateException("You cannot perform a transformation without Transformer, use the provider.withTransformation() method to specify it.");
+ throw new IllegalStateException(
+ "You cannot perform a transformation without Transformer, use the provider.withTransformation() method to specify it.");
}
try {
Transformer complexTransformer = transformer.getDeclaredConstructor().newInstance(null);
return complexTransformer.applyTransformation(value, targetClass);
- } catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
+ } catch (InstantiationException | IllegalAccessException | NoSuchMethodException |
+ InvocationTargetException e) {
throw new TransformationException(e);
}
}
diff --git a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/transform/Transformer.java b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/transform/Transformer.java
index 3c57b2aa9..d9aea2644 100644
--- a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/transform/Transformer.java
+++ b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/transform/Transformer.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,6 +11,7 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.parameters.transform;
import software.amazon.lambda.powertools.parameters.exception.TransformationException;
@@ -34,7 +35,8 @@ public interface Transformer {
/**
* Apply a transformation on the input value (String)
- * @param value the parameter value to transform
+ *
+ * @param value the parameter value to transform
* @param targetClass class of the target object
* @return a transformed parameter
* @throws TransformationException when a transformation error occurs
diff --git a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/AppConfigProviderTest.java b/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/AppConfigProviderTest.java
index 23f6271da..f467dca72 100644
--- a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/AppConfigProviderTest.java
+++ b/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/AppConfigProviderTest.java
@@ -1,5 +1,24 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.parameters;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
+import static org.assertj.core.api.Assertions.assertThatRuntimeException;
+import static org.mockito.MockitoAnnotations.openMocks;
+
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.ArgumentCaptor;
@@ -15,23 +34,18 @@
import software.amazon.lambda.powertools.parameters.cache.CacheManager;
import software.amazon.lambda.powertools.parameters.transform.TransformationManager;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
-import static org.assertj.core.api.Assertions.assertThatRuntimeException;
-import static org.mockito.MockitoAnnotations.openMocks;
-
public class AppConfigProviderTest {
private final String environmentName = "test";
private final String applicationName = "fakeApp";
private final String defaultTestKey = "key1";
-
+
@Mock
AppConfigDataClient client;
-
+
@Captor
ArgumentCaptor startSessionRequestCaptor;
-
+
@Captor
ArgumentCaptor getLatestConfigurationRequestCaptor;
private AppConfigProvider provider;
@@ -89,13 +103,17 @@ public void getValueRetrievesValue() {
// Assert
assertThat(returnedValue1).isEqualTo(firstResponse.configuration().asUtf8String());
assertThat(returnedValue2).isEqualTo(secondResponse.configuration().asUtf8String());
- assertThat(returnedValue3).isEqualTo(secondResponse.configuration().asUtf8String()); // Third response is mocked to return null and should re-use previous value
+ assertThat(returnedValue3).isEqualTo(secondResponse.configuration()
+ .asUtf8String()); // Third response is mocked to return null and should re-use previous value
assertThat(startSessionRequestCaptor.getValue().applicationIdentifier()).isEqualTo(applicationName);
assertThat(startSessionRequestCaptor.getValue().environmentIdentifier()).isEqualTo(environmentName);
assertThat(startSessionRequestCaptor.getValue().configurationProfileIdentifier()).isEqualTo(defaultTestKey);
- assertThat(getLatestConfigurationRequestCaptor.getAllValues().get(0).configurationToken()).isEqualTo(firstSession.initialConfigurationToken());
- assertThat(getLatestConfigurationRequestCaptor.getAllValues().get(1).configurationToken()).isEqualTo(firstResponse.nextPollConfigurationToken());
- assertThat(getLatestConfigurationRequestCaptor.getAllValues().get(2).configurationToken()).isEqualTo(secondResponse.nextPollConfigurationToken());
+ assertThat(getLatestConfigurationRequestCaptor.getAllValues().get(0).configurationToken()).isEqualTo(
+ firstSession.initialConfigurationToken());
+ assertThat(getLatestConfigurationRequestCaptor.getAllValues().get(1).configurationToken()).isEqualTo(
+ firstResponse.nextPollConfigurationToken());
+ assertThat(getLatestConfigurationRequestCaptor.getAllValues().get(2).configurationToken()).isEqualTo(
+ secondResponse.nextPollConfigurationToken());
}
@Test
@@ -156,10 +174,14 @@ public void multipleKeysRetrievalWorks() {
// Assert
assertThat(firstKeyValue).isEqualTo(param1Response.configuration().asUtf8String());
assertThat(secondKeyValue).isEqualTo(param2Response.configuration().asUtf8String());
- assertThat(startSessionRequestCaptor.getAllValues().get(0).configurationProfileIdentifier()).isEqualTo(param1Key);
- assertThat(startSessionRequestCaptor.getAllValues().get(1).configurationProfileIdentifier()).isEqualTo(param2Key);
- assertThat(getLatestConfigurationRequestCaptor.getAllValues().get(0).configurationToken()).isEqualTo(param1Session.initialConfigurationToken());
- assertThat(getLatestConfigurationRequestCaptor.getAllValues().get(1).configurationToken()).isEqualTo(param2Session.initialConfigurationToken());
+ assertThat(startSessionRequestCaptor.getAllValues().get(0).configurationProfileIdentifier()).isEqualTo(
+ param1Key);
+ assertThat(startSessionRequestCaptor.getAllValues().get(1).configurationProfileIdentifier()).isEqualTo(
+ param2Key);
+ assertThat(getLatestConfigurationRequestCaptor.getAllValues().get(0).configurationToken()).isEqualTo(
+ param1Session.initialConfigurationToken());
+ assertThat(getLatestConfigurationRequestCaptor.getAllValues().get(1).configurationToken()).isEqualTo(
+ param2Session.initialConfigurationToken());
}
diff --git a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/BaseProviderTest.java b/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/BaseProviderTest.java
index 8dd2d7658..edc671e2c 100644
--- a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/BaseProviderTest.java
+++ b/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/BaseProviderTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,20 +11,8 @@
* limitations under the License.
*
*/
-package software.amazon.lambda.powertools.parameters;
-
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import software.amazon.lambda.powertools.parameters.cache.CacheManager;
-import software.amazon.lambda.powertools.parameters.transform.ObjectToDeserialize;
-import software.amazon.lambda.powertools.parameters.transform.TransformationManager;
-import software.amazon.lambda.powertools.parameters.transform.Transformer;
-import java.time.Clock;
-import java.time.temporal.ChronoUnit;
-import java.util.Base64;
-import java.util.HashMap;
-import java.util.Map;
+package software.amazon.lambda.powertools.parameters;
import static java.time.Clock.offset;
import static java.time.Duration.of;
@@ -36,6 +24,18 @@
import static software.amazon.lambda.powertools.parameters.transform.Transformer.base64;
import static software.amazon.lambda.powertools.parameters.transform.Transformer.json;
+import java.time.Clock;
+import java.time.temporal.ChronoUnit;
+import java.util.Base64;
+import java.util.HashMap;
+import java.util.Map;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import software.amazon.lambda.powertools.parameters.cache.CacheManager;
+import software.amazon.lambda.powertools.parameters.transform.ObjectToDeserialize;
+import software.amazon.lambda.powertools.parameters.transform.TransformationManager;
+import software.amazon.lambda.powertools.parameters.transform.Transformer;
+
public class BaseProviderTest {
Clock clock;
@@ -45,33 +45,6 @@ public class BaseProviderTest {
boolean getFromStore = false;
- class BasicProvider extends BaseProvider {
-
- public BasicProvider(CacheManager cacheManager) {
- super(cacheManager);
- }
-
- private String value = "valueFromStore";
-
- public void setValue(String value) {
- this.value = value;
- }
-
- @Override
- protected String getValue(String key) {
- getFromStore = true;
- return value;
- }
-
- @Override
- protected Map getMultipleValues(String path) {
- getFromStore = true;
- Map map = new HashMap<>();
- map.put(path, value);
- return map;
- }
- }
-
@BeforeEach
public void setup() {
openMocks(this);
@@ -224,10 +197,11 @@ public void get_basicTransformation_shouldTransformInString() {
public void get_complexTransformation_shouldTransformInObject() {
provider.setValue("{\"foo\":\"Foo\", \"bar\":42, \"baz\":123456789}");
- ObjectToDeserialize objectToDeserialize = provider.withTransformation(json).get("foo", ObjectToDeserialize.class);
+ ObjectToDeserialize objectToDeserialize =
+ provider.withTransformation(json).get("foo", ObjectToDeserialize.class);
assertThat(objectToDeserialize).matches(
- o -> o.getFoo().equals("Foo")
+ o -> o.getFoo().equals("Foo")
&& o.getBar() == 42
&& o.getBaz() == 123456789);
}
@@ -400,4 +374,31 @@ public void getTwoParams_shouldResetTransformationOptionsInBetween() {
assertThat(foob64).isEqualTo("base64encoded");
assertThat(foostr).isEqualTo("string");
}
+
+ class BasicProvider extends BaseProvider {
+
+ private String value = "valueFromStore";
+
+ public BasicProvider(CacheManager cacheManager) {
+ super(cacheManager);
+ }
+
+ public void setValue(String value) {
+ this.value = value;
+ }
+
+ @Override
+ protected String getValue(String key) {
+ getFromStore = true;
+ return value;
+ }
+
+ @Override
+ protected Map getMultipleValues(String path) {
+ getFromStore = true;
+ Map map = new HashMap<>();
+ map.put(path, value);
+ return map;
+ }
+ }
}
diff --git a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/DynamoDbProviderE2ETest.java b/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/DynamoDbProviderE2ETest.java
index c9397676b..18212b45c 100644
--- a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/DynamoDbProviderE2ETest.java
+++ b/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/DynamoDbProviderE2ETest.java
@@ -1,5 +1,23 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.parameters;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.HashMap;
+import java.util.Map;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient;
@@ -8,16 +26,11 @@
import software.amazon.awssdk.services.dynamodb.model.PutItemRequest;
import software.amazon.lambda.powertools.parameters.cache.CacheManager;
-import java.util.HashMap;
-import java.util.Map;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
/**
* This class provides simple end-to-end style testing of the DynamoDBProvider class.
* It is ignored, for now, as it requires AWS access and that's not yet run as part
* of our unit test suite in the cloud.
- *
+ *
* The test is kept here for 1/ local development and 2/ in preparation for future
* E2E tests running in the cloud CI. Once the E2E test structure is merged we
* will move this across.
@@ -46,8 +59,8 @@ public void TestGetValue() {
testItem.put("id", AttributeValue.fromS("test_param"));
testItem.put("value", AttributeValue.fromS("the_value_is_hello!"));
ddbClient.putItem(PutItemRequest.builder()
- .tableName(ParamsTestTable)
- .item(testItem)
+ .tableName(ParamsTestTable)
+ .item(testItem)
.build());
// Act
diff --git a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/DynamoDbProviderTest.java b/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/DynamoDbProviderTest.java
index d6818a64f..abfc9ab8a 100644
--- a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/DynamoDbProviderTest.java
+++ b/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/DynamoDbProviderTest.java
@@ -1,5 +1,26 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.parameters;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
+import static org.mockito.MockitoAnnotations.openMocks;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -17,31 +38,18 @@
import software.amazon.lambda.powertools.parameters.exception.DynamoDbProviderSchemaException;
import software.amazon.lambda.powertools.parameters.transform.TransformationManager;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.UUID;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
-import static org.mockito.MockitoAnnotations.openMocks;
-
public class DynamoDbProviderTest {
+ private final String tableName = "ddb-test-table";
@Mock
DynamoDbClient client;
-
@Mock
TransformationManager transformationManager;
-
@Captor
ArgumentCaptor getItemValueCaptor;
-
@Captor
ArgumentCaptor queryRequestCaptor;
-
-
private DynamoDbProvider provider;
- private final String tableName = "ddb-test-table";
@BeforeEach
public void init() {
@@ -114,9 +122,10 @@ public void getValueWithMalformedRowThrows() {
.item(responseData)
.build());
// Act
- Assertions.assertThrows(DynamoDbProviderSchemaException.class, () -> {
- provider.getValue(key);
- });
+ Assertions.assertThrows(DynamoDbProviderSchemaException.class, () ->
+ {
+ provider.getValue(key);
+ });
}
@@ -180,10 +189,11 @@ public void getMultipleValuesMissingSortKey_throwsException() {
Mockito.when(client.query(queryRequestCaptor.capture())).thenReturn(response);
// Assert
- Assertions.assertThrows(DynamoDbProviderSchemaException.class, () -> {
- // Act
- provider.getMultipleValues(key);
- });
+ Assertions.assertThrows(DynamoDbProviderSchemaException.class, () ->
+ {
+ // Act
+ provider.getMultipleValues(key);
+ });
}
@Test
@@ -200,10 +210,11 @@ public void getValuesWithMalformedRowThrows() {
Mockito.when(client.query(queryRequestCaptor.capture())).thenReturn(response);
// Assert
- Assertions.assertThrows(DynamoDbProviderSchemaException.class, () -> {
- // Act
- provider.getMultipleValues(key);
- });
+ Assertions.assertThrows(DynamoDbProviderSchemaException.class, () ->
+ {
+ // Act
+ provider.getMultipleValues(key);
+ });
}
@Test
@@ -214,6 +225,7 @@ public void testDynamoDBBuilderMissingCacheManager_throwsException() {
.withTable("table")
.build());
}
+
@Test
public void testDynamoDBBuilderMissingTable_throwsException() {
diff --git a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerIntegrationTest.java b/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerIntegrationTest.java
index e1cb72be9..d6fbe66f0 100644
--- a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerIntegrationTest.java
+++ b/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerIntegrationTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,8 +11,21 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.parameters;
+import static org.apache.commons.lang3.reflect.FieldUtils.writeStaticField;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.mockito.MockitoAnnotations.openMocks;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
import org.assertj.core.data.MapEntry;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -31,19 +44,6 @@
import software.amazon.awssdk.services.ssm.model.GetParametersByPathResponse;
import software.amazon.awssdk.services.ssm.model.Parameter;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-import static org.apache.commons.lang3.reflect.FieldUtils.writeStaticField;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-import static org.mockito.MockitoAnnotations.openMocks;
-
public class ParamManagerIntegrationTest {
@Mock
@@ -51,21 +51,16 @@ public class ParamManagerIntegrationTest {
@Mock
DynamoDbClient ddbClient;
-
- @Mock
- private AppConfigDataClient appConfigDataClient;
-
@Captor
ArgumentCaptor ssmParamCaptor;
-
@Captor
ArgumentCaptor ssmParamByPathCaptor;
-
@Mock
SecretsManagerClient secretsManagerClient;
-
@Captor
ArgumentCaptor secretsCaptor;
+ @Mock
+ private AppConfigDataClient appConfigDataClient;
@BeforeEach
public void setup() throws IllegalAccessException {
diff --git a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerTest.java b/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerTest.java
index a21a6082c..b84fcf743 100644
--- a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerTest.java
+++ b/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerTest.java
@@ -11,18 +11,19 @@
* limitations under the License.
*
*/
-package software.amazon.lambda.powertools.parameters;
-import org.junit.jupiter.api.Test;
-import software.amazon.lambda.powertools.parameters.cache.CacheManager;
-import software.amazon.lambda.powertools.parameters.internal.CustomProvider;
-import software.amazon.lambda.powertools.parameters.transform.TransformationManager;
+package software.amazon.lambda.powertools.parameters;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
import static org.assertj.core.api.Assertions.assertThatRuntimeException;
import static org.junit.jupiter.api.Assertions.assertNotNull;
+import org.junit.jupiter.api.Test;
+import software.amazon.lambda.powertools.parameters.cache.CacheManager;
+import software.amazon.lambda.powertools.parameters.internal.CustomProvider;
+import software.amazon.lambda.powertools.parameters.transform.TransformationManager;
+
public class ParamManagerTest {
@Test
diff --git a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/SSMProviderTest.java b/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/SSMProviderTest.java
index e55f3d7e6..6a5aa3e68 100644
--- a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/SSMProviderTest.java
+++ b/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/SSMProviderTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,8 +11,22 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.parameters;
+import static java.util.Arrays.asList;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.mockito.MockitoAnnotations.openMocks;
+
+import java.time.temporal.ChronoUnit;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
import org.assertj.core.data.MapEntry;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -28,20 +42,6 @@
import software.amazon.lambda.powertools.parameters.cache.CacheManager;
import software.amazon.lambda.powertools.parameters.transform.TransformationManager;
-import java.time.temporal.ChronoUnit;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
-import static java.util.Arrays.asList;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-import static org.mockito.MockitoAnnotations.openMocks;
-
public class SSMProviderTest {
@Mock
@@ -165,7 +165,8 @@ public void getMultipleWithNextToken() {
List parameters1 = new ArrayList<>();
parameters1.add(Parameter.builder().name("/prod/app1/key1").value("foo1").build());
parameters1.add(Parameter.builder().name("/prod/app1/key2").value("foo2").build());
- GetParametersByPathResponse response1 = GetParametersByPathResponse.builder().parameters(parameters1).nextToken("123abc").build();
+ GetParametersByPathResponse response1 =
+ GetParametersByPathResponse.builder().parameters(parameters1).nextToken("123abc").build();
List parameters2 = new ArrayList<>();
parameters2.add(Parameter.builder().name("/prod/app1/key3").value("foo3").build());
@@ -184,11 +185,12 @@ public void getMultipleWithNextToken() {
GetParametersByPathRequest request1 = requestParams.get(0);
GetParametersByPathRequest request2 = requestParams.get(1);
- assertThat(asList(request1, request2)).allSatisfy(req -> {
- assertThat(req.path()).isEqualTo("/prod/app1");
- assertThat(req.withDecryption()).isFalse();
- assertThat(req.recursive()).isFalse();
- });
+ assertThat(asList(request1, request2)).allSatisfy(req ->
+ {
+ assertThat(req.path()).isEqualTo("/prod/app1");
+ assertThat(req.withDecryption()).isFalse();
+ assertThat(req.recursive()).isFalse();
+ });
assertThat(request1.nextToken()).isNull();
assertThat(request2.nextToken()).isEqualTo("123abc");
diff --git a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/SecretsProviderTest.java b/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/SecretsProviderTest.java
index 2ab72ffdd..f4f2d9bee 100644
--- a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/SecretsProviderTest.java
+++ b/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/SecretsProviderTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,8 +11,16 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.parameters;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
+import static org.assertj.core.api.Assertions.assertThatRuntimeException;
+import static org.mockito.MockitoAnnotations.openMocks;
+
+import java.time.temporal.ChronoUnit;
+import java.util.Base64;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.ArgumentCaptor;
@@ -26,14 +34,6 @@
import software.amazon.lambda.powertools.parameters.cache.CacheManager;
import software.amazon.lambda.powertools.parameters.transform.TransformationManager;
-import java.time.temporal.ChronoUnit;
-import java.util.Base64;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
-import static org.assertj.core.api.Assertions.assertThatRuntimeException;
-import static org.mockito.MockitoAnnotations.openMocks;
-
public class SecretsProviderTest {
@Mock
@@ -76,7 +76,8 @@ public void getValueBase64() {
String key = "Key2";
String expectedValue = "Value2";
byte[] valueb64 = Base64.getEncoder().encode(expectedValue.getBytes());
- GetSecretValueResponse response = GetSecretValueResponse.builder().secretBinary(SdkBytes.fromByteArray(valueb64)).build();
+ GetSecretValueResponse response =
+ GetSecretValueResponse.builder().secretBinary(SdkBytes.fromByteArray(valueb64)).build();
Mockito.when(client.getSecretValue(paramCaptor.capture())).thenReturn(response);
String value = provider.getValue(key);
@@ -99,9 +100,9 @@ public void testSecretsProviderBuilderMissingCacheManager_throwsException() {
// Act & Assert
assertThatIllegalStateException().isThrownBy(() -> SecretsProvider.builder()
- .withClient(client)
- .withTransformationManager(transformationManager)
- .build())
+ .withClient(client)
+ .withTransformationManager(transformationManager)
+ .build())
.withMessage("No CacheManager provided, please provide one");
}
}
diff --git a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/cache/CacheManagerTest.java b/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/cache/CacheManagerTest.java
index 2464b4278..2bcfcc566 100644
--- a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/cache/CacheManagerTest.java
+++ b/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/cache/CacheManagerTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,19 +11,19 @@
* limitations under the License.
*
*/
-package software.amazon.lambda.powertools.parameters.cache;
-
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import java.time.Clock;
-import java.util.Optional;
+package software.amazon.lambda.powertools.parameters.cache;
import static java.time.Clock.offset;
import static java.time.Duration.of;
import static java.time.temporal.ChronoUnit.SECONDS;
import static org.assertj.core.api.Assertions.assertThat;
+import java.time.Clock;
+import java.util.Optional;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
public class CacheManagerTest {
CacheManager manager;
diff --git a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/cache/DataStoreTest.java b/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/cache/DataStoreTest.java
index c68992bf1..e86ded9be 100644
--- a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/cache/DataStoreTest.java
+++ b/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/cache/DataStoreTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,19 +11,19 @@
* limitations under the License.
*
*/
-package software.amazon.lambda.powertools.parameters.cache;
-
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import java.time.Clock;
-import java.time.Instant;
+package software.amazon.lambda.powertools.parameters.cache;
import static java.time.Clock.offset;
import static java.time.Duration.of;
import static java.time.temporal.ChronoUnit.SECONDS;
import static org.assertj.core.api.Assertions.assertThat;
+import java.time.Clock;
+import java.time.Instant;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
public class DataStoreTest {
Clock clock;
diff --git a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/internal/AnotherObject.java b/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/internal/AnotherObject.java
index b58ad7b3d..074a08844 100644
--- a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/internal/AnotherObject.java
+++ b/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/internal/AnotherObject.java
@@ -1,11 +1,25 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.parameters.internal;
public class AnotherObject {
- public AnotherObject() {}
-
private String another;
private int object;
+ public AnotherObject() {
+ }
public String getAnother() {
return another;
diff --git a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/internal/CustomProvider.java b/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/internal/CustomProvider.java
index e58ef746c..2c9db3712 100644
--- a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/internal/CustomProvider.java
+++ b/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/internal/CustomProvider.java
@@ -1,11 +1,24 @@
-package software.amazon.lambda.powertools.parameters.internal;
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
-import software.amazon.lambda.powertools.parameters.BaseProvider;
-import software.amazon.lambda.powertools.parameters.cache.CacheManager;
+package software.amazon.lambda.powertools.parameters.internal;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
+import software.amazon.lambda.powertools.parameters.BaseProvider;
+import software.amazon.lambda.powertools.parameters.cache.CacheManager;
public class CustomProvider extends BaseProvider {
diff --git a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/internal/LambdaParametersAspectTest.java b/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/internal/LambdaParametersAspectTest.java
index c390a051e..d346a1aa4 100644
--- a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/internal/LambdaParametersAspectTest.java
+++ b/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/internal/LambdaParametersAspectTest.java
@@ -1,5 +1,27 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.parameters.internal;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
+import static org.mockito.Mockito.mockStatic;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.mockito.MockitoAnnotations.openMocks;
+
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mock;
@@ -12,14 +34,6 @@
import software.amazon.lambda.powertools.parameters.transform.JsonTransformer;
import software.amazon.lambda.powertools.parameters.transform.ObjectToDeserialize;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
-import static org.mockito.Mockito.mockStatic;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-import static org.mockito.MockitoAnnotations.openMocks;
-
public class LambdaParametersAspectTest {
@Mock
@@ -75,14 +89,17 @@ public void testWithComplexTransform() {
.isInstanceOf(ObjectToDeserialize.class)
.matches(
o -> o.getFoo().equals("Foo") &&
- o.getBar() == 42 &&
- o.getBaz() == 123456789);
+ o.getBar() == 42 &&
+ o.getBaz() == 123456789);
}
@Test
public void testWithComplexTransformWrongTargetClass_ShouldThrowException() {
assertThatExceptionOfType(TransformationException.class)
- .isThrownBy(() -> {AnotherObject obj = wrongTransform; });
+ .isThrownBy(() ->
+ {
+ AnotherObject obj = wrongTransform;
+ });
}
}
diff --git a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/transform/Base64TransformerTest.java b/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/transform/Base64TransformerTest.java
index 428b7e0ab..ea713b552 100644
--- a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/transform/Base64TransformerTest.java
+++ b/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/transform/Base64TransformerTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,16 +11,16 @@
* limitations under the License.
*
*/
-package software.amazon.lambda.powertools.parameters.transform;
-import org.junit.jupiter.api.Test;
-import software.amazon.lambda.powertools.parameters.exception.TransformationException;
-
-import java.util.Base64;
+package software.amazon.lambda.powertools.parameters.transform;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
+import java.util.Base64;
+import org.junit.jupiter.api.Test;
+import software.amazon.lambda.powertools.parameters.exception.TransformationException;
+
public class Base64TransformerTest {
@Test
diff --git a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/transform/JsonTransformerTest.java b/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/transform/JsonTransformerTest.java
index fe4fae0bb..5cb980cc7 100644
--- a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/transform/JsonTransformerTest.java
+++ b/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/transform/JsonTransformerTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,35 +11,38 @@
* limitations under the License.
*
*/
-package software.amazon.lambda.powertools.parameters.transform;
-import org.junit.jupiter.api.Test;
-import software.amazon.lambda.powertools.parameters.exception.TransformationException;
-
-import java.util.Map;
+package software.amazon.lambda.powertools.parameters.transform;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.assertj.core.data.MapEntry.entry;
+import java.util.Map;
+import org.junit.jupiter.api.Test;
+import software.amazon.lambda.powertools.parameters.exception.TransformationException;
+
public class JsonTransformerTest {
@Test
public void transform_json_shouldTransformInObject() throws TransformationException {
JsonTransformer transformation = new JsonTransformer<>();
- ObjectToDeserialize objectToDeserialize = transformation.applyTransformation("{\"foo\":\"Foo\", \"bar\":42, \"baz\":123456789}", ObjectToDeserialize.class);
+ ObjectToDeserialize objectToDeserialize =
+ transformation.applyTransformation("{\"foo\":\"Foo\", \"bar\":42, \"baz\":123456789}",
+ ObjectToDeserialize.class);
assertThat(objectToDeserialize).matches(
o -> o.getFoo().equals("Foo")
- && o.getBar() == 42
- && o.getBaz() == 123456789);
+ && o.getBar() == 42
+ && o.getBaz() == 123456789);
}
@Test
public void transform_json_shouldTransformInHashMap() throws TransformationException {
JsonTransformer
+
+
+
+ org.apache.maven.plugins
+ maven-checkstyle-plugin
+
+
+
+
\ No newline at end of file
diff --git a/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/SQSBatchProcessingException.java b/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/SQSBatchProcessingException.java
index 85231a003..7adc2afe5 100644
--- a/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/SQSBatchProcessingException.java
+++ b/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/SQSBatchProcessingException.java
@@ -1,15 +1,27 @@
-package software.amazon.lambda.powertools.sqs;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
-import com.amazonaws.services.lambda.runtime.events.SQSEvent;
+package software.amazon.lambda.powertools.sqs;
import static com.amazonaws.services.lambda.runtime.events.SQSEvent.SQSMessage;
-import static java.util.Collections.*;
+import static java.util.Collections.unmodifiableList;
import static java.util.stream.Collectors.joining;
+import com.amazonaws.services.lambda.runtime.events.SQSEvent;
+import java.util.ArrayList;
+import java.util.List;
+
/**
*
* When one or more {@link SQSMessage} fails and if any exception is thrown from {@link SqsMessageHandler#process(SQSMessage)}
@@ -47,6 +59,7 @@ public SQSBatchProcessingException(final List exceptions,
/**
* Details for exceptions that occurred while processing messages in {@link SqsMessageHandler#process(SQSMessage)}
+ *
* @return List of exceptions that occurred while processing messages
*/
public List getExceptions() {
@@ -55,6 +68,7 @@ public List getExceptions() {
/**
* List of returns from {@link SqsMessageHandler#process(SQSMessage)} that were successfully processed.
+ *
* @return List of returns from successfully processed messages
*/
public List successMessageReturnValues() {
@@ -63,6 +77,7 @@ public List successMessageReturnValues() {
/**
* Details of {@link SQSMessage} that failed in {@link SqsMessageHandler#process(SQSMessage)}
+ *
* @return List of failed messages
*/
public List getFailures() {
diff --git a/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/SqsBatch.java b/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/SqsBatch.java
index cd529ff22..d0ffe6a73 100644
--- a/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/SqsBatch.java
+++ b/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/SqsBatch.java
@@ -1,14 +1,27 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.sqs;
+import static com.amazonaws.services.lambda.runtime.events.SQSEvent.SQSMessage;
+
+import com.amazonaws.services.lambda.runtime.events.SQSEvent;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
-import com.amazonaws.services.lambda.runtime.events.SQSEvent;
-
-import static com.amazonaws.services.lambda.runtime.events.SQSEvent.*;
-
/**
* {@link SqsBatch} is used to process batch messages in {@link SQSEvent}
*
@@ -22,7 +35,7 @@
* will take care of deleting all the successful messages from SQS. When one or more single message fails processing due
* to exception thrown from {@link SqsMessageHandler#process(SQSMessage)}, Lambda execution will fail
* with {@link SQSBatchProcessingException}.
- *
+ *
* If all the messages are successfully processes, No SQS messages are deleted explicitly but is rather delegated to
* Lambda execution context for deletion.
*
@@ -35,14 +48,14 @@
*
* If you want certain exceptions to be treated as permanent failures, i.e. exceptions where the result of retrying will
* always be a failure and want these can be immediately moved to the dead letter queue associated to the source SQS queue,
- *
+ *
* you can use {@link SqsBatch#nonRetryableExceptions()} to configure such exceptions.
* Make sure function execution role has sqs:GetQueueAttributes permission on source SQS queue and sqs:SendMessage,
* sqs:SendMessageBatch permission for configured DLQ.
- *
+ *
* If you want such messages to be deleted instead, set {@link SqsBatch#deleteNonRetryableMessageFromQueue()} to true.
* By default its value is false.
- *
+ *
* If there is no DLQ configured on source SQS queue and {@link SqsBatch#nonRetryableExceptions()} attribute is set, if
* nonRetryableExceptions occurs from {@link SqsMessageHandler}, such exceptions will still be treated as temporary
* exceptions and the message will be moved back to source SQS queue for reprocessing. The same behaviour will occur if
@@ -69,6 +82,7 @@
*
* ...
*
+ *
* @see Amazon SQS dead-letter queues
*/
@Retention(RetentionPolicy.RUNTIME)
diff --git a/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/SqsLargeMessage.java b/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/SqsLargeMessage.java
index d96245006..847dd456c 100644
--- a/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/SqsLargeMessage.java
+++ b/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/SqsLargeMessage.java
@@ -1,3 +1,17 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.sqs;
import java.lang.annotation.ElementType;
@@ -58,7 +72,6 @@
*
*
To disable deletion of payloads setting the following annotation parameter
* {@code @SqsLargeMessage(deletePayloads=false)}
- *
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
diff --git a/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/SqsMessageHandler.java b/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/SqsMessageHandler.java
index 17e37797c..0c8f03ee9 100644
--- a/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/SqsMessageHandler.java
+++ b/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/SqsMessageHandler.java
@@ -1,9 +1,23 @@
-package software.amazon.lambda.powertools.sqs;
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
-import com.amazonaws.services.lambda.runtime.events.SQSEvent;
+package software.amazon.lambda.powertools.sqs;
import static com.amazonaws.services.lambda.runtime.events.SQSEvent.SQSMessage;
+import com.amazonaws.services.lambda.runtime.events.SQSEvent;
+
/**
*
* This interface should be implemented for processing {@link SQSMessage} inside {@link SQSEvent} received by lambda
@@ -20,6 +34,7 @@
*
+ *
* @param Return value type from {@link SqsMessageHandler#process(SQSMessage)}
*/
@FunctionalInterface
diff --git a/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/SqsUtils.java b/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/SqsUtils.java
index 9fff4dc6f..8c06a6291 100644
--- a/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/SqsUtils.java
+++ b/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/SqsUtils.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,30 +11,28 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.sqs;
+import static com.amazonaws.services.lambda.runtime.events.SQSEvent.SQSMessage;
+import static software.amazon.lambda.powertools.sqs.internal.SqsLargeMessageAspect.processMessages;
+
+import com.amazonaws.services.lambda.runtime.events.SQSEvent;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
-import java.util.LinkedList;
import java.util.List;
-import java.util.Queue;
import java.util.function.Function;
import java.util.stream.Collectors;
-
-import com.amazonaws.services.lambda.runtime.events.SQSEvent;
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.sqs.SqsClient;
import software.amazon.lambda.powertools.sqs.exception.SkippedMessageDueToFailedBatchException;
import software.amazon.lambda.powertools.sqs.internal.BatchContext;
-import software.amazon.payloadoffloading.PayloadS3Pointer;
import software.amazon.lambda.powertools.sqs.internal.SqsLargeMessageAspect;
-
-import static com.amazonaws.services.lambda.runtime.events.SQSEvent.SQSMessage;
-import static software.amazon.lambda.powertools.sqs.internal.SqsLargeMessageAspect.processMessages;
+import software.amazon.payloadoffloading.PayloadS3Pointer;
/**
* A class of helper functions to add additional functionality to {@link SQSEvent} processing.
@@ -43,11 +41,10 @@ public final class SqsUtils {
private static final Logger LOG = LoggerFactory.getLogger(SqsUtils.class);
private static final ObjectMapper objectMapper = new ObjectMapper();
- private static SqsClient client;
- private static S3Client s3Client;
-
// The attribute on an SQS-FIFO message used to record the message group ID
private static final String MESSAGE_GROUP_ID = "MessageGroupId";
+ private static SqsClient client;
+ private static S3Client s3Client;
private SqsUtils() {
}
@@ -176,23 +173,24 @@ public static List batchProcessor(final SQSEvent event,
* If you want certain exceptions to be treated as permanent failures, i.e. exceptions where the result of retrying will
* always be a failure and want these can be immediately moved to the dead letter queue associated to the source SQS queue,
* you can use nonRetryableExceptions parameter to configure such exceptions.
- *
+ *
* Make sure function execution role has sqs:GetQueueAttributes permission on source SQS queue and sqs:SendMessage,
* sqs:SendMessageBatch permission for configured DLQ.
- *
+ *
* If there is no DLQ configured on source SQS queue and {@link SqsBatch#nonRetryableExceptions()} attribute is set, if
* nonRetryableExceptions occurs from {@link SqsMessageHandler}, such exceptions will still be treated as temporary
* exceptions and the message will be moved back to source SQS queue for reprocessing. The same behaviour will occur if
* for some reason the utility is unable to move the message to the DLQ. An example of this could be because the function
* is missing the correct permissions.
*
- * @see Amazon SQS dead-letter queues
- * @param event {@link SQSEvent} received by lambda function.
- * @param handler Class implementing {@link SqsMessageHandler} which will be called for each message in event.
+ *
+ * @param event {@link SQSEvent} received by lambda function.
+ * @param handler Class implementing {@link SqsMessageHandler} which will be called for each message in event.
* @param nonRetryableExceptions exception classes that are to be treated as permanent exceptions and to be moved
* to DLQ.
* @return List of values returned by {@link SqsMessageHandler#process(SQSMessage)} while processing each message.
* @throws SQSBatchProcessingException if some messages fail during processing.
+ * @see Amazon SQS dead-letter queues
*/
@SafeVarargs
public static List batchProcessor(final SQSEvent event,
@@ -264,26 +262,26 @@ public static List batchProcessor(final SQSEvent event,
* If you want certain exceptions to be treated as permanent failures, i.e. exceptions where the result of retrying will
* always be a failure and want these can be immediately moved to the dead letter queue associated to the source SQS queue,
* you can use nonRetryableExceptions parameter to configure such exceptions.
- *
+ *
* Make sure function execution role has sqs:GetQueueAttributes permission on source SQS queue and sqs:SendMessage,
* sqs:SendMessageBatch permission for configured DLQ.
- *
+ *
* If there is no DLQ configured on source SQS queue and {@link SqsBatch#nonRetryableExceptions()} attribute is set, if
* nonRetryableExceptions occurs from {@link SqsMessageHandler}, such exceptions will still be treated as temporary
* exceptions and the message will be moved back to source SQS queue for reprocessing. The same behaviour will occur if
* for some reason the utility is unable to move the message to the DLQ. An example of this could be because the function
* is missing the correct permissions.
*
- * @see Amazon SQS dead-letter queues
*
- * @param event {@link SQSEvent} received by lambda function.
- * @param suppressException if this is set to true, No {@link SQSBatchProcessingException} is thrown even on failed
- * messages.
- * @param handler Class implementing {@link SqsMessageHandler} which will be called for each message in event.
+ * @param event {@link SQSEvent} received by lambda function.
+ * @param suppressException if this is set to true, No {@link SQSBatchProcessingException} is thrown even on failed
+ * messages.
+ * @param handler Class implementing {@link SqsMessageHandler} which will be called for each message in event.
* @param nonRetryableExceptions exception classes that are to be treated as permanent exceptions and to be moved
* to DLQ.
* @return List of values returned by {@link SqsMessageHandler#process(SQSMessage)} while processing each message.
* @throws SQSBatchProcessingException if some messages fail during processing.
+ * @see Amazon SQS dead-letter queues
*/
@SafeVarargs
public static List batchProcessor(final SQSEvent event,
@@ -325,28 +323,29 @@ public static List batchProcessor(final SQSEvent event,
* If you want certain exceptions to be treated as permanent failures, i.e. exceptions where the result of retrying will
* always be a failure and want these can be immediately moved to the dead letter queue associated to the source SQS queue,
* you can use nonRetryableExceptions parameter to configure such exceptions.
- *
+ *
* Make sure function execution role has sqs:GetQueueAttributes permission on source SQS queue and sqs:SendMessage,
* sqs:SendMessageBatch permission for configured DLQ.
- *
+ *
* If you want such messages to be deleted instead, set deleteNonRetryableMessageFromQueue to true.
- *
+ *
* If there is no DLQ configured on source SQS queue and {@link SqsBatch#nonRetryableExceptions()} attribute is set, if
* nonRetryableExceptions occurs from {@link SqsMessageHandler}, such exceptions will still be treated as temporary
* exceptions and the message will be moved back to source SQS queue for reprocessing. The same behaviour will occur if
* for some reason the utility is unable to move the message to the DLQ. An example of this could be because the function
* is missing the correct permissions.
*
- * @see Amazon SQS dead-letter queues
- * @param event {@link SQSEvent} received by lambda function.
- * @param suppressException if this is set to true, No {@link SQSBatchProcessingException} is thrown even on failed
- * messages.
- * @param handler Class implementing {@link SqsMessageHandler} which will be called for each message in event.
+ *
+ * @param event {@link SQSEvent} received by lambda function.
+ * @param suppressException if this is set to true, No {@link SQSBatchProcessingException} is thrown even on failed
+ * messages.
+ * @param handler Class implementing {@link SqsMessageHandler} which will be called for each message in event.
* @param deleteNonRetryableMessageFromQueue If messages with nonRetryableExceptions are to be deleted from SQS queue.
- * @param nonRetryableExceptions exception classes that are to be treated as permanent exceptions and to be moved
- * to DLQ.
+ * @param nonRetryableExceptions exception classes that are to be treated as permanent exceptions and to be moved
+ * to DLQ.
* @return List of values returned by {@link SqsMessageHandler#process(SQSMessage)} while processing each message.
* @throws SQSBatchProcessingException if some messages fail during processing.
+ * @see Amazon SQS dead-letter queues
*/
@SafeVarargs
public static List batchProcessor(final SQSEvent event,
@@ -356,7 +355,8 @@ public static List batchProcessor(final SQSEvent event,
final Class extends Exception>... nonRetryableExceptions) {
SqsMessageHandler handlerInstance = instantiatedHandler(handler);
- return batchProcessor(event, suppressException, handlerInstance, deleteNonRetryableMessageFromQueue, nonRetryableExceptions);
+ return batchProcessor(event, suppressException, handlerInstance, deleteNonRetryableMessageFromQueue,
+ nonRetryableExceptions);
}
/**
@@ -423,23 +423,24 @@ public static List batchProcessor(final SQSEvent event,
* If you want certain exceptions to be treated as permanent failures, i.e. exceptions where the result of retrying will
* always be a failure and want these can be immediately moved to the dead letter queue associated to the source SQS queue,
* you can use nonRetryableExceptions parameter to configure such exceptions.
- *
+ *
* Make sure function execution role has sqs:GetQueueAttributes permission on source SQS queue and sqs:SendMessage,
* sqs:SendMessageBatch permission for configured DLQ.
- *
+ *
* If there is no DLQ configured on source SQS queue and {@link SqsBatch#nonRetryableExceptions()} attribute is set, if
* nonRetryableExceptions occurs from {@link SqsMessageHandler}, such exceptions will still be treated as temporary
* exceptions and the message will be moved back to source SQS queue for reprocessing.The same behaviour will occur if
* for some reason the utility is unable to moved the message to the DLQ. An example of this could be because the function
* is missing the correct permissions.
*
- * @see Amazon SQS dead-letter queues
- * @param event {@link SQSEvent} received by lambda function.
- * @param handler Instance of class implementing {@link SqsMessageHandler} which will be called for each message in event.
+ *
+ * @param event {@link SQSEvent} received by lambda function.
+ * @param handler Instance of class implementing {@link SqsMessageHandler} which will be called for each message in event.
* @param nonRetryableExceptions exception classes that are to be treated as permanent exceptions and to be moved
* to DLQ.
* @return List of values returned by {@link SqsMessageHandler#process(SQSMessage)} while processing each message.
* @throws SQSBatchProcessingException if some messages fail during processing.
+ * @see Amazon SQS dead-letter queues
*/
@SafeVarargs
public static List batchProcessor(final SQSEvent event,
@@ -491,7 +492,7 @@ public static List batchProcessor(final SQSEvent event,
final Class extends Exception>... nonRetryableExceptions) {
final List handlerReturn = new ArrayList<>();
- if(client == null) {
+ if (client == null) {
client = SqsClient.create();
}
@@ -521,7 +522,8 @@ public static List batchProcessor(final SQSEvent event,
String messageGroupId = message.getAttributes() != null ?
message.getAttributes().get(MESSAGE_GROUP_ID) : null;
if (messageGroupId != null) {
- LOG.info("A message in a message batch with messageGroupId {} and messageId {} failed; failing the rest of the batch too"
+ LOG.info(
+ "A message in a message batch with messageGroupId {} and messageId {} failed; failing the rest of the batch too"
, messageGroupId, message.getMessageId());
failedBatch = true;
}
@@ -534,14 +536,16 @@ public static List batchProcessor(final SQSEvent event,
if (offset < event.getRecords().size()) {
event.getRecords()
.subList(offset, event.getRecords().size())
- .forEach(message -> {
- LOG.info("Skipping message {} as another message with a message group failed in this batch",
- message.getMessageId());
- batchContext.addFailure(message, new SkippedMessageDueToFailedBatchException());
- });
+ .forEach(message ->
+ {
+ LOG.info("Skipping message {} as another message with a message group failed in this batch",
+ message.getMessageId());
+ batchContext.addFailure(message, new SkippedMessageDueToFailedBatchException());
+ });
}
- batchContext.processSuccessAndHandleFailed(handlerReturn, suppressException, deleteNonRetryableMessageFromQueue, nonRetryableExceptions);
+ batchContext.processSuccessAndHandleFailed(handlerReturn, suppressException, deleteNonRetryableMessageFromQueue,
+ nonRetryableExceptions);
return handlerReturn;
}
@@ -552,7 +556,8 @@ private static SqsMessageHandler instantiatedHandler(final Class extend
return handler.getDeclaredConstructor().newInstance();
}
- final Constructor extends SqsMessageHandler> constructor = handler.getDeclaredConstructor(handler.getDeclaringClass());
+ final Constructor extends SqsMessageHandler> constructor =
+ handler.getDeclaredConstructor(handler.getDeclaringClass());
constructor.setAccessible(true);
return constructor.newInstance(handler.getDeclaringClass().getDeclaredConstructor().newInstance());
} catch (Exception e) {
@@ -576,7 +581,7 @@ public static ObjectMapper objectMapper() {
}
public static S3Client s3Client() {
- if(null == s3Client) {
+ if (null == s3Client) {
SqsUtils.s3Client = S3Client.create();
}
diff --git a/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/exception/SkippedMessageDueToFailedBatchException.java b/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/exception/SkippedMessageDueToFailedBatchException.java
index 9dbb66509..fbb4289d8 100644
--- a/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/exception/SkippedMessageDueToFailedBatchException.java
+++ b/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/exception/SkippedMessageDueToFailedBatchException.java
@@ -1,3 +1,17 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.sqs.exception;
/**
diff --git a/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/internal/BatchContext.java b/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/internal/BatchContext.java
index 1e4eff3bf..57ddeb22f 100644
--- a/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/internal/BatchContext.java
+++ b/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/internal/BatchContext.java
@@ -1,5 +1,26 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.sqs.internal;
+import static com.amazonaws.services.lambda.runtime.events.SQSEvent.SQSMessage;
+import static java.lang.String.format;
+import static java.util.Optional.ofNullable;
+import static java.util.stream.Collectors.toList;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
@@ -9,8 +30,6 @@
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.JsonNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import software.amazon.awssdk.core.SdkBytes;
@@ -28,11 +47,6 @@
import software.amazon.lambda.powertools.sqs.SQSBatchProcessingException;
import software.amazon.lambda.powertools.sqs.SqsUtils;
-import static com.amazonaws.services.lambda.runtime.events.SQSEvent.SQSMessage;
-import static java.lang.String.format;
-import static java.util.Optional.ofNullable;
-import static java.util.stream.Collectors.toList;
-
public final class BatchContext {
private static final Logger LOG = LoggerFactory.getLogger(BatchContext.class);
private static final Map QUEUE_ARN_TO_DLQ_URL_MAPPING = new HashMap<>();
@@ -69,16 +83,17 @@ public final void processSuccessAndHandleFailed(final List successReturns
exceptions.addAll(messageToException.values());
failedMessages.addAll(messageToException.keySet());
} else {
- messageToException.forEach((sqsMessage, exception) -> {
- boolean nonRetryableException = isNonRetryableException(exception, nonRetryableExceptions);
-
- if (nonRetryableException) {
- nonRetryableMessageToException.put(sqsMessage, exception);
- } else {
- exceptions.add(exception);
- failedMessages.add(sqsMessage);
- }
- });
+ messageToException.forEach((sqsMessage, exception) ->
+ {
+ boolean nonRetryableException = isNonRetryableException(exception, nonRetryableExceptions);
+
+ if (nonRetryableException) {
+ nonRetryableMessageToException.put(sqsMessage, exception);
+ } else {
+ exceptions.add(exception);
+ failedMessages.add(sqsMessage);
+ }
+ });
}
List messagesToBeDeleted = new ArrayList<>(success);
@@ -126,7 +141,8 @@ private boolean isNonRetryableException(Exception exception, Class extends Exc
.anyMatch(aClass -> aClass.isInstance(exception));
}
- private boolean moveNonRetryableMessagesToDlqIfConfigured(Map nonRetryableMessageToException) {
+ private boolean moveNonRetryableMessagesToDlqIfConfigured(
+ Map nonRetryableMessageToException) {
Optional dlqUrl = fetchDlqUrl(nonRetryableMessageToException);
if (!dlqUrl.isPresent()) {
@@ -134,76 +150,88 @@ private boolean moveNonRetryableMessagesToDlqIfConfigured(Map dlqMessages = nonRetryableMessageToException.keySet().stream()
- .map(sqsMessage -> {
- Map messageAttributesMap = new HashMap<>();
+ .map(sqsMessage ->
+ {
+ Map messageAttributesMap = new HashMap<>();
- sqsMessage.getMessageAttributes().forEach((s, messageAttribute) -> {
- MessageAttributeValue.Builder builder = MessageAttributeValue.builder();
+ sqsMessage.getMessageAttributes().forEach((s, messageAttribute) ->
+ {
+ MessageAttributeValue.Builder builder = MessageAttributeValue.builder();
- builder
- .dataType(messageAttribute.getDataType())
- .stringValue(messageAttribute.getStringValue());
+ builder
+ .dataType(messageAttribute.getDataType())
+ .stringValue(messageAttribute.getStringValue());
- if (null != messageAttribute.getBinaryValue()) {
- builder.binaryValue(SdkBytes.fromByteBuffer(messageAttribute.getBinaryValue()));
- }
+ if (null != messageAttribute.getBinaryValue()) {
+ builder.binaryValue(SdkBytes.fromByteBuffer(messageAttribute.getBinaryValue()));
+ }
- messageAttributesMap.put(s, builder.build());
- });
+ messageAttributesMap.put(s, builder.build());
+ });
- return SendMessageBatchRequestEntry.builder()
- .messageBody(sqsMessage.getBody())
- .id(sqsMessage.getMessageId())
- .messageAttributes(messageAttributesMap)
- .build();
- })
+ return SendMessageBatchRequestEntry.builder()
+ .messageBody(sqsMessage.getBody())
+ .id(sqsMessage.getMessageId())
+ .messageAttributes(messageAttributesMap)
+ .build();
+ })
.collect(toList());
- List sendMessageBatchResponses = batchRequest(dlqMessages, 10, entriesToSend -> {
+ List sendMessageBatchResponses = batchRequest(dlqMessages, 10, entriesToSend ->
+ {
- SendMessageBatchResponse sendMessageBatchResponse = client.sendMessageBatch(SendMessageBatchRequest.builder()
- .entries(entriesToSend)
- .queueUrl(dlqUrl.get())
- .build());
+ SendMessageBatchResponse sendMessageBatchResponse =
+ client.sendMessageBatch(SendMessageBatchRequest.builder()
+ .entries(entriesToSend)
+ .queueUrl(dlqUrl.get())
+ .build());
- LOG.debug("Response from send batch message to DLQ request {}", sendMessageBatchResponse);
+ LOG.debug("Response from send batch message to DLQ request {}", sendMessageBatchResponse);
- return sendMessageBatchResponse;
- });
+ return sendMessageBatchResponse;
+ });
return sendMessageBatchResponses.stream()
.filter(response -> null != response && response.hasFailed())
- .peek(sendMessageBatchResponse -> LOG.error("Failed sending message to the DLQ. Entire batch will be re processed. Check if needed permissions are configured for the function. Response: {}", sendMessageBatchResponse))
- .count() == 0;
+ .peek(sendMessageBatchResponse -> LOG.error(
+ "Failed sending message to the DLQ. Entire batch will be re processed. Check if needed permissions are configured for the function. Response: {}",
+ sendMessageBatchResponse))
+ .count() == 0;
}
private Optional fetchDlqUrl(Map nonRetryableMessageToException) {
return nonRetryableMessageToException.keySet().stream()
.findFirst()
- .map(sqsMessage -> QUEUE_ARN_TO_DLQ_URL_MAPPING.computeIfAbsent(sqsMessage.getEventSourceArn(), sourceArn -> {
- String queueUrl = url(sourceArn);
-
- GetQueueAttributesResponse queueAttributes = client.getQueueAttributes(GetQueueAttributesRequest.builder()
- .attributeNames(QueueAttributeName.REDRIVE_POLICY)
- .queueUrl(queueUrl)
- .build());
-
- return ofNullable(queueAttributes.attributes().get(QueueAttributeName.REDRIVE_POLICY))
- .map(policy -> {
- try {
- return SqsUtils.objectMapper().readTree(policy);
- } catch (JsonProcessingException e) {
- LOG.debug("Unable to parse Re drive policy for queue {}. Even if DLQ exists, failed messages will be send back to main queue.", queueUrl, e);
- return null;
- }
- })
- .map(node -> node.get("deadLetterTargetArn"))
- .map(JsonNode::asText)
- .map(this::url)
- .orElse(null);
- }));
+ .map(sqsMessage -> QUEUE_ARN_TO_DLQ_URL_MAPPING.computeIfAbsent(sqsMessage.getEventSourceArn(),
+ sourceArn ->
+ {
+ String queueUrl = url(sourceArn);
+
+ GetQueueAttributesResponse queueAttributes =
+ client.getQueueAttributes(GetQueueAttributesRequest.builder()
+ .attributeNames(QueueAttributeName.REDRIVE_POLICY)
+ .queueUrl(queueUrl)
+ .build());
+
+ return ofNullable(queueAttributes.attributes().get(QueueAttributeName.REDRIVE_POLICY))
+ .map(policy ->
+ {
+ try {
+ return SqsUtils.objectMapper().readTree(policy);
+ } catch (JsonProcessingException e) {
+ LOG.debug(
+ "Unable to parse Re drive policy for queue {}. Even if DLQ exists, failed messages will be send back to main queue.",
+ queueUrl, e);
+ return null;
+ }
+ })
+ .map(node -> node.get("deadLetterTargetArn"))
+ .map(JsonNode::asText)
+ .map(this::url)
+ .orElse(null);
+ }));
}
private boolean hasFailures() {
@@ -213,23 +241,25 @@ private boolean hasFailures() {
private void deleteMessagesFromQueue(final List messages) {
if (!messages.isEmpty()) {
- List entries = messages.stream().map(m -> DeleteMessageBatchRequestEntry.builder()
- .id(m.getMessageId())
- .receiptHandle(m.getReceiptHandle())
- .build()).collect(toList());
-
- batchRequest(entries, 10, entriesToDelete -> {
- DeleteMessageBatchRequest request = DeleteMessageBatchRequest.builder()
- .queueUrl(url(messages.get(0).getEventSourceArn()))
- .entries(entriesToDelete)
- .build();
+ List entries =
+ messages.stream().map(m -> DeleteMessageBatchRequestEntry.builder()
+ .id(m.getMessageId())
+ .receiptHandle(m.getReceiptHandle())
+ .build()).collect(toList());
+
+ batchRequest(entries, 10, entriesToDelete ->
+ {
+ DeleteMessageBatchRequest request = DeleteMessageBatchRequest.builder()
+ .queueUrl(url(messages.get(0).getEventSourceArn()))
+ .entries(entriesToDelete)
+ .build();
- DeleteMessageBatchResponse deleteMessageBatchResponse = client.deleteMessageBatch(request);
+ DeleteMessageBatchResponse deleteMessageBatchResponse = client.deleteMessageBatch(request);
- LOG.debug("Response from delete request {}", deleteMessageBatchResponse);
+ LOG.debug("Response from delete request {}", deleteMessageBatchResponse);
- return deleteMessageBatchResponse;
- });
+ return deleteMessageBatchResponse;
+ });
}
}
diff --git a/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/internal/SqsLargeMessageAspect.java b/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/internal/SqsLargeMessageAspect.java
index 588d434d7..7022e399a 100644
--- a/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/internal/SqsLargeMessageAspect.java
+++ b/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/internal/SqsLargeMessageAspect.java
@@ -1,13 +1,31 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.sqs.internal;
+import static com.amazonaws.services.lambda.runtime.events.SQSEvent.SQSMessage;
+import static java.lang.String.format;
+import static software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor.isHandlerMethod;
+import static software.amazon.lambda.powertools.sqs.SqsUtils.s3Client;
+
+import com.amazonaws.services.lambda.runtime.Context;
+import com.amazonaws.services.lambda.runtime.events.SQSEvent;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.function.Function;
-
-import com.amazonaws.services.lambda.runtime.Context;
-import com.amazonaws.services.lambda.runtime.events.SQSEvent;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
@@ -24,63 +42,32 @@
import software.amazon.lambda.powertools.sqs.SqsLargeMessage;
import software.amazon.payloadoffloading.PayloadS3Pointer;
-import static com.amazonaws.services.lambda.runtime.events.SQSEvent.SQSMessage;
-import static java.lang.String.format;
-import static software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor.isHandlerMethod;
-import static software.amazon.lambda.powertools.sqs.SqsUtils.s3Client;
-
@Aspect
public class SqsLargeMessageAspect {
private static final Logger LOG = LoggerFactory.getLogger(SqsLargeMessageAspect.class);
- @SuppressWarnings({"EmptyMethod"})
- @Pointcut("@annotation(sqsLargeMessage)")
- public void callAt(SqsLargeMessage sqsLargeMessage) {
- }
-
- @Around(value = "callAt(sqsLargeMessage) && execution(@SqsLargeMessage * *.*(..))", argNames = "pjp,sqsLargeMessage")
- public Object around(ProceedingJoinPoint pjp,
- SqsLargeMessage sqsLargeMessage) throws Throwable {
- Object[] proceedArgs = pjp.getArgs();
-
- if (isHandlerMethod(pjp)
- && placedOnSqsEventRequestHandler(pjp)) {
- List pointersToDelete = rewriteMessages((SQSEvent) proceedArgs[0]);
-
- Object proceed = pjp.proceed(proceedArgs);
-
- if (sqsLargeMessage.deletePayloads()) {
- pointersToDelete.forEach(SqsLargeMessageAspect::deleteMessage);
- }
- return proceed;
- }
-
- return pjp.proceed(proceedArgs);
- }
-
- private List rewriteMessages(SQSEvent sqsEvent) {
- List records = sqsEvent.getRecords();
- return processMessages(records);
- }
-
public static List processMessages(final List records) {
List s3Pointers = new ArrayList<>();
for (SQSMessage sqsMessage : records) {
if (isBodyLargeMessagePointer(sqsMessage.getBody())) {
PayloadS3Pointer s3Pointer = Optional.ofNullable(PayloadS3Pointer.fromJson(sqsMessage.getBody()))
- .orElseThrow(() -> new FailedProcessingLargePayloadException(format("Failed processing SQS body to extract S3 details. [ %s ].", sqsMessage.getBody())));
-
- ResponseInputStream s3Object = callS3Gracefully(s3Pointer, pointer -> {
- ResponseInputStream response = s3Client().getObject(GetObjectRequest.builder()
- .bucket(pointer.getS3BucketName())
- .key(pointer.getS3Key())
- .build());
-
- LOG.debug("Object downloaded with key: " + s3Pointer.getS3Key());
- return response;
- });
+ .orElseThrow(() -> new FailedProcessingLargePayloadException(
+ format("Failed processing SQS body to extract S3 details. [ %s ].",
+ sqsMessage.getBody())));
+
+ ResponseInputStream s3Object = callS3Gracefully(s3Pointer, pointer ->
+ {
+ ResponseInputStream response =
+ s3Client().getObject(GetObjectRequest.builder()
+ .bucket(pointer.getS3BucketName())
+ .key(pointer.getS3Key())
+ .build());
+
+ LOG.debug("Object downloaded with key: " + s3Pointer.getS3Key());
+ return response;
+ });
sqsMessage.setBody(readStringFromS3Object(s3Object, s3Pointer));
s3Pointers.add(s3Pointer);
@@ -100,31 +87,38 @@ private static String readStringFromS3Object(ResponseInputStream {
- s3Client().deleteObject(DeleteObjectRequest.builder()
- .bucket(pointer.getS3BucketName())
- .key(pointer.getS3Key())
- .build());
- LOG.info("Message deleted from S3: " + s3Pointer.toJson());
- return null;
- });
+ callS3Gracefully(s3Pointer, pointer ->
+ {
+ s3Client().deleteObject(DeleteObjectRequest.builder()
+ .bucket(pointer.getS3BucketName())
+ .key(pointer.getS3Key())
+ .build());
+ LOG.info("Message deleted from S3: " + s3Pointer.toJson());
+ return null;
+ });
}
private static R callS3Gracefully(final PayloadS3Pointer pointer,
- final Function function) {
+ final Function function) {
try {
return function.apply(pointer);
} catch (S3Exception e) {
LOG.error("A service exception", e);
- throw new FailedProcessingLargePayloadException(format("Failed processing S3 record with [Bucket Name: %s Bucket Key: %s]", pointer.getS3BucketName(), pointer.getS3Key()), e);
+ throw new FailedProcessingLargePayloadException(
+ format("Failed processing S3 record with [Bucket Name: %s Bucket Key: %s]",
+ pointer.getS3BucketName(), pointer.getS3Key()), e);
} catch (SdkClientException e) {
LOG.error("Some sort of client exception", e);
- throw new FailedProcessingLargePayloadException(format("Failed processing S3 record with [Bucket Name: %s Bucket Key: %s]", pointer.getS3BucketName(), pointer.getS3Key()), e);
+ throw new FailedProcessingLargePayloadException(
+ format("Failed processing S3 record with [Bucket Name: %s Bucket Key: %s]",
+ pointer.getS3BucketName(), pointer.getS3Key()), e);
}
}
@@ -134,6 +128,36 @@ public static boolean placedOnSqsEventRequestHandler(ProceedingJoinPoint pjp) {
&& pjp.getArgs()[1] instanceof Context;
}
+ @SuppressWarnings({"EmptyMethod"})
+ @Pointcut("@annotation(sqsLargeMessage)")
+ public void callAt(SqsLargeMessage sqsLargeMessage) {
+ }
+
+ @Around(value = "callAt(sqsLargeMessage) && execution(@SqsLargeMessage * *.*(..))", argNames = "pjp,sqsLargeMessage")
+ public Object around(ProceedingJoinPoint pjp,
+ SqsLargeMessage sqsLargeMessage) throws Throwable {
+ Object[] proceedArgs = pjp.getArgs();
+
+ if (isHandlerMethod(pjp)
+ && placedOnSqsEventRequestHandler(pjp)) {
+ List pointersToDelete = rewriteMessages((SQSEvent) proceedArgs[0]);
+
+ Object proceed = pjp.proceed(proceedArgs);
+
+ if (sqsLargeMessage.deletePayloads()) {
+ pointersToDelete.forEach(SqsLargeMessageAspect::deleteMessage);
+ }
+ return proceed;
+ }
+
+ return pjp.proceed(proceedArgs);
+ }
+
+ private List rewriteMessages(SQSEvent sqsEvent) {
+ List records = sqsEvent.getRecords();
+ return processMessages(records);
+ }
+
public static class FailedProcessingLargePayloadException extends RuntimeException {
public FailedProcessingLargePayloadException(String message, Throwable cause) {
super(message, cause);
diff --git a/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/internal/SqsMessageBatchProcessorAspect.java b/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/internal/SqsMessageBatchProcessorAspect.java
index 73e91c3a7..ff0b5b014 100644
--- a/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/internal/SqsMessageBatchProcessorAspect.java
+++ b/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/internal/SqsMessageBatchProcessorAspect.java
@@ -1,5 +1,23 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.sqs.internal;
+import static software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor.isHandlerMethod;
+import static software.amazon.lambda.powertools.sqs.SqsUtils.batchProcessor;
+import static software.amazon.lambda.powertools.sqs.internal.SqsLargeMessageAspect.placedOnSqsEventRequestHandler;
+
import com.amazonaws.services.lambda.runtime.events.SQSEvent;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
@@ -7,10 +25,6 @@
import org.aspectj.lang.annotation.Pointcut;
import software.amazon.lambda.powertools.sqs.SqsBatch;
-import static software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor.isHandlerMethod;
-import static software.amazon.lambda.powertools.sqs.SqsUtils.batchProcessor;
-import static software.amazon.lambda.powertools.sqs.internal.SqsLargeMessageAspect.placedOnSqsEventRequestHandler;
-
@Aspect
public class SqsMessageBatchProcessorAspect {
diff --git a/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/SampleSqsHandler.java b/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/SampleSqsHandler.java
index d48cded5f..557aa214d 100644
--- a/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/SampleSqsHandler.java
+++ b/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/SampleSqsHandler.java
@@ -1,3 +1,17 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.sqs;
import com.amazonaws.services.lambda.runtime.events.SQSEvent;
diff --git a/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/SqsUtilsBatchProcessorTest.java b/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/SqsUtilsBatchProcessorTest.java
index 43a089d2c..42e4b9d8f 100644
--- a/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/SqsUtilsBatchProcessorTest.java
+++ b/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/SqsUtilsBatchProcessorTest.java
@@ -1,14 +1,37 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.sqs;
+import static com.amazonaws.services.lambda.runtime.events.SQSEvent.SQSMessage;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoInteractions;
+import static org.mockito.Mockito.when;
+import static software.amazon.lambda.powertools.sqs.SqsUtils.batchProcessor;
+import static software.amazon.lambda.powertools.sqs.SqsUtils.overrideSqsClient;
+
+import com.amazonaws.services.lambda.runtime.events.SQSEvent;
+import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
-import java.util.Collection;
import java.util.HashMap;
import java.util.List;
-import java.util.function.Consumer;
-import java.util.function.Function;
-import com.amazonaws.services.lambda.runtime.events.SQSEvent;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
@@ -20,20 +43,6 @@
import software.amazon.awssdk.services.sqs.model.GetQueueAttributesResponse;
import software.amazon.awssdk.services.sqs.model.QueueAttributeName;
import software.amazon.awssdk.services.sqs.model.SendMessageBatchRequest;
-import software.amazon.awssdk.services.sqs.model.SendMessageBatchRequestEntry;
-
-import static com.amazonaws.services.lambda.runtime.events.SQSEvent.SQSMessage;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.reset;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoInteractions;
-import static org.mockito.Mockito.when;
-import static software.amazon.lambda.powertools.sqs.SqsUtils.batchProcessor;
-import static software.amazon.lambda.powertools.sqs.SqsUtils.overrideSqsClient;
class SqsUtilsBatchProcessorTest {
@@ -51,10 +60,11 @@ void setUp() throws IOException {
@Test
void shouldBatchProcessAndNotDeleteMessagesWhenAllSuccess() {
- List returnValues = batchProcessor(event, false, (message) -> {
- interactionClient.listQueues();
- return "Success";
- });
+ List returnValues = batchProcessor(event, false, (message) ->
+ {
+ interactionClient.listQueues();
+ return "Success";
+ });
assertThat(returnValues)
.hasSize(2)
@@ -66,7 +76,8 @@ void shouldBatchProcessAndNotDeleteMessagesWhenAllSuccess() {
@ParameterizedTest
@ValueSource(classes = {SampleInnerSqsHandler.class, SampleSqsHandler.class})
- void shouldBatchProcessViaClassAndNotDeleteMessagesWhenAllSuccess(Class extends SqsMessageHandler> handler) {
+ void shouldBatchProcessViaClassAndNotDeleteMessagesWhenAllSuccess(
+ Class extends SqsMessageHandler> handler) {
List returnValues = batchProcessor(event, handler);
assertThat(returnValues)
@@ -80,33 +91,35 @@ void shouldBatchProcessViaClassAndNotDeleteMessagesWhenAllSuccess(Class extend
void shouldBatchProcessAndDeleteSuccessMessageOnPartialFailures() {
String failedId = "2e1424d4-f796-459a-8184-9c92662be6da";
- SqsMessageHandler failedHandler = (message) -> {
- if (failedId.equals(message.getMessageId())) {
- throw new RuntimeException("Failed processing");
- }
+ SqsMessageHandler failedHandler = (message) ->
+ {
+ if (failedId.equals(message.getMessageId())) {
+ throw new RuntimeException("Failed processing");
+ }
- interactionClient.listQueues();
- return "Success";
- };
+ interactionClient.listQueues();
+ return "Success";
+ };
assertThatExceptionOfType(SQSBatchProcessingException.class)
.isThrownBy(() -> batchProcessor(event, failedHandler))
- .satisfies(e -> {
+ .satisfies(e ->
+ {
- assertThat(e.successMessageReturnValues())
- .hasSize(1)
- .contains("Success");
+ assertThat(e.successMessageReturnValues())
+ .hasSize(1)
+ .contains("Success");
- assertThat(e.getFailures())
- .hasSize(1)
- .extracting("messageId")
- .contains(failedId);
+ assertThat(e.getFailures())
+ .hasSize(1)
+ .extracting("messageId")
+ .contains(failedId);
- assertThat(e.getExceptions())
- .hasSize(1)
- .extracting("detailMessage")
- .contains("Failed processing");
- });
+ assertThat(e.getExceptions())
+ .hasSize(1)
+ .extracting("detailMessage")
+ .contains("Failed processing");
+ });
verify(interactionClient).listQueues();
@@ -119,29 +132,31 @@ void shouldBatchProcessAndDeleteSuccessMessageOnPartialFailures() {
@Test
void shouldBatchProcessAndFullFailuresInBatch() {
- SqsMessageHandler failedHandler = (message) -> {
- throw new RuntimeException(message.getMessageId());
- };
+ SqsMessageHandler failedHandler = (message) ->
+ {
+ throw new RuntimeException(message.getMessageId());
+ };
assertThatExceptionOfType(SQSBatchProcessingException.class)
.isThrownBy(() -> batchProcessor(event, failedHandler))
- .satisfies(e -> {
+ .satisfies(e ->
+ {
- assertThat(e.successMessageReturnValues())
- .isEmpty();
+ assertThat(e.successMessageReturnValues())
+ .isEmpty();
- assertThat(e.getFailures())
- .hasSize(2)
- .extracting("messageId")
- .containsExactly("059f36b4-87a3-44ab-83d2-661975830a7d",
- "2e1424d4-f796-459a-8184-9c92662be6da");
+ assertThat(e.getFailures())
+ .hasSize(2)
+ .extracting("messageId")
+ .containsExactly("059f36b4-87a3-44ab-83d2-661975830a7d",
+ "2e1424d4-f796-459a-8184-9c92662be6da");
- assertThat(e.getExceptions())
- .hasSize(2)
- .extracting("detailMessage")
- .containsExactly("059f36b4-87a3-44ab-83d2-661975830a7d",
- "2e1424d4-f796-459a-8184-9c92662be6da");
- });
+ assertThat(e.getExceptions())
+ .hasSize(2)
+ .extracting("detailMessage")
+ .containsExactly("059f36b4-87a3-44ab-83d2-661975830a7d",
+ "2e1424d4-f796-459a-8184-9c92662be6da");
+ });
verifyNoInteractions(sqsClient);
}
@@ -150,22 +165,23 @@ void shouldBatchProcessAndFullFailuresInBatch() {
void shouldBatchProcessViaClassAndDeleteSuccessMessageOnPartialFailures() {
assertThatExceptionOfType(SQSBatchProcessingException.class)
.isThrownBy(() -> batchProcessor(event, FailureSampleInnerSqsHandler.class))
- .satisfies(e -> {
+ .satisfies(e ->
+ {
- assertThat(e.successMessageReturnValues())
- .hasSize(1)
- .contains("Success");
+ assertThat(e.successMessageReturnValues())
+ .hasSize(1)
+ .contains("Success");
- assertThat(e.getFailures())
- .hasSize(1)
- .extracting("messageId")
- .contains("2e1424d4-f796-459a-8184-9c92662be6da");
+ assertThat(e.getFailures())
+ .hasSize(1)
+ .extracting("messageId")
+ .contains("2e1424d4-f796-459a-8184-9c92662be6da");
- assertThat(e.getExceptions())
- .hasSize(1)
- .extracting("detailMessage")
- .contains("Failed processing");
- });
+ assertThat(e.getExceptions())
+ .hasSize(1)
+ .extracting("detailMessage")
+ .contains("Failed processing");
+ });
verify(sqsClient).deleteMessageBatch(any(DeleteMessageBatchRequest.class));
}
@@ -175,14 +191,15 @@ void shouldBatchProcessViaClassAndDeleteSuccessMessageOnPartialFailures() {
void shouldBatchProcessAndSuppressExceptions() {
String failedId = "2e1424d4-f796-459a-8184-9c92662be6da";
- SqsMessageHandler failedHandler = (message) -> {
- if (failedId.equals(message.getMessageId())) {
- throw new RuntimeException("Failed processing");
- }
+ SqsMessageHandler failedHandler = (message) ->
+ {
+ if (failedId.equals(message.getMessageId())) {
+ throw new RuntimeException("Failed processing");
+ }
- interactionClient.listQueues();
- return "Success";
- };
+ interactionClient.listQueues();
+ return "Success";
+ };
List returnValues = batchProcessor(event, true, failedHandler);
@@ -206,16 +223,6 @@ void shouldBatchProcessViaClassAndSuppressExceptions() {
verify(sqsClient).deleteMessageBatch(any(DeleteMessageBatchRequest.class));
}
- public class SampleInnerSqsHandler implements SqsMessageHandler {
- private int counter;
-
- @Override
- public String process(SQSMessage message) {
- interactionClient.listQueues();
- return String.valueOf(counter++);
- }
- }
-
@Test
void shouldBatchProcessAndMoveNonRetryableExceptionToDlq() {
String failedId = "2e1424d4-f796-459a-8184-9c92662be6da";
@@ -226,18 +233,20 @@ void shouldBatchProcessAndMoveNonRetryableExceptionToDlq() {
" \"maxReceiveCount\": 2\n" +
"}");
- when(sqsClient.getQueueAttributes(any(GetQueueAttributesRequest.class))).thenReturn(GetQueueAttributesResponse.builder()
+ when(sqsClient.getQueueAttributes(any(GetQueueAttributesRequest.class))).thenReturn(
+ GetQueueAttributesResponse.builder()
.attributes(attributes)
- .build());
+ .build());
- List batchProcessor = batchProcessor(event, (message) -> {
- if (failedId.equals(message.getMessageId())) {
- throw new IllegalStateException("Failed processing");
- }
+ List batchProcessor = batchProcessor(event, (message) ->
+ {
+ if (failedId.equals(message.getMessageId())) {
+ throw new IllegalStateException("Failed processing");
+ }
- interactionClient.listQueues();
- return "Success";
- }, IllegalStateException.class, IllegalArgumentException.class);
+ interactionClient.listQueues();
+ return "Success";
+ }, IllegalStateException.class, IllegalArgumentException.class);
assertThat(batchProcessor)
.hasSize(1);
@@ -255,18 +264,20 @@ void shouldBatchProcessAndDeleteNonRetryableException() {
" \"maxReceiveCount\": 2\n" +
"}");
- when(sqsClient.getQueueAttributes(any(GetQueueAttributesRequest.class))).thenReturn(GetQueueAttributesResponse.builder()
- .attributes(attributes)
- .build());
+ when(sqsClient.getQueueAttributes(any(GetQueueAttributesRequest.class))).thenReturn(
+ GetQueueAttributesResponse.builder()
+ .attributes(attributes)
+ .build());
- List batchProcessor = batchProcessor(event, false, (message) -> {
- if (failedId.equals(message.getMessageId())) {
- throw new IllegalStateException("Failed processing");
- }
+ List batchProcessor = batchProcessor(event, false, (message) ->
+ {
+ if (failedId.equals(message.getMessageId())) {
+ throw new IllegalStateException("Failed processing");
+ }
- interactionClient.listQueues();
- return "Success";
- }, true, IllegalStateException.class, IllegalArgumentException.class);
+ interactionClient.listQueues();
+ return "Success";
+ }, true, IllegalStateException.class, IllegalArgumentException.class);
assertThat(batchProcessor)
.hasSize(1);
@@ -277,26 +288,28 @@ void shouldBatchProcessAndDeleteNonRetryableException() {
@Test
void shouldDeleteSuccessfulMessageInBatchesOfT10orLess() throws IOException {
- SQSEvent batch25Message = MAPPER.readValue(this.getClass().getResource("/sampleSqsBatchEventBatchSize25.json"), SQSEvent.class);
+ SQSEvent batch25Message =
+ MAPPER.readValue(this.getClass().getResource("/sampleSqsBatchEventBatchSize25.json"), SQSEvent.class);
assertThatExceptionOfType(SQSBatchProcessingException.class)
.isThrownBy(() -> batchProcessor(batch25Message, FailureSampleInnerSqsHandler.class))
- .satisfies(e -> {
+ .satisfies(e ->
+ {
- assertThat(e.successMessageReturnValues())
- .hasSize(24)
- .contains("Success");
+ assertThat(e.successMessageReturnValues())
+ .hasSize(24)
+ .contains("Success");
- assertThat(e.getFailures())
- .hasSize(1)
- .extracting("messageId")
- .contains("2e1424d4-f796-459a-8184-9c92662be6da");
+ assertThat(e.getFailures())
+ .hasSize(1)
+ .extracting("messageId")
+ .contains("2e1424d4-f796-459a-8184-9c92662be6da");
- assertThat(e.getExceptions())
- .hasSize(1)
- .extracting("detailMessage")
- .contains("Failed processing");
- });
+ assertThat(e.getExceptions())
+ .hasSize(1)
+ .extracting("detailMessage")
+ .contains("Failed processing");
+ });
ArgumentCaptor captor = ArgumentCaptor.forClass(DeleteMessageBatchRequest.class);
@@ -310,7 +323,8 @@ void shouldDeleteSuccessfulMessageInBatchesOfT10orLess() throws IOException {
@Test
void shouldBatchProcessAndMoveNonRetryableExceptionToDlqInBatchesOfT10orLess() throws IOException {
- SQSEvent batch25Message = MAPPER.readValue(this.getClass().getResource("/sampleSqsBatchEventBatchSize25.json"), SQSEvent.class);
+ SQSEvent batch25Message =
+ MAPPER.readValue(this.getClass().getResource("/sampleSqsBatchEventBatchSize25.json"), SQSEvent.class);
HashMap attributes = new HashMap<>();
@@ -319,18 +333,20 @@ void shouldBatchProcessAndMoveNonRetryableExceptionToDlqInBatchesOfT10orLess() t
" \"maxReceiveCount\": 2\n" +
"}");
- when(sqsClient.getQueueAttributes(any(GetQueueAttributesRequest.class))).thenReturn(GetQueueAttributesResponse.builder()
- .attributes(attributes)
- .build());
+ when(sqsClient.getQueueAttributes(any(GetQueueAttributesRequest.class))).thenReturn(
+ GetQueueAttributesResponse.builder()
+ .attributes(attributes)
+ .build());
- List batchProcessor = batchProcessor(batch25Message, (message) -> {
- if ("2e1424d4-f796-459a-8184-9c92662be6da".equals(message.getMessageId())) {
- interactionClient.listQueues();
- return "Success";
- }
+ List batchProcessor = batchProcessor(batch25Message, (message) ->
+ {
+ if ("2e1424d4-f796-459a-8184-9c92662be6da".equals(message.getMessageId())) {
+ interactionClient.listQueues();
+ return "Success";
+ }
- throw new IllegalStateException("Failed processing");
- }, IllegalStateException.class, IllegalArgumentException.class);
+ throw new IllegalStateException("Failed processing");
+ }, IllegalStateException.class, IllegalArgumentException.class);
assertThat(batchProcessor)
.hasSize(1);
@@ -346,6 +362,16 @@ void shouldBatchProcessAndMoveNonRetryableExceptionToDlqInBatchesOfT10orLess() t
.hasSize(24);
}
+ public class SampleInnerSqsHandler implements SqsMessageHandler {
+ private int counter;
+
+ @Override
+ public String process(SQSMessage message) {
+ interactionClient.listQueues();
+ return String.valueOf(counter++);
+ }
+ }
+
public class FailureSampleInnerSqsHandler implements SqsMessageHandler {
@Override
public String process(SQSEvent.SQSMessage message) {
diff --git a/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/SqsUtilsFifoBatchProcessorTest.java b/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/SqsUtilsFifoBatchProcessorTest.java
index cfa79dc36..53beeefcb 100644
--- a/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/SqsUtilsFifoBatchProcessorTest.java
+++ b/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/SqsUtilsFifoBatchProcessorTest.java
@@ -1,30 +1,44 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.sqs;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
+import static software.amazon.lambda.powertools.sqs.SqsUtils.batchProcessor;
+import static software.amazon.lambda.powertools.sqs.SqsUtils.overrideSqsClient;
+
import com.amazonaws.services.lambda.runtime.events.SQSEvent;
import com.amazonaws.services.lambda.runtime.tests.EventLoader;
-import com.fasterxml.jackson.databind.ObjectMapper;
+import java.io.IOException;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.stream.Collectors;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
-import org.mockito.*;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoSession;
import org.mockito.quality.Strictness;
import software.amazon.awssdk.services.sqs.SqsClient;
import software.amazon.awssdk.services.sqs.model.DeleteMessageBatchRequest;
import software.amazon.awssdk.services.sqs.model.DeleteMessageBatchRequestEntry;
import software.amazon.awssdk.services.sqs.model.DeleteMessageBatchResponse;
-import java.io.IOException;
-import java.util.List;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.stream.Collectors;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
-import static org.mockito.MockitoAnnotations.openMocks;
-import static software.amazon.lambda.powertools.sqs.SqsUtils.batchProcessor;
-import static software.amazon.lambda.powertools.sqs.SqsUtils.overrideSqsClient;
-
public class SqsUtilsFifoBatchProcessorTest {
private static SQSEvent sqsBatchEvent;
@@ -61,10 +75,11 @@ public void tearDown() {
public void processWholeBatch() {
// Act
AtomicInteger processedCount = new AtomicInteger();
- List results = batchProcessor(sqsBatchEvent, false, (message) -> {
- processedCount.getAndIncrement();
- return true;
- });
+ List results = batchProcessor(sqsBatchEvent, false, (message) ->
+ {
+ processedCount.getAndIncrement();
+ return true;
+ });
// Assert
assertThat(processedCount.get()).isEqualTo(3);
@@ -80,31 +95,34 @@ public void processWholeBatch() {
@Test
public void singleFailureInMiddleOfBatch() {
// Arrange
- Mockito.when(sqsClient.deleteMessageBatch(deleteMessageBatchCaptor.capture())).thenReturn(DeleteMessageBatchResponse
- .builder().build());
+ Mockito.when(sqsClient.deleteMessageBatch(deleteMessageBatchCaptor.capture()))
+ .thenReturn(DeleteMessageBatchResponse
+ .builder().build());
// Act
AtomicInteger processedCount = new AtomicInteger();
assertThatExceptionOfType(SQSBatchProcessingException.class)
- .isThrownBy(() -> batchProcessor(sqsBatchEvent, false, (message) -> {
- int value = processedCount.getAndIncrement();
- if (value == 1) {
- throw new RuntimeException("Whoops");
- }
- return true;
- }))
-
- // Assert
+ .isThrownBy(() -> batchProcessor(sqsBatchEvent, false, (message) ->
+ {
+ int value = processedCount.getAndIncrement();
+ if (value == 1) {
+ throw new RuntimeException("Whoops");
+ }
+ return true;
+ }))
+
+ // Assert
.isInstanceOf(SQSBatchProcessingException.class)
- .satisfies(e -> {
- List failures = ((SQSBatchProcessingException)e).getFailures();
- assertThat(failures.size()).isEqualTo(2);
- List failureIds = failures.stream()
- .map(SQSEvent.SQSMessage::getMessageId)
- .collect(Collectors.toList());
- assertThat(failureIds).contains(sqsBatchEvent.getRecords().get(1).getMessageId());
- assertThat(failureIds).contains(sqsBatchEvent.getRecords().get(2).getMessageId());
- });
+ .satisfies(e ->
+ {
+ List failures = ((SQSBatchProcessingException) e).getFailures();
+ assertThat(failures.size()).isEqualTo(2);
+ List failureIds = failures.stream()
+ .map(SQSEvent.SQSMessage::getMessageId)
+ .collect(Collectors.toList());
+ assertThat(failureIds).contains(sqsBatchEvent.getRecords().get(1).getMessageId());
+ assertThat(failureIds).contains(sqsBatchEvent.getRecords().get(2).getMessageId());
+ });
DeleteMessageBatchRequest deleteRequest = deleteMessageBatchCaptor.getValue();
List messageIds = deleteRequest.entries().stream()
@@ -119,20 +137,22 @@ public void singleFailureInMiddleOfBatch() {
public void singleFailureAtEndOfBatch() {
// Arrange
- Mockito.when(sqsClient.deleteMessageBatch(deleteMessageBatchCaptor.capture())).thenReturn(DeleteMessageBatchResponse
- .builder().build());
+ Mockito.when(sqsClient.deleteMessageBatch(deleteMessageBatchCaptor.capture()))
+ .thenReturn(DeleteMessageBatchResponse
+ .builder().build());
// Act
AtomicInteger processedCount = new AtomicInteger();
assertThatExceptionOfType(SQSBatchProcessingException.class)
- .isThrownBy(() -> batchProcessor(sqsBatchEvent, false, (message) -> {
- int value = processedCount.getAndIncrement();
- if (value == 2) {
- throw new RuntimeException("Whoops");
- }
- return true;
- }));
+ .isThrownBy(() -> batchProcessor(sqsBatchEvent, false, (message) ->
+ {
+ int value = processedCount.getAndIncrement();
+ if (value == 2) {
+ throw new RuntimeException("Whoops");
+ }
+ return true;
+ }));
// Assert
DeleteMessageBatchRequest deleteRequest = deleteMessageBatchCaptor.getValue();
@@ -150,17 +170,19 @@ public void messageFailureStopsGroupProcessing() {
String groupToFail = sqsBatchEvent.getRecords().get(0).getAttributes().get("MessageGroupId");
assertThatExceptionOfType(SQSBatchProcessingException.class)
- .isThrownBy(() -> batchProcessor(sqsBatchEvent, (message) -> {
- String groupId = message.getAttributes().get("MessageGroupId");
- if (groupId.equals(groupToFail)) {
- throw new RuntimeException("Failed processing");
- }
- return groupId;
- }))
- .satisfies(e -> {
- assertThat(e.successMessageReturnValues().size()).isEqualTo(0);
- assertThat(e.successMessageReturnValues().contains(groupToFail)).isFalse();
- });
+ .isThrownBy(() -> batchProcessor(sqsBatchEvent, (message) ->
+ {
+ String groupId = message.getAttributes().get("MessageGroupId");
+ if (groupId.equals(groupToFail)) {
+ throw new RuntimeException("Failed processing");
+ }
+ return groupId;
+ }))
+ .satisfies(e ->
+ {
+ assertThat(e.successMessageReturnValues().size()).isEqualTo(0);
+ assertThat(e.successMessageReturnValues().contains(groupToFail)).isFalse();
+ });
}
}
diff --git a/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/SqsUtilsLargeMessageTest.java b/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/SqsUtilsLargeMessageTest.java
index 48de3e6a9..d3b675371 100644
--- a/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/SqsUtilsLargeMessageTest.java
+++ b/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/SqsUtilsLargeMessageTest.java
@@ -1,13 +1,37 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.sqs;
+import static com.amazonaws.services.lambda.runtime.events.SQSEvent.SQSMessage;
+import static java.util.Collections.singletonList;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoInteractions;
+import static org.mockito.Mockito.when;
+import static org.mockito.MockitoAnnotations.openMocks;
+
+import com.amazonaws.services.lambda.runtime.events.SQSEvent;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Consumer;
import java.util.stream.Stream;
-
-import com.amazonaws.services.lambda.runtime.events.SQSEvent;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -28,23 +52,21 @@
import software.amazon.awssdk.utils.StringInputStream;
import software.amazon.lambda.powertools.sqs.internal.SqsLargeMessageAspect;
-import static com.amazonaws.services.lambda.runtime.events.SQSEvent.SQSMessage;
-import static java.util.Collections.singletonList;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoInteractions;
-import static org.mockito.Mockito.when;
-import static org.mockito.MockitoAnnotations.openMocks;
-
class SqsUtilsLargeMessageTest {
- @Mock
- private S3Client s3Client;
private static final String BUCKET_NAME = "ms-extended-sqs-client";
private static final String BUCKET_KEY = "c71eb2ae-37e0-4265-8909-32f4153faddf";
+ @Mock
+ private S3Client s3Client;
+
+ private static Stream exception() {
+ return Stream.of(Arguments.of(S3Exception.builder()
+ .message("Service Exception")
+ .build()),
+ Arguments.of(SdkClientException.builder()
+ .message("Client Exception")
+ .build()));
+ }
@BeforeEach
void setUp() {
@@ -54,16 +76,21 @@ void setUp() {
@Test
public void testLargeMessage() {
- ResponseInputStream s3Response = new ResponseInputStream<>(GetObjectResponse.builder().build(), AbortableInputStream.create(new ByteArrayInputStream("A big message".getBytes())));
+ ResponseInputStream s3Response =
+ new ResponseInputStream<>(GetObjectResponse.builder().build(),
+ AbortableInputStream.create(new ByteArrayInputStream("A big message".getBytes())));
when(s3Client.getObject(any(GetObjectRequest.class))).thenReturn(s3Response);
- SQSEvent sqsEvent = messageWithBody("[\"software.amazon.payloadoffloading.PayloadS3Pointer\",{\"s3BucketName\":\"" + BUCKET_NAME + "\",\"s3Key\":\"" + BUCKET_KEY + "\"}]");
+ SQSEvent sqsEvent = messageWithBody(
+ "[\"software.amazon.payloadoffloading.PayloadS3Pointer\",{\"s3BucketName\":\"" + BUCKET_NAME +
+ "\",\"s3Key\":\"" + BUCKET_KEY + "\"}]");
- Map sqsMessage = SqsUtils.enrichedMessageFromS3(sqsEvent, sqsMessages -> {
- Map someBusinessLogic = new HashMap<>();
- someBusinessLogic.put("Message", sqsMessages.get(0).getBody());
- return someBusinessLogic;
- });
+ Map sqsMessage = SqsUtils.enrichedMessageFromS3(sqsEvent, sqsMessages ->
+ {
+ Map someBusinessLogic = new HashMap<>();
+ someBusinessLogic.put("Message", sqsMessages.get(0).getBody());
+ return someBusinessLogic;
+ });
assertThat(sqsMessage)
.hasSize(1)
@@ -74,29 +101,35 @@ public void testLargeMessage() {
verify(s3Client).deleteObject(delete.capture());
Assertions.assertThat(delete.getValue())
- .satisfies((Consumer) deleteObjectRequest -> {
- assertThat(deleteObjectRequest.bucket())
- .isEqualTo(BUCKET_NAME);
+ .satisfies((Consumer) deleteObjectRequest ->
+ {
+ assertThat(deleteObjectRequest.bucket())
+ .isEqualTo(BUCKET_NAME);
- assertThat(deleteObjectRequest.key())
- .isEqualTo(BUCKET_KEY);
- });
+ assertThat(deleteObjectRequest.key())
+ .isEqualTo(BUCKET_KEY);
+ });
}
@ParameterizedTest
@ValueSource(booleans = {true, false})
public void testLargeMessageDeleteFromS3Toggle(boolean deleteS3Payload) {
- ResponseInputStream s3Response = new ResponseInputStream<>(GetObjectResponse.builder().build(), AbortableInputStream.create(new ByteArrayInputStream("A big message".getBytes())));
+ ResponseInputStream s3Response =
+ new ResponseInputStream<>(GetObjectResponse.builder().build(),
+ AbortableInputStream.create(new ByteArrayInputStream("A big message".getBytes())));
when(s3Client.getObject(any(GetObjectRequest.class))).thenReturn(s3Response);
- SQSEvent sqsEvent = messageWithBody("[\"software.amazon.payloadoffloading.PayloadS3Pointer\",{\"s3BucketName\":\"" + BUCKET_NAME + "\",\"s3Key\":\"" + BUCKET_KEY + "\"}]");
+ SQSEvent sqsEvent = messageWithBody(
+ "[\"software.amazon.payloadoffloading.PayloadS3Pointer\",{\"s3BucketName\":\"" + BUCKET_NAME +
+ "\",\"s3Key\":\"" + BUCKET_KEY + "\"}]");
- Map sqsMessage = SqsUtils.enrichedMessageFromS3(sqsEvent, deleteS3Payload, sqsMessages -> {
- Map someBusinessLogic = new HashMap<>();
- someBusinessLogic.put("Message", sqsMessages.get(0).getBody());
- return someBusinessLogic;
- });
+ Map sqsMessage = SqsUtils.enrichedMessageFromS3(sqsEvent, deleteS3Payload, sqsMessages ->
+ {
+ Map someBusinessLogic = new HashMap<>();
+ someBusinessLogic.put("Message", sqsMessages.get(0).getBody());
+ return someBusinessLogic;
+ });
assertThat(sqsMessage)
.hasSize(1)
@@ -107,13 +140,14 @@ public void testLargeMessageDeleteFromS3Toggle(boolean deleteS3Payload) {
verify(s3Client).deleteObject(delete.capture());
Assertions.assertThat(delete.getValue())
- .satisfies((Consumer) deleteObjectRequest -> {
- assertThat(deleteObjectRequest.bucket())
- .isEqualTo(BUCKET_NAME);
-
- assertThat(deleteObjectRequest.key())
- .isEqualTo(BUCKET_KEY);
- });
+ .satisfies((Consumer) deleteObjectRequest ->
+ {
+ assertThat(deleteObjectRequest.bucket())
+ .isEqualTo(BUCKET_NAME);
+
+ assertThat(deleteObjectRequest.key())
+ .isEqualTo(BUCKET_KEY);
+ });
} else {
verify(s3Client, never()).deleteObject(any(DeleteObjectRequest.class));
}
@@ -121,17 +155,20 @@ public void testLargeMessageDeleteFromS3Toggle(boolean deleteS3Payload) {
@Test
public void shouldNotProcessSmallMessageBody() {
- ResponseInputStream s3Response = new ResponseInputStream<>(GetObjectResponse.builder().build(), AbortableInputStream.create(new ByteArrayInputStream("A big message".getBytes())));
+ ResponseInputStream s3Response =
+ new ResponseInputStream<>(GetObjectResponse.builder().build(),
+ AbortableInputStream.create(new ByteArrayInputStream("A big message".getBytes())));
when(s3Client.getObject(any(GetObjectRequest.class))).thenReturn(s3Response);
SQSEvent sqsEvent = messageWithBody("This is small message");
- Map sqsMessage = SqsUtils.enrichedMessageFromS3(sqsEvent, sqsMessages -> {
- Map someBusinessLogic = new HashMap<>();
- someBusinessLogic.put("Message", sqsMessages.get(0).getBody());
- return someBusinessLogic;
- });
+ Map sqsMessage = SqsUtils.enrichedMessageFromS3(sqsEvent, sqsMessages ->
+ {
+ Map someBusinessLogic = new HashMap<>();
+ someBusinessLogic.put("Message", sqsMessages.get(0).getBody());
+ return someBusinessLogic;
+ });
assertThat(sqsMessage)
.containsEntry("Message", "This is small message");
@@ -144,7 +181,9 @@ public void shouldNotProcessSmallMessageBody() {
public void shouldFailEntireBatchIfFailedDownloadingFromS3(RuntimeException exception) {
when(s3Client.getObject(any(GetObjectRequest.class))).thenThrow(exception);
- String messageBody = "[\"software.amazon.payloadoffloading.PayloadS3Pointer\",{\"s3BucketName\":\"" + BUCKET_NAME + "\",\"s3Key\":\"" + BUCKET_KEY + "\"}]";
+ String messageBody =
+ "[\"software.amazon.payloadoffloading.PayloadS3Pointer\",{\"s3BucketName\":\"" + BUCKET_NAME +
+ "\",\"s3Key\":\"" + BUCKET_KEY + "\"}]";
SQSEvent sqsEvent = messageWithBody(messageBody);
assertThatExceptionOfType(SqsLargeMessageAspect.FailedProcessingLargePayloadException.class)
@@ -156,16 +195,20 @@ public void shouldFailEntireBatchIfFailedDownloadingFromS3(RuntimeException exce
@Test
public void shouldFailEntireBatchIfFailedProcessingDownloadMessageFromS3() {
- ResponseInputStream s3Response = new ResponseInputStream<>(GetObjectResponse.builder().build(), AbortableInputStream.create(new StringInputStream("test") {
- @Override
- public void close() throws IOException {
- throw new IOException("Failed");
- }
- }));
+ ResponseInputStream s3Response =
+ new ResponseInputStream<>(GetObjectResponse.builder().build(),
+ AbortableInputStream.create(new StringInputStream("test") {
+ @Override
+ public void close() throws IOException {
+ throw new IOException("Failed");
+ }
+ }));
when(s3Client.getObject(any(GetObjectRequest.class))).thenReturn(s3Response);
- String messageBody = "[\"software.amazon.payloadoffloading.PayloadS3Pointer\",{\"s3BucketName\":\"" + BUCKET_NAME + "\",\"s3Key\":\"" + BUCKET_KEY + "\"}]";
+ String messageBody =
+ "[\"software.amazon.payloadoffloading.PayloadS3Pointer\",{\"s3BucketName\":\"" + BUCKET_NAME +
+ "\",\"s3Key\":\"" + BUCKET_KEY + "\"}]";
SQSEvent sqsEvent = messageWithBody(messageBody);
assertThatExceptionOfType(SqsLargeMessageAspect.FailedProcessingLargePayloadException.class)
@@ -175,15 +218,6 @@ public void close() throws IOException {
verify(s3Client, never()).deleteObject(any(DeleteObjectRequest.class));
}
- private static Stream exception() {
- return Stream.of(Arguments.of(S3Exception.builder()
- .message("Service Exception")
- .build()),
- Arguments.of(SdkClientException.builder()
- .message("Client Exception")
- .build()));
- }
-
private SQSEvent messageWithBody(String messageBody) {
SQSMessage sqsMessage = new SQSMessage();
sqsMessage.setBody(messageBody);
diff --git a/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/handlers/LambdaHandlerApiGateway.java b/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/handlers/LambdaHandlerApiGateway.java
index b0d8177ac..3bad9644f 100644
--- a/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/handlers/LambdaHandlerApiGateway.java
+++ b/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/handlers/LambdaHandlerApiGateway.java
@@ -1,11 +1,25 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.sqs.handlers;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent;
-import software.amazon.lambda.powertools.sqs.SqsLargeMessage;
import software.amazon.lambda.powertools.sqs.SampleSqsHandler;
import software.amazon.lambda.powertools.sqs.SqsBatch;
+import software.amazon.lambda.powertools.sqs.SqsLargeMessage;
public class LambdaHandlerApiGateway implements RequestHandler {
diff --git a/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/handlers/PartialBatchFailureSuppressedHandler.java b/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/handlers/PartialBatchFailureSuppressedHandler.java
index 63f1573bf..172179057 100644
--- a/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/handlers/PartialBatchFailureSuppressedHandler.java
+++ b/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/handlers/PartialBatchFailureSuppressedHandler.java
@@ -1,14 +1,28 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.sqs.handlers;
+import static com.amazonaws.services.lambda.runtime.events.SQSEvent.SQSMessage;
+import static software.amazon.lambda.powertools.sqs.internal.SqsMessageBatchProcessorAspectTest.interactionClient;
+
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.lambda.runtime.events.SQSEvent;
import software.amazon.lambda.powertools.sqs.SqsBatch;
import software.amazon.lambda.powertools.sqs.SqsMessageHandler;
-import static com.amazonaws.services.lambda.runtime.events.SQSEvent.SQSMessage;
-import static software.amazon.lambda.powertools.sqs.internal.SqsMessageBatchProcessorAspectTest.interactionClient;
-
public class PartialBatchFailureSuppressedHandler implements RequestHandler {
@Override
@SqsBatch(value = InnerMessageHandler.class, suppressException = true)
diff --git a/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/handlers/PartialBatchPartialFailureHandler.java b/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/handlers/PartialBatchPartialFailureHandler.java
index 653459d82..6e3971269 100644
--- a/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/handlers/PartialBatchPartialFailureHandler.java
+++ b/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/handlers/PartialBatchPartialFailureHandler.java
@@ -1,14 +1,28 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.sqs.handlers;
+import static com.amazonaws.services.lambda.runtime.events.SQSEvent.SQSMessage;
+import static software.amazon.lambda.powertools.sqs.internal.SqsMessageBatchProcessorAspectTest.interactionClient;
+
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.lambda.runtime.events.SQSEvent;
import software.amazon.lambda.powertools.sqs.SqsBatch;
import software.amazon.lambda.powertools.sqs.SqsMessageHandler;
-import static com.amazonaws.services.lambda.runtime.events.SQSEvent.SQSMessage;
-import static software.amazon.lambda.powertools.sqs.internal.SqsMessageBatchProcessorAspectTest.interactionClient;
-
public class PartialBatchPartialFailureHandler implements RequestHandler {
@Override
@SqsBatch(InnerMessageHandler.class)
diff --git a/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/handlers/PartialBatchSuccessHandler.java b/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/handlers/PartialBatchSuccessHandler.java
index 926cdb4f5..acfcd7109 100644
--- a/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/handlers/PartialBatchSuccessHandler.java
+++ b/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/handlers/PartialBatchSuccessHandler.java
@@ -1,14 +1,28 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.sqs.handlers;
+import static com.amazonaws.services.lambda.runtime.events.SQSEvent.SQSMessage;
+import static software.amazon.lambda.powertools.sqs.internal.SqsMessageBatchProcessorAspectTest.interactionClient;
+
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.lambda.runtime.events.SQSEvent;
import software.amazon.lambda.powertools.sqs.SqsBatch;
import software.amazon.lambda.powertools.sqs.SqsMessageHandler;
-import static com.amazonaws.services.lambda.runtime.events.SQSEvent.SQSMessage;
-import static software.amazon.lambda.powertools.sqs.internal.SqsMessageBatchProcessorAspectTest.interactionClient;
-
public class PartialBatchSuccessHandler implements RequestHandler {
@Override
@SqsBatch(InnerMessageHandler.class)
diff --git a/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/handlers/SqsMessageHandler.java b/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/handlers/SqsMessageHandler.java
index ee8c100e6..de096679f 100644
--- a/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/handlers/SqsMessageHandler.java
+++ b/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/handlers/SqsMessageHandler.java
@@ -1,3 +1,17 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.sqs.handlers;
import com.amazonaws.services.lambda.runtime.Context;
diff --git a/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/handlers/SqsMessageHandlerWithNonRetryableHandler.java b/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/handlers/SqsMessageHandlerWithNonRetryableHandler.java
index 6eec87301..74ff02e2c 100644
--- a/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/handlers/SqsMessageHandlerWithNonRetryableHandler.java
+++ b/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/handlers/SqsMessageHandlerWithNonRetryableHandler.java
@@ -1,18 +1,33 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.sqs.handlers;
+import static com.amazonaws.services.lambda.runtime.events.SQSEvent.SQSMessage;
+import static software.amazon.lambda.powertools.sqs.internal.SqsMessageBatchProcessorAspectTest.interactionClient;
+
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.lambda.runtime.events.SQSEvent;
import software.amazon.lambda.powertools.sqs.SqsBatch;
import software.amazon.lambda.powertools.sqs.SqsMessageHandler;
-import static com.amazonaws.services.lambda.runtime.events.SQSEvent.SQSMessage;
-import static software.amazon.lambda.powertools.sqs.internal.SqsMessageBatchProcessorAspectTest.interactionClient;
-
public class SqsMessageHandlerWithNonRetryableHandler implements RequestHandler {
@Override
- @SqsBatch(value = InnerMessageHandler.class, nonRetryableExceptions = {IllegalStateException.class, IllegalArgumentException.class})
+ @SqsBatch(value = InnerMessageHandler.class, nonRetryableExceptions = {IllegalStateException.class,
+ IllegalArgumentException.class})
public String handleRequest(final SQSEvent sqsEvent,
final Context context) {
return "Success";
@@ -22,11 +37,11 @@ private class InnerMessageHandler implements SqsMessageHandler {
@Override
public String process(SQSMessage message) {
- if(message.getMessageId().isEmpty()) {
+ if (message.getMessageId().isEmpty()) {
throw new IllegalArgumentException("Invalid message and was moved to DLQ");
}
- if("2e1424d4-f796-459a-9696-9c92662ba5da".equals(message.getMessageId())) {
+ if ("2e1424d4-f796-459a-9696-9c92662ba5da".equals(message.getMessageId())) {
throw new RuntimeException("Invalid message and should be reprocessed");
}
diff --git a/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/handlers/SqsMessageHandlerWithNonRetryableHandlerWithDelete.java b/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/handlers/SqsMessageHandlerWithNonRetryableHandlerWithDelete.java
index 789a7b86d..5b341880e 100644
--- a/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/handlers/SqsMessageHandlerWithNonRetryableHandlerWithDelete.java
+++ b/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/handlers/SqsMessageHandlerWithNonRetryableHandlerWithDelete.java
@@ -1,14 +1,28 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.sqs.handlers;
+import static com.amazonaws.services.lambda.runtime.events.SQSEvent.SQSMessage;
+import static software.amazon.lambda.powertools.sqs.internal.SqsMessageBatchProcessorAspectTest.interactionClient;
+
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.lambda.runtime.events.SQSEvent;
import software.amazon.lambda.powertools.sqs.SqsBatch;
import software.amazon.lambda.powertools.sqs.SqsMessageHandler;
-import static com.amazonaws.services.lambda.runtime.events.SQSEvent.SQSMessage;
-import static software.amazon.lambda.powertools.sqs.internal.SqsMessageBatchProcessorAspectTest.interactionClient;
-
public class SqsMessageHandlerWithNonRetryableHandlerWithDelete implements RequestHandler {
@Override
@@ -24,11 +38,11 @@ private class InnerMessageHandler implements SqsMessageHandler {
@Override
public String process(SQSMessage message) {
- if(message.getMessageId().isEmpty()) {
+ if (message.getMessageId().isEmpty()) {
throw new IllegalArgumentException("Invalid message and was moved to DLQ");
}
- if("2e1424d4-f796-459a-9696-9c92662ba5da".equals(message.getMessageId())) {
+ if ("2e1424d4-f796-459a-9696-9c92662ba5da".equals(message.getMessageId())) {
throw new RuntimeException("Invalid message and should be reprocessed");
}
diff --git a/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/handlers/SqsNoDeleteMessageHandler.java b/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/handlers/SqsNoDeleteMessageHandler.java
index 337592004..e96dc5581 100644
--- a/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/handlers/SqsNoDeleteMessageHandler.java
+++ b/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/handlers/SqsNoDeleteMessageHandler.java
@@ -1,3 +1,17 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.sqs.handlers;
import com.amazonaws.services.lambda.runtime.Context;
diff --git a/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/internal/SqsLargeMessageAspectTest.java b/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/internal/SqsLargeMessageAspectTest.java
index 22844ab4c..ff04aba25 100644
--- a/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/internal/SqsLargeMessageAspectTest.java
+++ b/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/internal/SqsLargeMessageAspectTest.java
@@ -1,14 +1,39 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.sqs.internal;
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.util.function.Consumer;
-import java.util.stream.Stream;
+import static com.amazonaws.services.lambda.runtime.events.SQSEvent.SQSMessage;
+import static java.util.Collections.singletonList;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoInteractions;
+import static org.mockito.Mockito.when;
+import static org.mockito.MockitoAnnotations.openMocks;
+import static software.amazon.lambda.powertools.sqs.internal.SqsLargeMessageAspect.FailedProcessingLargePayloadException;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent;
import com.amazonaws.services.lambda.runtime.events.SQSEvent;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.util.function.Consumer;
+import java.util.stream.Stream;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -31,30 +56,24 @@
import software.amazon.lambda.powertools.sqs.handlers.SqsMessageHandler;
import software.amazon.lambda.powertools.sqs.handlers.SqsNoDeleteMessageHandler;
-import static com.amazonaws.services.lambda.runtime.events.SQSEvent.SQSMessage;
-import static java.util.Collections.singletonList;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoInteractions;
-import static org.mockito.Mockito.when;
-import static org.mockito.MockitoAnnotations.openMocks;
-import static software.amazon.lambda.powertools.sqs.internal.SqsLargeMessageAspect.FailedProcessingLargePayloadException;
-
public class SqsLargeMessageAspectTest {
+ private static final String BUCKET_NAME = "bucketname";
+ private static final String BUCKET_KEY = "c71eb2ae-37e0-4265-8909-32f4153faddf";
private RequestHandler requestHandler;
-
@Mock
private Context context;
-
@Mock
private S3Client s3Client;
- private static final String BUCKET_NAME = "bucketname";
- private static final String BUCKET_KEY = "c71eb2ae-37e0-4265-8909-32f4153faddf";
+ private static Stream exception() {
+ return Stream.of(Arguments.of(S3Exception.builder()
+ .message("Service Exception")
+ .build()),
+ Arguments.of(SdkClientException.builder()
+ .message("Client Exception")
+ .build()));
+ }
@BeforeEach
void setUp() {
@@ -67,7 +86,9 @@ void setUp() {
@Test
public void testLargeMessage() {
when(s3Client.getObject(any(GetObjectRequest.class))).thenReturn(s3ObjectWithLargeMessage());
- SQSEvent sqsEvent = messageWithBody("[\"software.amazon.payloadoffloading.PayloadS3Pointer\",{\"s3BucketName\":\"" + BUCKET_NAME + "\",\"s3Key\":\"" + BUCKET_KEY + "\"}]");
+ SQSEvent sqsEvent = messageWithBody(
+ "[\"software.amazon.payloadoffloading.PayloadS3Pointer\",{\"s3BucketName\":\"" + BUCKET_NAME +
+ "\",\"s3Key\":\"" + BUCKET_KEY + "\"}]");
String response = requestHandler.handleRequest(sqsEvent, context);
@@ -79,13 +100,14 @@ public void testLargeMessage() {
verify(s3Client).deleteObject(delete.capture());
Assertions.assertThat(delete.getValue())
- .satisfies((Consumer) deleteObjectRequest -> {
- assertThat(deleteObjectRequest.bucket())
- .isEqualTo(BUCKET_NAME);
-
- assertThat(deleteObjectRequest.key())
- .isEqualTo(BUCKET_KEY);
- });
+ .satisfies((Consumer) deleteObjectRequest ->
+ {
+ assertThat(deleteObjectRequest.bucket())
+ .isEqualTo(BUCKET_NAME);
+
+ assertThat(deleteObjectRequest.key())
+ .isEqualTo(BUCKET_KEY);
+ });
}
@Test
@@ -107,7 +129,9 @@ public void shouldNotProcessSmallMessageBody() {
public void shouldFailEntireBatchIfFailedDownloadingFromS3(RuntimeException exception) {
when(s3Client.getObject(any(GetObjectRequest.class))).thenThrow(exception);
- String messageBody = "[\"software.amazon.payloadoffloading.PayloadS3Pointer\",{\"s3BucketName\":\"" + BUCKET_NAME + "\",\"s3Key\":\"" + BUCKET_KEY + "\"}]";
+ String messageBody =
+ "[\"software.amazon.payloadoffloading.PayloadS3Pointer\",{\"s3BucketName\":\"" + BUCKET_NAME +
+ "\",\"s3Key\":\"" + BUCKET_KEY + "\"}]";
SQSEvent sqsEvent = messageWithBody(messageBody);
assertThatExceptionOfType(FailedProcessingLargePayloadException.class)
@@ -122,7 +146,9 @@ public void testLargeMessageWithDeletionOff() {
requestHandler = new SqsNoDeleteMessageHandler();
when(s3Client.getObject(any(GetObjectRequest.class))).thenReturn(s3ObjectWithLargeMessage());
- SQSEvent sqsEvent = messageWithBody("[\"software.amazon.payloadoffloading.PayloadS3Pointer\",{\"s3BucketName\":\"" + BUCKET_NAME + "\",\"s3Key\":\"" + BUCKET_KEY + "\"}]");
+ SQSEvent sqsEvent = messageWithBody(
+ "[\"software.amazon.payloadoffloading.PayloadS3Pointer\",{\"s3BucketName\":\"" + BUCKET_NAME +
+ "\",\"s3Key\":\"" + BUCKET_KEY + "\"}]");
String response = requestHandler.handleRequest(sqsEvent, context);
@@ -131,19 +157,22 @@ public void testLargeMessageWithDeletionOff() {
verify(s3Client, never()).deleteObject(any(DeleteObjectRequest.class));
}
-
@Test
public void shouldFailEntireBatchIfFailedProcessingDownloadMessageFromS3() {
- ResponseInputStream s3Response = new ResponseInputStream<>(GetObjectResponse.builder().build(), AbortableInputStream.create(new StringInputStream("test") {
- @Override
- public void close() throws IOException {
- throw new IOException("Failed");
- }
- }));
+ ResponseInputStream s3Response =
+ new ResponseInputStream<>(GetObjectResponse.builder().build(),
+ AbortableInputStream.create(new StringInputStream("test") {
+ @Override
+ public void close() throws IOException {
+ throw new IOException("Failed");
+ }
+ }));
when(s3Client.getObject(any(GetObjectRequest.class))).thenReturn(s3Response);
- String messageBody = "[\"software.amazon.payloadoffloading.PayloadS3Pointer\",{\"s3BucketName\":\"" + BUCKET_NAME + "\",\"s3Key\":\"" + BUCKET_KEY + "\"}]";
+ String messageBody =
+ "[\"software.amazon.payloadoffloading.PayloadS3Pointer\",{\"s3BucketName\":\"" + BUCKET_NAME +
+ "\",\"s3Key\":\"" + BUCKET_KEY + "\"}]";
SQSEvent sqsEvent = messageWithBody(messageBody);
assertThatExceptionOfType(FailedProcessingLargePayloadException.class)
@@ -157,7 +186,9 @@ public void close() throws IOException {
public void shouldNotDoAnyProcessingWhenNotSqsEvent() {
LambdaHandlerApiGateway handler = new LambdaHandlerApiGateway();
- String messageBody = "[\"software.amazon.payloadoffloading.PayloadS3Pointer\",{\"s3BucketName\":\"" + BUCKET_NAME + "\",\"s3Key\":\"" + BUCKET_KEY + "\"}]";
+ String messageBody =
+ "[\"software.amazon.payloadoffloading.PayloadS3Pointer\",{\"s3BucketName\":\"" + BUCKET_NAME +
+ "\",\"s3Key\":\"" + BUCKET_KEY + "\"}]";
APIGatewayProxyRequestEvent event = new APIGatewayProxyRequestEvent();
event.setBody(messageBody);
@@ -170,16 +201,8 @@ public void shouldNotDoAnyProcessingWhenNotSqsEvent() {
}
private ResponseInputStream s3ObjectWithLargeMessage() {
- return new ResponseInputStream<>(GetObjectResponse.builder().build(), AbortableInputStream.create(new ByteArrayInputStream("A big message".getBytes())));
- }
-
- private static Stream exception() {
- return Stream.of(Arguments.of(S3Exception.builder()
- .message("Service Exception")
- .build()),
- Arguments.of(SdkClientException.builder()
- .message("Client Exception")
- .build()));
+ return new ResponseInputStream<>(GetObjectResponse.builder().build(),
+ AbortableInputStream.create(new ByteArrayInputStream("A big message".getBytes())));
}
private SQSEvent messageWithBody(String messageBody) {
diff --git a/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/internal/SqsMessageBatchProcessorAspectTest.java b/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/internal/SqsMessageBatchProcessorAspectTest.java
index a65aa486b..b257c1962 100644
--- a/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/internal/SqsMessageBatchProcessorAspectTest.java
+++ b/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/internal/SqsMessageBatchProcessorAspectTest.java
@@ -1,12 +1,38 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.sqs.internal;
-import java.io.IOException;
-import java.util.HashMap;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoInteractions;
+import static org.mockito.Mockito.when;
+import static software.amazon.lambda.powertools.sqs.SqsUtils.overrideSqsClient;
+
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent;
import com.amazonaws.services.lambda.runtime.events.SQSEvent;
import com.fasterxml.jackson.databind.ObjectMapper;
+import java.io.IOException;
+import java.util.HashMap;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -27,28 +53,14 @@
import software.amazon.lambda.powertools.sqs.handlers.SqsMessageHandlerWithNonRetryableHandler;
import software.amazon.lambda.powertools.sqs.handlers.SqsMessageHandlerWithNonRetryableHandlerWithDelete;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.reset;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoInteractions;
-import static org.mockito.Mockito.when;
-import static software.amazon.lambda.powertools.sqs.SqsUtils.overrideSqsClient;
-
public class SqsMessageBatchProcessorAspectTest {
public static final SqsClient interactionClient = mock(SqsClient.class);
private static final SqsClient sqsClient = mock(SqsClient.class);
private static final ObjectMapper MAPPER = new ObjectMapper();
-
+ private final Context context = mock(Context.class);
private SQSEvent event;
private RequestHandler requestHandler;
- private final Context context = mock(Context.class);
-
@BeforeEach
void setUp() throws IOException {
overrideSqsClient(sqsClient);
@@ -73,21 +85,22 @@ void shouldBatchProcessMessageWithSuccessDeletedOnFailureInBatchFromSQS() {
assertThatExceptionOfType(SQSBatchProcessingException.class)
.isThrownBy(() -> requestHandler.handleRequest(event, context))
- .satisfies(e -> {
- assertThat(e.getExceptions())
- .hasSize(1)
- .extracting("message")
- .containsExactly("2e1424d4-f796-459a-8184-9c92662be6da");
-
- assertThat(e.getFailures())
- .hasSize(1)
- .extracting("messageId")
- .containsExactly("2e1424d4-f796-459a-8184-9c92662be6da");
-
- assertThat(e.successMessageReturnValues())
- .hasSize(1)
- .contains("Success");
- });
+ .satisfies(e ->
+ {
+ assertThat(e.getExceptions())
+ .hasSize(1)
+ .extracting("message")
+ .containsExactly("2e1424d4-f796-459a-8184-9c92662be6da");
+
+ assertThat(e.getFailures())
+ .hasSize(1)
+ .extracting("messageId")
+ .containsExactly("2e1424d4-f796-459a-8184-9c92662be6da");
+
+ assertThat(e.successMessageReturnValues())
+ .hasSize(1)
+ .contains("Success");
+ });
verify(interactionClient).listQueues();
verify(sqsClient).deleteMessageBatch(any(DeleteMessageBatchRequest.class));
@@ -124,9 +137,10 @@ void shouldBatchProcessAndMoveNonRetryableExceptionToDlq() {
" \"maxReceiveCount\": 2\n" +
"}");
- when(sqsClient.getQueueAttributes(any(GetQueueAttributesRequest.class))).thenReturn(GetQueueAttributesResponse.builder()
- .attributes(attributes)
- .build());
+ when(sqsClient.getQueueAttributes(any(GetQueueAttributesRequest.class))).thenReturn(
+ GetQueueAttributesResponse.builder()
+ .attributes(attributes)
+ .build());
requestHandler.handleRequest(event, context);
@@ -140,13 +154,14 @@ void shouldBatchProcessAndThrowExceptionForNonRetryableExceptionWhenMoveToDlqRet
requestHandler = new SqsMessageHandlerWithNonRetryableHandler();
event.getRecords().get(0).setMessageId("");
- when(sqsClient.sendMessageBatch(any(SendMessageBatchRequest.class))).thenReturn(SendMessageBatchResponse.builder()
+ when(sqsClient.sendMessageBatch(any(SendMessageBatchRequest.class))).thenReturn(
+ SendMessageBatchResponse.builder()
.failed(BatchResultErrorEntry.builder()
.message("Permission Error")
.code("KMS.AccessDeniedException")
.senderFault(true)
.build())
- .build());
+ .build());
HashMap attributes = new HashMap<>();
@@ -155,9 +170,10 @@ void shouldBatchProcessAndThrowExceptionForNonRetryableExceptionWhenMoveToDlqRet
" \"maxReceiveCount\": 2\n" +
"}");
- when(sqsClient.getQueueAttributes(any(GetQueueAttributesRequest.class))).thenReturn(GetQueueAttributesResponse.builder()
- .attributes(attributes)
- .build());
+ when(sqsClient.getQueueAttributes(any(GetQueueAttributesRequest.class))).thenReturn(
+ GetQueueAttributesResponse.builder()
+ .attributes(attributes)
+ .build());
Assertions.assertThatExceptionOfType(SQSBatchProcessingException.class).
isThrownBy(() -> requestHandler.handleRequest(event, context));
@@ -192,28 +208,31 @@ void shouldBatchProcessAndFailWithExceptionForNonRetryableExceptionAndNoDlq() {
requestHandler = new SqsMessageHandlerWithNonRetryableHandler();
event.getRecords().get(0).setMessageId("");
- event.getRecords().forEach(sqsMessage -> sqsMessage.setEventSourceArn(sqsMessage.getEventSourceArn() + "-temp"));
+ event.getRecords()
+ .forEach(sqsMessage -> sqsMessage.setEventSourceArn(sqsMessage.getEventSourceArn() + "-temp"));
- when(sqsClient.getQueueAttributes(any(GetQueueAttributesRequest.class))).thenReturn(GetQueueAttributesResponse.builder()
- .build());
+ when(sqsClient.getQueueAttributes(any(GetQueueAttributesRequest.class))).thenReturn(
+ GetQueueAttributesResponse.builder()
+ .build());
assertThatExceptionOfType(SQSBatchProcessingException.class)
.isThrownBy(() -> requestHandler.handleRequest(event, context))
- .satisfies(e -> {
- assertThat(e.getExceptions())
- .hasSize(1)
- .extracting("message")
- .containsExactly("Invalid message and was moved to DLQ");
-
- assertThat(e.getFailures())
- .hasSize(1)
- .extracting("messageId")
- .containsExactly("");
-
- assertThat(e.successMessageReturnValues())
- .hasSize(1)
- .contains("Success");
- });
+ .satisfies(e ->
+ {
+ assertThat(e.getExceptions())
+ .hasSize(1)
+ .extracting("message")
+ .containsExactly("Invalid message and was moved to DLQ");
+
+ assertThat(e.getFailures())
+ .hasSize(1)
+ .extracting("messageId")
+ .containsExactly("");
+
+ assertThat(e.successMessageReturnValues())
+ .hasSize(1)
+ .contains("Success");
+ });
verify(interactionClient).listQueues();
verify(sqsClient).deleteMessageBatch(any(DeleteMessageBatchRequest.class));
@@ -224,33 +243,36 @@ void shouldBatchProcessAndFailWithExceptionForNonRetryableExceptionAndNoDlq() {
void shouldBatchProcessAndFailWithExceptionForNonRetryableExceptionWhenFailedParsingPolicy() {
requestHandler = new SqsMessageHandlerWithNonRetryableHandler();
event.getRecords().get(0).setMessageId("");
- event.getRecords().forEach(sqsMessage -> sqsMessage.setEventSourceArn(sqsMessage.getEventSourceArn() + "-temp-queue"));
+ event.getRecords()
+ .forEach(sqsMessage -> sqsMessage.setEventSourceArn(sqsMessage.getEventSourceArn() + "-temp-queue"));
HashMap attributes = new HashMap<>();
attributes.put(QueueAttributeName.REDRIVE_POLICY, "MalFormedRedrivePolicy");
- when(sqsClient.getQueueAttributes(any(GetQueueAttributesRequest.class))).thenReturn(GetQueueAttributesResponse.builder()
- .attributes(attributes)
- .build());
+ when(sqsClient.getQueueAttributes(any(GetQueueAttributesRequest.class))).thenReturn(
+ GetQueueAttributesResponse.builder()
+ .attributes(attributes)
+ .build());
assertThatExceptionOfType(SQSBatchProcessingException.class)
.isThrownBy(() -> requestHandler.handleRequest(event, context))
- .satisfies(e -> {
- assertThat(e.getExceptions())
- .hasSize(1)
- .extracting("message")
- .containsExactly("Invalid message and was moved to DLQ");
-
- assertThat(e.getFailures())
- .hasSize(1)
- .extracting("messageId")
- .containsExactly("");
-
- assertThat(e.successMessageReturnValues())
- .hasSize(1)
- .contains("Success");
- });
+ .satisfies(e ->
+ {
+ assertThat(e.getExceptions())
+ .hasSize(1)
+ .extracting("message")
+ .containsExactly("Invalid message and was moved to DLQ");
+
+ assertThat(e.getFailures())
+ .hasSize(1)
+ .extracting("messageId")
+ .containsExactly("");
+
+ assertThat(e.successMessageReturnValues())
+ .hasSize(1)
+ .contains("Success");
+ });
verify(interactionClient).listQueues();
verify(sqsClient).deleteMessageBatch(any(DeleteMessageBatchRequest.class));
@@ -271,27 +293,29 @@ void shouldBatchProcessAndMoveNonRetryableExceptionToDlqAndThrowException() thro
" \"maxReceiveCount\": 2\n" +
"}");
- when(sqsClient.getQueueAttributes(any(GetQueueAttributesRequest.class))).thenReturn(GetQueueAttributesResponse.builder()
- .attributes(attributes)
- .build());
+ when(sqsClient.getQueueAttributes(any(GetQueueAttributesRequest.class))).thenReturn(
+ GetQueueAttributesResponse.builder()
+ .attributes(attributes)
+ .build());
assertThatExceptionOfType(SQSBatchProcessingException.class)
.isThrownBy(() -> requestHandler.handleRequest(event, context))
- .satisfies(e -> {
- assertThat(e.getExceptions())
- .hasSize(1)
- .extracting("message")
- .containsExactly("Invalid message and should be reprocessed");
-
- assertThat(e.getFailures())
- .hasSize(1)
- .extracting("messageId")
- .containsExactly("2e1424d4-f796-459a-9696-9c92662ba5da");
-
- assertThat(e.successMessageReturnValues())
- .hasSize(1)
- .contains("Success");
- });
+ .satisfies(e ->
+ {
+ assertThat(e.getExceptions())
+ .hasSize(1)
+ .extracting("message")
+ .containsExactly("Invalid message and should be reprocessed");
+
+ assertThat(e.getFailures())
+ .hasSize(1)
+ .extracting("messageId")
+ .containsExactly("2e1424d4-f796-459a-9696-9c92662ba5da");
+
+ assertThat(e.successMessageReturnValues())
+ .hasSize(1)
+ .contains("Success");
+ });
verify(interactionClient).listQueues();
verify(sqsClient).deleteMessageBatch(any(DeleteMessageBatchRequest.class));
diff --git a/powertools-test-suite/pom.xml b/powertools-test-suite/pom.xml
index 5737296da..4a79d2987 100644
--- a/powertools-test-suite/pom.xml
+++ b/powertools-test-suite/pom.xml
@@ -1,4 +1,18 @@
+
+
diff --git a/powertools-test-suite/src/test/java/software/amazon/lambda/powertools/testsuite/LoggingOrderTest.java b/powertools-test-suite/src/test/java/software/amazon/lambda/powertools/testsuite/LoggingOrderTest.java
index 7c3e79112..55349b267 100644
--- a/powertools-test-suite/src/test/java/software/amazon/lambda/powertools/testsuite/LoggingOrderTest.java
+++ b/powertools-test-suite/src/test/java/software/amazon/lambda/powertools/testsuite/LoggingOrderTest.java
@@ -1,6 +1,35 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.testsuite;
+import static java.util.Collections.emptyMap;
+import static java.util.Collections.singletonList;
+import static org.apache.commons.lang3.reflect.FieldUtils.writeStaticField;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.fail;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.when;
+import static org.mockito.MockitoAnnotations.openMocks;
+
+import com.amazonaws.services.lambda.runtime.Context;
+import com.amazonaws.services.lambda.runtime.events.SQSEvent;
+import com.amazonaws.services.lambda.runtime.events.models.s3.S3EventNotification;
+import com.amazonaws.xray.AWSXRay;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
@@ -12,13 +41,6 @@
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.Map;
-
-import com.amazonaws.services.lambda.runtime.Context;
-import com.amazonaws.services.lambda.runtime.events.SQSEvent;
-import com.amazonaws.services.lambda.runtime.events.models.s3.S3EventNotification;
-import com.amazonaws.xray.AWSXRay;
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.ThreadContext;
import org.junit.jupiter.api.AfterEach;
@@ -36,15 +58,6 @@
import software.amazon.lambda.powertools.testsuite.handler.LoggingOrderMessageHandler;
import software.amazon.lambda.powertools.testsuite.handler.TracingLoggingStreamMessageHandler;
-import static java.util.Collections.emptyMap;
-import static java.util.Collections.singletonList;
-import static org.apache.commons.lang3.reflect.FieldUtils.writeStaticField;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.fail;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.when;
-import static org.mockito.MockitoAnnotations.openMocks;
-
public class LoggingOrderTest {
private static final String BUCKET_NAME = "ms-extended-sqs-client";
@@ -79,25 +92,30 @@ void tearDown() {
* after the event has been altered
*/
@Test
- public void testThatLoggingAnnotationActsLast() throws IOException {
- ResponseInputStream s3Response = new ResponseInputStream<>(GetObjectResponse.builder().build(), AbortableInputStream.create(new ByteArrayInputStream("A big message".getBytes())));
+ public void testThatLoggingAnnotationActsLast() throws IOException {
+ ResponseInputStream s3Response =
+ new ResponseInputStream<>(GetObjectResponse.builder().build(),
+ AbortableInputStream.create(new ByteArrayInputStream("A big message".getBytes())));
when(s3Client.getObject(any(GetObjectRequest.class))).thenReturn(s3Response);
- SQSEvent sqsEvent = messageWithBody("[\"software.amazon.payloadoffloading.PayloadS3Pointer\",{\"s3BucketName\":\"" + BUCKET_NAME + "\",\"s3Key\":\"" + BUCKET_KEY + "\"}]");
+ SQSEvent sqsEvent = messageWithBody(
+ "[\"software.amazon.payloadoffloading.PayloadS3Pointer\",{\"s3BucketName\":\"" + BUCKET_NAME +
+ "\",\"s3Key\":\"" + BUCKET_KEY + "\"}]");
LoggingOrderMessageHandler requestHandler = new LoggingOrderMessageHandler();
requestHandler.handleRequest(sqsEvent, context);
assertThat(Files.lines(Paths.get("target/logfile.json")))
.hasSize(2)
- .satisfies(line -> {
- Map actual = parseToMap(line.get(0));
+ .satisfies(line ->
+ {
+ Map actual = parseToMap(line.get(0));
- String message = actual.get("message").toString();
+ String message = actual.get("message").toString();
- assertThat(message)
- .contains("A big message");
- });
+ assertThat(message)
+ .contains("A big message");
+ });
}
@Test
@@ -107,7 +125,8 @@ public void testLoggingAnnotationActsAfterTracingForStreamingHandler() throws IO
S3EventNotification s3EventNotification = s3EventNotification();
TracingLoggingStreamMessageHandler handler = new TracingLoggingStreamMessageHandler();
- handler.handleRequest(new ByteArrayInputStream(new ObjectMapper().writeValueAsBytes(s3EventNotification)), output, context);
+ handler.handleRequest(new ByteArrayInputStream(new ObjectMapper().writeValueAsBytes(s3EventNotification)),
+ output, context);
assertThat(new String(output.toByteArray(), StandardCharsets.UTF_8))
.isNotEmpty();
@@ -121,7 +140,8 @@ private void setupContext() {
when(context.getAwsRequestId()).thenReturn("RequestId");
}
- private void resetLogLevel(Level level) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
+ private void resetLogLevel(Level level)
+ throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
Method resetLogLevels = LambdaLoggingAspect.class.getDeclaredMethod("resetLogLevels", Level.class);
resetLogLevels.setAccessible(true);
resetLogLevels.invoke(null, level);
@@ -138,25 +158,27 @@ private Map parseToMap(String stringAsJson) {
}
private S3EventNotification s3EventNotification() {
- S3EventNotification.S3EventNotificationRecord record = new S3EventNotification.S3EventNotificationRecord("us-west-2",
- "ObjectCreated:Put",
- "aws:s3",
- null,
- "2.1",
- new S3EventNotification.RequestParametersEntity("127.0.0.1"),
- new S3EventNotification.ResponseElementsEntity("C3D13FE58DE4C810", "FMyUVURIY8/IgAtTv8xRjskZQpcIZ9KG4V5Wp6S7S/JRWeUWerMUE5JgHvANOjpD"),
- new S3EventNotification.S3Entity("testConfigRule",
- new S3EventNotification.S3BucketEntity("mybucket",
- new S3EventNotification.UserIdentityEntity("A3NL1KOZZKExample"),
- "arn:aws:s3:::mybucket"),
- new S3EventNotification.S3ObjectEntity("HappyFace.jpg",
- 1024L,
- "d41d8cd98f00b204e9800998ecf8427e",
- "096fKKXTRTtl3on89fVO.nfljtsv6qko",
- "0055AED6DCD90281E5"),
- "1.0"),
- new S3EventNotification.UserIdentityEntity("AIDAJDPLRKLG7UEXAMPLE")
- );
+ S3EventNotification.S3EventNotificationRecord record =
+ new S3EventNotification.S3EventNotificationRecord("us-west-2",
+ "ObjectCreated:Put",
+ "aws:s3",
+ null,
+ "2.1",
+ new S3EventNotification.RequestParametersEntity("127.0.0.1"),
+ new S3EventNotification.ResponseElementsEntity("C3D13FE58DE4C810",
+ "FMyUVURIY8/IgAtTv8xRjskZQpcIZ9KG4V5Wp6S7S/JRWeUWerMUE5JgHvANOjpD"),
+ new S3EventNotification.S3Entity("testConfigRule",
+ new S3EventNotification.S3BucketEntity("mybucket",
+ new S3EventNotification.UserIdentityEntity("A3NL1KOZZKExample"),
+ "arn:aws:s3:::mybucket"),
+ new S3EventNotification.S3ObjectEntity("HappyFace.jpg",
+ 1024L,
+ "d41d8cd98f00b204e9800998ecf8427e",
+ "096fKKXTRTtl3on89fVO.nfljtsv6qko",
+ "0055AED6DCD90281E5"),
+ "1.0"),
+ new S3EventNotification.UserIdentityEntity("AIDAJDPLRKLG7UEXAMPLE")
+ );
return new S3EventNotification(singletonList(record));
}
diff --git a/powertools-test-suite/src/test/java/software/amazon/lambda/powertools/testsuite/handler/LoggingOrderMessageHandler.java b/powertools-test-suite/src/test/java/software/amazon/lambda/powertools/testsuite/handler/LoggingOrderMessageHandler.java
index a85c81b1d..5592b1fd3 100644
--- a/powertools-test-suite/src/test/java/software/amazon/lambda/powertools/testsuite/handler/LoggingOrderMessageHandler.java
+++ b/powertools-test-suite/src/test/java/software/amazon/lambda/powertools/testsuite/handler/LoggingOrderMessageHandler.java
@@ -1,3 +1,17 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.testsuite.handler;
import com.amazonaws.services.lambda.runtime.Context;
diff --git a/powertools-test-suite/src/test/java/software/amazon/lambda/powertools/testsuite/handler/TracingLoggingStreamMessageHandler.java b/powertools-test-suite/src/test/java/software/amazon/lambda/powertools/testsuite/handler/TracingLoggingStreamMessageHandler.java
index d0f2b3ac5..4a60d0949 100644
--- a/powertools-test-suite/src/test/java/software/amazon/lambda/powertools/testsuite/handler/TracingLoggingStreamMessageHandler.java
+++ b/powertools-test-suite/src/test/java/software/amazon/lambda/powertools/testsuite/handler/TracingLoggingStreamMessageHandler.java
@@ -1,13 +1,26 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.testsuite.handler;
+import com.amazonaws.services.lambda.runtime.Context;
+import com.amazonaws.services.lambda.runtime.RequestStreamHandler;
+import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Map;
-
-import com.amazonaws.services.lambda.runtime.Context;
-import com.amazonaws.services.lambda.runtime.RequestStreamHandler;
-import com.fasterxml.jackson.databind.ObjectMapper;
import software.amazon.lambda.powertools.logging.Logging;
import software.amazon.lambda.powertools.tracing.Tracing;
diff --git a/powertools-tracing/pom.xml b/powertools-tracing/pom.xml
index 42a229f42..b5de90f7b 100644
--- a/powertools-tracing/pom.xml
+++ b/powertools-tracing/pom.xml
@@ -1,4 +1,18 @@
+
+
@@ -113,4 +127,13 @@
+
+
+
+ org.apache.maven.plugins
+ maven-checkstyle-plugin
+
+
+
+
\ No newline at end of file
diff --git a/powertools-tracing/src/main/java/software/amazon/lambda/powertools/tracing/CaptureMode.java b/powertools-tracing/src/main/java/software/amazon/lambda/powertools/tracing/CaptureMode.java
index 9fd09e8ee..29d10d188 100644
--- a/powertools-tracing/src/main/java/software/amazon/lambda/powertools/tracing/CaptureMode.java
+++ b/powertools-tracing/src/main/java/software/amazon/lambda/powertools/tracing/CaptureMode.java
@@ -1,3 +1,17 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.tracing;
public enum CaptureMode {
diff --git a/powertools-tracing/src/main/java/software/amazon/lambda/powertools/tracing/Tracing.java b/powertools-tracing/src/main/java/software/amazon/lambda/powertools/tracing/Tracing.java
index cb90f3315..6f17a2e33 100644
--- a/powertools-tracing/src/main/java/software/amazon/lambda/powertools/tracing/Tracing.java
+++ b/powertools-tracing/src/main/java/software/amazon/lambda/powertools/tracing/Tracing.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,6 +11,7 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.tracing;
import java.lang.annotation.ElementType;
@@ -39,7 +40,7 @@
* to a sub segment named after the method.
*
*
To disable this functionality you can specify {@code @Tracing( captureError = false)}
- *e
+ * e
*
All traces have a namespace set. If {@code @Tracing( namespace = "ExampleService")} is set
* this takes precedent over any value set in the environment variable {@code POWER_TOOLS_SERVICE_NAME}.
* If both are undefined then the value will default to {@code service_undefined}
@@ -48,6 +49,7 @@
@Target(ElementType.METHOD)
public @interface Tracing {
String namespace() default "";
+
/**
* @deprecated As of release 1.2.0, replaced by captureMode()
* in order to support different modes and support via
@@ -55,6 +57,7 @@
*/
@Deprecated
boolean captureResponse() default true;
+
/**
* @deprecated As of release 1.2.0, replaced by captureMode()
* in order to support different modes and support via
@@ -62,6 +65,8 @@
*/
@Deprecated
boolean captureError() default true;
+
String segmentName() default "";
+
CaptureMode captureMode() default CaptureMode.ENVIRONMENT_VAR;
}
diff --git a/powertools-tracing/src/main/java/software/amazon/lambda/powertools/tracing/TracingUtils.java b/powertools-tracing/src/main/java/software/amazon/lambda/powertools/tracing/TracingUtils.java
index 0e956e539..9fb021548 100644
--- a/powertools-tracing/src/main/java/software/amazon/lambda/powertools/tracing/TracingUtils.java
+++ b/powertools-tracing/src/main/java/software/amazon/lambda/powertools/tracing/TracingUtils.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,20 +11,20 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.tracing;
-import java.util.function.Consumer;
+import static software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor.serviceName;
+
import com.amazonaws.xray.AWSXRay;
import com.amazonaws.xray.entities.Entity;
import com.amazonaws.xray.entities.Subsegment;
import com.fasterxml.jackson.databind.ObjectMapper;
-
-import static software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor.serviceName;
+import java.util.function.Consumer;
/**
* A class of helper functions to add additional functionality and ease
* of use.
- *
*/
public final class TracingUtils {
private static ObjectMapper objectMapper;
@@ -32,7 +32,7 @@ public final class TracingUtils {
/**
* Put an annotation to the current subsegment with a String value.
*
- * @param key the key of the annotation
+ * @param key the key of the annotation
* @param value the value of the annotation
*/
public static void putAnnotation(String key, String value) {
@@ -43,33 +43,33 @@ public static void putAnnotation(String key, String value) {
/**
* Put an annotation to the current subsegment with a Number value.
*
- * @param key the key of the annotation
+ * @param key the key of the annotation
* @param value the value of the annotation
*/
public static void putAnnotation(String key, Number value) {
AWSXRay.getCurrentSubsegmentOptional()
- .ifPresent(segment -> segment.putAnnotation(key, value));
+ .ifPresent(segment -> segment.putAnnotation(key, value));
}
/**
* Put an annotation to the current subsegment with a Boolean value.
*
- * @param key the key of the annotation
+ * @param key the key of the annotation
* @param value the value of the annotation
*/
public static void putAnnotation(String key, Boolean value) {
AWSXRay.getCurrentSubsegmentOptional()
- .ifPresent(segment -> segment.putAnnotation(key, value));
+ .ifPresent(segment -> segment.putAnnotation(key, value));
}
/**
* Put additional metadata for the current subsegment.
- *
+ *
* The namespace used will be the namespace of the current subsegment if it
* is set else it will follow the namespace process as described in
* {@link Tracing}
*
- * @param key the key of the metadata
+ * @param key the key of the metadata
* @param value the value of the metadata
*/
public static void putMetadata(String key, Object value) {
@@ -83,8 +83,8 @@ public static void putMetadata(String key, Object value) {
* Put additional metadata for the current subsegment.
*
* @param namespace the namespace of the metadata
- * @param key the key of the metadata
- * @param value the value of the metadata
+ * @param key the key of the metadata
+ * @param value the value of the metadata
*/
public static void putMetadata(String namespace, String key, Object value) {
AWSXRay.getCurrentSubsegmentOptional()
@@ -94,14 +94,14 @@ public static void putMetadata(String namespace, String key, Object value) {
/**
* Adds a new subsegment around the passed consumer. This also provides access to
* the newly created subsegment.
- *
+ *
* The namespace used follows the flow as described in {@link Tracing}
- *
+ *
* This method is intended for use with multi-threaded programming where the
* context is lost between threads.
*
- * @param name the name of the subsegment
- * @param entity the current x-ray context
+ * @param name the name of the subsegment
+ * @param entity the current x-ray context
* @param subsegment the x-ray subsegment for the wrapped consumer
*/
public static void withEntitySubsegment(String name, Entity entity, Consumer subsegment) {
@@ -112,16 +112,17 @@ public static void withEntitySubsegment(String name, Entity entity, Consumer
* This method is intended for use with multi-threaded programming where the
* context is lost between threads.
*
- * @param namespace the namespace of the subsegment
- * @param name the name of the subsegment
- * @param entity the current x-ray context
+ * @param namespace the namespace of the subsegment
+ * @param name the name of the subsegment
+ * @param entity the current x-ray context
* @param subsegment the x-ray subsegment for the wrapped consumer
*/
- public static void withEntitySubsegment(String namespace, String name, Entity entity, Consumer subsegment) {
+ public static void withEntitySubsegment(String namespace, String name, Entity entity,
+ Consumer subsegment) {
AWSXRay.setTraceEntity(entity);
withSubsegment(namespace, name, subsegment);
}
@@ -129,10 +130,10 @@ public static void withEntitySubsegment(String namespace, String name, Entity en
/**
* Adds a new subsegment around the passed consumer. This also provides access to
* the newly created subsegment.
- *
+ *
* The namespace used follows the flow as described in {@link Tracing}
*
- * @param name the name of the subsegment
+ * @param name the name of the subsegment
* @param subsegment the x-ray subsegment for the wrapped consumer
*/
public static void withSubsegment(String name, Consumer subsegment) {
@@ -143,8 +144,8 @@ public static void withSubsegment(String name, Consumer subsegment)
* Adds a new subsegment around the passed consumer. This also provides access to
* the newly created subsegment.
*
- * @param namespace the namespace for the subsegment
- * @param name the name of the subsegment
+ * @param namespace the namespace for the subsegment
+ * @param name the name of the subsegment
* @param subsegment the x-ray subsegment for the wrapped consumer
*/
public static void withSubsegment(String namespace, String name, Consumer subsegment) {
diff --git a/powertools-tracing/src/main/java/software/amazon/lambda/powertools/tracing/internal/LambdaTracingAspect.java b/powertools-tracing/src/main/java/software/amazon/lambda/powertools/tracing/internal/LambdaTracingAspect.java
index 26feec66b..62416fce6 100644
--- a/powertools-tracing/src/main/java/software/amazon/lambda/powertools/tracing/internal/LambdaTracingAspect.java
+++ b/powertools-tracing/src/main/java/software/amazon/lambda/powertools/tracing/internal/LambdaTracingAspect.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,24 +11,25 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.tracing.internal;
-import java.util.function.Supplier;
+import static software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor.coldStartDone;
+import static software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor.isColdStart;
+import static software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor.isHandlerMethod;
+import static software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor.isSamLocal;
+import static software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor.serviceName;
+import static software.amazon.lambda.powertools.tracing.TracingUtils.objectMapper;
+
import com.amazonaws.xray.AWSXRay;
import com.amazonaws.xray.entities.Subsegment;
+import java.util.function.Supplier;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import software.amazon.lambda.powertools.tracing.Tracing;
-import static software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor.coldStartDone;
-import static software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor.isColdStart;
-import static software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor.isHandlerMethod;
-import static software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor.isSamLocal;
-import static software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor.serviceName;
-import static software.amazon.lambda.powertools.tracing.TracingUtils.objectMapper;
-
@Aspect
public final class LambdaTracingAspect {
@SuppressWarnings({"EmptyMethod"})
@@ -42,8 +43,8 @@ public Object around(ProceedingJoinPoint pjp,
Object[] proceedArgs = pjp.getArgs();
Subsegment segment = AWSXRay.beginSubsegment(
- customSegmentNameOrDefault(tracing,
- () -> "## " + pjp.getSignature().getName()));
+ customSegmentNameOrDefault(tracing,
+ () -> "## " + pjp.getSignature().getName()));
segment.setNamespace(namespace(tracing));
if (isHandlerMethod(pjp)) {
@@ -57,7 +58,8 @@ public Object around(ProceedingJoinPoint pjp,
try {
Object methodReturn = pjp.proceed(proceedArgs);
if (captureResponse) {
- segment.putMetadata(namespace(tracing), pjp.getSignature().getName() + " response", null != objectMapper() ? objectMapper().writeValueAsString(methodReturn): methodReturn);
+ segment.putMetadata(namespace(tracing), pjp.getSignature().getName() + " response",
+ null != objectMapper() ? objectMapper().writeValueAsString(methodReturn) : methodReturn);
}
if (isHandlerMethod(pjp)) {
@@ -67,7 +69,8 @@ public Object around(ProceedingJoinPoint pjp,
return methodReturn;
} catch (Exception e) {
if (captureError) {
- segment.putMetadata(namespace(tracing), pjp.getSignature().getName() + " error", null != objectMapper() ? objectMapper().writeValueAsString(e) : e);
+ segment.putMetadata(namespace(tracing), pjp.getSignature().getName() + " error",
+ null != objectMapper() ? objectMapper().writeValueAsString(e) : e);
}
throw e;
} finally {
@@ -81,7 +84,8 @@ private boolean captureResponse(Tracing powerToolsTracing) {
switch (powerToolsTracing.captureMode()) {
case ENVIRONMENT_VAR:
boolean captureResponse = environmentVariable("POWERTOOLS_TRACER_CAPTURE_RESPONSE");
- return isEnvironmentVariableSet("POWERTOOLS_TRACER_CAPTURE_RESPONSE") ? captureResponse : powerToolsTracing.captureResponse();
+ return isEnvironmentVariableSet("POWERTOOLS_TRACER_CAPTURE_RESPONSE") ? captureResponse :
+ powerToolsTracing.captureResponse();
case RESPONSE:
case RESPONSE_AND_ERROR:
return true;
@@ -95,7 +99,8 @@ private boolean captureError(Tracing powerToolsTracing) {
switch (powerToolsTracing.captureMode()) {
case ENVIRONMENT_VAR:
boolean captureError = environmentVariable("POWERTOOLS_TRACER_CAPTURE_ERROR");
- return isEnvironmentVariableSet("POWERTOOLS_TRACER_CAPTURE_ERROR") ? captureError : powerToolsTracing.captureError();
+ return isEnvironmentVariableSet("POWERTOOLS_TRACER_CAPTURE_ERROR") ? captureError :
+ powerToolsTracing.captureError();
case ERROR:
case RESPONSE_AND_ERROR:
return true;
diff --git a/powertools-tracing/src/main/java/software/amazon/lambda/powertools/tracing/internal/SystemWrapper.java b/powertools-tracing/src/main/java/software/amazon/lambda/powertools/tracing/internal/SystemWrapper.java
index da1a92ced..c66b8b7ee 100644
--- a/powertools-tracing/src/main/java/software/amazon/lambda/powertools/tracing/internal/SystemWrapper.java
+++ b/powertools-tracing/src/main/java/software/amazon/lambda/powertools/tracing/internal/SystemWrapper.java
@@ -1,3 +1,17 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.tracing.internal;
public class SystemWrapper {
diff --git a/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/TracingUtilsTest.java b/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/TracingUtilsTest.java
index d2a96ec65..69054d0c6 100644
--- a/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/TracingUtilsTest.java
+++ b/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/TracingUtilsTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,8 +11,15 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.tracing;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.entry;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static software.amazon.lambda.powertools.tracing.TracingUtils.withEntitySubsegment;
+
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.xray.AWSXRay;
import com.amazonaws.xray.entities.Entity;
@@ -20,12 +27,6 @@
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.entry;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static software.amazon.lambda.powertools.tracing.TracingUtils.withEntitySubsegment;
-
class TracingUtilsTest {
@BeforeEach
@@ -51,12 +52,12 @@ void shouldSetAnnotationOnCurrentSubSegment() {
TracingUtils.putAnnotation("booleanKey", false);
assertThat(AWSXRay.getTraceEntity().getAnnotations())
- .hasSize(3)
- .contains(
- entry("stringKey", "val"),
- entry("numberKey", 10),
- entry("booleanKey", false)
- );
+ .hasSize(3)
+ .contains(
+ entry("stringKey", "val"),
+ entry("numberKey", 10),
+ entry("booleanKey", false)
+ );
}
@Test
@@ -94,60 +95,64 @@ void shouldNotSetMetaDataIfNoCurrentSubSegment() {
void shouldInvokeCodeBlockWrappedWithinSubsegment() {
Context test = mock(Context.class);
- TracingUtils.withSubsegment("testSubSegment", subsegment -> {
- subsegment.putAnnotation("key", "val");
- subsegment.putMetadata("key", "val");
- test.getFunctionName();
- });
+ TracingUtils.withSubsegment("testSubSegment", subsegment ->
+ {
+ subsegment.putAnnotation("key", "val");
+ subsegment.putMetadata("key", "val");
+ test.getFunctionName();
+ });
verify(test).getFunctionName();
assertThat(AWSXRay.getTraceEntity().getSubsegments())
.hasSize(1)
- .allSatisfy(subsegment -> {
- assertThat(subsegment.getName())
- .isEqualTo("## testSubSegment");
+ .allSatisfy(subsegment ->
+ {
+ assertThat(subsegment.getName())
+ .isEqualTo("## testSubSegment");
- assertThat(subsegment.getNamespace())
- .isEqualTo("service_undefined");
+ assertThat(subsegment.getNamespace())
+ .isEqualTo("service_undefined");
- assertThat(subsegment.getAnnotations())
- .hasSize(1)
- .containsEntry("key", "val");
+ assertThat(subsegment.getAnnotations())
+ .hasSize(1)
+ .containsEntry("key", "val");
- assertThat(subsegment.getMetadata())
- .hasSize(1);
- });
+ assertThat(subsegment.getMetadata())
+ .hasSize(1);
+ });
}
@Test
void shouldInvokeCodeBlockWrappedWithinNamespacedSubsegment() {
Context test = mock(Context.class);
- TracingUtils.withSubsegment("testNamespace", "testSubSegment", subsegment -> {
- subsegment.putAnnotation("key", "val");
- subsegment.putMetadata("key", "val");
- test.getFunctionName();
- });
+ TracingUtils.withSubsegment("testNamespace", "testSubSegment", subsegment ->
+ {
+ subsegment.putAnnotation("key", "val");
+ subsegment.putMetadata("key", "val");
+ test.getFunctionName();
+ });
verify(test).getFunctionName();
assertThat(AWSXRay.getTraceEntity().getSubsegments())
.hasSize(1)
- .allSatisfy(subsegment -> {
- assertThat(subsegment.getName())
- .isEqualTo("## testSubSegment");
+ .allSatisfy(subsegment ->
+ {
+ assertThat(subsegment.getName())
+ .isEqualTo("## testSubSegment");
- assertThat(subsegment.getNamespace())
- .isEqualTo("testNamespace");
+ assertThat(subsegment.getNamespace())
+ .isEqualTo("testNamespace");
- assertThat(subsegment.getAnnotations())
- .hasSize(1)
- .containsEntry("key", "val");
+ assertThat(subsegment.getAnnotations())
+ .hasSize(1)
+ .containsEntry("key", "val");
- assertThat(subsegment.getMetadata())
- .hasSize(1);
- });
+ assertThat(subsegment.getMetadata())
+ .hasSize(1);
+ });
}
@Test
@@ -156,10 +161,11 @@ void shouldInvokeCodeBlockWrappedWithinEntitySubsegment() throws InterruptedExce
Entity traceEntity = AWSXRay.getTraceEntity();
- Thread thread = new Thread(() -> withEntitySubsegment("testSubSegment", traceEntity, subsegment -> {
- subsegment.putAnnotation("key", "val");
- test.getFunctionName();
- }));
+ Thread thread = new Thread(() -> withEntitySubsegment("testSubSegment", traceEntity, subsegment ->
+ {
+ subsegment.putAnnotation("key", "val");
+ test.getFunctionName();
+ }));
thread.start();
thread.join();
@@ -168,17 +174,18 @@ void shouldInvokeCodeBlockWrappedWithinEntitySubsegment() throws InterruptedExce
assertThat(AWSXRay.getTraceEntity().getSubsegments())
.hasSize(1)
- .allSatisfy(subsegment -> {
- assertThat(subsegment.getName())
- .isEqualTo("## testSubSegment");
-
- assertThat(subsegment.getNamespace())
- .isEqualTo("service_undefined");
-
- assertThat(subsegment.getAnnotations())
- .hasSize(1)
- .containsEntry("key", "val");
- });
+ .allSatisfy(subsegment ->
+ {
+ assertThat(subsegment.getName())
+ .isEqualTo("## testSubSegment");
+
+ assertThat(subsegment.getNamespace())
+ .isEqualTo("service_undefined");
+
+ assertThat(subsegment.getAnnotations())
+ .hasSize(1)
+ .containsEntry("key", "val");
+ });
}
@Test
@@ -187,10 +194,12 @@ void shouldInvokeCodeBlockWrappedWithinNamespacedEntitySubsegment() throws Inter
Entity traceEntity = AWSXRay.getTraceEntity();
- Thread thread = new Thread(() -> withEntitySubsegment("testNamespace", "testSubSegment", traceEntity, subsegment -> {
- subsegment.putAnnotation("key", "val");
- test.getFunctionName();
- }));
+ Thread thread =
+ new Thread(() -> withEntitySubsegment("testNamespace", "testSubSegment", traceEntity, subsegment ->
+ {
+ subsegment.putAnnotation("key", "val");
+ test.getFunctionName();
+ }));
thread.start();
thread.join();
@@ -199,16 +208,17 @@ void shouldInvokeCodeBlockWrappedWithinNamespacedEntitySubsegment() throws Inter
assertThat(AWSXRay.getTraceEntity().getSubsegments())
.hasSize(1)
- .allSatisfy(subsegment -> {
- assertThat(subsegment.getName())
- .isEqualTo("## testSubSegment");
-
- assertThat(subsegment.getNamespace())
- .isEqualTo("testNamespace");
-
- assertThat(subsegment.getAnnotations())
- .hasSize(1)
- .containsEntry("key", "val");
- });
+ .allSatisfy(subsegment ->
+ {
+ assertThat(subsegment.getName())
+ .isEqualTo("## testSubSegment");
+
+ assertThat(subsegment.getNamespace())
+ .isEqualTo("testNamespace");
+
+ assertThat(subsegment.getAnnotations())
+ .hasSize(1)
+ .containsEntry("key", "val");
+ });
}
}
\ No newline at end of file
diff --git a/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/handlers/PowerToolDisabled.java b/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/handlers/PowerToolDisabled.java
index 78878ffe5..1a9dc851a 100644
--- a/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/handlers/PowerToolDisabled.java
+++ b/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/handlers/PowerToolDisabled.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,6 +11,7 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.tracing.handlers;
import com.amazonaws.services.lambda.runtime.Context;
diff --git a/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/handlers/PowerToolDisabledForStream.java b/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/handlers/PowerToolDisabledForStream.java
index 80f37b8b6..49bc4e095 100644
--- a/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/handlers/PowerToolDisabledForStream.java
+++ b/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/handlers/PowerToolDisabledForStream.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,13 +11,13 @@
* limitations under the License.
*
*/
-package software.amazon.lambda.powertools.tracing.handlers;
-import java.io.InputStream;
-import java.io.OutputStream;
+package software.amazon.lambda.powertools.tracing.handlers;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestStreamHandler;
+import java.io.InputStream;
+import java.io.OutputStream;
public class PowerToolDisabledForStream implements RequestStreamHandler {
diff --git a/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/handlers/PowerTracerToolEnabled.java b/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/handlers/PowerTracerToolEnabled.java
index 3be79fb76..5af3c65af 100644
--- a/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/handlers/PowerTracerToolEnabled.java
+++ b/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/handlers/PowerTracerToolEnabled.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,6 +11,7 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.tracing.handlers;
import com.amazonaws.services.lambda.runtime.Context;
diff --git a/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/handlers/PowerTracerToolEnabledExplicitlyForResponseAndError.java b/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/handlers/PowerTracerToolEnabledExplicitlyForResponseAndError.java
index cd026f427..88b42c690 100644
--- a/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/handlers/PowerTracerToolEnabledExplicitlyForResponseAndError.java
+++ b/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/handlers/PowerTracerToolEnabledExplicitlyForResponseAndError.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,14 +11,15 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.tracing.handlers;
+import static software.amazon.lambda.powertools.tracing.CaptureMode.RESPONSE_AND_ERROR;
+
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import software.amazon.lambda.powertools.tracing.Tracing;
-import static software.amazon.lambda.powertools.tracing.CaptureMode.RESPONSE_AND_ERROR;
-
public class PowerTracerToolEnabledExplicitlyForResponseAndError implements RequestHandler {
@Override
diff --git a/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/handlers/PowerTracerToolEnabledForError.java b/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/handlers/PowerTracerToolEnabledForError.java
index c84d25763..47e23ed18 100644
--- a/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/handlers/PowerTracerToolEnabledForError.java
+++ b/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/handlers/PowerTracerToolEnabledForError.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,14 +11,15 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.tracing.handlers;
+import static software.amazon.lambda.powertools.tracing.CaptureMode.ERROR;
+
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import software.amazon.lambda.powertools.tracing.Tracing;
-import static software.amazon.lambda.powertools.tracing.CaptureMode.ERROR;
-
public class PowerTracerToolEnabledForError implements RequestHandler {
@Override
diff --git a/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/handlers/PowerTracerToolEnabledForResponse.java b/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/handlers/PowerTracerToolEnabledForResponse.java
index 1e82f2148..be0fe9b24 100644
--- a/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/handlers/PowerTracerToolEnabledForResponse.java
+++ b/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/handlers/PowerTracerToolEnabledForResponse.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,14 +11,15 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.tracing.handlers;
+import static software.amazon.lambda.powertools.tracing.CaptureMode.RESPONSE;
+
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import software.amazon.lambda.powertools.tracing.Tracing;
-import static software.amazon.lambda.powertools.tracing.CaptureMode.RESPONSE;
-
public class PowerTracerToolEnabledForResponse implements RequestHandler {
@Override
diff --git a/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/handlers/PowerTracerToolEnabledForResponseWithCustomMapper.java b/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/handlers/PowerTracerToolEnabledForResponseWithCustomMapper.java
index b7c908473..a18b1580d 100644
--- a/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/handlers/PowerTracerToolEnabledForResponseWithCustomMapper.java
+++ b/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/handlers/PowerTracerToolEnabledForResponseWithCustomMapper.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,9 +11,11 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.tracing.handlers;
-import java.io.IOException;
+import static software.amazon.lambda.powertools.tracing.CaptureMode.RESPONSE;
+
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.fasterxml.jackson.core.JsonGenerator;
@@ -21,11 +23,10 @@
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
+import java.io.IOException;
import software.amazon.lambda.powertools.tracing.Tracing;
import software.amazon.lambda.powertools.tracing.TracingUtils;
-import static software.amazon.lambda.powertools.tracing.CaptureMode.RESPONSE;
-
public class PowerTracerToolEnabledForResponseWithCustomMapper implements RequestHandler {
static {
ObjectMapper objectMapper = new ObjectMapper();
@@ -35,6 +36,7 @@ public class PowerTracerToolEnabledForResponseWithCustomMapper implements Reques
TracingUtils.defaultObjectMapper(objectMapper);
}
+
@Override
@Tracing(namespace = "lambdaHandler", captureMode = RESPONSE)
public Object handleRequest(Object input, Context context) {
@@ -44,6 +46,25 @@ public Object handleRequest(Object input, Context context) {
return parentClass;
}
+ public static class ChildSerializer extends StdSerializer {
+
+ public ChildSerializer() {
+ this(null);
+ }
+
+ public ChildSerializer(Class t) {
+ super(t);
+ }
+
+ @Override
+ public void serialize(ChildClass value, JsonGenerator jgen, SerializerProvider provider) throws IOException {
+ jgen.writeStartObject();
+ jgen.writeStringField("name", value.name);
+ jgen.writeStringField("p", value.p.name);
+ jgen.writeEndObject();
+ }
+ }
+
public class ParentClass {
public String name;
public ChildClass c;
@@ -66,23 +87,4 @@ public ChildClass(String name, ParentClass p) {
this.p = p;
}
}
-
- public static class ChildSerializer extends StdSerializer {
-
- public ChildSerializer() {
- this(null);
- }
-
- public ChildSerializer(Class t) {
- super(t);
- }
-
- @Override
- public void serialize(ChildClass value, JsonGenerator jgen, SerializerProvider provider) throws IOException {
- jgen.writeStartObject();
- jgen.writeStringField("name", value.name);
- jgen.writeStringField("p", value.p.name);
- jgen.writeEndObject();
- }
- }
}
diff --git a/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/handlers/PowerTracerToolEnabledForStream.java b/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/handlers/PowerTracerToolEnabledForStream.java
index e316ffe7d..5c693445a 100644
--- a/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/handlers/PowerTracerToolEnabledForStream.java
+++ b/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/handlers/PowerTracerToolEnabledForStream.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,14 +11,14 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.tracing.handlers;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestStreamHandler;
-import software.amazon.lambda.powertools.tracing.Tracing;
-
import java.io.InputStream;
import java.io.OutputStream;
+import software.amazon.lambda.powertools.tracing.Tracing;
public class PowerTracerToolEnabledForStream implements RequestStreamHandler {
diff --git a/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/handlers/PowerTracerToolEnabledForStreamWithNoMetaData.java b/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/handlers/PowerTracerToolEnabledForStreamWithNoMetaData.java
index 4cd381807..4cd2bb0b7 100644
--- a/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/handlers/PowerTracerToolEnabledForStreamWithNoMetaData.java
+++ b/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/handlers/PowerTracerToolEnabledForStreamWithNoMetaData.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,17 +11,17 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.tracing.handlers;
-import java.io.InputStream;
-import java.io.OutputStream;
+import static software.amazon.lambda.powertools.tracing.CaptureMode.DISABLED;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestStreamHandler;
+import java.io.InputStream;
+import java.io.OutputStream;
import software.amazon.lambda.powertools.tracing.Tracing;
-import static software.amazon.lambda.powertools.tracing.CaptureMode.DISABLED;
-
public class PowerTracerToolEnabledForStreamWithNoMetaData implements RequestStreamHandler {
@Override
diff --git a/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/handlers/PowerTracerToolEnabledWithException.java b/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/handlers/PowerTracerToolEnabledWithException.java
index cc184d020..88c506502 100644
--- a/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/handlers/PowerTracerToolEnabledWithException.java
+++ b/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/handlers/PowerTracerToolEnabledWithException.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,6 +11,7 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.tracing.handlers;
import com.amazonaws.services.lambda.runtime.Context;
diff --git a/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/handlers/PowerTracerToolEnabledWithNoMetaData.java b/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/handlers/PowerTracerToolEnabledWithNoMetaData.java
index 2109d6647..b4d77cde3 100644
--- a/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/handlers/PowerTracerToolEnabledWithNoMetaData.java
+++ b/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/handlers/PowerTracerToolEnabledWithNoMetaData.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,14 +11,15 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.tracing.handlers;
+import static software.amazon.lambda.powertools.tracing.CaptureMode.DISABLED;
+
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import software.amazon.lambda.powertools.tracing.Tracing;
-import static software.amazon.lambda.powertools.tracing.CaptureMode.DISABLED;
-
public class PowerTracerToolEnabledWithNoMetaData implements RequestHandler {
@Override
diff --git a/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/handlers/PowerTracerToolEnabledWithNoMetaDataDeprecated.java b/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/handlers/PowerTracerToolEnabledWithNoMetaDataDeprecated.java
index 2ded5e69f..c13f28df0 100644
--- a/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/handlers/PowerTracerToolEnabledWithNoMetaDataDeprecated.java
+++ b/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/handlers/PowerTracerToolEnabledWithNoMetaDataDeprecated.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,14 +11,13 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.tracing.handlers;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import software.amazon.lambda.powertools.tracing.Tracing;
-import static software.amazon.lambda.powertools.tracing.CaptureMode.DISABLED;
-
public class PowerTracerToolEnabledWithNoMetaDataDeprecated implements RequestHandler {
@Override
diff --git a/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/internal/LambdaTracingAspectTest.java b/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/internal/LambdaTracingAspectTest.java
index 8cd9b2f71..5e3ec6545 100644
--- a/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/internal/LambdaTracingAspectTest.java
+++ b/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/internal/LambdaTracingAspectTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,15 +11,24 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.tracing.internal;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
+import static org.apache.commons.lang3.reflect.FieldUtils.writeStaticField;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatNoException;
+import static org.assertj.core.api.Assertions.catchThrowable;
+import static org.mockito.Mockito.mockStatic;
+import static org.mockito.Mockito.when;
+import static org.mockito.MockitoAnnotations.openMocks;
+
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.lambda.runtime.RequestStreamHandler;
import com.amazonaws.xray.AWSXRay;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
@@ -41,14 +50,6 @@
import software.amazon.lambda.powertools.tracing.handlers.PowerTracerToolEnabledWithNoMetaDataDeprecated;
import software.amazon.lambda.powertools.tracing.nonhandler.PowerToolNonHandler;
-import static org.apache.commons.lang3.reflect.FieldUtils.writeStaticField;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatNoException;
-import static org.assertj.core.api.Assertions.catchThrowable;
-import static org.mockito.Mockito.mockStatic;
-import static org.mockito.Mockito.when;
-import static org.mockito.MockitoAnnotations.openMocks;
-
class LambdaTracingAspectTest {
private RequestHandler requestHandler;
private RequestStreamHandler streamHandler;
@@ -118,16 +119,17 @@ void shouldCaptureTraces() {
assertThat(AWSXRay.getTraceEntity().getSubsegmentsCopy())
.hasSize(1)
- .allSatisfy(subsegment -> {
- assertThat(subsegment.getAnnotations())
- .hasSize(2)
- .containsEntry("ColdStart", true)
- .containsEntry("Service", "lambdaHandler");
-
- assertThat(subsegment.getMetadata())
- .hasSize(1)
- .containsKey("lambdaHandler");
- });
+ .allSatisfy(subsegment ->
+ {
+ assertThat(subsegment.getAnnotations())
+ .hasSize(2)
+ .containsEntry("ColdStart", true)
+ .containsEntry("Service", "lambdaHandler");
+
+ assertThat(subsegment.getMetadata())
+ .hasSize(1)
+ .containsKey("lambdaHandler");
+ });
}
@Test
@@ -141,20 +143,21 @@ void shouldCaptureTracesWithExceptionMetaData() {
assertThat(AWSXRay.getTraceEntity().getSubsegmentsCopy())
.hasSize(1)
- .allSatisfy(subsegment -> {
- assertThat(subsegment.getAnnotations())
- .hasSize(2)
- .containsEntry("ColdStart", true)
- .containsEntry("Service", "lambdaHandler");
-
- assertThat(subsegment.getMetadata())
- .hasSize(1)
- .containsKey("lambdaHandler");
-
- assertThat(subsegment.getMetadata().get("lambdaHandler"))
- .satisfies(stringObjectMap -> assertThat(stringObjectMap)
- .containsEntry("handleRequest error", exception));
- });
+ .allSatisfy(subsegment ->
+ {
+ assertThat(subsegment.getAnnotations())
+ .hasSize(2)
+ .containsEntry("ColdStart", true)
+ .containsEntry("Service", "lambdaHandler");
+
+ assertThat(subsegment.getMetadata())
+ .hasSize(1)
+ .containsKey("lambdaHandler");
+
+ assertThat(subsegment.getMetadata().get("lambdaHandler"))
+ .satisfies(stringObjectMap -> assertThat(stringObjectMap)
+ .containsEntry("handleRequest error", exception));
+ });
}
@Test
@@ -166,16 +169,17 @@ void shouldCaptureTracesForStream() throws IOException {
assertThat(AWSXRay.getTraceEntity().getSubsegmentsCopy())
.hasSize(1)
- .allSatisfy(subsegment -> {
- assertThat(subsegment.getAnnotations())
- .hasSize(2)
- .containsEntry("ColdStart", true)
- .containsEntry("Service", "streamHandler");
-
- assertThat(subsegment.getMetadata())
- .hasSize(1)
- .containsKey("streamHandler");
- });
+ .allSatisfy(subsegment ->
+ {
+ assertThat(subsegment.getAnnotations())
+ .hasSize(2)
+ .containsEntry("ColdStart", true)
+ .containsEntry("Service", "streamHandler");
+
+ assertThat(subsegment.getMetadata())
+ .hasSize(1)
+ .containsKey("streamHandler");
+ });
}
@Test
@@ -207,15 +211,16 @@ void shouldCaptureTracesWithNoMetadata() {
assertThat(AWSXRay.getTraceEntity().getSubsegmentsCopy())
.hasSize(1)
- .allSatisfy(subsegment -> {
- assertThat(subsegment.getAnnotations())
- .hasSize(2)
- .containsEntry("ColdStart", true)
- .containsEntry("Service", "service_undefined");
-
- assertThat(subsegment.getMetadata())
- .isEmpty();
- });
+ .allSatisfy(subsegment ->
+ {
+ assertThat(subsegment.getAnnotations())
+ .hasSize(2)
+ .containsEntry("ColdStart", true)
+ .containsEntry("Service", "service_undefined");
+
+ assertThat(subsegment.getMetadata())
+ .isEmpty();
+ });
}
@Test
@@ -229,15 +234,16 @@ void shouldCaptureTracesForStreamWithNoMetadata() throws IOException {
assertThat(AWSXRay.getTraceEntity().getSubsegmentsCopy())
.hasSize(1)
- .allSatisfy(subsegment -> {
- assertThat(subsegment.getAnnotations())
- .hasSize(2)
- .containsEntry("ColdStart", true)
- .containsEntry("Service", "service_undefined");
-
- assertThat(subsegment.getMetadata())
- .isEmpty();
- });
+ .allSatisfy(subsegment ->
+ {
+ assertThat(subsegment.getAnnotations())
+ .hasSize(2)
+ .containsEntry("ColdStart", true)
+ .containsEntry("Service", "service_undefined");
+
+ assertThat(subsegment.getMetadata())
+ .isEmpty();
+ });
}
@Test
@@ -251,15 +257,16 @@ void shouldCaptureTracesWithNoMetadataDeprecated() {
assertThat(AWSXRay.getTraceEntity().getSubsegmentsCopy())
.hasSize(1)
- .allSatisfy(subsegment -> {
- assertThat(subsegment.getAnnotations())
- .hasSize(2)
- .containsEntry("ColdStart", true)
- .containsEntry("Service", "service_undefined");
-
- assertThat(subsegment.getMetadata())
- .isEmpty();
- });
+ .allSatisfy(subsegment ->
+ {
+ assertThat(subsegment.getAnnotations())
+ .hasSize(2)
+ .containsEntry("ColdStart", true)
+ .containsEntry("Service", "service_undefined");
+
+ assertThat(subsegment.getMetadata())
+ .isEmpty();
+ });
}
@Test
@@ -275,15 +282,16 @@ void shouldNotCaptureTracesIfDisabledViaEnvironmentVariable() {
assertThat(AWSXRay.getTraceEntity().getSubsegmentsCopy())
.hasSize(1)
- .allSatisfy(subsegment -> {
- assertThat(subsegment.getAnnotations())
- .hasSize(2)
- .containsEntry("ColdStart", true)
- .containsEntry("Service", "lambdaHandler");
-
- assertThat(subsegment.getMetadata())
- .isEmpty();
- });
+ .allSatisfy(subsegment ->
+ {
+ assertThat(subsegment.getAnnotations())
+ .hasSize(2)
+ .containsEntry("ColdStart", true)
+ .containsEntry("Service", "lambdaHandler");
+
+ assertThat(subsegment.getMetadata())
+ .isEmpty();
+ });
}
}
@@ -300,16 +308,17 @@ void shouldCaptureTracesIfExplicitlyEnabledAndEnvironmentVariableIsDisabled() {
assertThat(AWSXRay.getTraceEntity().getSubsegmentsCopy())
.hasSize(1)
- .allSatisfy(subsegment -> {
- assertThat(subsegment.getAnnotations())
- .hasSize(2)
- .containsEntry("ColdStart", true)
- .containsEntry("Service", "lambdaHandler");
-
- assertThat(subsegment.getMetadata())
- .hasSize(1)
- .containsKey("lambdaHandler");
- });
+ .allSatisfy(subsegment ->
+ {
+ assertThat(subsegment.getAnnotations())
+ .hasSize(2)
+ .containsEntry("ColdStart", true)
+ .containsEntry("Service", "lambdaHandler");
+
+ assertThat(subsegment.getMetadata())
+ .hasSize(1)
+ .containsKey("lambdaHandler");
+ });
}
}
@@ -324,14 +333,16 @@ void shouldCaptureTracesForSelfReferencingReturnTypesViaCustomMapper() {
assertThat(AWSXRay.getTraceEntity().getSubsegmentsCopy())
.hasSize(1)
- .allSatisfy(subsegment -> {
- assertThat(subsegment.getMetadata())
- .hasSize(1)
- .containsKey("lambdaHandler");
+ .allSatisfy(subsegment ->
+ {
+ assertThat(subsegment.getMetadata())
+ .hasSize(1)
+ .containsKey("lambdaHandler");
- assertThat(subsegment.getMetadata().get("lambdaHandler"))
- .hasFieldOrPropertyWithValue("handleRequest response", "{\"name\":\"parent\",\"c\":{\"name\":\"child\",\"p\":\"parent\"}}");
- });
+ assertThat(subsegment.getMetadata().get("lambdaHandler"))
+ .hasFieldOrPropertyWithValue("handleRequest response",
+ "{\"name\":\"parent\",\"c\":{\"name\":\"child\",\"p\":\"parent\"}}");
+ });
assertThatNoException().isThrownBy(AWSXRay::endSegment);
@@ -354,16 +365,17 @@ void shouldCaptureTracesIfExplicitlyEnabledBothAndEnvironmentVariableIsDisabled(
assertThat(AWSXRay.getTraceEntity().getSubsegmentsCopy())
.hasSize(1)
- .allSatisfy(subsegment -> {
- assertThat(subsegment.getAnnotations())
- .hasSize(2)
- .containsEntry("ColdStart", true)
- .containsEntry("Service", "lambdaHandler");
-
- assertThat(subsegment.getMetadata())
- .hasSize(1)
- .containsKey("lambdaHandler");
- });
+ .allSatisfy(subsegment ->
+ {
+ assertThat(subsegment.getAnnotations())
+ .hasSize(2)
+ .containsEntry("ColdStart", true)
+ .containsEntry("Service", "lambdaHandler");
+
+ assertThat(subsegment.getMetadata())
+ .hasSize(1)
+ .containsKey("lambdaHandler");
+ });
}
}
@@ -384,15 +396,16 @@ void shouldNotCaptureTracesWithExceptionMetaDataIfDisabledViaEnvironmentVariable
assertThat(AWSXRay.getTraceEntity().getSubsegmentsCopy())
.hasSize(1)
- .allSatisfy(subsegment -> {
- assertThat(subsegment.getAnnotations())
- .hasSize(2)
- .containsEntry("ColdStart", true)
- .containsEntry("Service", "lambdaHandler");
-
- assertThat(subsegment.getMetadata())
- .isEmpty();
- });
+ .allSatisfy(subsegment ->
+ {
+ assertThat(subsegment.getAnnotations())
+ .hasSize(2)
+ .containsEntry("ColdStart", true)
+ .containsEntry("Service", "lambdaHandler");
+
+ assertThat(subsegment.getMetadata())
+ .isEmpty();
+ });
}
}
@@ -410,20 +423,21 @@ void shouldCaptureTracesWithExceptionMetaDataEnabledExplicitlyAndEnvironmentVari
assertThat(AWSXRay.getTraceEntity().getSubsegmentsCopy())
.hasSize(1)
- .allSatisfy(subsegment -> {
- assertThat(subsegment.getAnnotations())
- .hasSize(2)
- .containsEntry("ColdStart", true)
- .containsEntry("Service", "lambdaHandler");
-
- assertThat(subsegment.getMetadata())
- .hasSize(1)
- .containsKey("lambdaHandler");
-
- assertThat(subsegment.getMetadata().get("lambdaHandler"))
- .satisfies(stringObjectMap -> assertThat(stringObjectMap)
- .containsEntry("handleRequest error", exception));
- });
+ .allSatisfy(subsegment ->
+ {
+ assertThat(subsegment.getAnnotations())
+ .hasSize(2)
+ .containsEntry("ColdStart", true)
+ .containsEntry("Service", "lambdaHandler");
+
+ assertThat(subsegment.getMetadata())
+ .hasSize(1)
+ .containsKey("lambdaHandler");
+
+ assertThat(subsegment.getMetadata().get("lambdaHandler"))
+ .satisfies(stringObjectMap -> assertThat(stringObjectMap)
+ .containsEntry("handleRequest error", exception));
+ });
}
}
diff --git a/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/nonhandler/PowerToolNonHandler.java b/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/nonhandler/PowerToolNonHandler.java
index 309eb5598..48ffc93ae 100644
--- a/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/nonhandler/PowerToolNonHandler.java
+++ b/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/nonhandler/PowerToolNonHandler.java
@@ -1,3 +1,17 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.tracing.nonhandler;
import software.amazon.lambda.powertools.tracing.Tracing;
diff --git a/powertools-validation/pom.xml b/powertools-validation/pom.xml
index 1469183ef..daec3aa99 100644
--- a/powertools-validation/pom.xml
+++ b/powertools-validation/pom.xml
@@ -1,4 +1,18 @@
+
+
@@ -119,4 +133,13 @@
+
+
+
+ org.apache.maven.plugins
+ maven-checkstyle-plugin
+
+
+
+
\ No newline at end of file
diff --git a/powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/Validation.java b/powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/Validation.java
index 68260cb47..f41364c1a 100644
--- a/powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/Validation.java
+++ b/powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/Validation.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,11 +11,13 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.validation;
+import static com.networknt.schema.SpecVersion.VersionFlag.V7;
+
import com.amazonaws.services.lambda.runtime.Context;
import com.networknt.schema.SpecVersion.VersionFlag;
-
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.annotation.ElementType;
@@ -23,8 +25,6 @@
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
-import static com.networknt.schema.SpecVersion.VersionFlag.V7;
-
/**
* {@link Validation} is used to specify that the annotated method input and/or output needs to be valid.
*
diff --git a/powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/ValidationConfig.java b/powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/ValidationConfig.java
index b29adf8d7..baf5e2465 100644
--- a/powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/ValidationConfig.java
+++ b/powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/ValidationConfig.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,6 +11,7 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.validation;
import com.fasterxml.jackson.databind.JsonNode;
@@ -26,7 +27,7 @@
/**
* Use this if you need to customize some part of the JSON Schema validation
* (eg. specification version, Jackson ObjectMapper, or adding functions to JMESPath).
- *
+ *
* For everything but the validation features (factory, schemaVersion), {@link ValidationConfig}
* is just a wrapper of {@link JsonConfig}.
*/
@@ -62,7 +63,7 @@ public void setSchemaVersion(SpecVersion.VersionFlag version) {
* {@link Base64Function} and {@link Base64GZipFunction} are already built-in.
*
* @param function the function to add
- * @param Must extend {@link BaseFunction}
+ * @param Must extend {@link BaseFunction}
*/
public void addFunction(T function) {
JsonConfig.get().addFunction(function);
diff --git a/powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/ValidationException.java b/powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/ValidationException.java
index 2d3e1b350..fd4cb66a6 100644
--- a/powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/ValidationException.java
+++ b/powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/ValidationException.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,6 +11,7 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.validation;
public class ValidationException extends RuntimeException {
diff --git a/powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/ValidationUtils.java b/powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/ValidationUtils.java
index 3c2322edc..4eecb3ab5 100644
--- a/powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/ValidationUtils.java
+++ b/powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/ValidationUtils.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,6 +11,7 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.validation;
import com.amazonaws.services.lambda.runtime.serialization.PojoSerializer;
@@ -22,8 +23,6 @@
import com.networknt.schema.JsonSchema;
import com.networknt.schema.ValidationMessage;
import io.burt.jmespath.Expression;
-import software.amazon.lambda.powertools.validation.internal.ValidationAspect;
-
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.Collections;
@@ -31,6 +30,7 @@
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
+import software.amazon.lambda.powertools.validation.internal.ValidationAspect;
/**
* Validation utility, used to manually validate Json against Json Schema
@@ -68,7 +68,8 @@ public static void validate(Object obj, JsonSchema jsonSchema, String envelope)
}
JsonNode subNode;
try {
- PojoSerializer pojoSerializer = LambdaEventSerializers.serializerFor(obj.getClass(), ClassLoader.getSystemClassLoader());
+ PojoSerializer pojoSerializer =
+ LambdaEventSerializers.serializerFor(obj.getClass(), ClassLoader.getSystemClassLoader());
ByteArrayOutputStream out = new ByteArrayOutputStream();
pojoSerializer.toJson(obj, out);
JsonNode jsonNode = ValidationConfig.get().getObjectMapper().readTree(out.toString("UTF-8"));
@@ -89,7 +90,8 @@ public static void validate(Object obj, JsonSchema jsonSchema, String envelope)
try {
validate(subNode.asText(), jsonSchema);
} catch (ValidationException e) {
- throw new ValidationException("Invalid format for '" + envelope + "': 'STRING' and no JSON found in it.");
+ throw new ValidationException(
+ "Invalid format for '" + envelope + "': 'STRING' and no JSON found in it.");
}
} else {
throw new ValidationException("Invalid format for '" + envelope + "': '" + subNode.getNodeType() + "'");
@@ -208,9 +210,11 @@ public static void validate(JsonNode jsonNode, JsonSchema jsonSchema) throws Val
if (!validationMessages.isEmpty()) {
String message;
try {
- message = ValidationConfig.get().getObjectMapper().writeValueAsString(new ValidationErrors(validationMessages));
+ message = ValidationConfig.get().getObjectMapper()
+ .writeValueAsString(new ValidationErrors(validationMessages));
} catch (JsonProcessingException e) {
- message = validationMessages.stream().map(ValidationMessage::getMessage).collect(Collectors.joining(", "));
+ message = validationMessages.stream().map(ValidationMessage::getMessage)
+ .collect(Collectors.joining(", "));
}
throw new ValidationException(message);
}
@@ -255,7 +259,8 @@ private static JsonSchema createJsonSchema(String schema) {
jsonSchema = ValidationConfig.get().getFactory().getSchema(schemaStream);
} catch (Exception e) {
- throw new IllegalArgumentException("'" + schema + "' is invalid, verify '" + filePath + "' is in your classpath");
+ throw new IllegalArgumentException(
+ "'" + schema + "' is invalid, verify '" + filePath + "' is in your classpath");
}
} else {
jsonSchema = ValidationConfig.get().getFactory().getSchema(schema);
@@ -270,7 +275,8 @@ private static void validateSchema(String schema, JsonSchema jsonSchema) {
validate(jsonSchema.getSchemaNode(),
getJsonSchema("classpath:/schemas/meta_schema_" + version));
} catch (ValidationException ve) {
- throw new IllegalArgumentException("The schema " + schema + " is not valid, it does not respect the specification " + version, ve);
+ throw new IllegalArgumentException(
+ "The schema " + schema + " is not valid, it does not respect the specification " + version, ve);
}
}
diff --git a/powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/internal/ValidationAspect.java b/powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/internal/ValidationAspect.java
index e659abbeb..6055f8d58 100644
--- a/powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/internal/ValidationAspect.java
+++ b/powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/internal/ValidationAspect.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,8 +11,17 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.validation.internal;
+import static com.networknt.schema.SpecVersion.VersionFlag.V201909;
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor.placedOnRequestHandler;
+import static software.amazon.lambda.powertools.utilities.jmespath.Base64Function.decode;
+import static software.amazon.lambda.powertools.utilities.jmespath.Base64GZipFunction.decompress;
+import static software.amazon.lambda.powertools.validation.ValidationUtils.getJsonSchema;
+import static software.amazon.lambda.powertools.validation.ValidationUtils.validate;
+
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent;
import com.amazonaws.services.lambda.runtime.events.APIGatewayV2HTTPEvent;
@@ -43,14 +52,6 @@
import software.amazon.lambda.powertools.validation.Validation;
import software.amazon.lambda.powertools.validation.ValidationConfig;
-import static com.networknt.schema.SpecVersion.VersionFlag.V201909;
-import static java.nio.charset.StandardCharsets.UTF_8;
-import static software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor.placedOnRequestHandler;
-import static software.amazon.lambda.powertools.utilities.jmespath.Base64Function.decode;
-import static software.amazon.lambda.powertools.utilities.jmespath.Base64GZipFunction.decompress;
-import static software.amazon.lambda.powertools.validation.ValidationUtils.getJsonSchema;
-import static software.amazon.lambda.powertools.validation.ValidationUtils.validate;
-
/**
* Aspect for {@link Validation} annotation
*/
@@ -108,27 +109,33 @@ public Object around(ProceedingJoinPoint pjp,
validate(event.getResourceProperties(), inboundJsonSchema);
} else if (obj instanceof KinesisEvent) {
KinesisEvent event = (KinesisEvent) obj;
- event.getRecords().forEach(record -> validate(decode(record.getKinesis().getData()), inboundJsonSchema));
+ event.getRecords()
+ .forEach(record -> validate(decode(record.getKinesis().getData()), inboundJsonSchema));
} else if (obj instanceof KinesisFirehoseEvent) {
KinesisFirehoseEvent event = (KinesisFirehoseEvent) obj;
event.getRecords().forEach(record -> validate(decode(record.getData()), inboundJsonSchema));
} else if (obj instanceof KafkaEvent) {
KafkaEvent event = (KafkaEvent) obj;
- event.getRecords().forEach((s, records) -> records.forEach(record -> validate(decode(record.getValue()), inboundJsonSchema)));
+ event.getRecords().forEach((s, records) -> records.forEach(
+ record -> validate(decode(record.getValue()), inboundJsonSchema)));
} else if (obj instanceof ActiveMQEvent) {
ActiveMQEvent event = (ActiveMQEvent) obj;
event.getMessages().forEach(record -> validate(decode(record.getData()), inboundJsonSchema));
} else if (obj instanceof RabbitMQEvent) {
RabbitMQEvent event = (RabbitMQEvent) obj;
- event.getRmqMessagesByQueue().forEach((s, records) -> records.forEach(record -> validate(decode(record.getData()), inboundJsonSchema)));
+ event.getRmqMessagesByQueue().forEach((s, records) -> records.forEach(
+ record -> validate(decode(record.getData()), inboundJsonSchema)));
} else if (obj instanceof KinesisAnalyticsFirehoseInputPreprocessingEvent) {
- KinesisAnalyticsFirehoseInputPreprocessingEvent event = (KinesisAnalyticsFirehoseInputPreprocessingEvent) obj;
+ KinesisAnalyticsFirehoseInputPreprocessingEvent event =
+ (KinesisAnalyticsFirehoseInputPreprocessingEvent) obj;
event.getRecords().forEach(record -> validate(decode(record.getData()), inboundJsonSchema));
} else if (obj instanceof KinesisAnalyticsStreamsInputPreprocessingEvent) {
- KinesisAnalyticsStreamsInputPreprocessingEvent event = (KinesisAnalyticsStreamsInputPreprocessingEvent) obj;
+ KinesisAnalyticsStreamsInputPreprocessingEvent event =
+ (KinesisAnalyticsStreamsInputPreprocessingEvent) obj;
event.getRecords().forEach(record -> validate(decode(record.getData()), inboundJsonSchema));
} else {
- LOG.warn("Unhandled event type {}, please use the 'envelope' parameter to specify what to validate", obj.getClass().getName());
+ LOG.warn("Unhandled event type {}, please use the 'envelope' parameter to specify what to validate",
+ obj.getClass().getName());
}
}
}
@@ -151,10 +158,12 @@ public Object around(ProceedingJoinPoint pjp,
ApplicationLoadBalancerResponseEvent response = (ApplicationLoadBalancerResponseEvent) result;
validate(response.getBody(), outboundJsonSchema);
} else if (result instanceof KinesisAnalyticsInputPreprocessingResponse) {
- KinesisAnalyticsInputPreprocessingResponse response = (KinesisAnalyticsInputPreprocessingResponse) result;
+ KinesisAnalyticsInputPreprocessingResponse response =
+ (KinesisAnalyticsInputPreprocessingResponse) result;
response.getRecords().forEach(record -> validate(decode(record.getData()), outboundJsonSchema));
} else {
- LOG.warn("Unhandled response type {}, please use the 'envelope' parameter to specify what to validate", result.getClass().getName());
+ LOG.warn("Unhandled response type {}, please use the 'envelope' parameter to specify what to validate",
+ result.getClass().getName());
}
}
diff --git a/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/ValidationUtilsTest.java b/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/ValidationUtilsTest.java
index 6669e46b1..86dddd3e2 100644
--- a/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/ValidationUtilsTest.java
+++ b/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/ValidationUtilsTest.java
@@ -1,25 +1,38 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
package software.amazon.lambda.powertools.validation;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
+import static org.assertj.core.api.Assertions.assertThatNoException;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static software.amazon.lambda.powertools.validation.ValidationUtils.getJsonSchema;
+import static software.amazon.lambda.powertools.validation.ValidationUtils.validate;
+
import com.fasterxml.jackson.databind.JsonNode;
import com.networknt.schema.JsonSchema;
import com.networknt.schema.SpecVersion;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import software.amazon.lambda.powertools.validation.model.Basket;
import software.amazon.lambda.powertools.validation.model.MyCustomEvent;
import software.amazon.lambda.powertools.validation.model.Product;
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.Map;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
-import static org.assertj.core.api.Assertions.assertThatNoException;
-import static org.assertj.core.api.Assertions.assertThatThrownBy;
-import static software.amazon.lambda.powertools.validation.ValidationUtils.getJsonSchema;
-import static software.amazon.lambda.powertools.validation.ValidationUtils.validate;
-
public class ValidationUtilsTest {
private String schemaString = "classpath:/schema_v7.json";
@@ -43,16 +56,18 @@ public void testLoadSchemaV7KO() {
ValidationConfig.get().setSchemaVersion(SpecVersion.VersionFlag.V7);
assertThatThrownBy(() -> getJsonSchema("classpath:/schema_v7_ko.json", true))
.isInstanceOf(IllegalArgumentException.class)
- .hasMessage("The schema classpath:/schema_v7_ko.json is not valid, it does not respect the specification V7");
+ .hasMessage(
+ "The schema classpath:/schema_v7_ko.json is not valid, it does not respect the specification V7");
}
@Test
public void testLoadMetaSchema_NoValidation() {
ValidationConfig.get().setSchemaVersion(SpecVersion.VersionFlag.V7);
- assertThatNoException().isThrownBy(() -> {
- getJsonSchema("classpath:/schema_v7_ko.json", false);
- });
+ assertThatNoException().isThrownBy(() ->
+ {
+ getJsonSchema("classpath:/schema_v7_ko.json", false);
+ });
}
@Test
@@ -99,16 +114,19 @@ public void testLoadSchemaNotFound() {
@Test
public void testValidateJsonNodeOK() throws IOException {
- JsonNode node = ValidationConfig.get().getObjectMapper().readTree(this.getClass().getResourceAsStream("/json_ok.json"));
+ JsonNode node =
+ ValidationConfig.get().getObjectMapper().readTree(this.getClass().getResourceAsStream("/json_ok.json"));
- assertThatNoException().isThrownBy(() -> {
- validate(node, schemaString);
- });
+ assertThatNoException().isThrownBy(() ->
+ {
+ validate(node, schemaString);
+ });
}
@Test
public void testValidateJsonNodeKO() throws IOException {
- JsonNode node = ValidationConfig.get().getObjectMapper().readTree(this.getClass().getResourceAsStream("/json_ko.json"));
+ JsonNode node =
+ ValidationConfig.get().getObjectMapper().readTree(this.getClass().getResourceAsStream("/json_ko.json"));
assertThatExceptionOfType(ValidationException.class).isThrownBy(() -> validate(node, schema));
}
@@ -121,9 +139,10 @@ public void testValidateMapOK() {
map.put("name", "FooBar XY");
map.put("price", 258);
- assertThatNoException().isThrownBy(() -> {
- validate(map, schemaString);
- });
+ assertThatNoException().isThrownBy(() ->
+ {
+ validate(map, schemaString);
+ });
}
@Test
@@ -147,9 +166,10 @@ public void testValidateMapNotValidJsonObject() {
public void testValidateStringOK() {
String json = "{\n \"id\": 43242,\n \"name\": \"FooBar XY\",\n \"price\": 258\n}";
- assertThatNoException().isThrownBy(() -> {
- validate(json, schemaString);
- });
+ assertThatNoException().isThrownBy(() ->
+ {
+ validate(json, schemaString);
+ });
}
@Test
@@ -163,9 +183,10 @@ public void testValidateStringKO() {
public void testValidateObjectOK() {
Product product = new Product(42, "FooBar", 42);
- assertThatNoException().isThrownBy(() -> {
- validate(product, schemaString);
- });
+ assertThatNoException().isThrownBy(() ->
+ {
+ validate(product, schemaString);
+ });
}
@Test
@@ -189,9 +210,10 @@ public void testValidateSubObjectOK() {
basket.add(product2);
MyCustomEvent event = new MyCustomEvent(basket);
- assertThatNoException().isThrownBy(() -> {
- validate(event, schemaString, "basket.products[0]");
- });
+ assertThatNoException().isThrownBy(() ->
+ {
+ validate(event, schemaString, "basket.products[0]");
+ });
}
@Test
@@ -203,7 +225,8 @@ public void testValidateSubObjectKO() {
basket.add(product2);
MyCustomEvent event = new MyCustomEvent(basket);
- assertThatExceptionOfType(ValidationException.class).isThrownBy(() -> validate(event, schema, "basket.products[0]"));
+ assertThatExceptionOfType(ValidationException.class).isThrownBy(
+ () -> validate(event, schema, "basket.products[0]"));
}
@Test
@@ -227,7 +250,8 @@ public void testValidateSubObjectListKO() {
basket.add(product2);
MyCustomEvent event = new MyCustomEvent(basket);
- assertThatExceptionOfType(ValidationException.class).isThrownBy(() -> validate(event, schema, "basket.products[*]"));
+ assertThatExceptionOfType(ValidationException.class).isThrownBy(
+ () -> validate(event, schema, "basket.products[*]"));
}
@Test
diff --git a/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/handlers/GenericSchemaV7Handler.java b/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/handlers/GenericSchemaV7Handler.java
index 1c64e7da1..5b8343d1b 100644
--- a/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/handlers/GenericSchemaV7Handler.java
+++ b/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/handlers/GenericSchemaV7Handler.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,6 +11,7 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.validation.handlers;
import com.amazonaws.services.lambda.runtime.Context;
diff --git a/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/handlers/MyCustomEventHandler.java b/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/handlers/MyCustomEventHandler.java
index 07954ddff..6989cdbb6 100644
--- a/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/handlers/MyCustomEventHandler.java
+++ b/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/handlers/MyCustomEventHandler.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,6 +11,7 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.validation.handlers;
import com.amazonaws.services.lambda.runtime.Context;
diff --git a/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/handlers/SQSWithCustomEnvelopeHandler.java b/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/handlers/SQSWithCustomEnvelopeHandler.java
index 9eb96c0e8..c49ebff69 100644
--- a/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/handlers/SQSWithCustomEnvelopeHandler.java
+++ b/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/handlers/SQSWithCustomEnvelopeHandler.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,6 +11,7 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.validation.handlers;
import com.amazonaws.services.lambda.runtime.Context;
diff --git a/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/handlers/SQSWithWrongEnvelopeHandler.java b/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/handlers/SQSWithWrongEnvelopeHandler.java
index c1859f29a..d3f46d4ad 100644
--- a/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/handlers/SQSWithWrongEnvelopeHandler.java
+++ b/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/handlers/SQSWithWrongEnvelopeHandler.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,6 +11,7 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.validation.handlers;
import com.amazonaws.services.lambda.runtime.Context;
diff --git a/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/handlers/ValidationInboundStringHandler.java b/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/handlers/ValidationInboundStringHandler.java
index 2e62ba88d..fd5692884 100644
--- a/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/handlers/ValidationInboundStringHandler.java
+++ b/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/handlers/ValidationInboundStringHandler.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,6 +11,7 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.validation.handlers;
import com.amazonaws.services.lambda.runtime.Context;
diff --git a/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/internal/ResponseEventsArgumentsProvider.java b/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/internal/ResponseEventsArgumentsProvider.java
index 9df0ff508..b634d6f8c 100644
--- a/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/internal/ResponseEventsArgumentsProvider.java
+++ b/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/internal/ResponseEventsArgumentsProvider.java
@@ -11,6 +11,7 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.validation.internal;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent;
@@ -18,15 +19,14 @@
import com.amazonaws.services.lambda.runtime.events.APIGatewayV2WebSocketResponse;
import com.amazonaws.services.lambda.runtime.events.ApplicationLoadBalancerResponseEvent;
import com.amazonaws.services.lambda.runtime.events.KinesisAnalyticsInputPreprocessingResponse;
-import org.junit.jupiter.api.extension.ExtensionContext;
-import org.junit.jupiter.params.provider.Arguments;
-import org.junit.jupiter.params.provider.ArgumentsProvider;
-
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;
+import org.junit.jupiter.api.extension.ExtensionContext;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.ArgumentsProvider;
public class ResponseEventsArgumentsProvider implements ArgumentsProvider {
@@ -49,9 +49,11 @@ public Stream extends Arguments> provideArguments(ExtensionContext context) {
KinesisAnalyticsInputPreprocessingResponse kaipResponse = new KinesisAnalyticsInputPreprocessingResponse();
List records = new ArrayList();
ByteBuffer buffer = ByteBuffer.wrap(body.getBytes(StandardCharsets.UTF_8));
- records.add(new KinesisAnalyticsInputPreprocessingResponse.Record("1", KinesisAnalyticsInputPreprocessingResponse.Result.Ok, buffer));
+ records.add(new KinesisAnalyticsInputPreprocessingResponse.Record("1",
+ KinesisAnalyticsInputPreprocessingResponse.Result.Ok, buffer));
kaipResponse.setRecords(records);
- return Stream.of(apiGWProxyResponseEvent, apiGWV2HTTPResponse, apiGWV2WebSocketResponse, albResponseEvent, kaipResponse).map(Arguments::of);
+ return Stream.of(apiGWProxyResponseEvent, apiGWV2HTTPResponse, apiGWV2WebSocketResponse, albResponseEvent,
+ kaipResponse).map(Arguments::of);
}
}
diff --git a/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/internal/ValidationAspectTest.java b/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/internal/ValidationAspectTest.java
index 63e93c3ac..9ea596ff3 100644
--- a/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/internal/ValidationAspectTest.java
+++ b/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/internal/ValidationAspectTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,8 +11,14 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.validation.internal;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
+import static org.assertj.core.api.Assertions.assertThatNoException;
+import static org.mockito.Mockito.when;
+
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent;
@@ -34,6 +40,8 @@
import com.amazonaws.services.lambda.runtime.serialization.PojoSerializer;
import com.amazonaws.services.lambda.runtime.serialization.events.LambdaEventSerializers;
import com.networknt.schema.SpecVersion;
+import java.io.IOException;
+import java.util.stream.Stream;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.junit.jupiter.api.BeforeEach;
@@ -53,14 +61,6 @@
import software.amazon.lambda.powertools.validation.handlers.ValidationInboundStringHandler;
import software.amazon.lambda.powertools.validation.model.MyCustomEvent;
-import java.io.IOException;
-import java.util.stream.Stream;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
-import static org.assertj.core.api.Assertions.assertThatNoException;
-import static org.mockito.Mockito.when;
-
public class ValidationAspectTest {
@@ -109,9 +109,10 @@ public void testValidateOutboundJsonSchema(Object object) throws Throwable {
when(validation.inboundSchema()).thenReturn("");
when(validation.outboundSchema()).thenReturn("classpath:/schema_v7.json");
- assertThatExceptionOfType(ValidationException.class).isThrownBy(() -> {
- validationAspect.around(pjp, validation);
- });
+ assertThatExceptionOfType(ValidationException.class).isThrownBy(() ->
+ {
+ validationAspect.around(pjp, validation);
+ });
}
@Test
@@ -184,7 +185,8 @@ public void validate_inputKO_schemaInString_shouldThrowValidationException() {
@Test
public void validate_SQS() {
- PojoSerializer pojoSerializer = LambdaEventSerializers.serializerFor(SQSEvent.class, ClassLoader.getSystemClassLoader());
+ PojoSerializer pojoSerializer =
+ LambdaEventSerializers.serializerFor(SQSEvent.class, ClassLoader.getSystemClassLoader());
SQSEvent event = pojoSerializer.fromJson(this.getClass().getResourceAsStream("/sqs.json"));
GenericSchemaV7Handler handler = new GenericSchemaV7Handler();
@@ -193,7 +195,8 @@ public void validate_SQS() {
@Test
public void validate_SQS_CustomEnvelopeTakePrecedence() {
- PojoSerializer pojoSerializer = LambdaEventSerializers.serializerFor(SQSEvent.class, ClassLoader.getSystemClassLoader());
+ PojoSerializer pojoSerializer =
+ LambdaEventSerializers.serializerFor(SQSEvent.class, ClassLoader.getSystemClassLoader());
SQSEvent event = pojoSerializer.fromJson(this.getClass().getResourceAsStream("/sqs_message.json"));
SQSWithCustomEnvelopeHandler handler = new SQSWithCustomEnvelopeHandler();
@@ -202,7 +205,8 @@ public void validate_SQS_CustomEnvelopeTakePrecedence() {
@Test
public void validate_SQS_WrongEnvelope_shouldThrowValidationException() {
- PojoSerializer pojoSerializer = LambdaEventSerializers.serializerFor(SQSEvent.class, ClassLoader.getSystemClassLoader());
+ PojoSerializer pojoSerializer =
+ LambdaEventSerializers.serializerFor(SQSEvent.class, ClassLoader.getSystemClassLoader());
SQSEvent event = pojoSerializer.fromJson(this.getClass().getResourceAsStream("/sqs_message.json"));
SQSWithWrongEnvelopeHandler handler = new SQSWithWrongEnvelopeHandler();
@@ -211,7 +215,8 @@ public void validate_SQS_WrongEnvelope_shouldThrowValidationException() {
@Test
public void validate_Kinesis() {
- PojoSerializer pojoSerializer = LambdaEventSerializers.serializerFor(KinesisEvent.class, ClassLoader.getSystemClassLoader());
+ PojoSerializer pojoSerializer =
+ LambdaEventSerializers.serializerFor(KinesisEvent.class, ClassLoader.getSystemClassLoader());
KinesisEvent event = pojoSerializer.fromJson(this.getClass().getResourceAsStream("/kinesis.json"));
GenericSchemaV7Handler handler = new GenericSchemaV7Handler();
@@ -221,7 +226,8 @@ public void validate_Kinesis() {
@ParameterizedTest
@MethodSource("provideEventAndEventType")
public void validateEEvent(String jsonResource, Class eventClass) throws IOException {
- Object event = ValidationConfig.get().getObjectMapper().readValue(this.getClass().getResourceAsStream(jsonResource), eventClass);
+ Object event = ValidationConfig.get().getObjectMapper()
+ .readValue(this.getClass().getResourceAsStream(jsonResource), eventClass);
GenericSchemaV7Handler handler = new GenericSchemaV7Handler();
assertThat(handler.handleRequest(event, context)).isEqualTo("OK");
diff --git a/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/model/Basket.java b/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/model/Basket.java
index 398f67265..881090bdc 100644
--- a/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/model/Basket.java
+++ b/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/model/Basket.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,6 +11,7 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.validation.model;
import java.util.ArrayList;
diff --git a/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/model/MyCustomEvent.java b/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/model/MyCustomEvent.java
index 12f3f99ca..04c7c3a4a 100644
--- a/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/model/MyCustomEvent.java
+++ b/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/model/MyCustomEvent.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,6 +11,7 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.validation.model;
public class MyCustomEvent {
diff --git a/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/model/Product.java b/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/model/Product.java
index fde888b76..93f5ab39f 100644
--- a/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/model/Product.java
+++ b/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/model/Product.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 Amazon.com, Inc. or its affiliates.
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
@@ -11,6 +11,7 @@
* limitations under the License.
*
*/
+
package software.amazon.lambda.powertools.validation.model;
public class Product {
From 8548397747be3dfc70eea10b7a3084f6ce15c637 Mon Sep 17 00:00:00 2001
From: Jerome Van Der Linden
Date: Thu, 27 Jul 2023 11:39:50 +0200
Subject: [PATCH 053/666] few formatting things
---
.../test/java/software/amazon/lambda/powertools/TracingE2ET.java | 1 -
.../powertools/logging/internal/AbstractJacksonLayoutCopy.java | 1 +
.../lambda/powertools/parameters/internal/AnotherObject.java | 1 +
.../powertools/parameters/transform/ObjectToDeserialize.java | 1 +
.../software/amazon/lambda/powertools/utilities/JsonConfig.java | 1 +
5 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/TracingE2ET.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/TracingE2ET.java
index cd4a21df4..043de5494 100644
--- a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/TracingE2ET.java
+++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/TracingE2ET.java
@@ -33,7 +33,6 @@
public class TracingE2ET {
private static final String service = "TracingE2EService_" + UUID.randomUUID();
- // "TracingE2EService_e479fb27-422b-4107-9f8c-086c62e1cd12";
private static Infrastructure infrastructure;
private static String functionName;
diff --git a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/AbstractJacksonLayoutCopy.java b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/AbstractJacksonLayoutCopy.java
index f98e2ee46..17d09729f 100644
--- a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/AbstractJacksonLayoutCopy.java
+++ b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/AbstractJacksonLayoutCopy.java
@@ -56,6 +56,7 @@ abstract class AbstractJacksonLayoutCopy extends AbstractStringLayout {
protected final boolean complete;
protected final boolean includeNullDelimiter;
protected final ResolvableKeyValuePair[] additionalFields;
+
@Deprecated
protected AbstractJacksonLayoutCopy(final Configuration config, final ObjectWriter objectWriter,
final Charset charset,
diff --git a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/internal/AnotherObject.java b/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/internal/AnotherObject.java
index 074a08844..5ce2b355f 100644
--- a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/internal/AnotherObject.java
+++ b/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/internal/AnotherObject.java
@@ -18,6 +18,7 @@ public class AnotherObject {
private String another;
private int object;
+
public AnotherObject() {
}
diff --git a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/transform/ObjectToDeserialize.java b/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/transform/ObjectToDeserialize.java
index 1d09fbeda..8b30858fd 100644
--- a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/transform/ObjectToDeserialize.java
+++ b/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/transform/ObjectToDeserialize.java
@@ -19,6 +19,7 @@ public class ObjectToDeserialize {
private String foo;
private int bar;
private long baz;
+
public ObjectToDeserialize() {
}
diff --git a/powertools-serialization/src/main/java/software/amazon/lambda/powertools/utilities/JsonConfig.java b/powertools-serialization/src/main/java/software/amazon/lambda/powertools/utilities/JsonConfig.java
index f5a6d8c11..baa6a0367 100644
--- a/powertools-serialization/src/main/java/software/amazon/lambda/powertools/utilities/JsonConfig.java
+++ b/powertools-serialization/src/main/java/software/amazon/lambda/powertools/utilities/JsonConfig.java
@@ -38,6 +38,7 @@ public class JsonConfig {
.withFunctionRegistry(customFunctions)
.build();
private JmesPath jmesPath = new JacksonRuntime(configuration, getObjectMapper());
+
private JsonConfig() {
}
From 0671bbeaf2366502fb603ae6c79dbb1865bb2067 Mon Sep 17 00:00:00 2001
From: Alexey Soshin
Date: Thu, 27 Jul 2023 12:42:02 +0100
Subject: [PATCH 054/666] Adding external examples from
https://github.com/aws/aws-sam-cli-app-templates (#1318)
---
examples/README.md | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/examples/README.md b/examples/README.md
index 1869b4e8f..b44ff2433 100644
--- a/examples/README.md
+++ b/examples/README.md
@@ -3,7 +3,7 @@
This directory holds example projects demoing different components of the Powertools for AWS Lambda (Java).
Each example can be copied from its subdirectory and used independently of the rest of this repository.
-## The Examples
+## Examples
* [powertools-examples-core](powertools-examples-core) - Demonstrates the core logging, tracing, and metrics modules
* [powertools-examples-idempotency](powertools-examples-idempotency) - An idempotent HTTP API
@@ -51,6 +51,17 @@ The first command will build the source of your application. The second command
You can find your API Gateway Endpoint URL in the output values displayed after deployment.
+### External examples
+
+You can find more examples in the https://github.com/aws/aws-sam-cli-app-templates project:
+
+* [Java 8 + Maven](https://github.com/aws/aws-sam-cli-app-templates/tree/master/java8/hello-pt-maven)
+* [Java 8 on Amazon Linux 2 + Maven](https://github.com/aws/aws-sam-cli-app-templates/tree/master/java8.al2/hello-pt-maven)
+* [Java 11 + Maven](https://github.com/aws/aws-sam-cli-app-templates/tree/master/java11/hello-pt-maven)
+* [Java 17 + Maven](https://github.com/aws/aws-sam-cli-app-templates/tree/master/java17/hello-pt-maven)
+* [Java 17 + Gradle](https://github.com/aws/aws-sam-cli-app-templates/tree/master/java17/hello-pt-gradle)
+
+
### SAM - Other Tools
If you prefer to use an integrated development environment (IDE) to build and test your application, you can use the AWS Toolkit.
From 661100c14b712b940d8af85f7623525012ae9466 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Thu, 27 Jul 2023 14:07:41 +0200
Subject: [PATCH 055/666] build(deps): bump com.puppycrawl.tools:checkstyle
from 10.9.1 to 10.12.1 (#1320)
Bumps [com.puppycrawl.tools:checkstyle](https://github.com/checkstyle/checkstyle) from 10.9.1 to 10.12.1.
- [Release notes](https://github.com/checkstyle/checkstyle/releases)
- [Commits](https://github.com/checkstyle/checkstyle/compare/checkstyle-10.9.1...checkstyle-10.12.1)
---
updated-dependencies:
- dependency-name: com.puppycrawl.tools:checkstyle
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pom.xml b/pom.xml
index 7744913fd..e8f85e3ff 100644
--- a/pom.xml
+++ b/pom.xml
@@ -564,7 +564,7 @@
com.puppycrawl.toolscheckstyle
- 10.9.1
+ 10.12.1
From 3dc84051a1a32cf90b8e3d716fe608e707ee4c16 Mon Sep 17 00:00:00 2001
From: Grzegorz Kozub
Date: Fri, 28 Jul 2023 08:56:43 +0200
Subject: [PATCH 056/666] docs: add support for docs versioning (#1239) (#1293)
* docs: add support for docs versioning (#1239)
* docs: change configuration to release docs only during the release or by hand. Rollback config for building doc for PR. (#1239)
* docs: Uncomment logic responsible for pushing changes to S3.(#1239)
---------
Co-authored-by: Scott Gerring
---
.github/workflows/build-docs.yml | 2 +-
.github/workflows/docs.yml | 41 -------
.github/workflows/rebuild-latest-docs.yml | 39 ++++++
.github/workflows/release-doc.yml | 19 +++
.github/workflows/reusable-publish-docs.yml | 124 ++++++++++++++++++++
mkdocs.yml | 3 +
6 files changed, 186 insertions(+), 42 deletions(-)
delete mode 100644 .github/workflows/docs.yml
create mode 100644 .github/workflows/rebuild-latest-docs.yml
create mode 100644 .github/workflows/release-doc.yml
create mode 100644 .github/workflows/reusable-publish-docs.yml
diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml
index cbcdcdd9e..15d08587d 100644
--- a/.github/workflows/build-docs.yml
+++ b/.github/workflows/build-docs.yml
@@ -34,4 +34,4 @@ jobs:
- name: Build docs website
run: |
echo "GIT_PYTHON_REFRESH=quiet"
- make build-docs-website
\ No newline at end of file
+ make build-docs-website
diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml
deleted file mode 100644
index 9c09e294d..000000000
--- a/.github/workflows/docs.yml
+++ /dev/null
@@ -1,41 +0,0 @@
-name: Docs
-
-on:
- release:
- types:
- - published
- workflow_dispatch: {}
-
-permissions:
- id-token: write
- contents: write
- pages: write
-
-jobs:
- docs:
- runs-on: ubuntu-latest
- environment: Docs
- steps:
- - uses: actions/checkout@v3
- - name: Set up Python
- uses: actions/setup-python@v4
- with:
- python-version: "3.8"
- - name: Capture branch and tag
- id: branch_name
- run: |
- echo "SOURCE_BRANCH=${GITHUB_REF#refs/heads/}" >> $GITHUB_ENV
- echo "SOURCE_TAG=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV
- - name: Build docs website
- run: |
- make build-docs-website
- - name: Configure AWS credentials
- uses: aws-actions/configure-aws-credentials@e1e17a757e536f70e52b5a12b2e8d1d1c60e04ef
- with:
- aws-region: us-east-1
- role-to-assume: ${{ secrets.AWS_DOCS_ROLE_ARN }}
- - name: Deploy Docs
- run: |
- aws s3 sync \
- dist \
- s3://${{ secrets.AWS_DOCS_BUCKET }}/lambda-java/
diff --git a/.github/workflows/rebuild-latest-docs.yml b/.github/workflows/rebuild-latest-docs.yml
new file mode 100644
index 000000000..853aaa1d3
--- /dev/null
+++ b/.github/workflows/rebuild-latest-docs.yml
@@ -0,0 +1,39 @@
+name: Rebuild latest docs
+
+# PROCESS
+#
+# 1. Build User Guide and API docs
+# 2. Publish to GitHub Pages
+# 3. Publish to S3 (new home)
+
+# USAGE
+#
+# Only used for deploying a documentation hotfix to /latest and its associated version w/o a full release.
+#
+# Steps:
+#
+# 1. Trigger "Rebuild latest docs" workflow manually: https://docs.github.com/en/actions/managing-workflow-runs/manually-running-a-workflow
+# 2. Use the latest version released under Releases e.g. 2.0.0
+
+on:
+ workflow_dispatch:
+ inputs:
+ latest_published_version:
+ description: "Latest published version to rebuild latest docs for, e.g. 1.4.2"
+ default: "1.4.2"
+ required: true
+
+permissions:
+ contents: read
+
+jobs:
+ release-docs:
+ permissions:
+ contents: write # push to gh-pages
+ pages: write # deploy gh-pages website
+ id-token: write # trade JWT token for AWS credentials in AWS Docs account
+ secrets: inherit
+ uses: ./.github/workflows/reusable_publish_docs.yml
+ with:
+ version: ${{ inputs.latest_published_version }}
+ alias: latest
diff --git a/.github/workflows/release-doc.yml b/.github/workflows/release-doc.yml
new file mode 100644
index 000000000..5f87f970a
--- /dev/null
+++ b/.github/workflows/release-doc.yml
@@ -0,0 +1,19 @@
+name: Docs
+
+on:
+ release:
+ types:
+ - published
+ workflow_dispatch: {}
+
+jobs:
+ release-docs:
+ permissions:
+ contents: write
+ pages: write
+ id-token: write
+ secrets: inherit
+ uses: ./.github/workflows/reusable-publish-docs.yml
+ with:
+ version: main
+ alias: stage
\ No newline at end of file
diff --git a/.github/workflows/reusable-publish-docs.yml b/.github/workflows/reusable-publish-docs.yml
new file mode 100644
index 000000000..9ab53dac2
--- /dev/null
+++ b/.github/workflows/reusable-publish-docs.yml
@@ -0,0 +1,124 @@
+name: Reusable Publish docs
+
+env:
+ BRANCH: main
+ ORIGIN: aws-powertools/powertools-lambda-java
+ VERSION: ""
+
+on:
+ workflow_call:
+ inputs:
+ version:
+ description: "Version to build and publish docs (1.28.0, develop)"
+ required: true
+ type: string
+ alias:
+ description: "Alias to associate version (latest, stage)"
+ required: true
+ type: string
+ detached_mode:
+ description: "Whether it's running in git detached mode to ensure git is sync'd"
+ required: false
+ default: false
+ type: boolean
+
+permissions:
+ contents: write
+ id-token: write
+ pages: write
+
+jobs:
+ publish-docs:
+ runs-on: ubuntu-latest
+ environment: Docs
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
+ with:
+ # While `fetch-depth` is used to allow the workflow to later commit & push the changes.
+ fetch-depth: 0
+ - name: Setup dependencies
+ uses: ./.github/actions/cached-node-modules
+ - name: Set up Python
+ uses: actions/setup-python@57ded4d7d5e986d7296eab16560982c6dd7c923b # v4.6.0
+ with:
+ python-version: "3.8"
+ - name: Install doc generation dependencies
+ run: |
+ pip install --upgrade pip
+ pip install -r docs/requirements.txt
+ - name: Setup doc deploy
+ run: |
+ git config --global user.name Docs deploy
+ git config --global user.email aws-devax-open-source@amazon.com
+ - name: Git refresh tip (detached mode)
+ # Git Detached mode (release notes) doesn't have origin
+ if: ${{ inputs.detached_mode }}
+ run: |
+ git config pull.rebase true
+ git config remote.origin.url >&- || git remote add origin https://github.com/"$ORIGIN"
+ git pull origin "$BRANCH"
+ - name: Normalize Version Number
+ run: echo "VERSION=$(echo ${{ inputs.version }} | sed 's/v//')" >> $GITHUB_ENV
+ - name: Build docs website and API reference
+ env:
+ ALIAS: ${{ inputs.alias }}
+ run: |
+ rm -rf site
+ mkdocs build
+ mike deploy --update-aliases --no-redirect ${{ env.VERSION }} ${{ env.ALIAS }} --branch backup-gh-pages
+ # Set latest version as a default
+ mike set-default latest --branch backup-gh-pages
+ - name: Configure AWS credentials
+ uses: aws-actions/configure-aws-credentials@e1e17a757e536f70e52b5a12b2e8d1d1c60e04ef # v2.0.0
+ with:
+ aws-region: us-east-1
+ role-to-assume: ${{ secrets.AWS_DOCS_ROLE_ARN }}
+ - name: Copy API Docs
+ run: |
+ cp -r api site/
+
+ - name: Deploy Docs (Version)
+ env:
+ VERSION: ${{ inputs.version }}
+ ALIAS: ${{ inputs.alias }}
+ run: |
+ aws s3 sync \
+ site/ \
+ s3://${{ secrets.AWS_DOCS_BUCKET }}/lambda-java/${{ env.VERSION }}/
+ - name: Deploy Docs (Alias)
+ env:
+ VERSION: ${{ inputs.version }}
+ ALIAS: ${{ inputs.alias }}
+ run: |
+ aws s3 sync \
+ site/ \
+ s3://${{ secrets.AWS_DOCS_BUCKET }}/lambda-java/${{ env.ALIAS }}/
+ - name: Deploy Docs (Version JSON)
+ env:
+ VERSION: ${{ inputs.version }}
+ ALIAS: ${{ inputs.alias }}
+
+
+ # We originally used "mike" from PyPi to manage versions for us, but since we moved to S3, we can't use it to manage versions any more.
+ # Instead, we're using some shell script that manages the versions.
+ #
+ # Operations:
+ # 1. Download the versions.json file from S3
+ # 2. Find any reference to the alias and delete it from the versions file
+ # 3. This is voodoo (don't use JQ):
+ # - we assign the input as $o and the new version/alias as $n,
+ # - we check if the version number exists in the file already (for republishing docs)
+ # - if it's an alias (stage/latest/*) or old version, we do nothing and output $o (original input)
+ # - if it's a new version number, we add it at position 0 in the array.
+ # 4. Once done, we'll upload it back to S3.
+
+ run: |
+ aws s3 cp \
+ s3://${{ secrets.AWS_DOCS_BUCKET }}/lambda-java/versions.json \
+ versions_old.json
+ jq 'del(.[].aliases[] | select(. == "${{ env.ALIAS }}"))' < versions_old.json > versions_proc.json
+ jq '. as $o | [{"title": "${{ env.VERSION }}", "version": "${{ env.VERSION }}", "aliases": ["${{env.ALIAS}}"] }] as $n | $n | if .[0].title | test("[a-z]+") or any($o[].title == "${{ env.VERSION }}";.) then $o else $n + $o end' < versions_proc.json > versions.json
+ aws s3 cp \
+ versions.json \
+ s3://${{ secrets.AWS_DOCS_BUCKET }}/lambda-java/versions.json
diff --git a/mkdocs.yml b/mkdocs.yml
index da00b24d1..05f02c5ca 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -82,6 +82,9 @@ extra_javascript:
- javascript/extra.js
extra:
+ version:
+ provider: mike
+ default: latest
powertools:
version: 1.16.1 # to update after each release (we do not want snapshot version here)
From a0c7d3860dd86c5f991c21e55177917d7119cd50 Mon Sep 17 00:00:00 2001
From: Grzegorz Kozub
Date: Fri, 28 Jul 2023 10:02:09 +0200
Subject: [PATCH 057/666] docs: versioning - fix typo (#1322)
* docs: add support for docs versioning (#1239)
* docs: change configuration to release docs only during the release or by hand. Rollback config for building doc for PR. (#1239)
* docs: HotFix - workflow path(#1239)
* docs: HotFix - workflow path(#1239)
* docs: typo. (#1239)
---
.github/workflows/rebuild-latest-docs.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/rebuild-latest-docs.yml b/.github/workflows/rebuild-latest-docs.yml
index 853aaa1d3..f176ca901 100644
--- a/.github/workflows/rebuild-latest-docs.yml
+++ b/.github/workflows/rebuild-latest-docs.yml
@@ -33,7 +33,7 @@ jobs:
pages: write # deploy gh-pages website
id-token: write # trade JWT token for AWS credentials in AWS Docs account
secrets: inherit
- uses: ./.github/workflows/reusable_publish_docs.yml
+ uses: ./.github/workflows/reusable-publish-docs.yml
with:
version: ${{ inputs.latest_published_version }}
alias: latest
From bddd99a84be8cdacfc18e53c710647434ed058f8 Mon Sep 17 00:00:00 2001
From: Scott Gerring
Date: Fri, 28 Jul 2023 09:59:55 +0100
Subject: [PATCH 058/666] fix: Rollback doc changes (#1323)
* Revert "docs: versioning - fix typo (#1322)"
This reverts commit a0c7d3860dd86c5f991c21e55177917d7119cd50.
* Revert "docs: add support for docs versioning (#1239) (#1293)"
This reverts commit 3dc84051a1a32cf90b8e3d716fe608e707ee4c16.
---
.github/workflows/build-docs.yml | 2 +-
.github/workflows/docs.yml | 41 +++++++
.github/workflows/rebuild-latest-docs.yml | 39 ------
.github/workflows/release-doc.yml | 19 ---
.github/workflows/reusable-publish-docs.yml | 124 --------------------
mkdocs.yml | 3 -
6 files changed, 42 insertions(+), 186 deletions(-)
create mode 100644 .github/workflows/docs.yml
delete mode 100644 .github/workflows/rebuild-latest-docs.yml
delete mode 100644 .github/workflows/release-doc.yml
delete mode 100644 .github/workflows/reusable-publish-docs.yml
diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml
index 15d08587d..cbcdcdd9e 100644
--- a/.github/workflows/build-docs.yml
+++ b/.github/workflows/build-docs.yml
@@ -34,4 +34,4 @@ jobs:
- name: Build docs website
run: |
echo "GIT_PYTHON_REFRESH=quiet"
- make build-docs-website
+ make build-docs-website
\ No newline at end of file
diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml
new file mode 100644
index 000000000..9c09e294d
--- /dev/null
+++ b/.github/workflows/docs.yml
@@ -0,0 +1,41 @@
+name: Docs
+
+on:
+ release:
+ types:
+ - published
+ workflow_dispatch: {}
+
+permissions:
+ id-token: write
+ contents: write
+ pages: write
+
+jobs:
+ docs:
+ runs-on: ubuntu-latest
+ environment: Docs
+ steps:
+ - uses: actions/checkout@v3
+ - name: Set up Python
+ uses: actions/setup-python@v4
+ with:
+ python-version: "3.8"
+ - name: Capture branch and tag
+ id: branch_name
+ run: |
+ echo "SOURCE_BRANCH=${GITHUB_REF#refs/heads/}" >> $GITHUB_ENV
+ echo "SOURCE_TAG=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV
+ - name: Build docs website
+ run: |
+ make build-docs-website
+ - name: Configure AWS credentials
+ uses: aws-actions/configure-aws-credentials@e1e17a757e536f70e52b5a12b2e8d1d1c60e04ef
+ with:
+ aws-region: us-east-1
+ role-to-assume: ${{ secrets.AWS_DOCS_ROLE_ARN }}
+ - name: Deploy Docs
+ run: |
+ aws s3 sync \
+ dist \
+ s3://${{ secrets.AWS_DOCS_BUCKET }}/lambda-java/
diff --git a/.github/workflows/rebuild-latest-docs.yml b/.github/workflows/rebuild-latest-docs.yml
deleted file mode 100644
index f176ca901..000000000
--- a/.github/workflows/rebuild-latest-docs.yml
+++ /dev/null
@@ -1,39 +0,0 @@
-name: Rebuild latest docs
-
-# PROCESS
-#
-# 1. Build User Guide and API docs
-# 2. Publish to GitHub Pages
-# 3. Publish to S3 (new home)
-
-# USAGE
-#
-# Only used for deploying a documentation hotfix to /latest and its associated version w/o a full release.
-#
-# Steps:
-#
-# 1. Trigger "Rebuild latest docs" workflow manually: https://docs.github.com/en/actions/managing-workflow-runs/manually-running-a-workflow
-# 2. Use the latest version released under Releases e.g. 2.0.0
-
-on:
- workflow_dispatch:
- inputs:
- latest_published_version:
- description: "Latest published version to rebuild latest docs for, e.g. 1.4.2"
- default: "1.4.2"
- required: true
-
-permissions:
- contents: read
-
-jobs:
- release-docs:
- permissions:
- contents: write # push to gh-pages
- pages: write # deploy gh-pages website
- id-token: write # trade JWT token for AWS credentials in AWS Docs account
- secrets: inherit
- uses: ./.github/workflows/reusable-publish-docs.yml
- with:
- version: ${{ inputs.latest_published_version }}
- alias: latest
diff --git a/.github/workflows/release-doc.yml b/.github/workflows/release-doc.yml
deleted file mode 100644
index 5f87f970a..000000000
--- a/.github/workflows/release-doc.yml
+++ /dev/null
@@ -1,19 +0,0 @@
-name: Docs
-
-on:
- release:
- types:
- - published
- workflow_dispatch: {}
-
-jobs:
- release-docs:
- permissions:
- contents: write
- pages: write
- id-token: write
- secrets: inherit
- uses: ./.github/workflows/reusable-publish-docs.yml
- with:
- version: main
- alias: stage
\ No newline at end of file
diff --git a/.github/workflows/reusable-publish-docs.yml b/.github/workflows/reusable-publish-docs.yml
deleted file mode 100644
index 9ab53dac2..000000000
--- a/.github/workflows/reusable-publish-docs.yml
+++ /dev/null
@@ -1,124 +0,0 @@
-name: Reusable Publish docs
-
-env:
- BRANCH: main
- ORIGIN: aws-powertools/powertools-lambda-java
- VERSION: ""
-
-on:
- workflow_call:
- inputs:
- version:
- description: "Version to build and publish docs (1.28.0, develop)"
- required: true
- type: string
- alias:
- description: "Alias to associate version (latest, stage)"
- required: true
- type: string
- detached_mode:
- description: "Whether it's running in git detached mode to ensure git is sync'd"
- required: false
- default: false
- type: boolean
-
-permissions:
- contents: write
- id-token: write
- pages: write
-
-jobs:
- publish-docs:
- runs-on: ubuntu-latest
- environment: Docs
- steps:
- - name: Checkout code
- uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
- with:
- # While `fetch-depth` is used to allow the workflow to later commit & push the changes.
- fetch-depth: 0
- - name: Setup dependencies
- uses: ./.github/actions/cached-node-modules
- - name: Set up Python
- uses: actions/setup-python@57ded4d7d5e986d7296eab16560982c6dd7c923b # v4.6.0
- with:
- python-version: "3.8"
- - name: Install doc generation dependencies
- run: |
- pip install --upgrade pip
- pip install -r docs/requirements.txt
- - name: Setup doc deploy
- run: |
- git config --global user.name Docs deploy
- git config --global user.email aws-devax-open-source@amazon.com
- - name: Git refresh tip (detached mode)
- # Git Detached mode (release notes) doesn't have origin
- if: ${{ inputs.detached_mode }}
- run: |
- git config pull.rebase true
- git config remote.origin.url >&- || git remote add origin https://github.com/"$ORIGIN"
- git pull origin "$BRANCH"
- - name: Normalize Version Number
- run: echo "VERSION=$(echo ${{ inputs.version }} | sed 's/v//')" >> $GITHUB_ENV
- - name: Build docs website and API reference
- env:
- ALIAS: ${{ inputs.alias }}
- run: |
- rm -rf site
- mkdocs build
- mike deploy --update-aliases --no-redirect ${{ env.VERSION }} ${{ env.ALIAS }} --branch backup-gh-pages
- # Set latest version as a default
- mike set-default latest --branch backup-gh-pages
- - name: Configure AWS credentials
- uses: aws-actions/configure-aws-credentials@e1e17a757e536f70e52b5a12b2e8d1d1c60e04ef # v2.0.0
- with:
- aws-region: us-east-1
- role-to-assume: ${{ secrets.AWS_DOCS_ROLE_ARN }}
- - name: Copy API Docs
- run: |
- cp -r api site/
-
- - name: Deploy Docs (Version)
- env:
- VERSION: ${{ inputs.version }}
- ALIAS: ${{ inputs.alias }}
- run: |
- aws s3 sync \
- site/ \
- s3://${{ secrets.AWS_DOCS_BUCKET }}/lambda-java/${{ env.VERSION }}/
- - name: Deploy Docs (Alias)
- env:
- VERSION: ${{ inputs.version }}
- ALIAS: ${{ inputs.alias }}
- run: |
- aws s3 sync \
- site/ \
- s3://${{ secrets.AWS_DOCS_BUCKET }}/lambda-java/${{ env.ALIAS }}/
- - name: Deploy Docs (Version JSON)
- env:
- VERSION: ${{ inputs.version }}
- ALIAS: ${{ inputs.alias }}
-
-
- # We originally used "mike" from PyPi to manage versions for us, but since we moved to S3, we can't use it to manage versions any more.
- # Instead, we're using some shell script that manages the versions.
- #
- # Operations:
- # 1. Download the versions.json file from S3
- # 2. Find any reference to the alias and delete it from the versions file
- # 3. This is voodoo (don't use JQ):
- # - we assign the input as $o and the new version/alias as $n,
- # - we check if the version number exists in the file already (for republishing docs)
- # - if it's an alias (stage/latest/*) or old version, we do nothing and output $o (original input)
- # - if it's a new version number, we add it at position 0 in the array.
- # 4. Once done, we'll upload it back to S3.
-
- run: |
- aws s3 cp \
- s3://${{ secrets.AWS_DOCS_BUCKET }}/lambda-java/versions.json \
- versions_old.json
- jq 'del(.[].aliases[] | select(. == "${{ env.ALIAS }}"))' < versions_old.json > versions_proc.json
- jq '. as $o | [{"title": "${{ env.VERSION }}", "version": "${{ env.VERSION }}", "aliases": ["${{env.ALIAS}}"] }] as $n | $n | if .[0].title | test("[a-z]+") or any($o[].title == "${{ env.VERSION }}";.) then $o else $n + $o end' < versions_proc.json > versions.json
- aws s3 cp \
- versions.json \
- s3://${{ secrets.AWS_DOCS_BUCKET }}/lambda-java/versions.json
diff --git a/mkdocs.yml b/mkdocs.yml
index 05f02c5ca..da00b24d1 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -82,9 +82,6 @@ extra_javascript:
- javascript/extra.js
extra:
- version:
- provider: mike
- default: latest
powertools:
version: 1.16.1 # to update after each release (we do not want snapshot version here)
From a2ad29251a7ade7433030b3efcb901573c2e5d5b Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Fri, 28 Jul 2023 13:24:40 +0200
Subject: [PATCH 059/666] build(deps): bump aws.sdk.version from 2.20.111 to
2.20.114 (#1324)
Bumps `aws.sdk.version` from 2.20.111 to 2.20.114.
Updates `software.amazon.awssdk:bom` from 2.20.111 to 2.20.114
Updates `software.amazon.awssdk:http-client-spi` from 2.20.111 to 2.20.114
Updates `software.amazon.awssdk:url-connection-client` from 2.20.111 to 2.20.114
Updates `software.amazon.awssdk:s3` from 2.20.111 to 2.20.114
Updates `software.amazon.awssdk:lambda` from 2.20.111 to 2.20.114
Updates `software.amazon.awssdk:cloudwatch` from 2.20.111 to 2.20.114
Updates `software.amazon.awssdk:xray` from 2.20.111 to 2.20.114
Updates `software.amazon.awssdk:cloudformation` from 2.20.111 to 2.20.114
Updates `software.amazon.awssdk:sts` from 2.20.111 to 2.20.114
---
updated-dependencies:
- dependency-name: software.amazon.awssdk:bom
dependency-type: direct:production
update-type: version-update:semver-patch
- dependency-name: software.amazon.awssdk:http-client-spi
dependency-type: direct:production
update-type: version-update:semver-patch
- dependency-name: software.amazon.awssdk:url-connection-client
dependency-type: direct:development
update-type: version-update:semver-patch
- dependency-name: software.amazon.awssdk:s3
dependency-type: direct:development
update-type: version-update:semver-patch
- dependency-name: software.amazon.awssdk:lambda
dependency-type: direct:development
update-type: version-update:semver-patch
- dependency-name: software.amazon.awssdk:cloudwatch
dependency-type: direct:development
update-type: version-update:semver-patch
- dependency-name: software.amazon.awssdk:xray
dependency-type: direct:development
update-type: version-update:semver-patch
- dependency-name: software.amazon.awssdk:cloudformation
dependency-type: direct:development
update-type: version-update:semver-patch
- dependency-name: software.amazon.awssdk:sts
dependency-type: direct:development
update-type: version-update:semver-patch
...
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
examples/powertools-examples-cloudformation/pom.xml | 2 +-
examples/powertools-examples-sqs/pom.xml | 2 +-
pom.xml | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml
index 843d8b5e8..2de8c75c4 100644
--- a/examples/powertools-examples-cloudformation/pom.xml
+++ b/examples/powertools-examples-cloudformation/pom.xml
@@ -16,7 +16,7 @@
true1.2.23.11.2
- 2.20.111
+ 2.20.114
diff --git a/examples/powertools-examples-sqs/pom.xml b/examples/powertools-examples-sqs/pom.xml
index 78e4b0904..98f7fc9c2 100644
--- a/examples/powertools-examples-sqs/pom.xml
+++ b/examples/powertools-examples-sqs/pom.xml
@@ -28,7 +28,7 @@
software.amazon.awssdkurl-connection-client
- 2.20.111
+ 2.20.114com.amazonaws
diff --git a/pom.xml b/pom.xml
index e8f85e3ff..c1ac76f72 100644
--- a/pom.xml
+++ b/pom.xml
@@ -74,7 +74,7 @@
2.20.02.15.21.9.7
- 2.20.111
+ 2.20.1142.14.02.1.3UTF-8
From 1261e58f837b5f883dcb7214f6a0e0d812f57a40 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 31 Jul 2023 11:17:18 +0200
Subject: [PATCH 060/666] build(deps): bump org.apache.commons:commons-lang3
from 3.12.0 to 3.13.0 (#1325)
Bumps org.apache.commons:commons-lang3 from 3.12.0 to 3.13.0.
---
updated-dependencies:
- dependency-name: org.apache.commons:commons-lang3
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pom.xml b/pom.xml
index c1ac76f72..b0f7030ec 100644
--- a/pom.xml
+++ b/pom.xml
@@ -263,7 +263,7 @@
org.apache.commonscommons-lang3
- 3.12.0
+ 3.13.0test
From 70da5f042ca289ee2584e2da89a32026f1a8cfa4 Mon Sep 17 00:00:00 2001
From: Scott Gerring
Date: Mon, 31 Jul 2023 10:23:20 +0100
Subject: [PATCH 061/666] docs: Add maintainers guide (#1326)
---
docs/processes/maintainers.md | 247 ++++++++++++++++++++++++++++++++++
mkdocs.yml | 2 +
2 files changed, 249 insertions(+)
create mode 100644 docs/processes/maintainers.md
diff --git a/docs/processes/maintainers.md b/docs/processes/maintainers.md
new file mode 100644
index 000000000..6b3d9e126
--- /dev/null
+++ b/docs/processes/maintainers.md
@@ -0,0 +1,247 @@
+---
+title: Maintainers playbook
+description: Process
+---
+
+
+
+## Overview
+
+!!! note "Please treat this content as a living document."
+
+This is document explains who the maintainers are, their responsibilities, and how they should be doing it. If you're interested in contributing,
+ see [CONTRIBUTING](https://github.com/aws-powertools/powertools-lambda-java/blob/main/CONTRIBUTING.md){target="_blank"}.
+
+## Current Maintainers
+
+| Maintainer | GitHub ID | Affiliation |
+|-----------------------|---------------------------------------------------------------------------------| ----------- |
+| Jerome Van Der Linden | [jeromevdl](https://github.com/jeromevdl){target="_blank"} | Amazon |
+| Michele Ricciardi | [mriccia](https://github.com/mriccia){target="_blank"} | Amazon |
+| Scott Gerring | [scottgerring](https://github.com/scottgerring){target="_blank"} | Amazon |
+
+## Emeritus
+
+Previous active maintainers who contributed to this project.
+
+| Maintainer | GitHub ID | Affiliation |
+|----------------|-----------------------------------------------------------------------------------------|---------------|
+| Mark Sailes | [msailes](https://github.com/msailes){target="_blank"} | Amazon |
+| Pankaj Agrawal | [pankajagrawal16](https://github.com/pankajagrawal16){target="_blank"} | Former Amazon |
+| Steve Houel | [stevehouel](https://github.com/stevehouel) | Amazon |
+
+## Labels
+
+These are the most common labels used by maintainers to triage issues, pull requests (PR), and for project management:
+
+| Label | Usage | Notes |
+|----------------------------------|---------------------------------------------------------------------------------------------------|----------------------------------------------------|
+| triage | New issues that require maintainers review | Issue template |
+| bug | Unexpected, reproducible and unintended software behavior | PR/Release automation; Doc snippets are excluded; |
+| documentation | Documentation improvements | PR/Release automation; Doc additions, fixes, etc.; |
+| duplicate | Dupe of another issue | |
+| enhancement | New or enhancements to existing features | Issue template |
+| RFC | Technical design documents related to a feature request | Issue template |
+| help wanted | Tasks you want help from anyone to move forward | Bandwidth, complex topics, etc. |
+| feature-parity | Adding features present in other Powertools for Lambda libraries | |
+| good first issue | Somewhere for new contributors to start | |
+| governance | Issues related to project governance - contributor guides, automation, etc. | |
+| question | Issues that are raised to ask questions | |
+| maven | Related to the build system | |
+| need-more-information | Missing information before making any calls | |
+| status/staged-next-release | Changes are merged and will be available once the next release is made. | |
+| status/staged-next-major-release | Contains breaking changes - merged changes will be available once the next major release is made. | |
+| blocked | Issues or PRs that are blocked for varying reasons | Timeline is uncertain |
+| priority:1 | Critical - needs urgent attention | |
+| priority:2 | High - core feature, or affects 60%+ of users | |
+| priority:3 | Neutral - not a core feature, or affects < 40% of users | |
+| priority:4 | Low - nice to have | |
+| priority:5 | Low - idea for later | |
+| invalid | This doesn't seem right | |
+| size/XS | PRs between 0-9 LOC | PR automation |
+| size/S | PRs between 10-29 LOC | PR automation |
+| size/M | PRs between 30-99 LOC | PR automation |
+| size/L | PRs between 100-499 LOC | PR automation |
+| size/XL | PRs between 500-999 LOC, often PRs that grown with feedback | PR automation |
+| size/XXL | PRs with 1K+ LOC, largely documentation related | PR automation |
+| dependencies | Changes that touch dependencies, e.g. Dependabot, etc. | PR/ automation |
+| maintenance | Address outstanding tech debt | |
+
+## Maintainer Responsibilities
+
+Maintainers are active and visible members of the community, and have
+[maintain-level permissions on a repository](https://docs.github.com/en/organizations/managing-access-to-your-organizations-repositories/repository-permission-levels-for-an-organization){target="_blank"}.
+Use those privileges to serve the community and evolve code as follows.
+
+Be aware of recurring ambiguous situations and [document them](#common-scenarios) to help your fellow maintainers.
+
+### Uphold Code of Conduct
+
+
+Model the behavior set forward by the
+[Code of Conduct](https://github.com/aws-powertools/powertools-lambda-java/blob/main/CODE_OF_CONDUCT.md){target="_blank"}
+and raise any violations to other maintainers and admins. There could be unusual circumstances where inappropriate
+behavior does not immediately fall within the [Code of Conduct](https://github.com/aws-powertools/powertools-lambda-java/blob/main/CODE_OF_CONDUCT.md){target="_blank"}.
+
+These might be nuanced and should be handled with extra care - when in doubt, do not engage and reach out to other maintainers
+and admins.
+
+### Prioritize Security
+
+Security is your number one priority. Maintainer's Github keys must be password protected securely and any reported
+security vulnerabilities are addressed before features or bugs.
+
+Note that this repository is monitored and supported 24/7 by Amazon Security, see
+[Security disclosures](https://github.com/aws-powertools/powertools-lambda-java/){target="_blank"} for details.
+
+### Review Pull Requests
+
+Review pull requests regularly, comment, suggest, reject, merge and close. Accept only high quality pull-requests.
+Provide code reviews and guidance on incoming pull requests.
+
+PRs are [labeled](#labels) based on file changes and semantic title. Pay attention to whether labels reflect the current
+state of the PR and correct accordingly.
+
+Use and enforce [semantic versioning](https://semver.org/){target="_blank" rel="nofollow"} pull request titles, as these will be used for
+[CHANGELOG](https://github.com/aws-powertools/powertools-lambda-java/blob/main/CHANGELOG.md){target="_blank"}
+and [Release notes](https://github.com/aws-powertools/powertools-lambda-java/releases) - make sure they communicate their
+intent at the human level.
+
+For issues linked to a PR, make sure `status/staged-next-release` label is applied to them when merging.
+[Upon release](#releasing-a-new-version), these issues will be notified which release version contains their change.
+
+See [Common scenarios](#common-scenarios) section for additional guidance.
+
+### Triage New Issues
+
+Manage [labels](#labels), review issues regularly, and create new labels as needed by the project. Remove `triage`
+label when you're able to confirm the validity of a request, a bug can be reproduced, etc.
+Give priority to the original author for implementation, unless it is a sensitive task that is best handled by maintainers.
+
+Make sure issues are assigned to our [board of activities](https://github.com/orgs/aws-powertools/projects/4).
+
+Use our [labels](#labels) to signal good first issues to new community members, and to set expectation that this might
+need additional feedback from the author, other customers, experienced community members and/or maintainers.
+
+Be aware of [casual contributors](https://opensource.com/article/17/10/managing-casual-contributors){target="_blank" rel="nofollow"} and recurring contributors.
+Provide the experience and attention you wish you had if you were starting in open source.
+
+See [Common scenarios](#common-scenarios) section for additional guidance.
+
+### Triage Bug Reports
+
+Be familiar with [our definition of bug](#is-that-a-bug). If it's not a bug, you can close it or adjust its title and
+labels - always communicate the reason accordingly.
+
+For bugs caused by upstream dependencies, replace `bug` with `bug-upstream` label. Ask the author whether they'd like to
+raise the issue upstream or if they prefer us to do so.
+
+Assess the impact and make the call on whether we need an emergency release. Contact other [maintainers](#current-maintainers) when in doubt.
+
+See [Common scenarios](#common-scenarios) section for additional guidance.
+
+### Triage RFCs
+
+RFC is a collaborative process to help us get to the most optimal solution given the context. Their purpose is to ensure
+everyone understands what this context is, their trade-offs, and alternative solutions that were part of the research
+before implementation begins.
+
+Make sure you ask these questions in mind when reviewing:
+
+- Does it use our [RFC template](https://github.com/aws-powertools/powertools-lambda-java/issues/new?assignees=&labels=RFC%2C+triage&projects=&template=rfc.md&title=RFC%3A+)?
+- Does it match our [Tenets](https://docs.powertools.aws.dev/lambda/java/latest/#tenets)?
+- Does the proposal address the use case? If so, is the recommended usage explicit?
+- Does it focus on the mechanics to solve the use case over fine-grained implementation details?
+- Can anyone familiar with the code base implement it?
+- If approved, are they interested in contributing? Do they need any guidance?
+- Does this significantly increase the overall project maintenance? Do we have the skills to maintain it?
+- If we can't take this use case, are there alternative projects we could recommend? Or does it call for a new project altogether?
+
+When necessary, be upfront that the time to review, approve, and implement a RFC can vary -
+see [Contribution is stuck](#contribution-is-stuck). Some RFCs may be further updated after implementation, as certain areas become clearer.
+
+Some examples using our initial and new RFC templates: #92, #94, #95, #991, #1226
+
+### Releasing a new version
+
+!!! note "The release process is currently a long, multi-step process. The team is in the process of automating at it."
+
+Firstly, make sure the commit history in the `main` branch **(1)** it's up to date, **(2)** commit messages are semantic,
+and **(3)** commit messages have their respective area, for example `feat: `, `chore: ...`).
+
+**Looks good, what's next?**
+
+Kickoff the `Prepare for maven central release` workflow with the intended rekease version. Once this has completed, it will
+draft a Pull Request named something like `chore: Prep release 1.19.0`. the PR will **(1)** roll all of the POM versions
+forward to the new release version and **(2)** release notes.
+
+Once this is done, check out the branch and clean up the release notes. These will be used both in the
+[CHANGELOG.md file](https://github.com/aws-powertools/powertools-lambda-java/blob/main/CHANGELOG.md)
+file and the [published github release information](https://github.com/aws-powertools/powertools-lambda-java/releases),
+and you can use the existing release notes to see how changes are summarized.
+
+Next, commit and push, wait for the build to complete, and merge to main. Once main has built successfully (i.e. build, tests and end-to-end tests should pass), create a
+tagged release from the Github UI, using the same release notes.
+
+Next, run the `Publish package to the Maven Central Repository` action to release the library.
+
+Finally, by hand, create a PR rolling all of the POMs onto the next snapshot version (e.g. `1.20.0-SNAPSHOT`).
+
+
+### Add Continuous Integration Checks
+
+Add integration checks that validate pull requests and pushes to ease the burden on Pull Request reviewers.
+Continuously revisit areas of improvement to reduce operational burden in all parties involved.
+
+### Negative Impact on the Project
+
+Actions that negatively impact the project will be handled by the admins, in coordination with other maintainers,
+in balance with the urgency of the issue. Examples would be
+[Code of Conduct](https://github.com/aws-powertools/powertools-lambda-java/blob/main/CODE_OF_CONDUCT.md){target="_blank"}
+violations, deliberate harmful or malicious actions, spam, monopolization, and security risks.
+
+## Common scenarios
+
+These are recurring ambiguous situations that new and existing maintainers may encounter. They serve as guidance.
+It is up to each maintainer to follow, adjust, or handle in a different manner as long as
+[our conduct is consistent](#uphold-code-of-conduct)
+
+### Contribution is stuck
+
+A contribution can get stuck often due to lack of bandwidth and language barrier. For bandwidth issues,
+check whether the author needs help. Make sure you get their permission before pushing code into their existing PR -
+do not create a new PR unless strictly necessary.
+
+For language barrier and others, offer a 1:1 chat to get them unblocked. Often times, English might not be their
+primary language, and writing in public might put them off, or come across not the way they intended to be.
+
+In other cases, you may have constrained capacity. Use `help wanted` label when you want to signal other maintainers
+and external contributors that you could use a hand to move it forward.
+
+### Insufficient feedback or information
+
+When in doubt, use the `need-more-information` label to signal more context and feedback are necessary before proceeding.
+
+### Crediting contributions
+
+We credit all contributions as part of each [release note](https://github.com/aws-powertools/powertools-lambda-java/releases){target="_blank"}
+as an automated process. If you find contributors are missing from the release note you're producing, please add them manually.
+
+### Is that a bug?
+
+A bug produces incorrect or unexpected results at runtime that differ from its intended behavior.
+Bugs must be reproducible. They directly affect customers experience at runtime despite following its recommended usage.
+
+Documentation snippets, use of internal components, or unadvertised functionalities are not considered bugs.
+
+### Mentoring contributions
+
+Always favor mentoring issue authors to contribute, unless they're not interested or the implementation is sensitive (_e.g., complexity, time to release, etc._).
+
+Make use of `help wanted` and `good first issue` to signal additional contributions the community can help.
+
+### Long running issues or PRs
+
+Try offering a 1:1 call in the attempt to get to a mutual understanding and clarify areas that maintainers could help.
+
+In the rare cases where both parties don't have the bandwidth or expertise to continue, it's best to use the `revisit-in-3-months` label. By then, see if it's possible to break the PR or issue in smaller chunks, and eventually close if there is no progress.
diff --git a/mkdocs.yml b/mkdocs.yml
index da00b24d1..841a95fae 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -18,6 +18,8 @@ nav:
- utilities/validation.md
- utilities/custom_resources.md
- utilities/serialization.md
+ - Processes:
+ - processes/maintainers.md
theme:
name: material
From bc40ea251eaba7320c2f5ef1e2c4883d4c35e02d Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 31 Jul 2023 13:58:07 +0200
Subject: [PATCH 062/666] build(deps): bump aws.sdk.version from 2.20.114 to
2.20.115 (#1328)
Bumps `aws.sdk.version` from 2.20.114 to 2.20.115.
Updates `software.amazon.awssdk:bom` from 2.20.114 to 2.20.115
Updates `software.amazon.awssdk:http-client-spi` from 2.20.114 to 2.20.115
Updates `software.amazon.awssdk:url-connection-client` from 2.20.114 to 2.20.115
Updates `software.amazon.awssdk:s3` from 2.20.114 to 2.20.115
Updates `software.amazon.awssdk:lambda` from 2.20.114 to 2.20.115
Updates `software.amazon.awssdk:cloudwatch` from 2.20.114 to 2.20.115
Updates `software.amazon.awssdk:xray` from 2.20.114 to 2.20.115
Updates `software.amazon.awssdk:cloudformation` from 2.20.114 to 2.20.115
Updates `software.amazon.awssdk:sts` from 2.20.114 to 2.20.115
---
updated-dependencies:
- dependency-name: software.amazon.awssdk:bom
dependency-type: direct:production
update-type: version-update:semver-patch
- dependency-name: software.amazon.awssdk:http-client-spi
dependency-type: direct:production
update-type: version-update:semver-patch
- dependency-name: software.amazon.awssdk:url-connection-client
dependency-type: direct:development
update-type: version-update:semver-patch
- dependency-name: software.amazon.awssdk:s3
dependency-type: direct:development
update-type: version-update:semver-patch
- dependency-name: software.amazon.awssdk:lambda
dependency-type: direct:development
update-type: version-update:semver-patch
- dependency-name: software.amazon.awssdk:cloudwatch
dependency-type: direct:development
update-type: version-update:semver-patch
- dependency-name: software.amazon.awssdk:xray
dependency-type: direct:development
update-type: version-update:semver-patch
- dependency-name: software.amazon.awssdk:cloudformation
dependency-type: direct:development
update-type: version-update:semver-patch
- dependency-name: software.amazon.awssdk:sts
dependency-type: direct:development
update-type: version-update:semver-patch
...
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
examples/powertools-examples-cloudformation/pom.xml | 2 +-
examples/powertools-examples-sqs/pom.xml | 2 +-
pom.xml | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml
index 2de8c75c4..5d6d3a4ad 100644
--- a/examples/powertools-examples-cloudformation/pom.xml
+++ b/examples/powertools-examples-cloudformation/pom.xml
@@ -16,7 +16,7 @@
true1.2.23.11.2
- 2.20.114
+ 2.20.115
diff --git a/examples/powertools-examples-sqs/pom.xml b/examples/powertools-examples-sqs/pom.xml
index 98f7fc9c2..13cb039bd 100644
--- a/examples/powertools-examples-sqs/pom.xml
+++ b/examples/powertools-examples-sqs/pom.xml
@@ -28,7 +28,7 @@
software.amazon.awssdkurl-connection-client
- 2.20.114
+ 2.20.115com.amazonaws
diff --git a/pom.xml b/pom.xml
index b0f7030ec..9ed8dbdd2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -74,7 +74,7 @@
2.20.02.15.21.9.7
- 2.20.114
+ 2.20.1152.14.02.1.3UTF-8
From e378d4dd4e7e852656995a4dcafc23aedafbfc0b Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 31 Jul 2023 14:03:50 +0200
Subject: [PATCH 063/666] build(deps): bump com.puppycrawl.tools:checkstyle
(#1329)
Bumps [com.puppycrawl.tools:checkstyle](https://github.com/checkstyle/checkstyle) from 10.12.1 to 10.12.2.
- [Release notes](https://github.com/checkstyle/checkstyle/releases)
- [Commits](https://github.com/checkstyle/checkstyle/compare/checkstyle-10.12.1...checkstyle-10.12.2)
---
updated-dependencies:
- dependency-name: com.puppycrawl.tools:checkstyle
dependency-type: direct:production
update-type: version-update:semver-patch
...
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pom.xml b/pom.xml
index 9ed8dbdd2..cab0a3574 100644
--- a/pom.xml
+++ b/pom.xml
@@ -564,7 +564,7 @@
com.puppycrawl.toolscheckstyle
- 10.12.1
+ 10.12.2
From e2ef948a08eb64887d8dd09f60cda29985fa0b8a Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Tue, 1 Aug 2023 13:50:34 +0200
Subject: [PATCH 064/666] build(deps): bump aws.sdk.version from 2.20.115 to
2.20.116 (#1331)
Bumps `aws.sdk.version` from 2.20.115 to 2.20.116.
Updates `software.amazon.awssdk:bom` from 2.20.115 to 2.20.116
Updates `software.amazon.awssdk:http-client-spi` from 2.20.115 to 2.20.116
Updates `software.amazon.awssdk:url-connection-client` from 2.20.115 to 2.20.116
Updates `software.amazon.awssdk:s3` from 2.20.115 to 2.20.116
Updates `software.amazon.awssdk:lambda` from 2.20.115 to 2.20.116
Updates `software.amazon.awssdk:cloudwatch` from 2.20.115 to 2.20.116
Updates `software.amazon.awssdk:xray` from 2.20.115 to 2.20.116
Updates `software.amazon.awssdk:cloudformation` from 2.20.115 to 2.20.116
Updates `software.amazon.awssdk:sts` from 2.20.115 to 2.20.116
---
updated-dependencies:
- dependency-name: software.amazon.awssdk:bom
dependency-type: direct:production
update-type: version-update:semver-patch
- dependency-name: software.amazon.awssdk:http-client-spi
dependency-type: direct:production
update-type: version-update:semver-patch
- dependency-name: software.amazon.awssdk:url-connection-client
dependency-type: direct:development
update-type: version-update:semver-patch
- dependency-name: software.amazon.awssdk:s3
dependency-type: direct:development
update-type: version-update:semver-patch
- dependency-name: software.amazon.awssdk:lambda
dependency-type: direct:development
update-type: version-update:semver-patch
- dependency-name: software.amazon.awssdk:cloudwatch
dependency-type: direct:development
update-type: version-update:semver-patch
- dependency-name: software.amazon.awssdk:xray
dependency-type: direct:development
update-type: version-update:semver-patch
- dependency-name: software.amazon.awssdk:cloudformation
dependency-type: direct:development
update-type: version-update:semver-patch
- dependency-name: software.amazon.awssdk:sts
dependency-type: direct:development
update-type: version-update:semver-patch
...
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
examples/powertools-examples-cloudformation/pom.xml | 2 +-
examples/powertools-examples-sqs/pom.xml | 2 +-
pom.xml | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml
index 5d6d3a4ad..20e1b4581 100644
--- a/examples/powertools-examples-cloudformation/pom.xml
+++ b/examples/powertools-examples-cloudformation/pom.xml
@@ -16,7 +16,7 @@
true1.2.23.11.2
- 2.20.115
+ 2.20.116
diff --git a/examples/powertools-examples-sqs/pom.xml b/examples/powertools-examples-sqs/pom.xml
index 13cb039bd..e1a4b659e 100644
--- a/examples/powertools-examples-sqs/pom.xml
+++ b/examples/powertools-examples-sqs/pom.xml
@@ -28,7 +28,7 @@
software.amazon.awssdkurl-connection-client
- 2.20.115
+ 2.20.116com.amazonaws
diff --git a/pom.xml b/pom.xml
index cab0a3574..1d80b3081 100644
--- a/pom.xml
+++ b/pom.xml
@@ -74,7 +74,7 @@
2.20.02.15.21.9.7
- 2.20.115
+ 2.20.1162.14.02.1.3UTF-8
From 3a106ca7af82c1b548789d8584d7ea9b52b8959c Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Tue, 1 Aug 2023 20:06:49 +0200
Subject: [PATCH 065/666] build(deps-dev): bump
software.amazon.awscdk:aws-cdk-lib (#1330)
---
powertools-e2e-tests/pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml
index 3e7f0f460..7e354d15e 100644
--- a/powertools-e2e-tests/pom.xml
+++ b/powertools-e2e-tests/pom.xml
@@ -31,7 +31,7 @@
1.81.810.2.69
- 2.88.0
+ 2.89.0true
From a05823bc45407704bda69272b483842d98190a26 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Van=20Der=20Linden?=
<117538+jeromevdl@users.noreply.github.com>
Date: Wed, 2 Aug 2023 11:53:24 +0200
Subject: [PATCH 066/666] feat: large message in SQS and SNS (#1310)
---
.github/workflows/run-e2e-tests.yml | 7 +
docs/utilities/large_messages.md | 419 ++++++++
docs/utilities/sqs_large_message_handling.md | 121 ++-
mkdocs.yml | 2 +-
pom.xml | 28 +-
.../handlers/idempotency/pom.xml | 12 +
.../lambda/powertools/e2e/Function.java | 2 +
.../idempotency/src/main/resources/log4j2.xml | 16 +
.../handlers/largemessage/pom.xml | 72 ++
.../lambda/powertools/e2e/Function.java | 77 ++
.../src/main/resources/log4j2.xml | 16 +
.../handlers/largemessage_idempotent/pom.xml | 77 ++
.../lambda/powertools/e2e/Function.java | 105 ++
.../src/main/resources/log4j2.xml | 16 +
powertools-e2e-tests/handlers/pom.xml | 20 +
powertools-e2e-tests/pom.xml | 28 +
.../lambda/powertools/IdempotencyE2ET.java | 7 +-
.../lambda/powertools/LargeMessageE2ET.java | 167 +++
.../LargeMessageIdempotentE2ET.java | 191 ++++
.../amazon/lambda/powertools/LoggingE2ET.java | 5 +-
.../amazon/lambda/powertools/MetricsE2ET.java | 5 +-
.../lambda/powertools/ParametersE2ET.java | 4 +-
.../amazon/lambda/powertools/TracingE2ET.java | 4 +-
.../powertools/testutils/Infrastructure.java | 89 +-
.../src/test/resources/large_sqs_message.txt | 977 ++++++++++++++++++
powertools-idempotency/pom.xml | 1 -
.../internal/IdempotentAspect.java | 3 +
powertools-large-messages/pom.xml | 166 +++
.../largemessages/LargeMessage.java | 70 ++
.../largemessages/LargeMessageConfig.java | 83 ++
.../LargeMessageProcessingException.java | 28 +
.../internal/LargeMessageAspect.java | 61 ++
.../internal/LargeMessageProcessor.java | 142 +++
.../LargeMessageProcessorFactory.java | 36 +
.../internal/LargeSNSMessageProcessor.java | 52 +
.../internal/LargeSQSMessageProcessor.java | 173 ++++
.../largemessages/LargeMessageConfigTest.java | 57 +
.../internal/LargeMessageAspectTest.java | 333 ++++++
.../LargeMessageProcessorFactoryTest.java | 46 +
powertools-sqs/pom.xml | 1 +
.../powertools/sqs/SqsLargeMessage.java | 8 +-
.../lambda/powertools/sqs/SqsUtils.java | 4 +
spotbugs-exclude.xml | 8 +
43 files changed, 3650 insertions(+), 89 deletions(-)
create mode 100644 docs/utilities/large_messages.md
create mode 100644 powertools-e2e-tests/handlers/idempotency/src/main/resources/log4j2.xml
create mode 100644 powertools-e2e-tests/handlers/largemessage/pom.xml
create mode 100644 powertools-e2e-tests/handlers/largemessage/src/main/java/software/amazon/lambda/powertools/e2e/Function.java
create mode 100644 powertools-e2e-tests/handlers/largemessage/src/main/resources/log4j2.xml
create mode 100644 powertools-e2e-tests/handlers/largemessage_idempotent/pom.xml
create mode 100644 powertools-e2e-tests/handlers/largemessage_idempotent/src/main/java/software/amazon/lambda/powertools/e2e/Function.java
create mode 100644 powertools-e2e-tests/handlers/largemessage_idempotent/src/main/resources/log4j2.xml
create mode 100644 powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/LargeMessageE2ET.java
create mode 100644 powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/LargeMessageIdempotentE2ET.java
create mode 100644 powertools-e2e-tests/src/test/resources/large_sqs_message.txt
create mode 100644 powertools-large-messages/pom.xml
create mode 100644 powertools-large-messages/src/main/java/software/amazon/lambda/powertools/largemessages/LargeMessage.java
create mode 100644 powertools-large-messages/src/main/java/software/amazon/lambda/powertools/largemessages/LargeMessageConfig.java
create mode 100644 powertools-large-messages/src/main/java/software/amazon/lambda/powertools/largemessages/LargeMessageProcessingException.java
create mode 100644 powertools-large-messages/src/main/java/software/amazon/lambda/powertools/largemessages/internal/LargeMessageAspect.java
create mode 100644 powertools-large-messages/src/main/java/software/amazon/lambda/powertools/largemessages/internal/LargeMessageProcessor.java
create mode 100644 powertools-large-messages/src/main/java/software/amazon/lambda/powertools/largemessages/internal/LargeMessageProcessorFactory.java
create mode 100644 powertools-large-messages/src/main/java/software/amazon/lambda/powertools/largemessages/internal/LargeSNSMessageProcessor.java
create mode 100644 powertools-large-messages/src/main/java/software/amazon/lambda/powertools/largemessages/internal/LargeSQSMessageProcessor.java
create mode 100644 powertools-large-messages/src/test/java/software/amazon/lambda/powertools/largemessages/LargeMessageConfigTest.java
create mode 100644 powertools-large-messages/src/test/java/software/amazon/lambda/powertools/largemessages/internal/LargeMessageAspectTest.java
create mode 100644 powertools-large-messages/src/test/java/software/amazon/lambda/powertools/largemessages/internal/LargeMessageProcessorFactoryTest.java
diff --git a/.github/workflows/run-e2e-tests.yml b/.github/workflows/run-e2e-tests.yml
index 4ed79ca80..a998e6b2d 100644
--- a/.github/workflows/run-e2e-tests.yml
+++ b/.github/workflows/run-e2e-tests.yml
@@ -14,9 +14,16 @@ on:
- 'powertools-idempotency/**'
- 'powertools-parameters/**'
- 'powertools-metrics/**'
+ - 'powertools-large-messages/**'
- 'pom.xml'
- '.github/workflows/**'
+ pull_request:
+ branches:
+ - main
+ paths:
+ - 'powertools-e2e-tests/**'
+
jobs:
e2e:
runs-on: ubuntu-latest
diff --git a/docs/utilities/large_messages.md b/docs/utilities/large_messages.md
new file mode 100644
index 000000000..c4947a6e8
--- /dev/null
+++ b/docs/utilities/large_messages.md
@@ -0,0 +1,419 @@
+---
+title: Large Messages
+description: Utility
+---
+
+The large message utility handles SQS and SNS messages which have had their payloads
+offloaded to S3 if they are larger than the maximum allowed size (256 KB).
+
+!!! Notice
+ The large message utility (available in the `powertools-sqs` module for versions v1.16.1 and earlier) is now deprecated
+ and replaced by the `powertools-large-messages` described in this page.
+ You can still get the documentation [here](sqs_large_message_handling.md)
+ and the migration guide [here](#migration-from-the-sqs-large-message-utility).
+
+## Features
+
+- Automatically retrieve the content of S3 objects when SQS or SNS messages have been offloaded to S3.
+- Automatically delete the S3 Objects after processing succeeds.
+- Compatible with the batch module (with SQS).
+
+## Background
+
+```mermaid
+stateDiagram-v2
+ direction LR
+ Function : Lambda Function
+
+ state Application {
+ direction TB
+ sendMsg: sendMessage(QueueUrl, MessageBody)
+ extendLib: extended-client-lib
+ [*] --> sendMsg
+ sendMsg --> extendLib
+ state extendLib {
+ state if_big <>
+ bigMsg: MessageBody > 256KB ?
+ putObject: putObject(S3Bucket, S3Key, Body)
+ updateMsg: Update MessageBody with a pointer to S3 and add a message attribute
+ bigMsg --> if_big
+ if_big --> [*]: size(body) <= 256kb
+ if_big --> putObject: size(body) > 256kb
+ putObject --> updateMsg
+ updateMsg --> [*]
+ }
+ }
+
+ state Function {
+ direction TB
+ iterateMsgs: Iterate over messages
+ ptLargeMsg: powertools-large-messages
+ [*] --> Handler
+ Handler --> iterateMsgs
+ iterateMsgs --> ptLargeMsg
+ state ptLargeMsg {
+ state if_pointer <>
+ pointer: Message attribute for large message ?
+ normalMsg: Small message, body left unchanged
+ getObject: getObject(S3Pointer)
+ deleteObject: deleteObject(S3Pointer)
+ updateBody: Update message body with content from S3 object and remove message attribute
+ updateMD5: Update MD5 of the body and attributes (SQS only)
+ yourcode: YOUR CODE HERE!
+ pointer --> if_pointer
+ if_pointer --> normalMsg : False
+ normalMsg --> [*]
+ if_pointer --> getObject : True
+ getObject --> updateBody
+ updateBody --> updateMD5
+ updateMD5 --> yourcode
+ yourcode --> deleteObject
+ deleteObject --> [*]
+ }
+ }
+
+ [*] --> Application
+ Application --> Function : Lambda Invocation
+ Function --> [*]
+
+```
+
+SQS and SNS message payload is limited to 256KB. If you wish to send messages with a larger payload, you can leverage the
+[amazon-sqs-java-extended-client-lib](https://github.com/awslabs/amazon-sqs-java-extended-client-lib)
+or [amazon-sns-java-extended-client-lib](https://github.com/awslabs/amazon-sns-java-extended-client-lib) which
+offload the message to Amazon S3. See documentation
+([SQS](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-s3-messages.html)
+/ [SNS](https://docs.aws.amazon.com/sns/latest/dg/large-message-payloads.html))
+
+When offloaded to S3, the message contains a specific message attribute and the payload only contains a pointer to the
+S3 object (bucket and object key).
+
+This utility automatically retrieves messages which have been offloaded to S3 using the
+extended client libraries. Once a message's payload has been processed successfully, the
+utility deletes the payload from S3.
+
+This utility is compatible with
+versions *[1.1.0+](https://github.com/awslabs/amazon-sqs-java-extended-client-lib/releases/tag/1.1.0)*
+of amazon-sqs-java-extended-client-lib
+and *[1.0.0+](https://github.com/awslabs/amazon-sns-java-extended-client-lib/releases/tag/1.0.0)*
+of amazon-sns-java-extended-client-lib.
+
+## Install
+
+Depending on your version of Java (either Java 1.8 or 11+), the configuration slightly changes.
+
+=== "Maven Java 11+"
+```xml hl_lines="3-7 16 18 24-27"
+
+...
+
+software.amazon.lambda
+powertools-large-messages
+{{ powertools.version }}
+
+...
+
+...
+
+
+
+...
+
+dev.aspectj
+aspectj-maven-plugin
+1.13.1
+
+11
+11
+11
+
+
+software.amazon.lambda
+powertools-large-messages
+
+
+
+
+
+
+compile
+
+
+
+
+...
+
+
+```
+
+=== "Maven Java 1.8"
+
+ ```xml hl_lines="3-7 16 18 24-27"
+
+ ...
+
+ software.amazon.lambda
+ powertools-large-messages
+ {{ powertools.version }}
+
+ ...
+
+ ...
+
+
+
+ ...
+
+ org.codehaus.mojo
+ aspectj-maven-plugin
+ 1.14.0
+
+ 1.8
+ 1.8
+ 1.8
+
+
+ software.amazon.lambda
+ powertools-large-messages
+
+
+
+
+
+
+ compile
+
+
+
+
+ ...
+
+
+ ```
+
+=== "Gradle Java 11+"
+
+ ```groovy hl_lines="3 11"
+ plugins {
+ id 'java'
+ id 'io.freefair.aspectj.post-compile-weaving' version '8.1.0'
+ }
+
+ repositories {
+ mavenCentral()
+ }
+
+ dependencies {
+ aspect 'software.amazon.lambda:powertools-large-messages:{{ powertools.version }}'
+ }
+
+ sourceCompatibility = 11 // or higher
+ targetCompatibility = 11 // or higher
+ ```
+
+=== "Gradle Java 1.8"
+
+ ```groovy hl_lines="3 11"
+ plugins {
+ id 'java'
+ id 'io.freefair.aspectj.post-compile-weaving' version '6.6.3'
+ }
+
+ repositories {
+ mavenCentral()
+ }
+
+ dependencies {
+ aspect 'software.amazon.lambda:powertools-large-messages:{{ powertools.version }}'
+ }
+
+ sourceCompatibility = 1.8
+ targetCompatibility = 1.8
+ ```
+
+## Permissions
+
+As the utility interacts with Amazon S3, the lambda function must have the following permissions
+on the S3 bucket used for the large messages offloading:
+
+- `s3:GetObject`
+- `s3:DeleteObject`
+
+## Annotation
+
+The annotation `@LargeMessage` can be used on any method where the *first* parameter is one of:
+
+- `SQSEvent.SQSMessage`
+- `SNSEvent.SNSRecord`
+
+=== "SQS Example"
+
+ ```java hl_lines="8 13 15"
+ import software.amazon.lambda.powertools.largemessages.LargeMessage;
+
+ public class SqsMessageHandler implements RequestHandler {
+
+ @Override
+ public SQSBatchResponse handleRequest(SQSEvent event, Context context) {
+ for (SQSMessage message: event.getRecords()) {
+ processRawMessage(message, context);
+ }
+ return SQSBatchResponse.builder().build();
+ }
+
+ @LargeMessage
+ private void processRawMessage(SQSEvent.SQSMessage sqsMessage, Context context) {
+ // sqsMessage.getBody() will contain the content of the S3 object
+ }
+ }
+ ```
+
+=== "SNS Example"
+
+ ```java hl_lines="7 11 13"
+ import software.amazon.lambda.powertools.largemessages.LargeMessage;
+
+ public class SnsRecordHandler implements RequestHandler {
+
+ @Override
+ public String handleRequest(SNSEvent event, Context context) {
+ processSNSRecord(event.records.get(0)); // there are always only one message
+ return "Hello World";
+ }
+
+ @LargeMessage
+ private void processSNSRecord(SNSEvent.SNSRecord snsRecord) {
+ // snsRecord.getSNS().getMessage() will contain the content of the S3 object
+ }
+ }
+ ```
+
+When the Lambda function is invoked with a SQS or SNS event, the utility first
+checks if the content was offloaded to S3. In the case of a large message, there is a message attribute
+specifying the size of the offloaded message and the message contains a pointer to the S3 object.
+
+If this is the case, the utility will retrieve the object from S3 using the `getObject(bucket, key)` API,
+and place the content of the object in the message payload. You can then directly use the content of the message.
+If there was an error during the S3 download, the function will fail with a `LargeMessageProcessingException`.
+
+After your code is invoked and returns without error, the object is deleted from S3
+using the `deleteObject(bucket, key)` API. You can disable the deletion of S3 objects with the following configuration:
+
+=== "Don't delete S3 Objects"
+ ```java
+ @LargeMessage(deleteS3Object = false)
+ private void processRawMessage(SQSEvent.SQSMessage sqsMessage) {
+ // do something with the message
+ }
+ ```
+
+!!! tip "Use together with batch module"
+ This utility works perfectly together with the batch module (`powertools-batch`), especially for SQS:
+
+ ```java hl_lines="2 5-7 12 15 16" title="Combining batch and large message modules"
+ public class SqsBatchHandler implements RequestHandler {
+ private final BatchMessageHandler handler;
+
+ public SqsBatchHandler() {
+ handler = new BatchMessageHandlerBuilder()
+ .withSqsBatchHandler()
+ .buildWithRawMessageHandler(this::processMessage);
+ }
+
+ @Override
+ public SQSBatchResponse handleRequest(SQSEvent sqsEvent, Context context) {
+ return handler.processBatch(sqsEvent, context);
+ }
+
+ @LargeMessage
+ private void processMessage(SQSEvent.SQSMessage sqsMessage) {
+ // do something with the message
+ }
+ }
+ ```
+
+!!! tip "Use together with idempotency module"
+ This utility also works together with the idempotency module (`powertools-idempotency`).
+ You can add both the `@LargeMessage` and `@Idempotent` annotations, in any order, to the same method.
+ The `@Idempotent` takes precedence over the `@LargeMessage` annotation.
+ It means Idempotency module will use the initial raw message (containing the S3 pointer) and not the large message.
+
+ ```java hl_lines="6 23-25" title="Combining idempotency and large message modules"
+ public class SqsBatchHandler implements RequestHandler {
+
+ public SqsBatchHandler() {
+ Idempotency.config().withConfig(
+ IdempotencyConfig.builder()
+ .withEventKeyJMESPath("body") // get the body of the message for the idempotency key
+ .build())
+ .withPersistenceStore(
+ DynamoDBPersistenceStore.builder()
+ .withTableName(System.getenv("IDEMPOTENCY_TABLE"))
+ .build()
+ ).configure();
+ }
+
+ @Override
+ public SQSBatchResponse handleRequest(SQSEvent sqsEvent, Context context) {
+ for (SQSMessage message: event.getRecords()) {
+ processRawMessage(message, context);
+ }
+ return SQSBatchResponse.builder().build();
+ }
+
+ @Idempotent
+ @LargeMessage
+ private String processRawMessage(@IdempotencyKey SQSEvent.SQSMessage sqsMessage, Context context) {
+ // do something with the message
+ }
+ }
+ ```
+
+## Customizing S3 client configuration
+
+To interact with S3, the utility creates a default S3 Client :
+
+=== "Default S3 Client"
+ ```java
+ S3Client client = S3Client.builder()
+ .httpClient(UrlConnectionHttpClient.builder().build())
+ .region(Region.of(System.getenv(AWS_REGION_ENV)))
+ .build();
+ ```
+
+If you need to customize this `S3Client`, you can leverage the `LargeMessageConfig` singleton:
+
+=== "Custom S3 Client"
+ ```java hl_lines="6"
+ import software.amazon.lambda.powertools.largemessages.LargeMessage;
+
+ public class SnsRecordHandler implements RequestHandler {
+
+ public SnsRecordHandler() {
+ LargeMessageConfig.init().withS3Client(/* put your custom S3Client here */);
+ }
+
+ @Override
+ public String handleRequest(SNSEvent event, Context context) {
+ processSNSRecord(event.records.get(0));
+ return "Hello World";
+ }
+
+ @LargeMessage
+ private void processSNSRecord(SNSEvent.SNSRecord snsRecord) {
+ // snsRecord.getSNS().getMessage() will contain the content of the S3 object
+ }
+ }
+ ```
+
+## Migration from the SQS Large Message utility
+
+- Replace the dependency in maven / gradle: `powertools-sqs` ==> `powertools-large-messages`
+- Replace the annotation: `@SqsLargeMessage` ==> `@LargeMessage` (the new module handles both SQS and SNS)
+- Move the annotation away from the Lambda `handleRequest` method and put it on a method with `SQSEvent.SQSMessage`
+ or `SNSEvent.SNSRecord` as first parameter.
+- The annotation now handles a single message, contrary to the previous version that was handling the complete batch.
+ It gives more control, especially when dealing with partial failures with SQS (see the batch module).
+- The new module only provides an annotation, an equivalent to the `SqsUtils` class is not available anymore in this new version.
+
+Finally, if you are still using the `powertools-sqs` library for batch processing, consider moving to `powertools-batch` at the same time to remove the dependency on this library completely; it has been deprecated and will be removed in v2.
\ No newline at end of file
diff --git a/docs/utilities/sqs_large_message_handling.md b/docs/utilities/sqs_large_message_handling.md
index 82e1afef4..6308f1c79 100644
--- a/docs/utilities/sqs_large_message_handling.md
+++ b/docs/utilities/sqs_large_message_handling.md
@@ -3,6 +3,10 @@ title: SQS Large Message Handling
description: Utility
---
+!!! warning
+This module is now deprecated and will be removed in version 2.
+See [Large Message Handling](large_messages.md) for the new module (`powertools-large-messages`) documentation.
+
The large message handling utility handles SQS messages which have had their payloads
offloaded to S3 due to them being larger than the SQS maximum.
@@ -11,16 +15,19 @@ The utility automatically retrieves messages which have been offloaded to S3 usi
client library. Once the message payloads have been processed successful the
utility can delete the message payloads from S3.
-This utility is compatible with versions *[1.1.0+](https://github.com/awslabs/amazon-sqs-java-extended-client-lib)* of amazon-sqs-java-extended-client-lib.
+This utility is compatible with versions *[1.1.0+](https://github.com/awslabs/amazon-sqs-java-extended-client-lib)* of
+amazon-sqs-java-extended-client-lib.
=== "Maven"
- ```xml
-
- com.amazonaws
- amazon-sqs-java-extended-client-lib
- 1.1.0
-
- ```
+
+```xml
+
+
+ com.amazonaws
+ amazon-sqs-java-extended-client-lib
+ 1.1.0
+
+```
=== "Gradle"
```groovy
@@ -33,48 +40,49 @@ This utility is compatible with versions *[1.1.0+](https://github.com/awslabs/am
Depending on your version of Java (either Java 1.8 or 11+), the configuration slightly changes.
=== "Maven Java 11+"
- ```xml hl_lines="3-7 16 18 24-27"
-
- ...
-
- software.amazon.lambda
- powertools-sqs
- {{ powertools.version }}
-
- ...
-
- ...
-
-
-
- ...
-
- dev.aspectj
- aspectj-maven-plugin
- 1.13.1
-
- 11
- 11
- 11
-
-
- software.amazon.lambda
- powertools-sqs
-
-
-
-
-
-
- compile
-
-
-
-
- ...
-
-
- ```
+
+```xml hl_lines="3-7 16 18 24-27"
+
+...
+
+software.amazon.lambda
+powertools-sqs
+{{ powertools.version }}
+
+...
+
+...
+
+
+
+...
+
+dev.aspectj
+aspectj-maven-plugin
+1.13.1
+
+11
+11
+11
+
+
+software.amazon.lambda
+powertools-sqs
+
+
+
+
+
+
+compile
+
+
+
+
+...
+
+
+```
=== "Maven Java 1.8"
@@ -186,12 +194,13 @@ which implements `com.amazonaws.services.lambda.runtime.RequestHandler` with
`@SqsLargeMessage` creates a default S3 Client `AmazonS3 amazonS3 = AmazonS3ClientBuilder.defaultClient()`.
-!!! tip
- When the Lambda function is invoked with an event from SQS, each received record
- in the SQSEvent is checked to see to validate if it is offloaded to S3.
- If it does then `getObject(bucket, key)` will be called, and the payload retrieved.
- If there is an error during this process then the function will fail with a `FailedProcessingLargePayloadException` exception.
-
+!!! tip
+When the Lambda function is invoked with an event from SQS, each received record
+in the SQSEvent is checked to see to validate if it is offloaded to S3.
+If it does then `getObject(bucket, key)` will be called, and the payload retrieved.
+If there is an error during this process then the function will fail with a `FailedProcessingLargePayloadException`
+exception.
+
If the request handler method returns without error then each payload will be
deleted from S3 using `deleteObject(bucket, key)`
diff --git a/mkdocs.yml b/mkdocs.yml
index 841a95fae..62d8d75ce 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -13,7 +13,7 @@ nav:
- Utilities:
- utilities/idempotency.md
- utilities/parameters.md
- - utilities/sqs_large_message_handling.md
+ - utilities/large_messages.md
- utilities/batch.md
- utilities/validation.md
- utilities/custom_resources.md
diff --git a/pom.xml b/pom.xml
index 1d80b3081..3e751f186 100644
--- a/pom.xml
+++ b/pom.xml
@@ -52,6 +52,7 @@
powertools-test-suitepowertools-cloudformationpowertools-idempotency
+ powertools-large-messagespowertools-e2e-testsexamples
@@ -89,7 +90,7 @@
3.5.03.3.03.1.0
- 5.9.3
+ 5.10.01.0.60.5.1
@@ -243,21 +244,16 @@
- org.junit.jupiter
- junit-jupiter-api
- ${junit-jupiter.version}
- test
-
-
- org.junit.jupiter
- junit-jupiter-engine
- ${junit-jupiter.version}
- test
+ org.junit
+ junit-bom
+ ${junit.version}
+ pom
+ import
- org.junit.jupiter
- junit-jupiter-params
- ${junit-jupiter.version}
+ org.junit-pioneer
+ junit-pioneer
+ 1.9.1test
@@ -540,9 +536,9 @@
- jdk11
+ newerThanJdk8
- 11
+ [9,)
diff --git a/powertools-e2e-tests/handlers/idempotency/pom.xml b/powertools-e2e-tests/handlers/idempotency/pom.xml
index 4e24c738c..25dfbfabf 100644
--- a/powertools-e2e-tests/handlers/idempotency/pom.xml
+++ b/powertools-e2e-tests/handlers/idempotency/pom.xml
@@ -17,6 +17,14 @@
software.amazon.lambdapowertools-idempotency
+
+ software.amazon.lambda
+ powertools-logging
+
+
+ org.apache.logging.log4j
+ log4j-slf4j2-impl
+ com.amazonawsaws-lambda-java-events
@@ -38,6 +46,10 @@
software.amazon.lambdapowertools-idempotency
+
+ software.amazon.lambda
+ powertools-logging
+
diff --git a/powertools-e2e-tests/handlers/idempotency/src/main/java/software/amazon/lambda/powertools/e2e/Function.java b/powertools-e2e-tests/handlers/idempotency/src/main/java/software/amazon/lambda/powertools/e2e/Function.java
index 8c2b5fc58..e4c2f2b9a 100644
--- a/powertools-e2e-tests/handlers/idempotency/src/main/java/software/amazon/lambda/powertools/e2e/Function.java
+++ b/powertools-e2e-tests/handlers/idempotency/src/main/java/software/amazon/lambda/powertools/e2e/Function.java
@@ -28,6 +28,7 @@
import software.amazon.lambda.powertools.idempotency.IdempotencyConfig;
import software.amazon.lambda.powertools.idempotency.Idempotent;
import software.amazon.lambda.powertools.idempotency.persistence.DynamoDBPersistenceStore;
+import software.amazon.lambda.powertools.logging.Logging;
public class Function implements RequestHandler {
@@ -53,6 +54,7 @@ public Function(DynamoDbClient client) {
).configure();
}
+ @Logging(logEvent = true)
@Idempotent
public String handleRequest(Input input, Context context) {
DateTimeFormatter dtf = DateTimeFormatter.ISO_DATE_TIME.withZone(TimeZone.getTimeZone("UTC").toZoneId());
diff --git a/powertools-e2e-tests/handlers/idempotency/src/main/resources/log4j2.xml b/powertools-e2e-tests/handlers/idempotency/src/main/resources/log4j2.xml
new file mode 100644
index 000000000..8925f70b9
--- /dev/null
+++ b/powertools-e2e-tests/handlers/idempotency/src/main/resources/log4j2.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/powertools-e2e-tests/handlers/largemessage/pom.xml b/powertools-e2e-tests/handlers/largemessage/pom.xml
new file mode 100644
index 000000000..c626f5f64
--- /dev/null
+++ b/powertools-e2e-tests/handlers/largemessage/pom.xml
@@ -0,0 +1,72 @@
+
+ 4.0.0
+
+
+ software.amazon.lambda
+ e2e-test-handlers-parent
+ 1.0.0
+
+
+ e2e-test-handler-largemessage
+ jar
+ A Lambda function using Powertools for AWS Lambda (Java) large message
+
+
+
+ software.amazon.awssdk
+ dynamodb
+
+
+ software.amazon.lambda
+ powertools-large-messages
+
+
+ software.amazon.lambda
+ powertools-logging
+
+
+ com.amazonaws
+ aws-lambda-java-events
+
+
+ org.apache.logging.log4j
+ log4j-slf4j2-impl
+
+
+
+
+
+
+ dev.aspectj
+ aspectj-maven-plugin
+
+ ${maven.compiler.source}
+ ${maven.compiler.target}
+ ${maven.compiler.target}
+
+
+ software.amazon.lambda
+ powertools-large-messages
+
+
+ software.amazon.lambda
+ powertools-logging
+
+
+
+
+
+
+ compile
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-shade-plugin
+
+
+
+
diff --git a/powertools-e2e-tests/handlers/largemessage/src/main/java/software/amazon/lambda/powertools/e2e/Function.java b/powertools-e2e-tests/handlers/largemessage/src/main/java/software/amazon/lambda/powertools/e2e/Function.java
new file mode 100644
index 000000000..70f1bceea
--- /dev/null
+++ b/powertools-e2e-tests/handlers/largemessage/src/main/java/software/amazon/lambda/powertools/e2e/Function.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
+package software.amazon.lambda.powertools.e2e;
+
+import com.amazonaws.services.lambda.runtime.Context;
+import com.amazonaws.services.lambda.runtime.RequestHandler;
+import com.amazonaws.services.lambda.runtime.events.SQSBatchResponse;
+import com.amazonaws.services.lambda.runtime.events.SQSEvent;
+import com.amazonaws.services.lambda.runtime.events.SQSEvent.SQSMessage;
+import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
+import software.amazon.awssdk.services.dynamodb.model.AttributeValue;
+import software.amazon.awssdk.services.dynamodb.model.PutItemRequest;
+import software.amazon.awssdk.utils.BinaryUtils;
+import software.amazon.awssdk.utils.Md5Utils;
+import software.amazon.lambda.powertools.largemessages.LargeMessage;
+import software.amazon.lambda.powertools.logging.Logging;
+
+import java.nio.charset.StandardCharsets;
+import java.util.HashMap;
+import java.util.Map;
+
+public class Function implements RequestHandler {
+
+ private static final String TABLE_FOR_ASYNC_TESTS = System.getenv("TABLE_FOR_ASYNC_TESTS");
+ private DynamoDbClient client;
+
+ public Function() {
+ if (client == null) {
+ client = DynamoDbClient.builder()
+ .httpClient(UrlConnectionHttpClient.builder().build())
+ .region(Region.of(System.getenv("AWS_REGION")))
+ .build();
+ }
+ }
+
+ @Logging(logEvent = true)
+ public SQSBatchResponse handleRequest(SQSEvent event, Context context) {
+ for (SQSMessage message: event.getRecords()) {
+ processRawMessage(message, context);
+ }
+ return SQSBatchResponse.builder().build();
+ }
+
+ @LargeMessage
+ private void processRawMessage(SQSMessage sqsMessage, Context context) {
+ String bodyMD5 = md5(sqsMessage.getBody());
+ if (!sqsMessage.getMd5OfBody().equals(bodyMD5)) {
+ throw new SecurityException(String.format("message digest does not match, expected %s, got %s", sqsMessage.getMd5OfBody(), bodyMD5));
+ }
+
+ Map item = new HashMap<>();
+ item.put("functionName", AttributeValue.builder().s(context.getFunctionName()).build());
+ item.put("id", AttributeValue.builder().s(sqsMessage.getMessageId()).build());
+ item.put("bodyMD5", AttributeValue.builder().s(bodyMD5).build());
+ item.put("bodySize", AttributeValue.builder().n(String.valueOf(sqsMessage.getBody().getBytes(StandardCharsets.UTF_8).length)).build());
+
+ client.putItem(PutItemRequest.builder().tableName(TABLE_FOR_ASYNC_TESTS).item(item).build());
+ }
+
+ private String md5(String message) {
+ return BinaryUtils.toHex(Md5Utils.computeMD5Hash(message.getBytes(StandardCharsets.UTF_8)));
+ }
+}
\ No newline at end of file
diff --git a/powertools-e2e-tests/handlers/largemessage/src/main/resources/log4j2.xml b/powertools-e2e-tests/handlers/largemessage/src/main/resources/log4j2.xml
new file mode 100644
index 000000000..8925f70b9
--- /dev/null
+++ b/powertools-e2e-tests/handlers/largemessage/src/main/resources/log4j2.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/powertools-e2e-tests/handlers/largemessage_idempotent/pom.xml b/powertools-e2e-tests/handlers/largemessage_idempotent/pom.xml
new file mode 100644
index 000000000..9635efd87
--- /dev/null
+++ b/powertools-e2e-tests/handlers/largemessage_idempotent/pom.xml
@@ -0,0 +1,77 @@
+
+ 4.0.0
+
+
+ software.amazon.lambda
+ e2e-test-handlers-parent
+ 1.0.0
+
+
+ e2e-test-handler-large-msg-idempotent
+ jar
+ A Lambda function using Powertools for AWS Lambda (Java) idempotency with large messages
+
+
+
+ software.amazon.lambda
+ powertools-idempotency
+
+
+ software.amazon.lambda
+ powertools-large-messages
+
+
+ software.amazon.lambda
+ powertools-logging
+
+
+ com.amazonaws
+ aws-lambda-java-events
+
+
+ org.apache.logging.log4j
+ log4j-slf4j2-impl
+
+
+
+
+
+
+
+ dev.aspectj
+ aspectj-maven-plugin
+
+ ${maven.compiler.source}
+ ${maven.compiler.target}
+ ${maven.compiler.target}
+
+
+ software.amazon.lambda
+ powertools-idempotency
+
+
+ software.amazon.lambda
+ powertools-large-messages
+
+
+ software.amazon.lambda
+ powertools-logging
+
+
+
+
+
+
+ compile
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-shade-plugin
+
+
+
+
diff --git a/powertools-e2e-tests/handlers/largemessage_idempotent/src/main/java/software/amazon/lambda/powertools/e2e/Function.java b/powertools-e2e-tests/handlers/largemessage_idempotent/src/main/java/software/amazon/lambda/powertools/e2e/Function.java
new file mode 100644
index 000000000..b9f737857
--- /dev/null
+++ b/powertools-e2e-tests/handlers/largemessage_idempotent/src/main/java/software/amazon/lambda/powertools/e2e/Function.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
+package software.amazon.lambda.powertools.e2e;
+
+import com.amazonaws.services.lambda.runtime.Context;
+import com.amazonaws.services.lambda.runtime.RequestHandler;
+import com.amazonaws.services.lambda.runtime.events.SQSBatchResponse;
+import com.amazonaws.services.lambda.runtime.events.SQSEvent;
+import java.nio.charset.StandardCharsets;
+import java.time.Duration;
+import java.time.Instant;
+import java.time.format.DateTimeFormatter;
+import java.time.temporal.ChronoUnit;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.TimeZone;
+import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
+import software.amazon.awssdk.services.dynamodb.model.AttributeValue;
+import software.amazon.awssdk.services.dynamodb.model.PutItemRequest;
+import software.amazon.awssdk.utils.BinaryUtils;
+import software.amazon.awssdk.utils.Md5Utils;
+import software.amazon.lambda.powertools.idempotency.Idempotency;
+import software.amazon.lambda.powertools.idempotency.IdempotencyConfig;
+import software.amazon.lambda.powertools.idempotency.IdempotencyKey;
+import software.amazon.lambda.powertools.idempotency.Idempotent;
+import software.amazon.lambda.powertools.idempotency.persistence.DynamoDBPersistenceStore;
+import software.amazon.lambda.powertools.largemessages.LargeMessage;
+import software.amazon.lambda.powertools.logging.Logging;
+
+public class Function implements RequestHandler {
+
+ private static final String TABLE_FOR_ASYNC_TESTS = System.getenv("TABLE_FOR_ASYNC_TESTS");
+ private final DynamoDbClient client;
+
+ public Function() {
+ this(DynamoDbClient
+ .builder()
+ .httpClient(UrlConnectionHttpClient.builder().build())
+ .region(Region.of(System.getenv("AWS_REGION")))
+ .build());
+ }
+
+ public Function(DynamoDbClient client) {
+ this.client = client;
+ Idempotency.config().withConfig(
+ IdempotencyConfig.builder()
+ .withExpiration(Duration.of(22, ChronoUnit.SECONDS))
+ .withEventKeyJMESPath("body") // get the body of the message
+ .build())
+ .withPersistenceStore(
+ DynamoDBPersistenceStore.builder()
+ .withDynamoDbClient(client)
+ .withTableName(System.getenv("IDEMPOTENCY_TABLE"))
+ .build()
+ ).configure();
+ }
+
+ @Logging(logEvent = true)
+ public SQSBatchResponse handleRequest(SQSEvent event, Context context) {
+ for (SQSEvent.SQSMessage message: event.getRecords()) {
+ processRawMessage(message, context);
+ }
+ return SQSBatchResponse.builder().build();
+ }
+
+ @Idempotent
+ @LargeMessage(deleteS3Object = false)
+ private String processRawMessage(@IdempotencyKey SQSEvent.SQSMessage sqsMessage, Context context) {
+ String bodyMD5 = md5(sqsMessage.getBody());
+ if (!sqsMessage.getMd5OfBody().equals(bodyMD5)) {
+ throw new SecurityException(String.format("message digest does not match, expected %s, got %s", sqsMessage.getMd5OfBody(), bodyMD5));
+ }
+
+ Instant now = Instant.now();
+ Map item = new HashMap<>();
+ item.put("functionName", AttributeValue.builder().s(context.getFunctionName()).build());
+ item.put("id", AttributeValue.builder().s(sqsMessage.getMessageId()).build());
+ item.put("bodyMD5", AttributeValue.builder().s(bodyMD5).build());
+ item.put("now", AttributeValue.builder().n(String.valueOf(now.getEpochSecond())).build());
+ item.put("bodySize", AttributeValue.builder().n(String.valueOf(sqsMessage.getBody().getBytes(StandardCharsets.UTF_8).length)).build());
+
+ client.putItem(PutItemRequest.builder().tableName(TABLE_FOR_ASYNC_TESTS).item(item).build());
+
+ DateTimeFormatter dtf = DateTimeFormatter.ISO_DATE_TIME.withZone(TimeZone.getTimeZone("UTC").toZoneId());
+ return dtf.format(now);
+ }
+
+ private String md5(String message) {
+ return BinaryUtils.toHex(Md5Utils.computeMD5Hash(message.getBytes(StandardCharsets.UTF_8)));
+ }
+}
\ No newline at end of file
diff --git a/powertools-e2e-tests/handlers/largemessage_idempotent/src/main/resources/log4j2.xml b/powertools-e2e-tests/handlers/largemessage_idempotent/src/main/resources/log4j2.xml
new file mode 100644
index 000000000..8925f70b9
--- /dev/null
+++ b/powertools-e2e-tests/handlers/largemessage_idempotent/src/main/resources/log4j2.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/powertools-e2e-tests/handlers/pom.xml b/powertools-e2e-tests/handlers/pom.xml
index ae26364dd..4dd8cbb45 100644
--- a/powertools-e2e-tests/handlers/pom.xml
+++ b/powertools-e2e-tests/handlers/pom.xml
@@ -20,6 +20,8 @@
3.5.01.13.13.11.0
+ 2.20.108
+ 2.20.0
@@ -32,6 +34,14 @@
+
+ software.amazon.awssdk
+ bom
+ ${aws.sdk.version}
+ pom
+ import
+
+
software.amazon.lambdapowertools-logging
@@ -57,6 +67,11 @@
powertools-parameters${lambda.powertools.version}
+
+ software.amazon.lambda
+ powertools-large-messages
+ ${lambda.powertools.version}
+ com.amazonawsaws-lambda-java-core
@@ -67,6 +82,11 @@
aws-lambda-java-events${lambda.java.events}
+
+ org.apache.logging.log4j
+ log4j-slf4j2-impl
+ ${log4j.version}
+
diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml
index 7e354d15e..500b7f30a 100644
--- a/powertools-e2e-tests/pom.xml
+++ b/powertools-e2e-tests/pom.xml
@@ -51,6 +51,13 @@
test
+
+ software.amazon.awssdk
+ dynamodb
+ ${aws.sdk.version}
+ test
+
+
software.amazon.awssdkcloudwatch
@@ -65,6 +72,20 @@
test
+
+ software.amazon.awssdk
+ sqs
+ ${aws.sdk.version}
+ test
+
+
+
+ com.amazonaws
+ amazon-sqs-java-extended-client-lib
+ 2.0.3
+ test
+
+
software.amazon.awssdkurl-connection-client
@@ -77,6 +98,12 @@
test
+
+ commons-io
+ commons-io
+ 2.11.0
+
+
org.junit.jupiterjunit-jupiter-engine
@@ -182,6 +209,7 @@
+ 1**/*E2ET.java
diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/IdempotencyE2ET.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/IdempotencyE2ET.java
index fed823299..242d1a2db 100644
--- a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/IdempotencyE2ET.java
+++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/IdempotencyE2ET.java
@@ -14,10 +14,11 @@
package software.amazon.lambda.powertools;
+import static software.amazon.lambda.powertools.testutils.Infrastructure.FUNCTION_NAME_OUTPUT;
import static software.amazon.lambda.powertools.testutils.lambda.LambdaInvoker.invokeFunction;
import java.time.Year;
-import java.util.Collections;
+import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import org.assertj.core.api.Assertions;
@@ -40,9 +41,9 @@ public static void setup() {
.testName(IdempotencyE2ET.class.getSimpleName())
.pathToFunction("idempotency")
.idempotencyTable("idempo" + random)
- .environmentVariables(Collections.singletonMap("IDEMPOTENCY_TABLE", "idempo" + random))
.build();
- functionName = infrastructure.deploy();
+ Map outputs = infrastructure.deploy();
+ functionName = outputs.get(FUNCTION_NAME_OUTPUT);
}
@AfterAll
diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/LargeMessageE2ET.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/LargeMessageE2ET.java
new file mode 100644
index 000000000..2d9f74135
--- /dev/null
+++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/LargeMessageE2ET.java
@@ -0,0 +1,167 @@
+package software.amazon.lambda.powertools;
+
+import com.amazon.sqs.javamessaging.AmazonSQSExtendedClient;
+import com.amazon.sqs.javamessaging.ExtendedClientConfiguration;
+import org.apache.commons.io.IOUtils;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.Timeout;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import software.amazon.awssdk.http.SdkHttpClient;
+import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
+import software.amazon.awssdk.services.dynamodb.model.AttributeValue;
+import software.amazon.awssdk.services.dynamodb.model.DeleteItemRequest;
+import software.amazon.awssdk.services.dynamodb.model.QueryRequest;
+import software.amazon.awssdk.services.dynamodb.model.QueryResponse;
+import software.amazon.awssdk.services.s3.S3Client;
+import software.amazon.awssdk.services.sqs.SqsClient;
+import software.amazon.awssdk.services.sqs.model.SendMessageRequest;
+import software.amazon.lambda.powertools.testutils.Infrastructure;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.TimeUnit;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static software.amazon.lambda.powertools.testutils.Infrastructure.FUNCTION_NAME_OUTPUT;
+
+public class LargeMessageE2ET {
+
+ private static final Logger LOG = LoggerFactory.getLogger(LargeMessageE2ET.class);
+ private static final SdkHttpClient httpClient = UrlConnectionHttpClient.builder().build();
+ private static final Region region = Region.of(System.getProperty("AWS_DEFAULT_REGION", "eu-west-1"));
+
+ private static final S3Client s3Client = S3Client.builder()
+ .httpClient(httpClient)
+ .region(region)
+ .build();
+ private static final DynamoDbClient dynamoDbClient = DynamoDbClient.builder()
+ .httpClient(httpClient)
+ .region(region)
+ .build();
+
+ private static Infrastructure infrastructure;
+ private static String functionName;
+ private static String bucketName;
+ private static String queueUrl;
+ private static String tableName;
+ private String messageId;
+
+ @BeforeAll
+ @Timeout(value = 5, unit = TimeUnit.MINUTES)
+ public static void setup() {
+ String random = UUID.randomUUID().toString().substring(0, 6);
+ bucketName = "largemessagebucket" + random;
+ String queueName = "largemessagequeue" + random;
+
+ infrastructure = Infrastructure.builder()
+ .testName(LargeMessageE2ET.class.getSimpleName())
+ .queue(queueName)
+ .largeMessagesBucket(bucketName)
+ .pathToFunction("largemessage")
+ .timeoutInSeconds(60)
+ .build();
+
+ Map outputs = infrastructure.deploy();
+ functionName = outputs.get(FUNCTION_NAME_OUTPUT);
+ queueUrl = outputs.get("QueueURL");
+ tableName = outputs.get("TableNameForAsyncTests");
+
+ LOG.info("Testing '" + LargeMessageE2ET.class.getSimpleName() + "'");
+ }
+
+ @AfterEach
+ public void reset() {
+ if (messageId != null) {
+ Map itemToDelete = new HashMap<>();
+ itemToDelete.put("functionName", AttributeValue.builder().s(functionName).build());
+ itemToDelete.put("id", AttributeValue.builder().s(messageId).build());
+ dynamoDbClient.deleteItem(DeleteItemRequest.builder().tableName(tableName).key(itemToDelete).build());
+ messageId = null;
+ }
+ }
+
+ @AfterAll
+ public static void tearDown() {
+ if (infrastructure != null)
+ infrastructure.destroy();
+ }
+
+ @Test
+ public void bigSQSMessageOffloadedToS3_shouldLoadFromS3() throws IOException, InterruptedException {
+ // given
+ final ExtendedClientConfiguration extendedClientConfig =
+ new ExtendedClientConfiguration()
+ .withPayloadSupportEnabled(s3Client, bucketName);
+ AmazonSQSExtendedClient client = new AmazonSQSExtendedClient(SqsClient.builder().httpClient(httpClient).build(), extendedClientConfig);
+ InputStream inputStream = this.getClass().getResourceAsStream("/large_sqs_message.txt");
+ String bigMessage = IOUtils.toString(inputStream, StandardCharsets.UTF_8);
+
+ // when
+ client.sendMessage(SendMessageRequest
+ .builder()
+ .queueUrl(queueUrl)
+ .messageBody(bigMessage)
+ .build());
+
+ Thread.sleep(30000); // wait for function to be executed
+
+ // then
+ QueryRequest request = QueryRequest
+ .builder()
+ .tableName(tableName)
+ .keyConditionExpression("functionName = :func")
+ .expressionAttributeValues(Collections.singletonMap(":func", AttributeValue.builder().s(functionName).build()))
+ .build();
+ QueryResponse response = dynamoDbClient.query(request);
+ List
+ *
+ *
To disable the deletion of S3 objects, you can configure the {@code deleteS3Object} option to false (default is true):
+ *
+ * @LargeMessage(deleteS3Object = false)
+ *
+ *
+ *
+ *
Note 1: Retrieving payloads and deleting objects from S3 will increase the duration of the
+ * Lambda function.
+ *
Note 2: Make sure to configure your function with enough memory to be able to retrieve S3 objects.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+public @interface LargeMessage {
+
+ /**
+ * Specify if S3 objects must be deleted after being processed (default = true)
+ Alternatively you might consider using S3 lifecycle policies to remove the payloads automatically after a period of time.
+ */
+ boolean deleteS3Object() default true;
+}
diff --git a/powertools-large-messages/src/main/java/software/amazon/lambda/powertools/largemessages/LargeMessageConfig.java b/powertools-large-messages/src/main/java/software/amazon/lambda/powertools/largemessages/LargeMessageConfig.java
new file mode 100644
index 000000000..fb8ea9b15
--- /dev/null
+++ b/powertools-large-messages/src/main/java/software/amazon/lambda/powertools/largemessages/LargeMessageConfig.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
+package software.amazon.lambda.powertools.largemessages;
+
+import static software.amazon.lambda.powertools.core.internal.LambdaConstants.AWS_REGION_ENV;
+
+import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.services.s3.S3Client;
+import software.amazon.awssdk.services.s3.S3ClientBuilder;
+
+/**
+ * Singleton instance for Large Message Config. We need this to provide a way to customize the S3 client configuration used by the annotation.
+ *
+ * Optional: Use it in your Lambda constructor to pass a custom {@link S3Client} to the {@link software.amazon.lambda.powertools.largemessages.internal.LargeMessageProcessor}
+ *
+ * If you don't use this, a default S3Client will be created.
+ *
+ */
+public class LargeMessageConfig {
+
+ private static final LargeMessageConfig INSTANCE = new LargeMessageConfig();
+ private S3Client s3Client;
+
+ private LargeMessageConfig() {
+ }
+
+ /**
+ * Retrieve the singleton instance (you generally don't need to use this one, used internally by the library)
+ *
+ * @return the singleton instance
+ */
+ public static LargeMessageConfig get() {
+ return INSTANCE;
+ }
+
+ /**
+ * Initialize the singleton instance
+ *
+ * @return the singleton instance
+ */
+ public static LargeMessageConfig init() {
+ return INSTANCE;
+ }
+
+ public void withS3Client(S3Client s3Client) {
+ if (this.s3Client == null) {
+ this.s3Client = s3Client;
+ }
+ }
+
+ // For tests purpose
+ void resetS3Client() {
+ this.s3Client = null;
+ }
+
+ // Getter needs to initialize if not done with setter
+ public S3Client getS3Client() {
+ if (this.s3Client == null) {
+ S3ClientBuilder s3ClientBuilder = S3Client.builder()
+ .httpClient(UrlConnectionHttpClient.builder().build())
+ .region(Region.of(System.getenv(AWS_REGION_ENV)));
+ this.s3Client = s3ClientBuilder.build();
+ }
+ return this.s3Client;
+ }
+}
diff --git a/powertools-large-messages/src/main/java/software/amazon/lambda/powertools/largemessages/LargeMessageProcessingException.java b/powertools-large-messages/src/main/java/software/amazon/lambda/powertools/largemessages/LargeMessageProcessingException.java
new file mode 100644
index 000000000..20b19230a
--- /dev/null
+++ b/powertools-large-messages/src/main/java/software/amazon/lambda/powertools/largemessages/LargeMessageProcessingException.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
+package software.amazon.lambda.powertools.largemessages;
+
+/**
+ * Exception that occurs when the utility fails to retrieve the content from S3
+ */
+public class LargeMessageProcessingException extends RuntimeException {
+ public LargeMessageProcessingException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public LargeMessageProcessingException(String message) {
+ super(message);
+ }
+}
diff --git a/powertools-large-messages/src/main/java/software/amazon/lambda/powertools/largemessages/internal/LargeMessageAspect.java b/powertools-large-messages/src/main/java/software/amazon/lambda/powertools/largemessages/internal/LargeMessageAspect.java
new file mode 100644
index 000000000..861193203
--- /dev/null
+++ b/powertools-large-messages/src/main/java/software/amazon/lambda/powertools/largemessages/internal/LargeMessageAspect.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
+package software.amazon.lambda.powertools.largemessages.internal;
+
+import java.util.Optional;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Pointcut;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import software.amazon.lambda.powertools.largemessages.LargeMessage;
+
+/**
+ * Handle {@link LargeMessage} annotations.
+ */
+@Aspect
+public class LargeMessageAspect {
+
+ private static final Logger LOG = LoggerFactory.getLogger(LargeMessageAspect.class);
+
+ @SuppressWarnings({"EmptyMethod"})
+ @Pointcut("@annotation(largeMessage)")
+ public void callAt(LargeMessage largeMessage) {
+ }
+
+ @Around(value = "callAt(largeMessage) && execution(@LargeMessage * *.*(..))", argNames = "pjp,largeMessage")
+ public Object around(ProceedingJoinPoint pjp,
+ LargeMessage largeMessage) throws Throwable {
+ Object[] proceedArgs = pjp.getArgs();
+
+ // we need a message to process
+ if (proceedArgs.length == 0) {
+ LOG.warn("@LargeMessage annotation is placed on a method without any message to process, proceeding");
+ return pjp.proceed(proceedArgs);
+ }
+
+ Object message = proceedArgs[0];
+ Optional> largeMessageProcessor = LargeMessageProcessorFactory.get(message);
+
+ if (!largeMessageProcessor.isPresent()) {
+ LOG.warn("@LargeMessage annotation is placed on a method with unsupported message type [{}], proceeding", message.getClass());
+ return pjp.proceed(proceedArgs);
+ }
+
+ return largeMessageProcessor.get().process(pjp, largeMessage.deleteS3Object());
+ }
+
+}
diff --git a/powertools-large-messages/src/main/java/software/amazon/lambda/powertools/largemessages/internal/LargeMessageProcessor.java b/powertools-large-messages/src/main/java/software/amazon/lambda/powertools/largemessages/internal/LargeMessageProcessor.java
new file mode 100644
index 000000000..f0e89e631
--- /dev/null
+++ b/powertools-large-messages/src/main/java/software/amazon/lambda/powertools/largemessages/internal/LargeMessageProcessor.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
+package software.amazon.lambda.powertools.largemessages.internal;
+
+import static java.lang.String.format;
+
+import java.nio.charset.StandardCharsets;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import software.amazon.awssdk.core.exception.SdkException;
+import software.amazon.awssdk.services.s3.S3Client;
+import software.amazon.lambda.powertools.largemessages.LargeMessageConfig;
+import software.amazon.lambda.powertools.largemessages.LargeMessageProcessingException;
+import software.amazon.payloadoffloading.S3BackedPayloadStore;
+import software.amazon.payloadoffloading.S3Dao;
+
+/**
+ * Abstract processor for Large Messages. Handle the download from S3 and replace the actual S3 pointer with the content
+ * of the S3 Object leveraging the payloadoffloading library.
+ *
+ * @param any message type that support Large Messages with S3 pointers
+ * ({@link com.amazonaws.services.lambda.runtime.events.SQSEvent.SQSMessage} and {@link com.amazonaws.services.lambda.runtime.events.SNSEvent.SNSRecord} at the moment)
+ */
+abstract class LargeMessageProcessor {
+ protected static final String RESERVED_ATTRIBUTE_NAME = "ExtendedPayloadSize";
+ private static final Logger LOG = LoggerFactory.getLogger(LargeMessageProcessor.class);
+
+ private final S3Client s3Client = LargeMessageConfig.get().getS3Client();
+ private final S3BackedPayloadStore payloadStore = new S3BackedPayloadStore(new S3Dao(s3Client), "DUMMY");
+
+ public Object process(ProceedingJoinPoint pjp, boolean deleteS3Object) throws Throwable {
+ Object[] proceedArgs = pjp.getArgs();
+ T message = (T) proceedArgs[0];
+
+ if (!isLargeMessage(message)) {
+ LOG.warn("Not a large message, proceeding");
+ return pjp.proceed(proceedArgs);
+ }
+
+ String payloadPointer = getMessageContent(message);
+ if (payloadPointer == null) {
+ LOG.warn("No content in the message, proceeding");
+ return pjp.proceed(proceedArgs);
+ }
+ // legacy attribute (sqs only)
+ payloadPointer = payloadPointer.replace("com.amazon.sqs.javamessaging.MessageS3Pointer", "software.amazon.payloadoffloading.PayloadS3Pointer");
+
+ if (LOG.isInfoEnabled()) {
+ LOG.info("Large message [{}]: retrieving content from S3", getMessageId(message));
+ }
+
+ String s3ObjectContent = getS3ObjectContent(payloadPointer);
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Large message [{}] retrieved in S3 [{}]: {}KB", getMessageId(message), payloadPointer,
+ s3ObjectContent.getBytes(StandardCharsets.UTF_8).length / 1024);
+ }
+
+ updateMessageContent(message, s3ObjectContent);
+ removeLargeMessageAttributes(message);
+
+ Object response = pjp.proceed(proceedArgs);
+
+ if (deleteS3Object) {
+ if (LOG.isInfoEnabled()) {
+ LOG.info("Large message [{}]: deleting object from S3", getMessageId(message));
+ }
+ deleteS3Object(payloadPointer);
+ }
+
+ return response;
+ }
+
+ /**
+ * Retrieve the message id
+ *
+ * @param message the message itself
+ * @return the id of the message (String format)
+ */
+ protected abstract String getMessageId(T message);
+
+ /**
+ * Retrieve the content of the message (ex: body of an SQSMessage)
+ *
+ * @param message the message itself
+ * @return the content of the message (String format)
+ */
+ protected abstract String getMessageContent(T message);
+
+ /**
+ * Update the message content of the message (ex: body of an SQSMessage)
+ *
+ * @param message the message itself
+ * @param messageContent the new content of the message (String format)
+ */
+ protected abstract void updateMessageContent(T message, String messageContent);
+
+ /**
+ * Check if the message is actually a large message (indicator in message attributes)
+ *
+ * @param message the message itself
+ * @return true if the message is a large message
+ */
+ protected abstract boolean isLargeMessage(T message);
+
+ /**
+ * Remove the large message indicator (in message attributes)
+ *
+ * @param message the message itself
+ */
+ protected abstract void removeLargeMessageAttributes(T message);
+
+ private String getS3ObjectContent(String payloadPointer) {
+ try {
+ return payloadStore.getOriginalPayload(payloadPointer);
+ } catch (SdkException e) {
+ throw new LargeMessageProcessingException(format("Failed processing S3 record [%s]", payloadPointer), e);
+ }
+ }
+
+ private void deleteS3Object(String payloadPointer) {
+ try {
+ payloadStore.deleteOriginalPayload(payloadPointer);
+ } catch (SdkException e) {
+ throw new LargeMessageProcessingException(format("Failed deleting S3 record [%s]", payloadPointer), e);
+ }
+ }
+
+}
diff --git a/powertools-large-messages/src/main/java/software/amazon/lambda/powertools/largemessages/internal/LargeMessageProcessorFactory.java b/powertools-large-messages/src/main/java/software/amazon/lambda/powertools/largemessages/internal/LargeMessageProcessorFactory.java
new file mode 100644
index 000000000..26c33738a
--- /dev/null
+++ b/powertools-large-messages/src/main/java/software/amazon/lambda/powertools/largemessages/internal/LargeMessageProcessorFactory.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
+package software.amazon.lambda.powertools.largemessages.internal;
+
+import com.amazonaws.services.lambda.runtime.events.SNSEvent.SNSRecord;
+import com.amazonaws.services.lambda.runtime.events.SQSEvent.SQSMessage;
+import java.util.Optional;
+
+class LargeMessageProcessorFactory {
+
+ private LargeMessageProcessorFactory() {
+ // not intended to be instantiated
+ }
+
+ public static Optional> get(Object message) {
+ if (message instanceof SQSMessage) {
+ return Optional.of(new LargeSQSMessageProcessor());
+ } else if (message instanceof SNSRecord) {
+ return Optional.of(new LargeSNSMessageProcessor());
+ } else {
+ return Optional.empty();
+ }
+ }
+}
diff --git a/powertools-large-messages/src/main/java/software/amazon/lambda/powertools/largemessages/internal/LargeSNSMessageProcessor.java b/powertools-large-messages/src/main/java/software/amazon/lambda/powertools/largemessages/internal/LargeSNSMessageProcessor.java
new file mode 100644
index 000000000..1ed7f5eaa
--- /dev/null
+++ b/powertools-large-messages/src/main/java/software/amazon/lambda/powertools/largemessages/internal/LargeSNSMessageProcessor.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
+package software.amazon.lambda.powertools.largemessages.internal;
+
+import com.amazonaws.services.lambda.runtime.events.SNSEvent.MessageAttribute;
+import com.amazonaws.services.lambda.runtime.events.SNSEvent.SNSRecord;
+import java.util.HashMap;
+import java.util.Map;
+
+class LargeSNSMessageProcessor extends LargeMessageProcessor {
+
+ @Override
+ protected String getMessageId(SNSRecord message) {
+ return message.getSNS().getMessageId();
+ }
+
+ @Override
+ protected String getMessageContent(SNSRecord message) {
+ return message.getSNS().getMessage();
+ }
+
+ @Override
+ protected void updateMessageContent(SNSRecord message, String messageContent) {
+ message.getSNS().setMessage(messageContent);
+ }
+
+ @Override
+ protected boolean isLargeMessage(SNSRecord message) {
+ Map msgAttributes = message.getSNS().getMessageAttributes();
+ return msgAttributes != null && msgAttributes.containsKey(RESERVED_ATTRIBUTE_NAME);
+ }
+
+ @Override
+ protected void removeLargeMessageAttributes(SNSRecord message) {
+ // message.getSNS().getMessageAttributes() does not support remove operation, copy to new map
+ Map newAttributes = new HashMap<>(message.getSNS().getMessageAttributes());
+ newAttributes.remove(RESERVED_ATTRIBUTE_NAME);
+ message.getSNS().setMessageAttributes(newAttributes);
+ }
+}
diff --git a/powertools-large-messages/src/main/java/software/amazon/lambda/powertools/largemessages/internal/LargeSQSMessageProcessor.java b/powertools-large-messages/src/main/java/software/amazon/lambda/powertools/largemessages/internal/LargeSQSMessageProcessor.java
new file mode 100644
index 000000000..18c99e300
--- /dev/null
+++ b/powertools-large-messages/src/main/java/software/amazon/lambda/powertools/largemessages/internal/LargeSQSMessageProcessor.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
+package software.amazon.lambda.powertools.largemessages.internal;
+
+import com.amazonaws.services.lambda.runtime.events.SQSEvent.MessageAttribute;
+import com.amazonaws.services.lambda.runtime.events.SQSEvent.SQSMessage;
+import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import software.amazon.awssdk.utils.BinaryUtils;
+import software.amazon.awssdk.utils.Md5Utils;
+
+class LargeSQSMessageProcessor extends LargeMessageProcessor {
+
+ private static final Logger LOG = LoggerFactory.getLogger(LargeSQSMessageProcessor.class);
+ private static final String LEGACY_RESERVED_ATTRIBUTE_NAME = "SQSLargePayloadSize";
+ private static final int INTEGER_SIZE_IN_BYTES = 4;
+ private static final byte STRING_TYPE_FIELD_INDEX = 1;
+ private static final byte BINARY_TYPE_FIELD_INDEX = 2;
+ private static final byte STRING_LIST_TYPE_FIELD_INDEX = 3;
+ private static final byte BINARY_LIST_TYPE_FIELD_INDEX = 4;
+
+ @Override
+ protected String getMessageId(SQSMessage message) {
+ return message.getMessageId();
+ }
+
+ @Override
+ protected String getMessageContent(SQSMessage message) {
+ return message.getBody();
+ }
+
+ @Override
+ protected void updateMessageContent(SQSMessage message, String messageContent) {
+ message.setBody(messageContent);
+ // we update the MD5 digest so it doesn't look tempered
+ message.setMd5OfBody(calculateMessageBodyMd5(messageContent).orElse(message.getMd5OfBody()));
+ }
+
+ @Override
+ protected boolean isLargeMessage(SQSMessage message) {
+ Map msgAttributes = message.getMessageAttributes();
+ return msgAttributes != null && (msgAttributes.containsKey(RESERVED_ATTRIBUTE_NAME) || msgAttributes.containsKey(LEGACY_RESERVED_ATTRIBUTE_NAME));
+ }
+
+ @Override
+ protected void removeLargeMessageAttributes(SQSMessage message) {
+ // message.getMessageAttributes() does not support remove operation, copy to new map
+ Map newAttributes = new HashMap<>(message.getMessageAttributes());
+ newAttributes.remove(RESERVED_ATTRIBUTE_NAME);
+ newAttributes.remove(LEGACY_RESERVED_ATTRIBUTE_NAME);
+ message.setMessageAttributes(newAttributes);
+ // we update the MD5 digest so it doesn't look tempered
+ message.setMd5OfMessageAttributes(calculateMessageAttributesMd5(newAttributes).orElse(message.getMd5OfMessageAttributes()));
+ }
+
+ /**
+ * Compute the MD5 of the message body.
+ * Inspired from {@code software.amazon.awssdk.services.sqs.internal.MessageMD5ChecksumInterceptor}.
+ * package protected for testing purpose.
+ *
+ * @param messageBody body of the SQS Message
+ * @return the MD5 digest of the SQS Message body (or empty in case of error)
+ */
+ static Optional calculateMessageBodyMd5(String messageBody) {
+ byte[] expectedMd5;
+ try {
+ expectedMd5 = Md5Utils.computeMD5Hash(messageBody.getBytes(StandardCharsets.UTF_8));
+ } catch (Exception e) {
+ LOG.warn("Unable to calculate the MD5 hash of the message body. ", e);
+ return Optional.empty();
+ }
+ return Optional.of(BinaryUtils.toHex(expectedMd5));
+ }
+
+ /**
+ * Compute the MD5 of the message attributes.
+ * Inspired from {@code software.amazon.awssdk.services.sqs.internal.MessageMD5ChecksumInterceptor}.
+ * package protected for testing purpose.
+ *
+ * @param messageAttributes attributes of the SQS Message
+ * @return the MD5 digest of the SQS Message attributes (or empty in case of error)
+ */
+ @SuppressWarnings("squid:S4790") // MD5 algorithm is used by SQS, we must use MD5
+ static Optional calculateMessageAttributesMd5(final Map messageAttributes) {
+ List sortedAttributeNames = new ArrayList<>(messageAttributes.keySet());
+ Collections.sort(sortedAttributeNames);
+
+ MessageDigest md5Digest;
+ try {
+ md5Digest = MessageDigest.getInstance("MD5");
+
+ for (String attrName : sortedAttributeNames) {
+ MessageAttribute attrValue = messageAttributes.get(attrName);
+
+ // Encoded Name
+ updateLengthAndBytes(md5Digest, attrName);
+
+ // Encoded Type
+ updateLengthAndBytes(md5Digest, attrValue.getDataType());
+
+ // Encoded Value
+ if (attrValue.getStringValue() != null) {
+ md5Digest.update(STRING_TYPE_FIELD_INDEX);
+ updateLengthAndBytes(md5Digest, attrValue.getStringValue());
+ } else if (attrValue.getBinaryValue() != null) {
+ md5Digest.update(BINARY_TYPE_FIELD_INDEX);
+ updateLengthAndBytes(md5Digest, attrValue.getBinaryValue());
+ } else if (attrValue.getStringListValues() != null &&
+ attrValue.getStringListValues().size() > 0) {
+ md5Digest.update(STRING_LIST_TYPE_FIELD_INDEX);
+ for (String strListMember : attrValue.getStringListValues()) {
+ updateLengthAndBytes(md5Digest, strListMember);
+ }
+ } else if (attrValue.getBinaryListValues() != null &&
+ attrValue.getBinaryListValues().size() > 0) {
+ md5Digest.update(BINARY_LIST_TYPE_FIELD_INDEX);
+ for (ByteBuffer byteListMember : attrValue.getBinaryListValues()) {
+ updateLengthAndBytes(md5Digest, byteListMember);
+ }
+ }
+ }
+ } catch (Exception e) {
+ LOG.warn("Unable to calculate the MD5 hash of the message attributes. ", e);
+ return Optional.empty();
+ }
+
+ return Optional.of(BinaryUtils.toHex(md5Digest.digest()));
+ }
+
+ /**
+ * Update the digest using a sequence of bytes that consists of the length (in 4 bytes) of the
+ * input String and the actual utf8-encoded byte values.
+ */
+ private static void updateLengthAndBytes(MessageDigest digest, String str) {
+ byte[] utf8Encoded = str.getBytes(StandardCharsets.UTF_8);
+ ByteBuffer lengthBytes = ByteBuffer.allocate(INTEGER_SIZE_IN_BYTES).putInt(utf8Encoded.length);
+ digest.update(lengthBytes.array());
+ digest.update(utf8Encoded);
+ }
+
+ /**
+ * Update the digest using a sequence of bytes that consists of the length (in 4 bytes) of the
+ * input ByteBuffer and all the bytes it contains.
+ */
+ private static void updateLengthAndBytes(MessageDigest digest, ByteBuffer binaryValue) {
+ ByteBuffer readOnlyBuffer = binaryValue.asReadOnlyBuffer();
+ int size = readOnlyBuffer.remaining();
+ ByteBuffer lengthBytes = ByteBuffer.allocate(INTEGER_SIZE_IN_BYTES).putInt(size);
+ digest.update(lengthBytes.array());
+ digest.update(readOnlyBuffer);
+ }
+}
diff --git a/powertools-large-messages/src/test/java/software/amazon/lambda/powertools/largemessages/LargeMessageConfigTest.java b/powertools-large-messages/src/test/java/software/amazon/lambda/powertools/largemessages/LargeMessageConfigTest.java
new file mode 100644
index 000000000..b6bcaf6b5
--- /dev/null
+++ b/powertools-large-messages/src/test/java/software/amazon/lambda/powertools/largemessages/LargeMessageConfigTest.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
+package software.amazon.lambda.powertools.largemessages;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.services.s3.S3Client;
+
+public class LargeMessageConfigTest {
+
+ @BeforeEach
+ public void setup() {
+ LargeMessageConfig.get().resetS3Client();
+ }
+
+ @AfterEach
+ public void tearDown() {
+ LargeMessageConfig.get().resetS3Client();
+ }
+
+ @Test
+ public void singleton_shouldNotChangeWhenCalledMultipleTimes() {
+ LargeMessageConfig.init().withS3Client(S3Client.builder().region(Region.US_EAST_1).build());
+ LargeMessageConfig config = LargeMessageConfig.get();
+
+ LargeMessageConfig.init().withS3Client(null);
+ LargeMessageConfig config2 = LargeMessageConfig.get();
+
+ assertThat(config2).isEqualTo(config);
+ }
+
+ @Test
+ public void singletonWithDefaultClient_shouldNotChangeWhenCalledMultipleTimes() {
+ S3Client s3Client = LargeMessageConfig.get().getS3Client();
+
+ LargeMessageConfig.init().withS3Client(S3Client.create());
+ S3Client s3Client2 = LargeMessageConfig.get().getS3Client();
+
+ assertThat(s3Client2).isEqualTo(s3Client);
+ }
+}
diff --git a/powertools-large-messages/src/test/java/software/amazon/lambda/powertools/largemessages/internal/LargeMessageAspectTest.java b/powertools-large-messages/src/test/java/software/amazon/lambda/powertools/largemessages/internal/LargeMessageAspectTest.java
new file mode 100644
index 000000000..95dfd445a
--- /dev/null
+++ b/powertools-large-messages/src/test/java/software/amazon/lambda/powertools/largemessages/internal/LargeMessageAspectTest.java
@@ -0,0 +1,333 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
+package software.amazon.lambda.powertools.largemessages.internal;
+
+import static java.lang.String.format;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoInteractions;
+import static org.mockito.Mockito.when;
+import static org.mockito.MockitoAnnotations.openMocks;
+import static software.amazon.lambda.powertools.largemessages.internal.LargeSQSMessageProcessor.calculateMessageAttributesMd5;
+import static software.amazon.lambda.powertools.largemessages.internal.LargeSQSMessageProcessor.calculateMessageBodyMd5;
+
+import com.amazonaws.services.lambda.runtime.Context;
+import com.amazonaws.services.lambda.runtime.events.KinesisEvent.KinesisEventRecord;
+import com.amazonaws.services.lambda.runtime.events.SNSEvent;
+import com.amazonaws.services.lambda.runtime.events.SNSEvent.SNS;
+import com.amazonaws.services.lambda.runtime.events.SNSEvent.SNSRecord;
+import com.amazonaws.services.lambda.runtime.events.SQSEvent.MessageAttribute;
+import com.amazonaws.services.lambda.runtime.events.SQSEvent.SQSMessage;
+import java.io.ByteArrayInputStream;
+import java.lang.reflect.Field;
+import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.function.Consumer;
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import software.amazon.awssdk.core.ResponseInputStream;
+import software.amazon.awssdk.http.AbortableInputStream;
+import software.amazon.awssdk.services.s3.S3Client;
+import software.amazon.awssdk.services.s3.model.DeleteObjectRequest;
+import software.amazon.awssdk.services.s3.model.GetObjectRequest;
+import software.amazon.awssdk.services.s3.model.GetObjectResponse;
+import software.amazon.awssdk.services.s3.model.S3Exception;
+import software.amazon.lambda.powertools.largemessages.LargeMessage;
+import software.amazon.lambda.powertools.largemessages.LargeMessageConfig;
+import software.amazon.lambda.powertools.largemessages.LargeMessageProcessingException;
+
+public class LargeMessageAspectTest {
+
+ private static final String BIG_MSG = "A biiiiiiiig message";
+ private static final String BIG_MSG_MD5 = "919ebd392d8cb7161f95cb612a903d42";
+
+ private static final String BUCKET_NAME = "bucketname";
+ private static final String BUCKET_KEY = "c71eb2ae-37e0-4265-8909-32f4153faddf";
+
+ private static final String BIG_MESSAGE_BODY = "[\"software.amazon.payloadoffloading.PayloadS3Pointer\", {\"s3BucketName\":\"" + BUCKET_NAME + "\", \"s3Key\":\"" + BUCKET_KEY + "\"}]";
+
+ @Mock
+ private S3Client s3Client;
+ @Mock
+ private Context context;
+
+ @BeforeEach
+ public void init() throws NoSuchFieldException, IllegalAccessException {
+ openMocks(this);
+ setupContext();
+ // need to clean the s3Client with introspection (singleton)
+ Field client = LargeMessageConfig.class.getDeclaredField("s3Client");
+ client.setAccessible(true);
+ client.set(LargeMessageConfig.get(), null);
+ LargeMessageConfig.init().withS3Client(s3Client);
+ }
+
+ @LargeMessage
+ private String processSQSMessage(SQSMessage sqsMessage, Context context) {
+ return sqsMessage.getBody();
+ }
+
+ @LargeMessage
+ private String processSQSMessageWithMd5Checks(SQSMessage transformedMessage, String initialBodyMD5, String initialAttributesMD5) {
+ assertThat(transformedMessage.getMd5OfBody()).isNotEqualTo(initialBodyMD5);
+ assertThat(transformedMessage.getMd5OfBody()).isEqualTo(BIG_MSG_MD5);
+
+ assertThat(transformedMessage.getMessageAttributes()).hasSize(3);
+
+ assertThat(transformedMessage.getMd5OfMessageAttributes()).isNotEqualTo(initialAttributesMD5);
+ return transformedMessage.getBody();
+ }
+
+ @LargeMessage
+ private String processSNSMessageWithoutContext(SNSRecord snsRecord) {
+ return snsRecord.getSNS().getMessage();
+ }
+
+ @LargeMessage(deleteS3Object = false)
+ private String processSQSMessageNoDelete(SQSMessage sqsMessage, Context context) {
+ return sqsMessage.getBody();
+ }
+
+ @LargeMessage
+ private String processKinesisMessage(KinesisEventRecord kinesisEventRecord) {
+ return kinesisEventRecord.getEventID();
+ }
+
+ @LargeMessage
+ private String processNoMessage() {
+ return "Hello World";
+ }
+
+ @Test
+ public void testLargeSQSMessageWithDefaultDeletion() {
+ // given
+ when(s3Client.getObject(any(GetObjectRequest.class))).thenReturn(s3ObjectWithLargeMessage());
+ SQSMessage sqsMessage = sqsMessageWithBody(BIG_MESSAGE_BODY, true);
+
+ // when
+ String message = processSQSMessage(sqsMessage, context);
+
+ // then
+ assertThat(message).isEqualTo(BIG_MSG);
+ ArgumentCaptor delete = ArgumentCaptor.forClass(DeleteObjectRequest.class);
+ verify(s3Client).deleteObject(delete.capture());
+ Assertions.assertThat(delete.getValue())
+ .satisfies((Consumer) deleteObjectRequest -> {
+ assertThat(deleteObjectRequest.bucket())
+ .isEqualTo(BUCKET_NAME);
+
+ assertThat(deleteObjectRequest.key())
+ .isEqualTo(BUCKET_KEY);
+ });
+ }
+
+ @Test
+ public void testLargeSQSMessage_shouldChangeMd5OfBodyAndAttributes() {
+ // given
+ when(s3Client.getObject(any(GetObjectRequest.class))).thenReturn(s3ObjectWithLargeMessage());
+
+ MessageAttribute stringListAttribute = new MessageAttribute();
+ stringListAttribute.setStringListValues(Collections.singletonList("customAttributeValue"));
+ stringListAttribute.setDataType("StringList");
+
+ MessageAttribute binAttribute = new MessageAttribute();
+ binAttribute.setBinaryValue(ByteBuffer.wrap("customAttributeValue".getBytes(StandardCharsets.UTF_8)));
+ binAttribute.setDataType("Binary");
+
+ MessageAttribute listBinAttribute = new MessageAttribute();
+ listBinAttribute.setBinaryListValues(Collections.singletonList(ByteBuffer.wrap("customAttributeValue".getBytes(StandardCharsets.UTF_8))));
+ listBinAttribute.setDataType("BinaryList");
+
+ Map attrs = new HashMap<>();
+ attrs.put("stringListAttribute", stringListAttribute);
+ attrs.put("binAttribute", binAttribute);
+ attrs.put("listBinAttribute", listBinAttribute);
+ SQSMessage sqsMessage = sqsMessageWithBody(BIG_MESSAGE_BODY, true, attrs);
+
+ // when
+ String message = processSQSMessageWithMd5Checks(sqsMessage, sqsMessage.getMd5OfBody(), sqsMessage.getMd5OfMessageAttributes());
+
+ // then
+ assertThat(message).isEqualTo(BIG_MSG);
+ }
+
+ @Test
+ public void testLargeSNSMessageWithDefaultDeletion() {
+ // given
+ when(s3Client.getObject(any(GetObjectRequest.class))).thenReturn(s3ObjectWithLargeMessage());
+ SNSRecord snsRecord = snsRecordWithMessage(BIG_MESSAGE_BODY, true);
+
+ //when
+ String message = processSNSMessageWithoutContext(snsRecord);
+
+ // then
+ assertThat(message).isEqualTo(BIG_MSG);
+ ArgumentCaptor delete = ArgumentCaptor.forClass(DeleteObjectRequest.class);
+ verify(s3Client).deleteObject(delete.capture());
+ Assertions.assertThat(delete.getValue())
+ .satisfies((Consumer) deleteObjectRequest -> {
+ assertThat(deleteObjectRequest.bucket())
+ .isEqualTo(BUCKET_NAME);
+
+ assertThat(deleteObjectRequest.key())
+ .isEqualTo(BUCKET_KEY);
+ });
+ }
+
+ @Test
+ public void testLargeSQSMessageWithNoDeletion_shouldNotDelete() {
+ // given
+ when(s3Client.getObject(any(GetObjectRequest.class))).thenReturn(s3ObjectWithLargeMessage());
+ SQSMessage sqsMessage = sqsMessageWithBody(BIG_MESSAGE_BODY, true);
+
+ // when
+ String message = processSQSMessageNoDelete(sqsMessage, context);
+
+ // then
+ assertThat(message).isEqualTo(BIG_MSG);
+ verify(s3Client, never()).deleteObject(any(DeleteObjectRequest.class));
+ }
+
+ @Test
+ public void testKinesisMessage_shouldProceedWithoutS3() {
+ // given
+ KinesisEventRecord kinesisEventRecord = new KinesisEventRecord();
+ kinesisEventRecord.setEventID("kinesis_id1234567890");
+
+ // when
+ String message = processKinesisMessage(kinesisEventRecord);
+
+ // then
+ assertThat(message).isEqualTo("kinesis_id1234567890");
+ verifyNoInteractions(s3Client);
+ }
+
+ @Test
+ public void testNoMessage_shouldProceedWithoutS3() {
+ // when
+ String message = processNoMessage();
+
+ // then
+ assertThat(message).isEqualTo("Hello World");
+ verifyNoInteractions(s3Client);
+ }
+
+ @Test
+ public void testSmallMessage_shouldProceedWithoutS3() {
+ // given
+ SQSMessage sqsMessage = sqsMessageWithBody("This is small message", false);
+
+ // when
+ String message = processSQSMessage(sqsMessage, context);
+
+ // then
+ assertThat(message)
+ .isEqualTo("This is small message");
+ verifyNoInteractions(s3Client);
+ }
+
+ @Test
+ public void testNullMessage_shouldProceedWithoutS3() {
+ // given
+ SQSMessage sqsMessage = sqsMessageWithBody(null, true);
+
+ // when
+ String message = processSQSMessage(sqsMessage, context);
+
+ // then
+ assertThat(message).isNull();
+ verifyNoInteractions(s3Client);
+ }
+
+ @Test
+ public void testGetS3ObjectException_shouldThrowLargeMessageProcessingException() {
+ // given
+ when(s3Client.getObject(any(GetObjectRequest.class))).thenThrow(S3Exception.create("Permission denied", new Exception("User is not allowed to access bucket " + BUCKET_NAME)));
+ SQSMessage sqsMessage = sqsMessageWithBody(BIG_MESSAGE_BODY, true);
+
+ // when / then
+ assertThatThrownBy(() -> processSQSMessage(sqsMessage, context))
+ .isInstanceOf(LargeMessageProcessingException.class)
+ .hasMessage(format("Failed processing S3 record [%s]", BIG_MESSAGE_BODY));
+ }
+
+ @Test
+ public void testDeleteS3ObjectException_shouldThrowLargeMessageProcessingException() {
+ // given
+ when(s3Client.getObject(any(GetObjectRequest.class))).thenReturn(s3ObjectWithLargeMessage());
+ when(s3Client.deleteObject(any(DeleteObjectRequest.class))).thenThrow(S3Exception.create("Permission denied", new Exception("User is not allowed to access bucket " + BUCKET_NAME)));
+ SQSMessage sqsMessage = sqsMessageWithBody(BIG_MESSAGE_BODY, true);
+
+ // when / then
+ assertThatThrownBy(() -> processSQSMessage(sqsMessage, context))
+ .isInstanceOf(LargeMessageProcessingException.class)
+ .hasMessage(format("Failed deleting S3 record [%s]", BIG_MESSAGE_BODY));
+ }
+
+ private ResponseInputStream s3ObjectWithLargeMessage() {
+ return new ResponseInputStream<>(GetObjectResponse.builder().build(), AbortableInputStream.create(new ByteArrayInputStream(BIG_MSG.getBytes())));
+ }
+
+ private SQSMessage sqsMessageWithBody(String messageBody, boolean largeMessage) {
+ return sqsMessageWithBody(messageBody, largeMessage, null);
+ }
+
+ private SQSMessage sqsMessageWithBody(String messageBody, boolean largeMessage, Map optionalAttributes) {
+ SQSMessage sqsMessage = new SQSMessage();
+ sqsMessage.setBody(messageBody);
+ if (messageBody != null) {
+ sqsMessage.setMd5OfBody(calculateMessageBodyMd5(messageBody).orElseThrow(() -> new RuntimeException("Unable to md5 body " + messageBody)));
+ }
+
+ if (largeMessage) {
+ Map attributeMap = new HashMap<>();
+ if (optionalAttributes != null) {
+ attributeMap.putAll(optionalAttributes);
+ }
+ MessageAttribute payloadAttribute = new MessageAttribute();
+ payloadAttribute.setStringValue("300450");
+ payloadAttribute.setDataType("Number");
+ attributeMap.put(LargeMessageProcessor.RESERVED_ATTRIBUTE_NAME, payloadAttribute);
+
+ sqsMessage.setMessageAttributes(attributeMap);
+ sqsMessage.setMd5OfMessageAttributes(calculateMessageAttributesMd5(attributeMap).orElseThrow(() -> new RuntimeException("Unable to md5 attributes " + attributeMap)));
+ }
+ return sqsMessage;
+ }
+
+ private SNSRecord snsRecordWithMessage(String messageBody, boolean largeMessage) {
+ SNS sns = new SNS().withMessage(messageBody);
+ if (largeMessage) {
+ sns.setMessageAttributes(Collections.singletonMap(LargeMessageProcessor.RESERVED_ATTRIBUTE_NAME, new SNSEvent.MessageAttribute()));
+ }
+ return new SNSRecord().withSns(sns);
+ }
+
+ private void setupContext() {
+ when(context.getFunctionName()).thenReturn("testFunction");
+ when(context.getInvokedFunctionArn()).thenReturn("testArn");
+ when(context.getFunctionVersion()).thenReturn("1");
+ when(context.getMemoryLimitInMB()).thenReturn(1024);
+ }
+}
diff --git a/powertools-large-messages/src/test/java/software/amazon/lambda/powertools/largemessages/internal/LargeMessageProcessorFactoryTest.java b/powertools-large-messages/src/test/java/software/amazon/lambda/powertools/largemessages/internal/LargeMessageProcessorFactoryTest.java
new file mode 100644
index 000000000..3011c8189
--- /dev/null
+++ b/powertools-large-messages/src/test/java/software/amazon/lambda/powertools/largemessages/internal/LargeMessageProcessorFactoryTest.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License 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.
+ *
+ */
+
+package software.amazon.lambda.powertools.largemessages.internal;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import com.amazonaws.services.lambda.runtime.events.KinesisEvent;
+import com.amazonaws.services.lambda.runtime.events.SNSEvent;
+import com.amazonaws.services.lambda.runtime.events.SQSEvent;
+import org.junit.jupiter.api.Test;
+
+public class LargeMessageProcessorFactoryTest {
+
+ @Test
+ public void createLargeSQSMessageProcessor() {
+ assertThat(LargeMessageProcessorFactory.get(new SQSEvent.SQSMessage()))
+ .isPresent()
+ .get()
+ .isInstanceOf(LargeSQSMessageProcessor.class);
+ }
+
+ @Test
+ public void createLargeSNSMessageProcessor() {
+ assertThat(LargeMessageProcessorFactory.get(new SNSEvent.SNSRecord()))
+ .isPresent()
+ .get()
+ .isInstanceOf(LargeSNSMessageProcessor.class);
+ }
+
+ @Test
+ public void createUnknownMessageProcessor() {
+ assertThat(LargeMessageProcessorFactory.get(new KinesisEvent.KinesisEventRecord())).isNotPresent();
+ }
+}
diff --git a/powertools-sqs/pom.xml b/powertools-sqs/pom.xml
index d8afac783..c21943fba 100644
--- a/powertools-sqs/pom.xml
+++ b/powertools-sqs/pom.xml
@@ -29,6 +29,7 @@
Powertools for AWS Lambda (Java) library SQS
+ Deprecated: Batch processing is now handled in powertools-batch and large messages in powertools-large-messages modules.
A suite of utilities for AWS Lambda Functions that makes tracing with AWS X-Ray, structured logging and creating custom metrics asynchronously easier.
https://aws.amazon.com/lambda/
diff --git a/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/SqsLargeMessage.java b/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/SqsLargeMessage.java
index 847dd456c..a3a92cea1 100644
--- a/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/SqsLargeMessage.java
+++ b/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/SqsLargeMessage.java
@@ -20,9 +20,12 @@
import java.lang.annotation.Target;
/**
- * {@code SqsLargeMessage} is used to signal that the annotated method
+ * @deprecated See software.amazon.lambda.powertools.largemessages.LargeMessage in powertools-large-messages module.
+ * Will be removed in version 2.
+ *
+ *
{@code SqsLargeMessage} is used to signal that the annotated method
* should be extended to handle large SQS messages which have been offloaded
- * to S3
+ * to S3
*
*
{@code SqsLargeMessage} automatically retrieves and deletes messages
* which have been offloaded to S3 using the {@code amazon-sqs-java-extended-client-lib}
@@ -73,6 +76,7 @@
*
To disable deletion of payloads setting the following annotation parameter
* {@code @SqsLargeMessage(deletePayloads=false)}