From 1681e19f352d899a651ba870f826aa8f43a99652 Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Tue, 19 Aug 2025 11:05:25 +0200 Subject: [PATCH 01/65] PoC for Metrics and Logging UA Configuration. --- .../sam/pom.xml | 5 +++ .../sam/src/main/java/helloworld/App.java | 26 +++++++++++++ .../sam/template.yaml | 11 ++++++ .../internal/UserAgentConfigurator.java | 20 +++++++--- .../internal/UserAgentConfiguratorTest.java | 16 ++++++-- .../powertools-logging-log4j/pom.xml | 9 ++++- .../internal/LoggingUserAgentInterceptor.java | 37 +++++++++++++++++++ .../global/handlers/execution.interceptors | 1 + powertools-metrics/pom.xml | 5 +++ .../internal/MetricsUserAgentInterceptor.java | 37 +++++++++++++++++++ .../global/handlers/execution.interceptors | 1 + 11 files changed, 156 insertions(+), 12 deletions(-) create mode 100644 powertools-logging/powertools-logging-log4j/src/main/java/software/amazon/lambda/powertools/logging/log4/internal/LoggingUserAgentInterceptor.java create mode 100644 powertools-logging/powertools-logging-log4j/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors create mode 100644 powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/MetricsUserAgentInterceptor.java create mode 100644 powertools-metrics/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors diff --git a/examples/powertools-examples-core-utilities/sam/pom.xml b/examples/powertools-examples-core-utilities/sam/pom.xml index 3df44f441..b184f402f 100644 --- a/examples/powertools-examples-core-utilities/sam/pom.xml +++ b/examples/powertools-examples-core-utilities/sam/pom.xml @@ -45,6 +45,11 @@ aspectjrt ${aspectj.version} + + software.amazon.awssdk + s3 + 2.32.8 + diff --git a/examples/powertools-examples-core-utilities/sam/src/main/java/helloworld/App.java b/examples/powertools-examples-core-utilities/sam/src/main/java/helloworld/App.java index 2675c96eb..4a1d86205 100644 --- a/examples/powertools-examples-core-utilities/sam/src/main/java/helloworld/App.java +++ b/examples/powertools-examples-core-utilities/sam/src/main/java/helloworld/App.java @@ -34,6 +34,13 @@ import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; +import software.amazon.awssdk.auth.credentials.EnvironmentVariableCredentialsProvider; +import software.amazon.awssdk.core.SdkSystemSetting; +import software.amazon.awssdk.core.interceptor.ExecutionAttributes; +import software.amazon.awssdk.core.interceptor.ExecutionInterceptor; +import software.amazon.awssdk.http.SdkHttpRequest; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.s3.S3Client; import software.amazon.lambda.powertools.logging.Logging; import software.amazon.lambda.powertools.metrics.FlushMetrics; import software.amazon.lambda.powertools.metrics.Metrics; @@ -50,13 +57,32 @@ */ public class App implements RequestHandler { private static final Logger log = LoggerFactory.getLogger(App.class); + private static final S3Client s3Client = S3Client.builder() + .region(Region.of(System.getenv(SdkSystemSetting.AWS_REGION.environmentVariable()))) + .credentialsProvider(EnvironmentVariableCredentialsProvider.create()) + .overrideConfiguration(c -> c.addExecutionInterceptor(new ExecutionInterceptor() { + @Override + public void beforeTransmission( + software.amazon.awssdk.core.interceptor.Context.BeforeTransmission context, + ExecutionAttributes executionAttributes) { + SdkHttpRequest request = context.httpRequest(); + log.info("User-Agent header: {}", request.headers().get("User-Agent")); + } + })) + .build(); private static final Metrics metrics = MetricsFactory.getMetricsInstance(); + public App() { + log.info("sdk.ua.appId system property: {}", System.getProperty("sdk.ua.appId")); + s3Client.listBuckets(); + } + @Logging(logEvent = true, samplingRate = 0.7) @Tracing(captureMode = CaptureMode.RESPONSE_AND_ERROR) @FlushMetrics(namespace = "ServerlessAirline", service = "payment", captureColdStart = true) public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) { Map headers = new HashMap<>(); + s3Client.listBuckets(); headers.put("Content-Type", "application/json"); headers.put("X-Custom-Header", "application/json"); diff --git a/examples/powertools-examples-core-utilities/sam/template.yaml b/examples/powertools-examples-core-utilities/sam/template.yaml index 9a51a1ba9..af0a553fb 100644 --- a/examples/powertools-examples-core-utilities/sam/template.yaml +++ b/examples/powertools-examples-core-utilities/sam/template.yaml @@ -19,11 +19,22 @@ Globals: POWERTOOLS_METRICS_NAMESPACE: Coreutilities Resources: + TestBucket: + Type: AWS::S3::Bucket + HelloWorldFunction: Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction Properties: CodeUri: . Handler: helloworld.App::handleRequest + Policies: + - S3ReadPolicy: + BucketName: !Ref TestBucket + - Statement: + - Effect: Allow + Action: + - s3:ListAllMyBuckets + Resource: "*" Environment: # More info about Env Vars: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#environment-object Variables: POWERTOOLS_SERVICE_NAME: hello diff --git a/powertools-common/src/main/java/software/amazon/lambda/powertools/common/internal/UserAgentConfigurator.java b/powertools-common/src/main/java/software/amazon/lambda/powertools/common/internal/UserAgentConfigurator.java index d2e592902..264598788 100644 --- a/powertools-common/src/main/java/software/amazon/lambda/powertools/common/internal/UserAgentConfigurator.java +++ b/powertools-common/src/main/java/software/amazon/lambda/powertools/common/internal/UserAgentConfigurator.java @@ -19,14 +19,14 @@ import java.io.IOException; import java.io.InputStream; import java.util.Properties; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; - /** * Can be used to create a string that can server as a User-Agent suffix in requests made with the AWS SDK clients */ -public class UserAgentConfigurator { +public final class UserAgentConfigurator { public static final String NA = "NA"; public static final String VERSION_KEY = "powertools.version"; @@ -37,7 +37,7 @@ public class UserAgentConfigurator { private static final Logger LOG = LoggerFactory.getLogger(UserAgentConfigurator.class); private static final String NO_OP = "no-op"; private static final String POWERTOOLS_VERSION = getProjectVersion(); - private static final String USER_AGENT_PATTERN = "PT/" + PT_FEATURE_VARIABLE + "/" + POWERTOOLS_VERSION + " PTEnv/" + private static final String USER_AGENT_PATTERN = "PT/" + PT_FEATURE_VARIABLE + "/" + POWERTOOLS_VERSION + " PTENV/" + PT_EXEC_ENV_VARIABLE; private UserAgentConfigurator() { @@ -53,7 +53,6 @@ static String getProjectVersion() { return getVersionFromProperties(VERSION_PROPERTIES_FILENAME, VERSION_KEY); } - /** * Retrieves the project version from a properties file. * The file should be in the resources folder. @@ -83,9 +82,18 @@ static String getVersionFromProperties(String propertyFileName, String versionKe return NA; } + /** + * Configures the AWS SDK to use Powertools user agent by setting the sdk.ua.appId system property. + * This should be called during library initialization to ensure the user agent is properly configured. + */ + public static void configureUserAgent(String ptFeature) { + System.out.println("CONFIGURE UA " + ptFeature); + System.setProperty("sdk.ua.appId", getUserAgent(ptFeature)); + } + /** * Retrieves the user agent string for the Powertools for AWS Lambda. - * It follows the pattern PT/{PT_FEATURE}/{PT_VERSION} PTEnv/{PT_EXEC_ENV} + * It follows the pattern PT/{PT_FEATURE}/{PT_VERSION} PTENV/{PT_EXEC_ENV} * The version of the project is automatically retrieved. * The PT_EXEC_ENV is automatically retrieved from the AWS_EXECUTION_ENV environment variable. * If it AWS_EXECUTION_ENV is not set, PT_EXEC_ENV defaults to "NA" @@ -105,7 +113,7 @@ public static String getUserAgent(String ptFeature) { ptFeature = NO_OP; } return userAgent - .replace(PT_FEATURE_VARIABLE, ptFeature) + .replace(PT_FEATURE_VARIABLE, ptFeature.toUpperCase()) .replace(PT_EXEC_ENV_VARIABLE, ptExecEnv); } } diff --git a/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/UserAgentConfiguratorTest.java b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/UserAgentConfiguratorTest.java index 0c7935a55..ba33de49a 100644 --- a/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/UserAgentConfiguratorTest.java +++ b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/UserAgentConfiguratorTest.java @@ -91,7 +91,7 @@ void testGetUserAgent() { assertThat(userAgent) .isNotNull() - .isEqualTo("PT/test-feature/" + VERSION + " PTEnv/NA"); + .isEqualTo("PT/TEST-FEATURE/" + VERSION + " PTENV/NA"); } @@ -101,7 +101,7 @@ void testGetUserAgent_NoFeature() { assertThat(userAgent) .isNotNull() - .isEqualTo("PT/no-op/" + VERSION + " PTEnv/NA"); + .isEqualTo("PT/NO-OP/" + VERSION + " PTENV/NA"); } @Test @@ -110,7 +110,7 @@ void testGetUserAgent_NullFeature() { assertThat(userAgent) .isNotNull() - .isEqualTo("PT/no-op/" + VERSION + " PTEnv/NA"); + .isEqualTo("PT/NO-OP/" + VERSION + " PTENV/NA"); } @Test @@ -120,7 +120,15 @@ void testGetUserAgent_SetAWSExecutionEnv() { assertThat(userAgent) .isNotNull() - .isEqualTo("PT/test-feature/" + VERSION + " PTEnv/AWS_Lambda_java8"); + .isEqualTo("PT/TEST-FEATURE/" + VERSION + " PTENV/AWS_Lambda_java8"); + } + + @Test + void testConfigureUserAgent() { + UserAgentConfigurator.configureUserAgent("test-feature"); + + assertThat(System.getProperty("sdk.ua.appId")) + .isEqualTo("PT/TEST-FEATURE/" + VERSION + " PTENV/NA"); } } diff --git a/powertools-logging/powertools-logging-log4j/pom.xml b/powertools-logging/powertools-logging-log4j/pom.xml index 88e1ced39..2d734cdcb 100644 --- a/powertools-logging/powertools-logging-log4j/pom.xml +++ b/powertools-logging/powertools-logging-log4j/pom.xml @@ -1,7 +1,7 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 @@ -39,6 +39,11 @@ org.apache.logging.log4j log4j-layout-template-json + + software.amazon.awssdk + sdk-core + provided + diff --git a/powertools-logging/powertools-logging-log4j/src/main/java/software/amazon/lambda/powertools/logging/log4/internal/LoggingUserAgentInterceptor.java b/powertools-logging/powertools-logging-log4j/src/main/java/software/amazon/lambda/powertools/logging/log4/internal/LoggingUserAgentInterceptor.java new file mode 100644 index 000000000..a4d19363e --- /dev/null +++ b/powertools-logging/powertools-logging-log4j/src/main/java/software/amazon/lambda/powertools/logging/log4/internal/LoggingUserAgentInterceptor.java @@ -0,0 +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.logging.log4.internal; + +import software.amazon.awssdk.core.SdkRequest; +import software.amazon.awssdk.core.interceptor.Context; +import software.amazon.awssdk.core.interceptor.ExecutionAttributes; +import software.amazon.awssdk.core.interceptor.ExecutionInterceptor; +import software.amazon.lambda.powertools.common.internal.UserAgentConfigurator; + +/** + * Global interceptor that configures the User-Agent for all AWS SDK clients + * when the metrics module is on the classpath. + */ +public final class LoggingUserAgentInterceptor implements ExecutionInterceptor { + static { + UserAgentConfigurator.configureUserAgent("logging"); + } + + @Override + public SdkRequest modifyRequest(Context.ModifyRequest context, ExecutionAttributes executionAttributes) { + // This is a no-op interceptor. We use this class to configure the PT User-Agent in the static block. It is + // loaded by AWS SDK Global Interceptors. + return context.request(); + } +} diff --git a/powertools-logging/powertools-logging-log4j/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors b/powertools-logging/powertools-logging-log4j/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors new file mode 100644 index 000000000..7917018f2 --- /dev/null +++ b/powertools-logging/powertools-logging-log4j/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors @@ -0,0 +1 @@ +software.amazon.lambda.powertools.logging.log4.internal.LoggingUserAgentInterceptor diff --git a/powertools-metrics/pom.xml b/powertools-metrics/pom.xml index 57da447dd..e13b38cb9 100644 --- a/powertools-metrics/pom.xml +++ b/powertools-metrics/pom.xml @@ -73,6 +73,11 @@ org.apache.commons commons-lang3 + + software.amazon.awssdk + sdk-core + provided + diff --git a/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/MetricsUserAgentInterceptor.java b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/MetricsUserAgentInterceptor.java new file mode 100644 index 000000000..5a466cc3a --- /dev/null +++ b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/MetricsUserAgentInterceptor.java @@ -0,0 +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.metrics.internal; + +import software.amazon.awssdk.core.SdkRequest; +import software.amazon.awssdk.core.interceptor.Context; +import software.amazon.awssdk.core.interceptor.ExecutionAttributes; +import software.amazon.awssdk.core.interceptor.ExecutionInterceptor; +import software.amazon.lambda.powertools.common.internal.UserAgentConfigurator; + +/** + * Global interceptor that configures the User-Agent for all AWS SDK clients + * when the metrics module is on the classpath. + */ +public final class MetricsUserAgentInterceptor implements ExecutionInterceptor { + static { + UserAgentConfigurator.configureUserAgent("metrics"); + } + + @Override + public SdkRequest modifyRequest(Context.ModifyRequest context, ExecutionAttributes executionAttributes) { + // This is a no-op interceptor. We use this class to configure the PT User-Agent in the static block. It is + // loaded by AWS SDK Global Interceptors. + return context.request(); + } +} diff --git a/powertools-metrics/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors b/powertools-metrics/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors new file mode 100644 index 000000000..544bd8ead --- /dev/null +++ b/powertools-metrics/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors @@ -0,0 +1 @@ +software.amazon.lambda.powertools.metrics.internal.MetricsUserAgentInterceptor \ No newline at end of file From 046ac85469e22695dd0b0a8eeb7edb9c3a588e4b Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Wed, 20 Aug 2025 15:50:29 +0200 Subject: [PATCH 02/65] Add Idempotency GraalVM example and remove unncessary dependencies from pom.xml --- examples/README.md | 30 ++-- examples/pom.xml | 3 +- .../sam-graalvm/Dockerfile | 14 ++ .../sam-graalvm/Makefile | 5 + .../sam-graalvm/README.md | 61 +++++++ .../sam-graalvm/pom.xml | 167 ++++++++++++++++++ .../sam-graalvm/src/main/config/bootstrap | 4 + .../src/main/java/helloworld/App.java | 0 .../aws-lambda-java-core/reflect-config.json | 13 ++ .../reflect-config.json | 35 ++++ .../jni-config.json | 11 ++ .../native-image.properties | 1 + .../reflect-config.json | 34 ++++ .../resource-config.json | 19 ++ .../reflect-config.json | 25 +++ .../helloworld/reflect-config.json | 11 ++ .../helloworld/resource-config.json | 7 + .../src/main/resources/log4j2.xml | 0 .../sam-graalvm/template.yaml | 60 +++++++ .../{ => sam}/README.md | 0 .../{ => sam}/pom.xml | 61 +------ .../sam/src/main/java/helloworld/App.java | 142 +++++++++++++++ .../sam/src/main/resources/log4j2.xml | 16 ++ .../{ => sam}/template.yaml | 0 .../demo/kafka/protobuf/ProtobufProduct.java | 6 +- .../protobuf/ProtobufProductOrBuilder.java | 2 +- .../protobuf/ProtobufProductOuterClass.java | 6 +- 27 files changed, 655 insertions(+), 78 deletions(-) create mode 100644 examples/powertools-examples-idempotency/sam-graalvm/Dockerfile create mode 100644 examples/powertools-examples-idempotency/sam-graalvm/Makefile create mode 100644 examples/powertools-examples-idempotency/sam-graalvm/README.md create mode 100644 examples/powertools-examples-idempotency/sam-graalvm/pom.xml create mode 100644 examples/powertools-examples-idempotency/sam-graalvm/src/main/config/bootstrap rename examples/powertools-examples-idempotency/{ => sam-graalvm}/src/main/java/helloworld/App.java (100%) create mode 100644 examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json create mode 100644 examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json create mode 100644 examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json create mode 100644 examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties create mode 100644 examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json create mode 100644 examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json create mode 100644 examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json create mode 100644 examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/helloworld/reflect-config.json create mode 100644 examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/helloworld/resource-config.json rename examples/powertools-examples-idempotency/{ => sam-graalvm}/src/main/resources/log4j2.xml (100%) create mode 100644 examples/powertools-examples-idempotency/sam-graalvm/template.yaml rename examples/powertools-examples-idempotency/{ => sam}/README.md (100%) rename examples/powertools-examples-idempotency/{ => sam}/pom.xml (65%) create mode 100644 examples/powertools-examples-idempotency/sam/src/main/java/helloworld/App.java create mode 100644 examples/powertools-examples-idempotency/sam/src/main/resources/log4j2.xml rename examples/powertools-examples-idempotency/{ => sam}/template.yaml (100%) diff --git a/examples/README.md b/examples/README.md index 41640b5ad..727bc652e 100644 --- a/examples/README.md +++ b/examples/README.md @@ -1,26 +1,35 @@ # Powertools for AWS Lambda (Java) Examples 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. ## Examples * [powertools-examples-core-utilities](powertools-examples-core-utilities) - Demonstrates the core logging, tracing, and metrics modules with different build tools and languages * [CDK](./powertools-examples-core-utilities/cdk) - * [Gradle](./powertools-examples-core-utilities/gradle) * [SAM](./powertools-examples-core-utilities/sam) + * [SAM GraalVM](./powertools-examples-core-utilities/sam-graalvm) * [Serverless](./powertools-examples-core-utilities/serverless) + * [Terraform](./powertools-examples-core-utilities/terraform) + * [Gradle](./powertools-examples-core-utilities/gradle) * [Kotlin](./powertools-examples-core-utilities/kotlin) * [powertools-examples-idempotency](powertools-examples-idempotency) - An idempotent HTTP API + * [SAM](./powertools-examples-idempotency/sam) + * [SAM GraalVM](./powertools-examples-idempotency/sam-graalvm) * [powertools-examples-parameters](powertools-examples-parameters) - Uses the parameters module to provide runtime parameters to a function + * [SAM](./powertools-examples-parameters/sam) + * [SAM GraalVM](./powertools-examples-parameters/sam-graalvm) * [powertools-examples-serialization](powertools-examples-serialization) - Uses the serialization module to serialize and deserialize API Gateway & SQS payloads + * [SAM](./powertools-examples-serialization/sam) + * [SAM GraalVM](./powertools-examples-serialization/sam-graalvm) * [powertools-examples-validation](powertools-examples-validation) - Uses the validation module to validate user requests received via API Gateway * [powertools-examples-cloudformation](powertools-examples-cloudformation) - Deploys a Cloudformation custom resource * [powertools-examples-batch](powertools-examples-batch) - Examples for each of the different batch processing deployments +* [powertools-examples-kafka](powertools-examples-kafka) - Examples for Kafka event processing ## Working with AWS Serverless Application Model (SAM) Examples -Many of the examples use [AWS Serverless Application Model](https://aws.amazon.com/serverless/sam/) (SAM). To get started -with them, you can use the SAM Command Line Interface (SAM CLI) to build it and deploy an example to AWS. +Many of the examples use [AWS Serverless Application Model](https://aws.amazon.com/serverless/sam/) (SAM). To get started with them, you can use the SAM Command Line Interface (SAM CLI) to build it and deploy an example to AWS. To use the SAM CLI, you need the following tools. @@ -29,17 +38,13 @@ To use the SAM CLI, you need the following tools. * Maven - [Install Maven](https://maven.apache.org/install.html) * Docker - [Install Docker community edition](https://hub.docker.com/search/?type=edition&offering=community) -To learn more about SAM, -[check out the developer guide](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/using-sam-cli.html). -You can use the CLI to [test events locally](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/using-sam-cli-local-invoke.html), -and [run the application locally](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/using-sam-cli-local-start-api.html), -amongst other things. +To learn more about SAM, [check out the developer guide](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/using-sam-cli.html). You can use the CLI to [test events locally](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/using-sam-cli-local-invoke.html), and [run the application locally](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/using-sam-cli-local-start-api.html), amongst other things. To build and deploy an example application for the first time, run the following in your shell: ```bash # Switch to the directory containing an example for the powertools-idempotency module -$ cd powertools-examples-idempotency +$ cd powertools-examples-idempotency/sam # Build and deploy the example $ sam build @@ -56,7 +61,7 @@ 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. -If you're not using SAM, you can look for examples for other tools under [powertools-examples-core](./powertools-examples-core) +If you're not using SAM, you can look for examples for other tools under [powertools-examples-core-utilities](./powertools-examples-core-utilities) ### External examples @@ -69,10 +74,9 @@ You can find more examples in the https://github.com/aws/aws-sam-cli-app-templat ### 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. -The AWS Toolkit is an open source plug-in for popular IDEs that uses the SAM CLI to build and deploy serverless applications on AWS. The AWS Toolkit also adds a simplified step-through debugging experience for Lambda function code. See the following links to get started. +If you prefer to use an integrated development environment (IDE) to build and test your application, you can use the AWS Toolkit. The AWS Toolkit is an open source plug-in for popular IDEs that uses the SAM CLI to build and deploy serverless applications on AWS. The AWS Toolkit also adds a simplified step-through debugging experience for Lambda function code. See the following links to get started. * [PyCharm](https://docs.aws.amazon.com/toolkit-for-jetbrains/latest/userguide/welcome.html) * [IntelliJ](https://docs.aws.amazon.com/toolkit-for-jetbrains/latest/userguide/welcome.html) * [VS Code](https://docs.aws.amazon.com/toolkit-for-vscode/latest/userguide/welcome.html) -* [Visual Studio](https://docs.aws.amazon.com/toolkit-for-visual-studio/latest/user-guide/welcome.html) \ No newline at end of file +* [Visual Studio](https://docs.aws.amazon.com/toolkit-for-visual-studio/latest/user-guide/welcome.html) diff --git a/examples/pom.xml b/examples/pom.xml index 2c561b00f..554e97168 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -35,7 +35,8 @@ powertools-examples-core-utilities/cdk/infra powertools-examples-core-utilities/serverless powertools-examples-core-utilities/terraform - powertools-examples-idempotency + powertools-examples-idempotency/sam + powertools-examples-idempotency/sam-graalvm powertools-examples-parameters/sam powertools-examples-parameters/sam-graalvm powertools-examples-serialization/sam diff --git a/examples/powertools-examples-idempotency/sam-graalvm/Dockerfile b/examples/powertools-examples-idempotency/sam-graalvm/Dockerfile new file mode 100644 index 000000000..dac9390e5 --- /dev/null +++ b/examples/powertools-examples-idempotency/sam-graalvm/Dockerfile @@ -0,0 +1,14 @@ +# Use the official AWS SAM base image for Java 21 +FROM public.ecr.aws/sam/build-java21@sha256:a5554d68374e19450c6c88448516ac95a9acedc779f318040f5c230134b4e461 + +# Install GraalVM dependencies +RUN curl -4 -L curl https://download.oracle.com/graalvm/21/latest/graalvm-jdk-21_linux-x64_bin.tar.gz | tar -xvz +RUN mv graalvm-jdk-21.* /usr/lib/graalvm + +# Make native image and mvn available on CLI +RUN ln -s /usr/lib/graalvm/bin/native-image /usr/bin/native-image +RUN ln -s /usr/lib/maven/bin/mvn /usr/bin/mvn + +# Set GraalVM as default +ENV JAVA_HOME=/usr/lib/graalvm +ENV PATH=/usr/lib/graalvm/bin:$PATH diff --git a/examples/powertools-examples-idempotency/sam-graalvm/Makefile b/examples/powertools-examples-idempotency/sam-graalvm/Makefile new file mode 100644 index 000000000..6fb4e537c --- /dev/null +++ b/examples/powertools-examples-idempotency/sam-graalvm/Makefile @@ -0,0 +1,5 @@ +build-IdempotencyFunction: + chmod +x target/hello-world + cp target/hello-world $(ARTIFACTS_DIR) # (ARTIFACTS_DIR --> https://github.com/aws/aws-lambda-builders/blob/develop/aws_lambda_builders/workflows/custom_make/DESIGN.md#implementation) + chmod +x src/main/config/bootstrap + cp src/main/config/bootstrap $(ARTIFACTS_DIR) diff --git a/examples/powertools-examples-idempotency/sam-graalvm/README.md b/examples/powertools-examples-idempotency/sam-graalvm/README.md new file mode 100644 index 000000000..1c44bd791 --- /dev/null +++ b/examples/powertools-examples-idempotency/sam-graalvm/README.md @@ -0,0 +1,61 @@ +# Powertools for AWS Lambda (Java) - Idempotency Example with SAM on GraalVM + +This project contains an example of a Lambda function using the idempotency 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/idempotency/). + +The example exposes a HTTP POST endpoint. When the user sends the address of a webpage to it, the endpoint fetches the contents of the URL and returns them to the user. + +Have a look at [App.java](src/main/java/helloworld/App.java) for the full details. + +## Build the sample application + +> [!NOTE] +> Building AWS Lambda packages on macOS (ARM64/Intel) for deployment on AWS Lambda (Linux x86_64 or ARM64) will result in incompatible binary dependencies that cause import errors at runtime. + +Choose the appropriate build method based on your operating system: + +### Build locally using Docker + +Recommended for macOS and Windows users: Cross-compile using Docker to match target platform of Lambda: + +```shell +docker build --platform linux/amd64 . -t powertools-examples-idempotency-sam-graalvm +docker run --platform linux/amd64 -it -v `pwd`:`pwd` -w `pwd` -v ~/.m2:/root/.m2 powertools-examples-idempotency-sam-graalvm mvn clean -Pnative-image package -DskipTests +sam build --use-container --build-image powertools-examples-idempotency-sam-graalvm +``` + +**Note**: The Docker run command mounts your local Maven cache (`~/.m2`) and builds the native binary with SNAPSHOT support, then SAM packages the pre-built binary. + +### Build on native OS + +For Linux users with GraalVM installed: + +```shell +export JAVA_HOME= +mvn clean -Pnative-image package -DskipTests +sam build +``` + +## Deploy the sample application + +```shell +sam deploy +``` + +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 + +```bash +curl -X POST https://[REST-API-ID].execute-api.[REGION].amazonaws.com/Prod/helloidem/ -H "Content-Type: application/json" -d '{"address": "https://checkip.amazonaws.com"}' +``` + +this should return the contents of the webpage, for instance: + +```json +{ "message": "hello world", "location": "123.123.123.1" } +``` + +- First call will execute the handleRequest normally, and store the response in the idempotency table (Look into DynamoDB) +- 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). + +Check out [App.java](src/main/java/helloworld/App.java) to see how it works! diff --git a/examples/powertools-examples-idempotency/sam-graalvm/pom.xml b/examples/powertools-examples-idempotency/sam-graalvm/pom.xml new file mode 100644 index 000000000..6abb743f9 --- /dev/null +++ b/examples/powertools-examples-idempotency/sam-graalvm/pom.xml @@ -0,0 +1,167 @@ + + 4.0.0 + software.amazon.lambda.examples + 2.3.0 + powertools-examples-idempotency-sam-graalvm + jar + Powertools for AWS Lambda (Java) - Examples - Idempotency GraalVM + + + 11 + 11 + 1.9.20.1 + + + + + software.amazon.lambda + powertools-tracing + ${project.version} + + + software.amazon.lambda + powertools-logging-log4j + ${project.version} + + + software.amazon.lambda + powertools-idempotency-dynamodb + ${project.version} + + + + com.amazonaws + aws-lambda-java-core + 1.3.0 + + + com.amazonaws + aws-lambda-java-events + 3.16.1 + + + com.amazonaws + aws-lambda-java-runtime-interface-client + 2.8.3 + + + + org.aspectj + aspectjrt + ${aspectj.version} + + + + + + + dev.aspectj + aspectj-maven-plugin + 1.14.1 + + ${maven.compiler.source} + ${maven.compiler.target} + ${maven.compiler.target} + + + software.amazon.lambda + powertools-tracing + + + software.amazon.lambda + powertools-logging + + + software.amazon.lambda + powertools-idempotency-core + + + + + + + compile + + + + + + org.aspectj + aspectjtools + ${aspectj.version} + + + + + org.apache.maven.plugins + maven-shade-plugin + 3.6.0 + + + package + + shade + + + false + + + + + + + + + org.apache.logging.log4j + log4j-transform-maven-shade-plugin-extensions + 0.2.0 + + + + + + org.apache.maven.plugins + maven-deploy-plugin + 3.1.4 + + true + + + + + + + native-image + + + + org.graalvm.buildtools + native-maven-plugin + 0.11.0 + true + + + build-native + + build + + package + + + + hello-world + com.amazonaws.services.lambda.runtime.api.client.AWSLambda + + + --enable-url-protocols=http,https + --add-opens java.base/java.util=ALL-UNNAMED + + + + + + + + diff --git a/examples/powertools-examples-idempotency/sam-graalvm/src/main/config/bootstrap b/examples/powertools-examples-idempotency/sam-graalvm/src/main/config/bootstrap new file mode 100644 index 000000000..8e7928cd3 --- /dev/null +++ b/examples/powertools-examples-idempotency/sam-graalvm/src/main/config/bootstrap @@ -0,0 +1,4 @@ +#!/bin/bash +set -e + +./hello-world $_HANDLER \ No newline at end of file diff --git a/examples/powertools-examples-idempotency/src/main/java/helloworld/App.java b/examples/powertools-examples-idempotency/sam-graalvm/src/main/java/helloworld/App.java similarity index 100% rename from examples/powertools-examples-idempotency/src/main/java/helloworld/App.java rename to examples/powertools-examples-idempotency/sam-graalvm/src/main/java/helloworld/App.java diff --git a/examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json b/examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json new file mode 100644 index 000000000..2780aca09 --- /dev/null +++ b/examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json @@ -0,0 +1,13 @@ +[ + { + "name":"com.amazonaws.services.lambda.runtime.LambdaRuntime", + "methods":[{"name":"","parameterTypes":[] }], + "fields":[{"name":"logger"}], + "allPublicMethods":true + }, + { + "name":"com.amazonaws.services.lambda.runtime.LambdaRuntimeInternal", + "methods":[{"name":"","parameterTypes":[] }], + "allPublicMethods":true + } +] \ No newline at end of file diff --git a/examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json b/examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json new file mode 100644 index 000000000..ddda5d5f1 --- /dev/null +++ b/examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json @@ -0,0 +1,35 @@ +[ + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent$ProxyRequestContext", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent$RequestIdentity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "allPublicClasses": true + } +] \ No newline at end of file diff --git a/examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json b/examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json new file mode 100644 index 000000000..91be72f7a --- /dev/null +++ b/examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json @@ -0,0 +1,11 @@ +[ + { + "name":"com.amazonaws.services.lambda.runtime.api.client.runtimeapi.LambdaRuntimeClientException", + "methods":[{"name":"","parameterTypes":["java.lang.String","int"] }] + }, + { + "name":"com.amazonaws.services.lambda.runtime.api.client.runtimeapi.dto.InvocationRequest", + "fields":[{"name":"id"}, {"name":"invokedFunctionArn"}, {"name":"deadlineTimeInMs"}, {"name":"xrayTraceId"}, {"name":"clientContext"}, {"name":"cognitoIdentity"}, {"name": "tenantId"}, {"name":"content"}], + "allPublicMethods":true + } +] \ No newline at end of file diff --git a/examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties b/examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties new file mode 100644 index 000000000..20f8b7801 --- /dev/null +++ b/examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties @@ -0,0 +1 @@ +Args = --initialize-at-build-time=jdk.xml.internal.SecuritySupport \ No newline at end of file diff --git a/examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json b/examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json new file mode 100644 index 000000000..10152cc64 --- /dev/null +++ b/examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json @@ -0,0 +1,34 @@ +[ + { + "name":"com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.Deserializers[]" + }, + { + "name":"com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.Java7SupportImpl", + "methods":[{"name":"","parameterTypes":[] }] + }, + { + "name":"com.amazonaws.services.lambda.runtime.LambdaRuntime", + "fields":[{"name":"logger"}] + }, + { + "name":"java.lang.Void", + "methods":[{"name":"","parameterTypes":[] }] + }, + { + "name":"java.util.Collections$UnmodifiableMap", + "fields":[{"name":"m"}] + }, + { + "name":"jdk.internal.module.IllegalAccessLogger", + "fields":[{"name":"logger"}] + }, + { + "name":"sun.misc.Unsafe", + "fields":[{"name":"theUnsafe"}] + }, + { + "name":"com.amazonaws.services.lambda.runtime.api.client.runtimeapi.dto.InvocationRequest", + "fields":[{"name":"id"}, {"name":"invokedFunctionArn"}, {"name":"deadlineTimeInMs"}, {"name":"xrayTraceId"}, {"name":"clientContext"}, {"name":"cognitoIdentity"}, {"name": "tenantId"}, {"name":"content"}], + "allPublicMethods":true + } +] \ No newline at end of file diff --git a/examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json b/examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json new file mode 100644 index 000000000..1062b4249 --- /dev/null +++ b/examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json @@ -0,0 +1,19 @@ +{ + "resources": { + "includes": [ + { + "pattern": "\\Qjni/libaws-lambda-jni.linux-aarch_64.so\\E" + }, + { + "pattern": "\\Qjni/libaws-lambda-jni.linux-x86_64.so\\E" + }, + { + "pattern": "\\Qjni/libaws-lambda-jni.linux_musl-aarch_64.so\\E" + }, + { + "pattern": "\\Qjni/libaws-lambda-jni.linux_musl-x86_64.so\\E" + } + ] + }, + "bundles": [] +} \ No newline at end of file diff --git a/examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json b/examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json new file mode 100644 index 000000000..9890688f9 --- /dev/null +++ b/examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json @@ -0,0 +1,25 @@ +[ + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.Deserializers[]" + }, + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.Java7HandlersImpl", + "methods": [{ "name": "", "parameterTypes": [] }] + }, + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.Java7SupportImpl", + "methods": [{ "name": "", "parameterTypes": [] }] + }, + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.Serializers[]" + }, + { + "name": "org.joda.time.DateTime", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "allPublicClasses": true + } +] diff --git a/examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/helloworld/reflect-config.json b/examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/helloworld/reflect-config.json new file mode 100644 index 000000000..d01f93780 --- /dev/null +++ b/examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/helloworld/reflect-config.json @@ -0,0 +1,11 @@ +[ + { + "name": "helloworld.App", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "allPublicClasses": true + } +] \ No newline at end of file diff --git a/examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/helloworld/resource-config.json b/examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/helloworld/resource-config.json new file mode 100644 index 000000000..be6aac3f6 --- /dev/null +++ b/examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/helloworld/resource-config.json @@ -0,0 +1,7 @@ +{ + "resources":{ + "includes":[{ + "pattern":"\\Qlog4j2.xml\\E" + }]}, + "bundles":[] +} diff --git a/examples/powertools-examples-idempotency/src/main/resources/log4j2.xml b/examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/log4j2.xml similarity index 100% rename from examples/powertools-examples-idempotency/src/main/resources/log4j2.xml rename to examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/log4j2.xml diff --git a/examples/powertools-examples-idempotency/sam-graalvm/template.yaml b/examples/powertools-examples-idempotency/sam-graalvm/template.yaml new file mode 100644 index 000000000..5ffd70255 --- /dev/null +++ b/examples/powertools-examples-idempotency/sam-graalvm/template.yaml @@ -0,0 +1,60 @@ +AWSTemplateFormatVersion: "2010-09-09" +Transform: AWS::Serverless-2016-10-31 +Description: > + Idempotency demo with GraalVM + +Globals: + Function: + Timeout: 20 + MemorySize: 512 + Tracing: Active + Environment: + Variables: + POWERTOOLS_LOG_LEVEL: INFO + POWERTOOLS_LOGGER_SAMPLE_RATE: 0.1 + POWERTOOLS_LOGGER_LOG_EVENT: true + +Resources: + IdempotencyTable: + Type: AWS::DynamoDB::Table + Properties: + AttributeDefinitions: + - AttributeName: id + AttributeType: S + KeySchema: + - AttributeName: id + KeyType: HASH + TimeToLiveSpecification: + AttributeName: expiration + Enabled: true + BillingMode: PAY_PER_REQUEST + + IdempotencyFunction: + Type: AWS::Serverless::Function + Properties: + CodeUri: . + Handler: helloworld.App::handleRequest + Runtime: provided.al2023 + MemorySize: 512 + Tracing: Active + Policies: + - DynamoDBCrudPolicy: + TableName: !Ref IdempotencyTable + Environment: + Variables: + POWERTOOLS_SERVICE_NAME: idempotency + IDEMPOTENCY_TABLE: !Ref IdempotencyTable + Events: + HelloWorld: + Type: Api + Properties: + Path: /helloidem + Method: post + +Outputs: + HelloWorldApi: + Description: "API Gateway endpoint URL for Prod stage for Idempotent function" + Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/helloidem/" + HelloWorldFunction: + Description: "Idempotent Lambda Function ARN" + Value: !GetAtt IdempotencyFunction.Arn diff --git a/examples/powertools-examples-idempotency/README.md b/examples/powertools-examples-idempotency/sam/README.md similarity index 100% rename from examples/powertools-examples-idempotency/README.md rename to examples/powertools-examples-idempotency/sam/README.md diff --git a/examples/powertools-examples-idempotency/pom.xml b/examples/powertools-examples-idempotency/sam/pom.xml similarity index 65% rename from examples/powertools-examples-idempotency/pom.xml rename to examples/powertools-examples-idempotency/sam/pom.xml index eb235437b..1b82ab3ed 100644 --- a/examples/powertools-examples-idempotency/pom.xml +++ b/examples/powertools-examples-idempotency/sam/pom.xml @@ -13,7 +13,7 @@ --> + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 software.amazon.lambda.examples @@ -44,6 +44,7 @@ powertools-idempotency-dynamodb ${project.version} + com.amazonaws aws-lambda-java-core @@ -54,24 +55,12 @@ aws-lambda-java-events 3.16.1 + org.aspectj aspectjrt ${aspectj.version} - - - org.mockito - mockito-core - 5.18.0 - test - - - org.junit.jupiter - junit-jupiter-api - 5.11.1 - test - @@ -114,39 +103,7 @@ - - org.apache.maven.plugins - maven-dependency-plugin - - - copy - test-compile - - copy-dependencies - - - test - so,dll,dylib - ${project.build.directory}/native-libs - - - - - - org.apache.maven.plugins - maven-surefire-plugin - 3.5.3 - - - ${project.build.directory}/native-libs - - - idempotency - eu-central-1 - LOG_ERROR - - - + org.apache.maven.plugins maven-shade-plugin @@ -159,19 +116,9 @@ false - - - - - - org.apache.logging.log4j - log4j-transform-maven-shade-plugin-extensions - 0.2.0 - - org.apache.maven.plugins diff --git a/examples/powertools-examples-idempotency/sam/src/main/java/helloworld/App.java b/examples/powertools-examples-idempotency/sam/src/main/java/helloworld/App.java new file mode 100644 index 000000000..ebe9fac22 --- /dev/null +++ b/examples/powertools-examples-idempotency/sam/src/main/java/helloworld/App.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 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.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Collectors; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import software.amazon.awssdk.services.dynamodb.DynamoDbClient; +import software.amazon.lambda.powertools.idempotency.Idempotency; +import software.amazon.lambda.powertools.idempotency.IdempotencyConfig; +import software.amazon.lambda.powertools.idempotency.Idempotent; +import software.amazon.lambda.powertools.idempotency.persistence.dynamodb.DynamoDBPersistenceStore; +import software.amazon.lambda.powertools.logging.Logging; +import software.amazon.lambda.powertools.tracing.Tracing; +import software.amazon.lambda.powertools.utilities.JsonConfig; + +public class App implements RequestHandler { + private static final Logger log = LoggerFactory.getLogger(App.class); + + public App() { + this(null); + } + + public App(DynamoDbClient client) { + Idempotency.config().withConfig( + IdempotencyConfig.builder() + .withEventKeyJMESPath("powertools_json(body).address") + .withResponseHook((responseData, dataRecord) -> { + if (responseData instanceof APIGatewayProxyResponseEvent) { + APIGatewayProxyResponseEvent proxyResponse = (APIGatewayProxyResponseEvent) responseData; + final Map headers = new HashMap<>(); + headers.putAll(proxyResponse.getHeaders()); + headers.put("x-idempotency-response", "true"); + headers.put("x-idempotency-expiration", + String.valueOf(dataRecord.getExpiryTimestamp())); + + proxyResponse.setHeaders(headers); + + return proxyResponse; + } + + return responseData; + }) + .build()) + .withPersistenceStore( + DynamoDBPersistenceStore.builder() + .withDynamoDbClient(client) + .withTableName(System.getenv("IDEMPOTENCY_TABLE")) + .build()) + .configure(); + } + + /** + * This is your 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: + * + *

+     *     curl -X POST https://[REST-API-ID].execute-api.[REGION].amazonaws.com/Prod/helloidem/ -H "Content-Type: application/json" -d '{"address": "https://checkip.amazonaws.com"}'
+     * 
+ *
    + *
  • First call will execute the handleRequest normally, and store the response in the idempotency table (Look + * into DynamoDB)
  • + *
  • 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! + @Logging(logEvent = true) + @Tracing + public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) { + Map headers = new HashMap<>(); + + headers.put("Content-Type", "application/json"); + headers.put("Access-Control-Allow-Origin", "*"); + headers.put("Access-Control-Allow-Methods", "GET, OPTIONS"); + headers.put("Access-Control-Allow-Headers", "*"); + + 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); + + log.info("ip is {}", pageContents); + return response + .withStatusCode(200) + .withBody(output); + + } catch (IOException e) { + return response + .withBody("{}") + .withStatusCode(500); + } + } + + /** + * 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 + */ + @Tracing + private String getPageContents(String address) throws IOException { + URL url = new URL(address); + try (BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream(), StandardCharsets.UTF_8))) { + return br.lines().collect(Collectors.joining(System.lineSeparator())); + } + } +} diff --git a/examples/powertools-examples-idempotency/sam/src/main/resources/log4j2.xml b/examples/powertools-examples-idempotency/sam/src/main/resources/log4j2.xml new file mode 100644 index 000000000..5dede7b58 --- /dev/null +++ b/examples/powertools-examples-idempotency/sam/src/main/resources/log4j2.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/examples/powertools-examples-idempotency/template.yaml b/examples/powertools-examples-idempotency/sam/template.yaml similarity index 100% rename from examples/powertools-examples-idempotency/template.yaml rename to examples/powertools-examples-idempotency/sam/template.yaml diff --git a/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProduct.java b/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProduct.java index 250f37090..21961ad2b 100644 --- a/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProduct.java +++ b/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProduct.java @@ -1,7 +1,7 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: ProtobufProduct.proto -// Protobuf Java Version: 4.31.1 +// Protobuf Java Version: 4.32.0 package org.demo.kafka.protobuf; @@ -18,8 +18,8 @@ public final class ProtobufProduct extends com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, /* major= */ 4, - /* minor= */ 31, - /* patch= */ 1, + /* minor= */ 32, + /* patch= */ 0, /* suffix= */ "", ProtobufProduct.class.getName()); } diff --git a/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProductOrBuilder.java b/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProductOrBuilder.java index b2d185f6d..347ea854a 100644 --- a/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProductOrBuilder.java +++ b/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProductOrBuilder.java @@ -1,7 +1,7 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: ProtobufProduct.proto -// Protobuf Java Version: 4.31.1 +// Protobuf Java Version: 4.32.0 package org.demo.kafka.protobuf; diff --git a/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProductOuterClass.java b/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProductOuterClass.java index adbfdd73a..046283d9a 100644 --- a/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProductOuterClass.java +++ b/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProductOuterClass.java @@ -1,7 +1,7 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: ProtobufProduct.proto -// Protobuf Java Version: 4.31.1 +// Protobuf Java Version: 4.32.0 package org.demo.kafka.protobuf; @@ -12,8 +12,8 @@ private ProtobufProductOuterClass() {} com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, /* major= */ 4, - /* minor= */ 31, - /* patch= */ 1, + /* minor= */ 32, + /* patch= */ 0, /* suffix= */ "", ProtobufProductOuterClass.class.getName()); } From 56b1aa66812e30a3de66785476329e99ae2a8d67 Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Thu, 14 Aug 2025 14:07:15 +0200 Subject: [PATCH 03/65] chore(ci): Run unit tests for GraalVM as well during build. --- .github/workflows/check-build.yml | 62 ++++++++++++++++--------------- 1 file changed, 33 insertions(+), 29 deletions(-) diff --git a/.github/workflows/check-build.yml b/.github/workflows/check-build.yml index 45fef40b9..56fd193c1 100644 --- a/.github/workflows/check-build.yml +++ b/.github/workflows/check-build.yml @@ -2,15 +2,13 @@ # # Description: # Runs the build for every java version we support -# +# # Triggers: # - pull_request: when a PR is sent to us # - push: when code is pushed to a specified branch # # Notes: -# The matrix build for this workflow is unusual, we need to make it dyanmic since -# we need to change java versions we build for depending on the branch. - +# Builds against Java 11, 17, and 21 which are the supported versions. on: workflow_dispatch: @@ -38,7 +36,7 @@ on: push: branches: - main - paths: # add other modules when there are under e2e tests + paths: - 'powertools-batch/**' - 'powertools-core/**' - 'powertools-cloudformation/**' @@ -63,31 +61,11 @@ name: Build run-name: Build - ${{ github.event_name }} jobs: - setup: - runs-on: ubuntu-latest - outputs: - build_matrix: ${{ format('{0}{1}', steps.build_matrix_v1.outputs.build_matrix, steps.build_matrix_v1.outputs.build_matrix) }} - steps: - - id: base - name: Base - run: | - echo build_version=$(test ${{ github.ref }} == "v2" && echo "v2" || echo "v1") >> $GITHUB_OUTPUT - - id: build_matrix_v1 - name: Build matrix (v1) - if: ${{ steps.base.outputs.build_version == 'v1' }} - run: | - echo build_matrix='["8", "11", "17", "21"]' >> "$GITHUB_OUTPUT" - - id: build_matrix_v2 - name: Build matrix (v2) - if: ${{ steps.base.outputs.build_version == 'v2' }} - run: | - echo build_matrix='["11", "17", "21"]'>> "$GITHUB_OUTPUT" - build: + java-build: runs-on: ubuntu-latest strategy: matrix: java: - - 8 - 11 - 17 - 21 @@ -96,13 +74,39 @@ jobs: name: Checkout repository uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Setup Java - uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 + uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 with: distribution: corretto java-version: ${{ matrix.java }} cache: maven - id: build-maven name: Build (Maven) - if: ${{ matrix.java != '8' }} run: | - mvn -B install --file pom.xml \ No newline at end of file + mvn -B install --file pom.xml + + graalvm-build: + runs-on: ubuntu-latest + steps: + - id: checkout + name: Checkout repository + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - name: Setup GraalVM + uses: graalvm/setup-graalvm@7f488cf82a3629ee755e4e97342c01d6bed318fa # v1.3.5 + with: + java-version: "21" + distribution: "graalvm" + cache: maven + - id: graalvm-native-test + name: GraalVM Native Test + run: | + # Find modules with graalvm-native profile and run tests. + # This will make sure to discover new GraalVM supported modules automatically in the future. + for module in powertools-*/pom.xml; do + if grep -q "graalvm-native" "$module"; then + module_dir=$(dirname "$module") + echo "Regenerating GraalVM metadata for $module_dir" + mvn -B -f "$module" -Pgenerate-graalvm-files clean test + echo "Running GraalVM native tests for $module_dir" + mvn -B -f "$module" -Pgraalvm-native test + fi + done From 1a1413561f62e8d303393859e4c92dcfcca812e3 Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Thu, 14 Aug 2025 18:07:29 +0200 Subject: [PATCH 04/65] Test GraalVM unit tests on Mockito 5.16.0. --- pom.xml | 5 ++--- powertools-common/pom.xml | 2 -- powertools-logging/pom.xml | 2 -- powertools-logging/powertools-logging-log4j/pom.xml | 2 -- powertools-logging/powertools-logging-logback/pom.xml | 2 -- powertools-parameters/pom.xml | 2 -- .../powertools-parameters-appconfig/pom.xml | 2 -- powertools-parameters/powertools-parameters-dynamodb/pom.xml | 2 -- powertools-parameters/powertools-parameters-secrets/pom.xml | 2 -- powertools-parameters/powertools-parameters-ssm/pom.xml | 4 +--- powertools-parameters/powertools-parameters-tests/pom.xml | 2 -- powertools-serialization/pom.xml | 2 -- powertools-tracing/pom.xml | 2 -- 13 files changed, 3 insertions(+), 28 deletions(-) diff --git a/pom.xml b/pom.xml index bb2854c33..a6fea9dd7 100644 --- a/pom.xml +++ b/pom.xml @@ -100,7 +100,6 @@ 3.11.2 3.3.1 3.2.1 - 5.10.0 1.14.1 3.5.3 0.8.13 @@ -114,8 +113,8 @@ 1.12.781 2.18.0 1.7.0 - 5.18.0 - 5.18.0 + 5.16.0 + 5.16.0 2.3.0 1.5.0 diff --git a/powertools-common/pom.xml b/powertools-common/pom.xml index 9f8456842..101a08824 100644 --- a/powertools-common/pom.xml +++ b/powertools-common/pom.xml @@ -94,7 +94,6 @@ org.mockito mockito-subclass - 5.18.0 test @@ -120,7 +119,6 @@ org.mockito mockito-subclass - 5.18.0 test diff --git a/powertools-logging/pom.xml b/powertools-logging/pom.xml index 7757be572..e2ba53878 100644 --- a/powertools-logging/pom.xml +++ b/powertools-logging/pom.xml @@ -120,7 +120,6 @@ org.mockito mockito-subclass - 5.18.0 test @@ -146,7 +145,6 @@ org.mockito mockito-subclass - 5.18.0 test diff --git a/powertools-logging/powertools-logging-log4j/pom.xml b/powertools-logging/powertools-logging-log4j/pom.xml index 2d734cdcb..acdfdc42b 100644 --- a/powertools-logging/powertools-logging-log4j/pom.xml +++ b/powertools-logging/powertools-logging-log4j/pom.xml @@ -104,7 +104,6 @@ org.mockito mockito-subclass - 5.18.0 test @@ -130,7 +129,6 @@ org.mockito mockito-subclass - 5.18.0 test diff --git a/powertools-logging/powertools-logging-logback/pom.xml b/powertools-logging/powertools-logging-logback/pom.xml index 41750ec70..b9ea7f8de 100644 --- a/powertools-logging/powertools-logging-logback/pom.xml +++ b/powertools-logging/powertools-logging-logback/pom.xml @@ -92,7 +92,6 @@ org.mockito mockito-subclass - 5.18.0 test @@ -115,7 +114,6 @@ org.mockito mockito-subclass - 5.18.0 test diff --git a/powertools-parameters/pom.xml b/powertools-parameters/pom.xml index d43221b5e..fec1b8efa 100644 --- a/powertools-parameters/pom.xml +++ b/powertools-parameters/pom.xml @@ -97,7 +97,6 @@ org.mockito mockito-subclass - 5.18.0 test @@ -123,7 +122,6 @@ org.mockito mockito-subclass - 5.18.0 test diff --git a/powertools-parameters/powertools-parameters-appconfig/pom.xml b/powertools-parameters/powertools-parameters-appconfig/pom.xml index 4d650c58b..0a83d36e2 100644 --- a/powertools-parameters/powertools-parameters-appconfig/pom.xml +++ b/powertools-parameters/powertools-parameters-appconfig/pom.xml @@ -86,7 +86,6 @@ org.mockito mockito-subclass - 5.18.0 test @@ -112,7 +111,6 @@ org.mockito mockito-subclass - 5.18.0 test diff --git a/powertools-parameters/powertools-parameters-dynamodb/pom.xml b/powertools-parameters/powertools-parameters-dynamodb/pom.xml index 1834b229d..9ffca4ad8 100644 --- a/powertools-parameters/powertools-parameters-dynamodb/pom.xml +++ b/powertools-parameters/powertools-parameters-dynamodb/pom.xml @@ -87,7 +87,6 @@ org.mockito mockito-subclass - 5.18.0 test @@ -113,7 +112,6 @@ org.mockito mockito-subclass - 5.18.0 test diff --git a/powertools-parameters/powertools-parameters-secrets/pom.xml b/powertools-parameters/powertools-parameters-secrets/pom.xml index ef032f0c3..9b6696900 100644 --- a/powertools-parameters/powertools-parameters-secrets/pom.xml +++ b/powertools-parameters/powertools-parameters-secrets/pom.xml @@ -87,7 +87,6 @@ org.mockito mockito-subclass - 5.18.0 test @@ -113,7 +112,6 @@ org.mockito mockito-subclass - 5.18.0 test diff --git a/powertools-parameters/powertools-parameters-ssm/pom.xml b/powertools-parameters/powertools-parameters-ssm/pom.xml index fcb7b5311..52b51c1d9 100644 --- a/powertools-parameters/powertools-parameters-ssm/pom.xml +++ b/powertools-parameters/powertools-parameters-ssm/pom.xml @@ -101,7 +101,6 @@ org.mockito mockito-subclass - 5.18.0 test @@ -127,7 +126,6 @@ org.mockito mockito-subclass - 5.18.0 test @@ -187,4 +185,4 @@ - \ No newline at end of file + diff --git a/powertools-parameters/powertools-parameters-tests/pom.xml b/powertools-parameters/powertools-parameters-tests/pom.xml index abd2a02d2..f09d79ac9 100644 --- a/powertools-parameters/powertools-parameters-tests/pom.xml +++ b/powertools-parameters/powertools-parameters-tests/pom.xml @@ -97,7 +97,6 @@ org.mockito mockito-subclass - 5.18.0 test @@ -123,7 +122,6 @@ org.mockito mockito-subclass - 5.18.0 test diff --git a/powertools-serialization/pom.xml b/powertools-serialization/pom.xml index d6cc33891..8bb3a6f67 100644 --- a/powertools-serialization/pom.xml +++ b/powertools-serialization/pom.xml @@ -97,7 +97,6 @@ org.mockito mockito-subclass - 5.18.0 test @@ -120,7 +119,6 @@ org.mockito mockito-subclass - 5.18.0 test diff --git a/powertools-tracing/pom.xml b/powertools-tracing/pom.xml index cb7f8218f..b95caf56b 100644 --- a/powertools-tracing/pom.xml +++ b/powertools-tracing/pom.xml @@ -125,7 +125,6 @@ org.mockito mockito-subclass - 5.18.0 test @@ -151,7 +150,6 @@ org.mockito mockito-subclass - 5.18.0 test From 1e32df2e517b4c70503208f106c60e892d6ca1e3 Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Fri, 15 Aug 2025 09:03:05 +0200 Subject: [PATCH 05/65] Fix native tests in powertools-serialization. Remove mockito dependency there. --- powertools-serialization/pom.xml | 37 +++++++++----------------------- 1 file changed, 10 insertions(+), 27 deletions(-) diff --git a/powertools-serialization/pom.xml b/powertools-serialization/pom.xml index 8bb3a6f67..dc2cd8cd5 100644 --- a/powertools-serialization/pom.xml +++ b/powertools-serialization/pom.xml @@ -14,8 +14,8 @@ --> + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 @@ -54,6 +54,11 @@ junit-jupiter-api test + + org.junit.jupiter + junit-jupiter-engine + test + org.slf4j slf4j-simple @@ -107,7 +112,9 @@ maven-surefire-plugin 3.5.3 - -Dmockito.mock.maker=subclass -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-serialization,experimental-class-define-support + + -Dorg.graalvm.nativeimage.imagecode=agent + -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-serialization,experimental-class-define-support @@ -115,13 +122,6 @@ graalvm-native - - - org.mockito - mockito-subclass - test - - @@ -147,28 +147,11 @@ --no-fallback -Dorg.graalvm.nativeimage.imagecode=agent - -H:ClassInitialization=net.bytebuddy.ClassFileVersion:rerun - -H:ClassInitialization=net.bytebuddy.utility.dispatcher.JavaDispatcher:rerun - -H:ClassInitialization=net.bytebuddy.utility.Invoker$Dispatcher:rerun - -H:ClassInitialization=net.bytebuddy.utility.GraalImageCode:rerun --initialize-at-build-time=org.slf4j.simple.SimpleLogger --initialize-at-build-time=org.slf4j.LoggerFactory --initialize-at-build-time=org.junit.Ignore --initialize-at-build-time=java.lang.annotation.Annotation --initialize-at-build-time=org.junit.runners.model.FrameworkField - --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase - --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic - --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$1 - --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$2 - --initialize-at-build-time=net.bytebuddy.utility.dispatcher.JavaDispatcher$DynamicClassLoader - --initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable - --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase - --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$ForLoadedType - --initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$ForLoadedMethod - --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Super$Instantiation$2 - - --trace-class-initialization=net.bytebuddy.description.type.TypeDescription$ForLoadedType,net.bytebuddy.description.method.MethodDescription$ForLoadedMethod,net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable - --verbose From 68942468e25f284b5b36438e0d7d386df13170cf Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Fri, 15 Aug 2025 11:26:32 +0200 Subject: [PATCH 06/65] Remove mockito from powertools-common. --- pom.xml | 6 +- powertools-common/pom.xml | 43 +-------- .../internal/LambdaHandlerProcessorTest.java | 53 ++++++----- .../common/stubs/TestInputStream.java | 24 +++++ .../common/stubs/TestLambdaContext.java | 77 ++++++++++++++++ .../common/stubs/TestOutputStream.java | 23 +++++ .../common/stubs/TestProceedingJoinPoint.java | 90 +++++++++++++++++++ .../common/stubs/TestSignature.java | 55 ++++++++++++ 8 files changed, 301 insertions(+), 70 deletions(-) create mode 100644 powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestInputStream.java create mode 100644 powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestLambdaContext.java create mode 100644 powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestOutputStream.java create mode 100644 powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestProceedingJoinPoint.java create mode 100644 powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestSignature.java diff --git a/pom.xml b/pom.xml index a6fea9dd7..c2a792d91 100644 --- a/pom.xml +++ b/pom.xml @@ -113,8 +113,8 @@ 1.12.781 2.18.0 1.7.0 - 5.16.0 - 5.16.0 + 5.19.0 + 5.19.0 2.3.0 1.5.0 @@ -321,7 +321,7 @@ org.junit-pioneer junit-pioneer - 2.0.0 + ${junit-pioneer.version} test diff --git a/powertools-common/pom.xml b/powertools-common/pom.xml index 101a08824..5f173c604 100644 --- a/powertools-common/pom.xml +++ b/powertools-common/pom.xml @@ -14,8 +14,8 @@ --> + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 powertools-common @@ -76,11 +76,6 @@ assertj-core test - - org.mockito - mockito-core - test - org.slf4j slf4j-simple @@ -90,13 +85,6 @@ generate-graalvm-files - - - org.mockito - mockito-subclass - test - - @@ -104,7 +92,8 @@ maven-surefire-plugin 3.5.3 - -Dmockito.mock.maker=subclass -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-common,experimental-class-define-support + -Dorg.graalvm.nativeimage.imagecode=agent + -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-common,experimental-class-define-support --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED @@ -115,13 +104,6 @@ graalvm-native - - - org.mockito - mockito-subclass - test - - @@ -145,28 +127,11 @@ --add-opens java.base/java.lang=ALL-UNNAMED --no-fallback -Dorg.graalvm.nativeimage.imagecode=agent - -H:ClassInitialization=net.bytebuddy.ClassFileVersion:rerun - -H:ClassInitialization=net.bytebuddy.utility.dispatcher.JavaDispatcher:rerun - -H:ClassInitialization=net.bytebuddy.utility.Invoker$Dispatcher:rerun - -H:ClassInitialization=net.bytebuddy.utility.GraalImageCode:rerun --initialize-at-build-time=org.slf4j.simple.SimpleLogger --initialize-at-build-time=org.slf4j.LoggerFactory --initialize-at-build-time=org.junit.Ignore --initialize-at-build-time=java.lang.annotation.Annotation --initialize-at-build-time=org.junit.runners.model.FrameworkField - --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase - --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic - --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$1 - --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$2 - --initialize-at-build-time=net.bytebuddy.utility.dispatcher.JavaDispatcher$DynamicClassLoader - --initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable - --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase - --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$ForLoadedType - --initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$ForLoadedMethod - --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Super$Instantiation$2 - - --trace-class-initialization=net.bytebuddy.description.type.TypeDescription$ForLoadedType,net.bytebuddy.description.method.MethodDescription$ForLoadedMethod,net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable - --verbose --native-image-info -H:+UnlockExperimentalVMOptions diff --git a/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/LambdaHandlerProcessorTest.java b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/LambdaHandlerProcessorTest.java index 15d7bccdb..11eac7a4c 100644 --- a/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/LambdaHandlerProcessorTest.java +++ b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/LambdaHandlerProcessorTest.java @@ -16,15 +16,10 @@ 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.when; -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.junitpioneer.jupiter.ClearEnvironmentVariable; import org.junitpioneer.jupiter.SetEnvironmentVariable; @@ -33,14 +28,18 @@ import com.amazonaws.services.lambda.runtime.RequestHandler; import com.amazonaws.services.lambda.runtime.RequestStreamHandler; -class LambdaHandlerProcessorTest { +import software.amazon.lambda.powertools.common.stubs.TestLambdaContext; +import software.amazon.lambda.powertools.common.stubs.TestInputStream; +import software.amazon.lambda.powertools.common.stubs.TestOutputStream; +import software.amazon.lambda.powertools.common.stubs.TestProceedingJoinPoint; +import software.amazon.lambda.powertools.common.stubs.TestSignature; - private Signature signature = mock(Signature.class); - private ProceedingJoinPoint pjpMock = mock(ProceedingJoinPoint.class); +class LambdaHandlerProcessorTest { @Test void isHandlerMethod_shouldRecognizeRequestHandler() { - Object[] args = {new Object(), mock(Context.class)}; + Context context = new TestLambdaContext(); + Object[] args = { new Object(), context }; ProceedingJoinPoint pjpMock = mockRequestHandlerPjp(RequestHandler.class, args); assertThat(LambdaHandlerProcessor.isHandlerMethod(pjpMock)).isTrue(); @@ -48,7 +47,7 @@ void isHandlerMethod_shouldRecognizeRequestHandler() { @Test void isHandlerMethod_shouldRecognizeRequestStreamHandler() { - Object[] args = {mock(InputStream.class), mock(OutputStream.class), mock(Context.class)}; + Object[] args = { new TestInputStream(), new TestOutputStream(), new TestLambdaContext() }; ProceedingJoinPoint pjpMock = mockRequestHandlerPjp(RequestStreamHandler.class, args); assertThat(LambdaHandlerProcessor.isHandlerMethod(pjpMock)).isTrue(); @@ -65,7 +64,7 @@ void isHandlerMethod_shouldReturnFalse() { @Test void placedOnRequestHandler_shouldRecognizeRequestHandler() { - Object[] args = {new Object(), mock(Context.class)}; + Object[] args = { new Object(), new TestLambdaContext() }; ProceedingJoinPoint pjpMock = mockRequestHandlerPjp(RequestHandler.class, args); assertThat(LambdaHandlerProcessor.placedOnRequestHandler(pjpMock)).isTrue(); @@ -73,7 +72,7 @@ void placedOnRequestHandler_shouldRecognizeRequestHandler() { @Test void placedOnStreamHandler_shouldRecognizeRequestStreamHandler() { - Object[] args = {mock(InputStream.class), mock(OutputStream.class), mock(Context.class)}; + Object[] args = { new TestInputStream(), new TestOutputStream(), new TestLambdaContext() }; ProceedingJoinPoint pjpMock = mockRequestHandlerPjp(RequestStreamHandler.class, args); assertThat(LambdaHandlerProcessor.placedOnStreamHandler(pjpMock)).isTrue(); @@ -81,7 +80,7 @@ void placedOnStreamHandler_shouldRecognizeRequestStreamHandler() { @Test void placedOnRequestHandler_shouldInvalidateOnWrongNoOfArgs() { - Object[] args = {new Object()}; + Object[] args = { new Object() }; ProceedingJoinPoint pjpMock = mockRequestHandlerPjp(RequestHandler.class, args); boolean isPlacedOnRequestHandler = LambdaHandlerProcessor.placedOnRequestHandler(pjpMock); @@ -91,7 +90,7 @@ void placedOnRequestHandler_shouldInvalidateOnWrongNoOfArgs() { @Test void placedOnRequestHandler_shouldInvalidateOnWrongTypeOfArgs() { - Object[] args = {new Object(), new Object()}; + Object[] args = { new Object(), new Object() }; ProceedingJoinPoint pjpMock = mockRequestHandlerPjp(RequestHandler.class, args); boolean isPlacedOnRequestHandler = LambdaHandlerProcessor.placedOnRequestHandler(pjpMock); @@ -101,7 +100,7 @@ void placedOnRequestHandler_shouldInvalidateOnWrongTypeOfArgs() { @Test void placedOnStreamHandler_shouldInvalidateOnWrongNoOfArgs() { - Object[] args = {new Object()}; + Object[] args = { new Object() }; ProceedingJoinPoint pjpMock = mockRequestHandlerPjp(RequestStreamHandler.class, args); boolean isPlacedOnStreamHandler = LambdaHandlerProcessor.placedOnStreamHandler(pjpMock); @@ -111,7 +110,7 @@ void placedOnStreamHandler_shouldInvalidateOnWrongNoOfArgs() { @Test void placedOnStreamHandler_shouldInvalidateOnWrongTypeOfArgs() { - Object[] args = {new Object(), new Object(), new Object()}; + Object[] args = { new Object(), new Object(), new Object() }; ProceedingJoinPoint pjpMock = mockRequestHandlerPjp(RequestStreamHandler.class, args); boolean isPlacedOnStreamHandler = LambdaHandlerProcessor.placedOnStreamHandler(pjpMock); @@ -121,7 +120,7 @@ void placedOnStreamHandler_shouldInvalidateOnWrongTypeOfArgs() { @Test void placedOnStreamHandler_shouldInvalidateOnTypeOfArgs_invalidOutputStreamArg() { - Object[] args = {mock(InputStream.class), new Object(), mock(Context.class)}; + Object[] args = { new TestInputStream(), new Object(), new TestLambdaContext() }; ProceedingJoinPoint pjpMock = mockRequestHandlerPjp(RequestStreamHandler.class, args); boolean isPlacedOnStreamHandler = LambdaHandlerProcessor.placedOnStreamHandler(pjpMock); @@ -131,7 +130,7 @@ void placedOnStreamHandler_shouldInvalidateOnTypeOfArgs_invalidOutputStreamArg() @Test void placedOnStreamHandler_shouldInvalidateOnTypeOfArgs_invalidContextArg() { - Object[] args = {mock(InputStream.class), mock(OutputStream.class), new Object()}; + Object[] args = { new TestInputStream(), new TestOutputStream(), new Object() }; ProceedingJoinPoint pjpMock = mockRequestHandlerPjp(RequestStreamHandler.class, args); boolean isPlacedOnStreamHandler = LambdaHandlerProcessor.placedOnStreamHandler(pjpMock); @@ -144,9 +143,9 @@ void placedOnStreamHandler_shouldInvalidateOnTypeOfArgs_invalidContextArg() { void getXrayTraceId_present() { String traceID = "Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1\""; - Optional xRayTraceId = LambdaHandlerProcessor.getXrayTraceId(); + Optional xRayTraceId = LambdaHandlerProcessor.getXrayTraceId(); - assertThat(xRayTraceId.isPresent()).isTrue(); + assertThat(xRayTraceId).isPresent(); assertThat(traceID.split(";")[0].replace(LambdaConstants.ROOT_EQUALS, "")).isEqualTo(xRayTraceId.get()); } @@ -161,7 +160,7 @@ void getXrayTraceId_notPresent() { @Test void extractContext_fromRequestHandler() { - Object[] args = {new Object(), mock(Context.class)}; + Object[] args = { new Object(), new TestLambdaContext() }; ProceedingJoinPoint pjpMock = mockRequestHandlerPjp(RequestHandler.class, args); Context context = LambdaHandlerProcessor.extractContext(pjpMock); @@ -171,7 +170,7 @@ void extractContext_fromRequestHandler() { @Test void extractContext_fromStreamRequestHandler() { - Object[] args = {mock(InputStream.class), mock(OutputStream.class), mock(Context.class)}; + Object[] args = { new TestInputStream(), new TestOutputStream(), new TestLambdaContext() }; ProceedingJoinPoint pjpMock = mockRequestHandlerPjp(RequestStreamHandler.class, args); Context context = LambdaHandlerProcessor.extractContext(pjpMock); @@ -181,7 +180,7 @@ void extractContext_fromStreamRequestHandler() { @Test void extractContext_notKnownHandler() { - Object[] args = {new Object()}; + Object[] args = { new Object() }; ProceedingJoinPoint pjpMock = mockRequestHandlerPjp(Object.class, args); Context context = LambdaHandlerProcessor.extractContext(pjpMock); @@ -230,10 +229,8 @@ void serviceName_Undefined() { assertThat(LambdaHandlerProcessor.serviceName()).isEqualTo(LambdaConstants.SERVICE_UNDEFINED); } - private ProceedingJoinPoint mockRequestHandlerPjp(Class handlerClass, Object[] handlerArgs) { - when(signature.getDeclaringType()).thenReturn(handlerClass); - when(pjpMock.getArgs()).thenReturn(handlerArgs); - when(pjpMock.getSignature()).thenReturn(signature); - return pjpMock; + private ProceedingJoinPoint mockRequestHandlerPjp(Class handlerClass, Object[] handlerArgs) { + TestSignature signature = new TestSignature(handlerClass); + return new TestProceedingJoinPoint(signature, handlerArgs); } } diff --git a/powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestInputStream.java b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestInputStream.java new file mode 100644 index 000000000..cb9122966 --- /dev/null +++ b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestInputStream.java @@ -0,0 +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.common.stubs; + +import java.io.InputStream; + +public class TestInputStream extends InputStream { + @Override + public int read() { + return -1; + } +} diff --git a/powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestLambdaContext.java b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestLambdaContext.java new file mode 100644 index 000000000..6b66b66b7 --- /dev/null +++ b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestLambdaContext.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.common.stubs; + +import com.amazonaws.services.lambda.runtime.ClientContext; +import com.amazonaws.services.lambda.runtime.CognitoIdentity; +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.LambdaLogger; + +public class TestLambdaContext implements Context { + @Override + public String getAwsRequestId() { + return "test-request-id"; + } + + @Override + public String getLogGroupName() { + return "test-log-group"; + } + + @Override + public String getLogStreamName() { + return "test-log-stream"; + } + + @Override + public String getFunctionName() { + return "test-function"; + } + + @Override + public String getFunctionVersion() { + return "1"; + } + + @Override + public String getInvokedFunctionArn() { + return "arn:aws:lambda:us-east-1:123456789012:function:test"; + } + + @Override + public CognitoIdentity getIdentity() { + return null; + } + + @Override + public ClientContext getClientContext() { + return null; + } + + @Override + public int getRemainingTimeInMillis() { + return 30000; + } + + @Override + public int getMemoryLimitInMB() { + return 128; + } + + @Override + public LambdaLogger getLogger() { + return null; + } +} diff --git a/powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestOutputStream.java b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestOutputStream.java new file mode 100644 index 000000000..b64b4759d --- /dev/null +++ b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestOutputStream.java @@ -0,0 +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.common.stubs; + +import java.io.OutputStream; + +public class TestOutputStream extends OutputStream { + @Override + public void write(int b) { + } +} diff --git a/powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestProceedingJoinPoint.java b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestProceedingJoinPoint.java new file mode 100644 index 000000000..e0285518c --- /dev/null +++ b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestProceedingJoinPoint.java @@ -0,0 +1,90 @@ +/* + * 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.common.stubs; + +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.Signature; +import org.aspectj.lang.reflect.SourceLocation; +import org.aspectj.runtime.internal.AroundClosure; + +public class TestProceedingJoinPoint implements ProceedingJoinPoint { + private final Signature signature; + private final Object[] args; + + public TestProceedingJoinPoint(Signature signature, Object[] args) { + this.signature = signature; + this.args = args; + } + + @Override + public Object[] getArgs() { + return args; + } + + @Override + public Signature getSignature() { + return signature; + } + + @Override + public Object getTarget() { + return null; + } + + @Override + public Object getThis() { + return null; + } + + @Override + public StaticPart getStaticPart() { + return null; + } + + @Override + public String getKind() { + return null; + } + + @Override + public SourceLocation getSourceLocation() { + return null; + } + + @Override + public Object proceed() { + return null; + } + + @Override + public Object proceed(Object[] args) { + return null; + } + + @Override + public void set$AroundClosure(AroundClosure arc) { + // Stubbed method + } + + @Override + public String toLongString() { + return "handleRequest"; + } + + @Override + public String toShortString() { + return "handleRequest"; + } +} diff --git a/powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestSignature.java b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestSignature.java new file mode 100644 index 000000000..903e4c8fa --- /dev/null +++ b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestSignature.java @@ -0,0 +1,55 @@ +/* + * 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.common.stubs; + +import org.aspectj.lang.Signature; + +public class TestSignature implements Signature { + private final Class declaringType; + + public TestSignature(Class declaringType) { + this.declaringType = declaringType; + } + + @Override + public Class getDeclaringType() { + return declaringType; + } + + @Override + public String getDeclaringTypeName() { + return declaringType.getName(); + } + + @Override + public int getModifiers() { + return 0; + } + + @Override + public String getName() { + return "handleRequest"; + } + + @Override + public String toLongString() { + return "handleRequest"; + } + + @Override + public String toShortString() { + return "handleRequest"; + } +} From 24e9e27587c370dcdc99d880d7dfa4828a06225f Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Fri, 15 Aug 2025 11:49:06 +0200 Subject: [PATCH 07/65] Remove mockito from powertools-metrics and re-use TestLamdaContext from powertools-common. --- powertools-common/pom.xml | 13 ++++ powertools-metrics/pom.xml | 60 ++------------- .../metrics/ConfigurationPrecedenceTest.java | 10 +-- .../internal/EmfMetricsLoggerTest.java | 8 +- .../internal/LambdaMetricsAspectTest.java | 18 ++--- .../metrics/testutils/TestContext.java | 77 ------------------- 6 files changed, 39 insertions(+), 147 deletions(-) delete mode 100644 powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/testutils/TestContext.java diff --git a/powertools-common/pom.xml b/powertools-common/pom.xml index 5f173c604..bca268359 100644 --- a/powertools-common/pom.xml +++ b/powertools-common/pom.xml @@ -155,5 +155,18 @@ src/main/resources + + + org.apache.maven.plugins + maven-jar-plugin + + + + test-jar + + + + + diff --git a/powertools-metrics/pom.xml b/powertools-metrics/pom.xml index e13b38cb9..d7aefb1e5 100644 --- a/powertools-metrics/pom.xml +++ b/powertools-metrics/pom.xml @@ -90,16 +90,6 @@ junit-jupiter-engine test - - org.mockito - mockito-core - test - - - org.mockito - mockito-junit-jupiter - test - org.slf4j slf4j-simple @@ -120,6 +110,13 @@ assertj-core test + + software.amazon.lambda + powertools-common + ${project.version} + test-jar + test + @@ -142,20 +139,13 @@ generate-graalvm-files - - - org.mockito - mockito-subclass - test - - org.apache.maven.plugins maven-surefire-plugin - -Dmockito.mock.maker=subclass -Dorg.graalvm.nativeimage.imagecode=agent + -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-metrics,experimental-class-define-support --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED @@ -167,13 +157,6 @@ graalvm-native - - - org.mockito - mockito-subclass - test - - @@ -197,38 +180,11 @@ --add-opens java.base/java.lang=ALL-UNNAMED --no-fallback -Dorg.graalvm.nativeimage.imagecode=agent - -H:ClassInitialization=net.bytebuddy.ClassFileVersion:rerun - -H:ClassInitialization=net.bytebuddy.utility.dispatcher.JavaDispatcher:rerun - -H:ClassInitialization=net.bytebuddy.utility.Invoker$Dispatcher:rerun - -H:ClassInitialization=net.bytebuddy.utility.GraalImageCode:rerun --initialize-at-build-time=org.slf4j.simple.SimpleLogger --initialize-at-build-time=org.slf4j.LoggerFactory --initialize-at-build-time=org.junit.Ignore --initialize-at-build-time=java.lang.annotation.Annotation --initialize-at-build-time=org.junit.runners.model.FrameworkField - - --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase - - --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic - - --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$1 - - --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$2 - - --initialize-at-build-time=net.bytebuddy.utility.dispatcher.JavaDispatcher$DynamicClassLoader - - --initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable - - --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase - - --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$ForLoadedType - - --initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$ForLoadedMethod - - --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Super$Instantiation$2 - - --trace-class-initialization=net.bytebuddy.description.type.TypeDescription$ForLoadedType,net.bytebuddy.description.method.MethodDescription$ForLoadedMethod,net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable - --verbose diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/ConfigurationPrecedenceTest.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/ConfigurationPrecedenceTest.java index 1bf3b6a69..ecc7c13a1 100644 --- a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/ConfigurationPrecedenceTest.java +++ b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/ConfigurationPrecedenceTest.java @@ -34,7 +34,7 @@ import software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor; import software.amazon.lambda.powertools.metrics.model.MetricUnit; -import software.amazon.lambda.powertools.metrics.testutils.TestContext; +import software.amazon.lambda.powertools.common.stubs.TestLambdaContext; /** * Tests to verify the hierarchy of precedence for configuration: @@ -89,7 +89,7 @@ void annotationShouldOverrideBuilderAndEnvironment() throws Exception { .build(); RequestHandler, String> handler = new HandlerWithMetricsAnnotation(); - Context context = new TestContext(); + Context context = new TestLambdaContext(); Map input = new HashMap<>(); // When @@ -118,7 +118,7 @@ void builderShouldOverrideEnvironment() throws Exception { .build(); RequestHandler, String> handler = new HandlerWithDefaultMetricsAnnotation(); - Context context = new TestContext(); + Context context = new TestLambdaContext(); Map input = new HashMap<>(); // When @@ -141,7 +141,7 @@ void builderShouldOverrideEnvironment() throws Exception { void environmentVariablesShouldBeUsedWhenNoOverrides() throws Exception { // Given RequestHandler, String> handler = new HandlerWithDefaultMetricsAnnotation(); - Context context = new TestContext(); + Context context = new TestLambdaContext(); Map input = new HashMap<>(); // When @@ -166,7 +166,7 @@ void shouldUseDefaultsWhenNoConfiguration() throws Exception { .build(); RequestHandler, String> handler = new HandlerWithDefaultMetricsAnnotation(); - Context context = new TestContext(); + Context context = new TestLambdaContext(); Map input = new HashMap<>(); // When diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/EmfMetricsLoggerTest.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/EmfMetricsLoggerTest.java index a4fc0d61c..6c324221c 100644 --- a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/EmfMetricsLoggerTest.java +++ b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/EmfMetricsLoggerTest.java @@ -45,7 +45,7 @@ import software.amazon.lambda.powertools.metrics.model.DimensionSet; import software.amazon.lambda.powertools.metrics.model.MetricResolution; import software.amazon.lambda.powertools.metrics.model.MetricUnit; -import software.amazon.lambda.powertools.metrics.testutils.TestContext; +import software.amazon.lambda.powertools.common.stubs.TestLambdaContext; class EmfMetricsLoggerTest { @@ -373,7 +373,7 @@ void shouldClearDefaultDimensions() throws Exception { @Test void shouldCaptureColdStartMetric() throws Exception { // Given - Context testContext = new TestContext(); + Context testContext = new TestLambdaContext(); // When metrics.captureColdStartMetric(testContext); @@ -425,7 +425,7 @@ void shouldReuseNamespaceForColdStartMetric() throws Exception { String customNamespace = "CustomNamespace"; metrics.setNamespace(customNamespace); - Context testContext = new TestContext(); + Context testContext = new TestLambdaContext(); DimensionSet dimensions = DimensionSet.of("CustomDim", "CustomValue"); @@ -497,7 +497,7 @@ void shouldNotFlushMetricsWhenDisabled() { @SetEnvironmentVariable(key = "POWERTOOLS_METRICS_DISABLED", value = "true") void shouldNotCaptureColdStartMetricWhenDisabled() { // Given - Context testContext = new TestContext(); + Context testContext = new TestLambdaContext(); // When metrics.captureColdStartMetric(testContext); 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 068d19ccb..326dd2ffe 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 @@ -37,7 +37,7 @@ import software.amazon.lambda.powertools.metrics.Metrics; import software.amazon.lambda.powertools.metrics.MetricsFactory; import software.amazon.lambda.powertools.metrics.model.MetricUnit; -import software.amazon.lambda.powertools.metrics.testutils.TestContext; +import software.amazon.lambda.powertools.common.stubs.TestLambdaContext; class LambdaMetricsAspectTest { @@ -74,7 +74,7 @@ void tearDown() throws Exception { void shouldCaptureMetricsFromAnnotatedHandler() throws Exception { // Given RequestHandler, String> handler = new HandlerWithMetricsAnnotation(); - Context context = new TestContext(); + Context context = new TestLambdaContext(); Map input = new HashMap<>(); // When @@ -98,7 +98,7 @@ void shouldCaptureMetricsFromAnnotatedHandler() throws Exception { void shouldOverrideEnvironmentVariablesWithAnnotation() throws Exception { // Given RequestHandler, String> handler = new HandlerWithMetricsAnnotation(); - Context context = new TestContext(); + Context context = new TestLambdaContext(); Map input = new HashMap<>(); // When @@ -120,7 +120,7 @@ void shouldOverrideEnvironmentVariablesWithAnnotation() throws Exception { void shouldUseEnvironmentVariablesWhenNoAnnotationOverrides() throws Exception { // Given RequestHandler, String> handler = new HandlerWithDefaultMetricsAnnotation(); - Context context = new TestContext(); + Context context = new TestLambdaContext(); Map input = new HashMap<>(); // When @@ -140,7 +140,7 @@ void shouldUseEnvironmentVariablesWhenNoAnnotationOverrides() throws Exception { void shouldCaptureColdStartMetricWhenConfigured() throws Exception { // Given RequestHandler, String> handler = new HandlerWithColdStartMetricsAnnotation(); - Context context = new TestContext(); + Context context = new TestLambdaContext(); Map input = new HashMap<>(); // When @@ -166,7 +166,7 @@ void shouldCaptureColdStartMetricWhenConfigured() throws Exception { void shouldNotIncludeServiceDimensionInColdStartMetricWhenServiceUndefined() throws Exception { // Given - no service name set, so it will use the default undefined value RequestHandler, String> handler = new HandlerWithColdStartMetricsAnnotation(); - Context context = new TestContext(); + Context context = new TestLambdaContext(); Map input = new HashMap<>(); // When @@ -195,7 +195,7 @@ void shouldNotIncludeServiceDimensionInColdStartMetricWhenServiceUndefined() thr void shouldUseCustomFunctionNameWhenProvidedForColdStartMetric() throws Exception { // Given RequestHandler, String> handler = new HandlerWithCustomFunctionName(); - Context context = new TestContext(); + Context context = new TestLambdaContext(); Map input = new HashMap<>(); // When @@ -228,7 +228,7 @@ void shouldUseCustomFunctionNameWhenProvidedForColdStartMetric() throws Exceptio void shouldUseServiceNameWhenProvidedForColdStartMetric() throws Exception { // Given RequestHandler, String> handler = new HandlerWithServiceNameAndColdStart(); - Context context = new TestContext(); + Context context = new TestLambdaContext(); Map input = new HashMap<>(); // When @@ -247,7 +247,7 @@ void shouldUseServiceNameWhenProvidedForColdStartMetric() throws Exception { void shouldHaveNoEffectOnNonHandlerMethod() { // Given RequestHandler, String> handler = new HandlerWithAnnotationOnWrongMethod(); - Context context = new TestContext(); + Context context = new TestLambdaContext(); Map input = new HashMap<>(); // When diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/testutils/TestContext.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/testutils/TestContext.java deleted file mode 100644 index c4f5e4455..000000000 --- a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/testutils/TestContext.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * 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.testutils; - -import com.amazonaws.services.lambda.runtime.Context; - -/** - * Simple Lambda context implementation for unit tests - */ -public class TestContext implements Context { - @Override - public String getAwsRequestId() { - return "test-request-id"; - } - - @Override - public String getLogGroupName() { - return "test-log-group"; - } - - @Override - public String getLogStreamName() { - return "test-log-stream"; - } - - @Override - public String getFunctionName() { - return "test-function"; - } - - @Override - public String getFunctionVersion() { - return "test-version"; - } - - @Override - public String getInvokedFunctionArn() { - return "test-arn"; - } - - @Override - public com.amazonaws.services.lambda.runtime.CognitoIdentity getIdentity() { - return null; - } - - @Override - public com.amazonaws.services.lambda.runtime.ClientContext getClientContext() { - return null; - } - - @Override - public int getRemainingTimeInMillis() { - return 1000; - } - - @Override - public int getMemoryLimitInMB() { - return 128; - } - - @Override - public com.amazonaws.services.lambda.runtime.LambdaLogger getLogger() { - return null; - } -} From 88a416cc322f777e79ba6ec51a123fce5dda47f3 Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Fri, 15 Aug 2025 11:53:14 +0200 Subject: [PATCH 08/65] Remove mockito from powertools-serialization. --- powertools-serialization/pom.xml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/powertools-serialization/pom.xml b/powertools-serialization/pom.xml index dc2cd8cd5..46f57d040 100644 --- a/powertools-serialization/pom.xml +++ b/powertools-serialization/pom.xml @@ -98,13 +98,6 @@ generate-graalvm-files - - - org.mockito - mockito-subclass - test - - From 61002fccd5f19d65cab7dd7641c8651893abeaca Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Fri, 15 Aug 2025 12:03:35 +0200 Subject: [PATCH 09/65] Remove mockito from powertools-logging. --- powertools-logging/pom.xml | 52 ++++----------- .../internal/LambdaLoggingAspectTest.java | 66 +++++++++---------- 2 files changed, 42 insertions(+), 76 deletions(-) diff --git a/powertools-logging/pom.xml b/powertools-logging/pom.xml index e2ba53878..aa4c92555 100644 --- a/powertools-logging/pom.xml +++ b/powertools-logging/pom.xml @@ -14,8 +14,8 @@ --> + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 @@ -67,11 +67,6 @@ junit-jupiter-engine test - - org.mockito - mockito-core - test - org.slf4j slf4j-simple @@ -112,17 +107,17 @@ jsonassert test + + software.amazon.lambda + powertools-common + ${project.version} + test-jar + test + generate-graalvm-files - - - org.mockito - mockito-subclass - test - - @@ -130,7 +125,8 @@ maven-surefire-plugin 3.5.3 - -Dmockito.mock.maker=subclass -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging,experimental-class-define-support + -Dorg.graalvm.nativeimage.imagecode=agent + -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging,experimental-class-define-support --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED @@ -141,19 +137,12 @@ graalvm-native - - - org.mockito - mockito-subclass - test - - org.graalvm.buildtools native-maven-plugin - 0.11.0 + 0.11.0 true @@ -171,28 +160,11 @@ --add-opens java.base/java.lang=ALL-UNNAMED --no-fallback -Dorg.graalvm.nativeimage.imagecode=agent - -H:ClassInitialization=net.bytebuddy.ClassFileVersion:rerun - -H:ClassInitialization=net.bytebuddy.utility.dispatcher.JavaDispatcher:rerun - -H:ClassInitialization=net.bytebuddy.utility.Invoker$Dispatcher:rerun - -H:ClassInitialization=net.bytebuddy.utility.GraalImageCode:rerun --initialize-at-build-time=org.slf4j.simple.SimpleLogger --initialize-at-build-time=org.slf4j.LoggerFactory --initialize-at-build-time=org.junit.Ignore --initialize-at-build-time=java.lang.annotation.Annotation --initialize-at-build-time=org.junit.runners.model.FrameworkField - --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase - --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic - --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$1 - --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$2 - --initialize-at-build-time=net.bytebuddy.utility.dispatcher.JavaDispatcher$DynamicClassLoader - --initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable - --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase - --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$ForLoadedType - --initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$ForLoadedMethod - --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Super$Instantiation$2 - - --trace-class-initialization=net.bytebuddy.description.type.TypeDescription$ForLoadedType,net.bytebuddy.description.method.MethodDescription$ForLoadedMethod,net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable - --verbose diff --git a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspectTest.java b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspectTest.java index aba4664fe..751d195b5 100644 --- a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspectTest.java +++ b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspectTest.java @@ -18,8 +18,6 @@ import static org.apache.commons.lang3.reflect.FieldUtils.writeStaticField; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.contentOf; -import static org.mockito.Mockito.when; -import static org.mockito.MockitoAnnotations.openMocks; import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.FUNCTION_ARN; import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.FUNCTION_COLD_START; import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.FUNCTION_MEMORY_SIZE; @@ -54,7 +52,6 @@ import org.junitpioneer.jupiter.ClearEnvironmentVariable; import org.junitpioneer.jupiter.SetEnvironmentVariable; import org.junitpioneer.jupiter.SetSystemProperty; -import org.mockito.Mock; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.slf4j.MDC; @@ -72,6 +69,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor; +import software.amazon.lambda.powertools.common.stubs.TestLambdaContext; import software.amazon.lambda.powertools.logging.argument.StructuredArgument; import software.amazon.lambda.powertools.logging.handlers.PowertoolsLogAlbCorrelationId; import software.amazon.lambda.powertools.logging.handlers.PowertoolsLogApiGatewayHttpApiCorrelationId; @@ -99,15 +97,13 @@ class LambdaLoggingAspectTest { private RequestStreamHandler requestStreamHandler; private RequestHandler requestHandler; - @Mock private Context context; @BeforeEach void setUp() throws IllegalAccessException, NoSuchMethodException, InvocationTargetException, IOException { - openMocks(this); MDC.clear(); writeStaticField(LambdaHandlerProcessor.class, "IS_COLD_START", null, true); - setupContext(); + context = new TestLambdaContext(); requestHandler = new PowertoolsLogEnabled(); requestStreamHandler = new PowertoolsLogEnabledForStream(); resetLogLevel(Level.INFO); @@ -124,7 +120,7 @@ void setUp() throws IllegalAccessException, NoSuchMethodException, InvocationTar @AfterEach void cleanUp() throws IOException { - //Make sure file is cleaned up before running full stack logging regression + // Make sure file is cleaned up before running full stack logging regression FileChannel.open(Paths.get("target/logfile.json"), StandardOpenOption.WRITE).truncate(0).close(); } @@ -224,7 +220,8 @@ void shouldLogWarnWhenPowertoolsLevelEnvVarIsWarnAndLambdaLevelVarIsInfo() throw assertThat(LOG.isInfoEnabled()).isFalse(); assertThat(LOG.isWarnEnabled()).isTrue(); File logFile = new File("target/logfile.json"); - assertThat(contentOf(logFile)).doesNotContain(" does not match AWS Lambda Advanced Logging Controls minimum log level"); + assertThat(contentOf(logFile)) + .doesNotContain(" does not match AWS Lambda Advanced Logging Controls minimum log level"); } @Test @@ -241,7 +238,8 @@ void shouldLogInfoWhenPowertoolsLevelEnvVarIsInfoAndLambdaLevelVarIsWarn() throw assertThat(LOG.isInfoEnabled()).isTrue(); File logFile = new File("target/logfile.json"); // should log a warning as powertools level is lower than lambda level - assertThat(contentOf(logFile)).contains("Current log level (INFO) does not match AWS Lambda Advanced Logging Controls minimum log level (WARN). This can lead to data loss, consider adjusting them."); + assertThat(contentOf(logFile)).contains( + "Current log level (INFO) does not match AWS Lambda Advanced Logging Controls minimum log level (WARN). This can lead to data loss, consider adjusting them."); } @Test @@ -265,11 +263,11 @@ void shouldSetLambdaContextWhenEnabled() { assertThat(MDC.getCopyOfContextMap()) .hasSize(EXPECTED_CONTEXT_SIZE) - .containsEntry(FUNCTION_ARN.getName(), "testArn") - .containsEntry(FUNCTION_MEMORY_SIZE.getName(), "10") + .containsEntry(FUNCTION_ARN.getName(), "arn:aws:lambda:us-east-1:123456789012:function:test") + .containsEntry(FUNCTION_MEMORY_SIZE.getName(), "128") .containsEntry(FUNCTION_VERSION.getName(), "1") - .containsEntry(FUNCTION_NAME.getName(), "testFunction") - .containsEntry(FUNCTION_REQUEST_ID.getName(), "RequestId") + .containsEntry(FUNCTION_NAME.getName(), "test-function") + .containsEntry(FUNCTION_REQUEST_ID.getName(), "test-request-id") .containsKey(FUNCTION_COLD_START.getName()) .containsKey(SERVICE.getName()); } @@ -278,30 +276,30 @@ void shouldSetLambdaContextWhenEnabled() { void shouldSetLambdaContextForStreamHandlerWhenEnabled() throws IOException { requestStreamHandler = new PowertoolsLogEnabledForStream(); - requestStreamHandler.handleRequest(new ByteArrayInputStream(new byte[]{}), new ByteArrayOutputStream(), + requestStreamHandler.handleRequest(new ByteArrayInputStream(new byte[] {}), new ByteArrayOutputStream(), context); assertThat(MDC.getCopyOfContextMap()) .hasSize(EXPECTED_CONTEXT_SIZE) - .containsEntry(FUNCTION_ARN.getName(), "testArn") - .containsEntry(FUNCTION_MEMORY_SIZE.getName(), "10") + .containsEntry(FUNCTION_ARN.getName(), "arn:aws:lambda:us-east-1:123456789012:function:test") + .containsEntry(FUNCTION_MEMORY_SIZE.getName(), "128") .containsEntry(FUNCTION_VERSION.getName(), "1") - .containsEntry(FUNCTION_NAME.getName(), "testFunction") - .containsEntry(FUNCTION_REQUEST_ID.getName(), "RequestId") + .containsEntry(FUNCTION_NAME.getName(), "test-function") + .containsEntry(FUNCTION_REQUEST_ID.getName(), "test-request-id") .containsKey(FUNCTION_COLD_START.getName()) .containsKey(SERVICE.getName()); } @Test void shouldSetColdStartFlagOnFirstCallNotOnSecondCall() throws IOException { - requestStreamHandler.handleRequest(new ByteArrayInputStream(new byte[]{}), new ByteArrayOutputStream(), + requestStreamHandler.handleRequest(new ByteArrayInputStream(new byte[] {}), new ByteArrayOutputStream(), context); assertThat(MDC.getCopyOfContextMap()) .hasSize(EXPECTED_CONTEXT_SIZE) .containsEntry(FUNCTION_COLD_START.getName(), "true"); - requestStreamHandler.handleRequest(new ByteArrayInputStream(new byte[]{}), new ByteArrayOutputStream(), + requestStreamHandler.handleRequest(new ByteArrayInputStream(new byte[] {}), new ByteArrayOutputStream(), context); assertThat(MDC.getCopyOfContextMap()) @@ -346,7 +344,7 @@ void shouldLogDebugWhenSamplingEqualsOne() { } @Test - void shouldLogDebugWhenSamplingEnvVarEqualsOne() throws IllegalAccessException { + void shouldLogDebugWhenSamplingEnvVarEqualsOne() { // GIVEN LoggingConstants.POWERTOOLS_SAMPLING_RATE = "1"; PowertoolsLogEnabled handler = new PowertoolsLogEnabled(); @@ -360,7 +358,7 @@ void shouldLogDebugWhenSamplingEnvVarEqualsOne() throws IllegalAccessException { } @Test - void shouldNotLogDebugWhenSamplingEnvVarIsTooBig() throws IllegalAccessException { + void shouldNotLogDebugWhenSamplingEnvVarIsTooBig() { // GIVEN LoggingConstants.POWERTOOLS_SAMPLING_RATE = "42"; @@ -378,7 +376,7 @@ void shouldNotLogDebugWhenSamplingEnvVarIsInvalid() { LoggingConstants.POWERTOOLS_SAMPLING_RATE = "NotANumber"; // WHEN - requestHandler.handleRequest(new Object(), context); + requestHandler.handleRequest(new Object(), context); // THEN File logFile = new File("target/logfile.json"); @@ -509,7 +507,7 @@ void shouldNotLogEventForHandlerWhenEnvVariableSetToFalse() { requestHandler.handleRequest(singletonList("ListOfOneElement"), context); // THEN - TestLogger logger = (TestLogger) ((PowertoolsLogEventEnvVar)requestHandler).getLogger(); + TestLogger logger = (TestLogger) ((PowertoolsLogEventEnvVar) requestHandler).getLogger(); assertThat(logger.getArguments()).isNull(); } @@ -521,7 +519,8 @@ void shouldLogEventForStreamHandler() throws IOException { Map map = Collections.singletonMap("key", "value"); // WHEN - requestStreamHandler.handleRequest(new ByteArrayInputStream(new ObjectMapper().writeValueAsBytes(map)), output, context); + requestStreamHandler.handleRequest(new ByteArrayInputStream(new ObjectMapper().writeValueAsBytes(map)), output, + context); // THEN assertThat(new String(output.toByteArray(), StandardCharsets.UTF_8)) @@ -586,7 +585,8 @@ void shouldLogResponseForStreamHandler() throws IOException { String input = "BobThe Sponge"; // WHEN - requestStreamHandler.handleRequest(new ByteArrayInputStream(input.getBytes(StandardCharsets.UTF_8)), output, context); + requestStreamHandler.handleRequest(new ByteArrayInputStream(input.getBytes(StandardCharsets.UTF_8)), output, + context); // THEN assertThat(new String(output.toByteArray(), StandardCharsets.UTF_8)) @@ -737,7 +737,8 @@ void testMultipleLoggingManagers_shouldWarnAndSelectFirstOne() throws Unsupporte String output = outputStream.toString("UTF-8"); assertThat(output) .contains("WARN. Multiple LoggingManagers were found on the classpath") - .contains("WARN. Make sure to have only one of powertools-logging-log4j OR powertools-logging-logback to your dependencies") + .contains( + "WARN. Make sure to have only one of powertools-logging-log4j OR powertools-logging-logback to your dependencies") .contains("WARN. Using the first LoggingManager found on the classpath: [" + list.get(0) + "]"); } @@ -757,19 +758,12 @@ void testNoLoggingManagers_shouldWarnAndCreateDefault() throws UnsupportedEncodi assertThat(output) .contains("ERROR. No LoggingManager was found on the classpath") .contains("ERROR. Applying default LoggingManager: POWERTOOLS_LOG_LEVEL variable is ignored") - .contains("ERROR. Make sure to add either powertools-logging-log4j or powertools-logging-logback to your dependencies"); + .contains( + "ERROR. Make sure to add either powertools-logging-log4j or powertools-logging-logback to your dependencies"); assertThat(loggingManager).isExactlyInstanceOf(DefautlLoggingManager.class); } - private void setupContext() { - when(context.getFunctionName()).thenReturn("testFunction"); - when(context.getInvokedFunctionArn()).thenReturn("testArn"); - when(context.getFunctionVersion()).thenReturn("1"); - when(context.getMemoryLimitInMB()).thenReturn(10); - when(context.getAwsRequestId()).thenReturn("RequestId"); - } - private void resetLogLevel(Level level) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { Method setLogLevels = LambdaLoggingAspect.class.getDeclaredMethod("setLogLevels", Level.class); From ae29b6192c32630b7e72552c178734cf449ff774 Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Fri, 15 Aug 2025 14:49:47 +0200 Subject: [PATCH 10/65] Remove mockito from powertools-logging-log4j. --- .../powertools-logging-log4j/pom.xml | 47 ++++--------------- .../PowerToolsResolverFactoryTest.java | 27 ++++------- .../PowertoolsResolverArgumentsTest.java | 31 +++++------- 3 files changed, 29 insertions(+), 76 deletions(-) diff --git a/powertools-logging/powertools-logging-log4j/pom.xml b/powertools-logging/powertools-logging-log4j/pom.xml index acdfdc42b..da6bd3652 100644 --- a/powertools-logging/powertools-logging-log4j/pom.xml +++ b/powertools-logging/powertools-logging-log4j/pom.xml @@ -56,11 +56,6 @@ junit-jupiter-engine test - - org.mockito - mockito-core - test - org.junit-pioneer junit-pioneer @@ -96,17 +91,17 @@ jsonassert test + + software.amazon.lambda + powertools-common + ${project.version} + test-jar + test + generate-graalvm-files - - - org.mockito - mockito-subclass - test - - @@ -114,7 +109,8 @@ maven-surefire-plugin 3.5.3 - -Dmockito.mock.maker=subclass -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-log4j,experimental-class-define-support + -Dorg.graalvm.nativeimage.imagecode=agent + -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-log4j,experimental-class-define-support --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED @@ -125,13 +121,6 @@ graalvm-native - - - org.mockito - mockito-subclass - test - - @@ -155,29 +144,11 @@ --add-opens java.base/java.lang=ALL-UNNAMED --no-fallback -Dorg.graalvm.nativeimage.imagecode=agent - -H:ClassInitialization=net.bytebuddy.ClassFileVersion:rerun - -H:ClassInitialization=net.bytebuddy.utility.dispatcher.JavaDispatcher:rerun - -H:ClassInitialization=net.bytebuddy.utility.Invoker$Dispatcher:rerun - -H:ClassInitialization=net.bytebuddy.utility.GraalImageCode:rerun --initialize-at-build-time=org.slf4j.simple.SimpleLogger --initialize-at-build-time=org.slf4j.LoggerFactory --initialize-at-build-time=org.junit.Ignore --initialize-at-build-time=java.lang.annotation.Annotation --initialize-at-build-time=org.junit.runners.model.FrameworkField - --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase - --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic - --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$1 - --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$2 - --initialize-at-build-time=net.bytebuddy.utility.dispatcher.JavaDispatcher$DynamicClassLoader - --initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable - --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase - --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$ForLoadedType - --initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$ForLoadedMethod - --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Super$Instantiation$2 - - --trace-class-initialization=net.bytebuddy.description.type.TypeDescription$ForLoadedType,net.bytebuddy.description.method.MethodDescription$ForLoadedMethod,net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable - - --verbose diff --git a/powertools-logging/powertools-logging-log4j/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/PowerToolsResolverFactoryTest.java b/powertools-logging/powertools-logging-log4j/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/PowerToolsResolverFactoryTest.java index 4cf798a47..7ea81d690 100644 --- a/powertools-logging/powertools-logging-log4j/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/PowerToolsResolverFactoryTest.java +++ b/powertools-logging/powertools-logging-log4j/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/PowerToolsResolverFactoryTest.java @@ -17,37 +17,36 @@ import static org.apache.commons.lang3.reflect.FieldUtils.writeStaticField; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.contentOf; -import static org.mockito.Mockito.when; -import static org.mockito.MockitoAnnotations.openMocks; -import com.amazonaws.services.lambda.runtime.Context; import java.io.File; import java.io.IOException; import java.nio.channels.FileChannel; import java.nio.file.NoSuchFileException; import java.nio.file.Paths; import java.nio.file.StandardOpenOption; + import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Test; -import org.mockito.Mock; import org.slf4j.MDC; + +import com.amazonaws.services.lambda.runtime.Context; + import software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor; +import software.amazon.lambda.powertools.common.stubs.TestLambdaContext; import software.amazon.lambda.powertools.logging.internal.handler.PowertoolsLogEnabled; @Order(1) class PowerToolsResolverFactoryTest { - @Mock private Context context; @BeforeEach void setUp() throws IllegalAccessException, IOException { - openMocks(this); MDC.clear(); writeStaticField(LambdaHandlerProcessor.class, "IS_COLD_START", null, true); - setupContext(); + context = new TestLambdaContext(); // Make sure file is cleaned up before running tests try { FileChannel.open(Paths.get("target/logfile.json"), StandardOpenOption.WRITE).truncate(0).close(); @@ -58,7 +57,7 @@ void setUp() throws IllegalAccessException, IOException { } @AfterEach - void cleanUp() throws IOException{ + void cleanUp() throws IOException { FileChannel.open(Paths.get("target/logfile.json"), StandardOpenOption.WRITE).truncate(0).close(); FileChannel.open(Paths.get("target/ecslogfile.json"), StandardOpenOption.WRITE).truncate(0).close(); } @@ -70,7 +69,7 @@ void shouldLogInJsonFormat() { File logFile = new File("target/logfile.json"); assertThat(contentOf(logFile)).contains( - "{\"level\":\"DEBUG\",\"message\":\"Test debug event\",\"cold_start\":true,\"function_arn\":\"arn:aws:lambda:eu-west-1:012345678910:function:testFunction:1\",\"function_memory_size\":1024,\"function_name\":\"testFunction\",\"function_request_id\":\"RequestId\",\"function_version\":\"1\",\"service\":\"testLog4j\",\"timestamp\":") + "{\"level\":\"DEBUG\",\"message\":\"Test debug event\",\"cold_start\":true,\"function_arn\":\"arn:aws:lambda:us-east-1:123456789012:function:test\",\"function_memory_size\":128,\"function_name\":\"test-function\",\"function_request_id\":\"test-request-id\",\"function_version\":\"1\",\"service\":\"testLog4j\",\"timestamp\":") .contains("\"xray_trace_id\":\"1-63441c4a-abcdef012345678912345678\",\"myKey\":\"myValue\"}\n"); } @@ -81,15 +80,7 @@ void shouldLogInEcsFormat() { File logFile = new File("target/ecslogfile.json"); assertThat(contentOf(logFile)).contains( - "\"ecs.version\":\"1.2.0\",\"log.level\":\"DEBUG\",\"message\":\"Test debug event\",\"service.name\":\"testLog4j\",\"service.version\":\"1\",\"log.logger\":\"software.amazon.lambda.powertools.logging.internal.handler.PowertoolsLogEnabled\",\"process.thread.name\":\"main\",\"cloud.provider\":\"aws\",\"cloud.service.name\":\"lambda\",\"cloud.region\":\"eu-central-1\",\"cloud.account.id\":\"012345678910\",\"faas.id\":\"arn:aws:lambda:eu-west-1:012345678910:function:testFunction:1\",\"faas.name\":\"testFunction\",\"faas.version\":\"1\",\"faas.memory\":1024,\"faas.execution\":\"RequestId\",\"faas.coldstart\":true,\"trace.id\":\"1-63441c4a-abcdef012345678912345678\",\"myKey\":\"myValue\"}\n"); + "\"ecs.version\":\"1.2.0\",\"log.level\":\"DEBUG\",\"message\":\"Test debug event\",\"service.name\":\"testLog4j\",\"service.version\":\"1\",\"log.logger\":\"software.amazon.lambda.powertools.logging.internal.handler.PowertoolsLogEnabled\",\"process.thread.name\":\"main\",\"cloud.provider\":\"aws\",\"cloud.service.name\":\"lambda\",\"cloud.region\":\"eu-central-1\",\"cloud.account.id\":\"123456789012\",\"faas.id\":\"arn:aws:lambda:us-east-1:123456789012:function:test\",\"faas.name\":\"test-function\",\"faas.version\":\"1\",\"faas.memory\":128,\"faas.execution\":\"test-request-id\",\"faas.coldstart\":true,\"trace.id\":\"1-63441c4a-abcdef012345678912345678\",\"myKey\":\"myValue\"}\n"); } - private void setupContext() { - when(context.getFunctionName()).thenReturn("testFunction"); - when(context.getInvokedFunctionArn()).thenReturn( - "arn:aws:lambda:eu-west-1:012345678910:function:testFunction:1"); - when(context.getFunctionVersion()).thenReturn("1"); - when(context.getMemoryLimitInMB()).thenReturn(1024); - when(context.getAwsRequestId()).thenReturn("RequestId"); - } } diff --git a/powertools-logging/powertools-logging-log4j/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/PowertoolsResolverArgumentsTest.java b/powertools-logging/powertools-logging-log4j/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/PowertoolsResolverArgumentsTest.java index 463ad043d..5432e45ae 100644 --- a/powertools-logging/powertools-logging-log4j/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/PowertoolsResolverArgumentsTest.java +++ b/powertools-logging/powertools-logging-log4j/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/PowertoolsResolverArgumentsTest.java @@ -16,11 +16,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.contentOf; -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 java.io.File; import java.io.IOException; import java.nio.channels.FileChannel; @@ -29,27 +25,29 @@ import java.nio.file.StandardOpenOption; import java.util.Arrays; import java.util.Collections; + import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Test; -import org.mockito.Mock; import org.slf4j.MDC; +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.events.SQSEvent; + +import software.amazon.lambda.powertools.common.stubs.TestLambdaContext; import software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields; import software.amazon.lambda.powertools.logging.internal.handler.PowertoolsArguments; @Order(2) class PowertoolsResolverArgumentsTest { - @Mock private Context context; @BeforeEach void setUp() throws IOException { - openMocks(this); MDC.clear(); - setupContext(); + context = new TestLambdaContext(); try { FileChannel.open(Paths.get("target/logfile.json"), StandardOpenOption.WRITE).truncate(0).close(); @@ -61,7 +59,7 @@ void setUp() throws IOException { @AfterEach void cleanUp() throws IOException { - //Make sure file is cleaned up before running full stack logging regression + // Make sure file is cleaned up before running full stack logging regression FileChannel.open(Paths.get("target/logfile.json"), StandardOpenOption.WRITE).truncate(0).close(); FileChannel.open(Paths.get("target/ecslogfile.json"), StandardOpenOption.WRITE).truncate(0).close(); } @@ -74,7 +72,7 @@ void shouldLogArgumentsAsJsonWhenUsingRawJson() { msg.setMessageId("1212abcd"); msg.setBody("plop"); msg.setEventSource("eb"); - msg.setAwsRegion("eu-west-1"); + msg.setAwsRegion("us-east-1"); SQSEvent.MessageAttribute attribute = new SQSEvent.MessageAttribute(); attribute.setStringListValues(Arrays.asList("val1", "val2", "val3")); msg.setMessageAttributes(Collections.singletonMap("keyAttribute", attribute)); @@ -86,7 +84,7 @@ void shouldLogArgumentsAsJsonWhenUsingRawJson() { File logFile = new File("target/logfile.json"); assertThat(contentOf(logFile)) .contains( - "\"input\":{\"awsRegion\":\"eu-west-1\",\"body\":\"plop\",\"eventSource\":\"eb\",\"messageAttributes\":{\"keyAttribute\":{\"stringListValues\":[\"val1\",\"val2\",\"val3\"]}},\"messageId\":\"1212abcd\"}") + "\"input\":{\"awsRegion\":\"us-east-1\",\"body\":\"plop\",\"eventSource\":\"eb\",\"messageAttributes\":{\"keyAttribute\":{\"stringListValues\":[\"val1\",\"val2\",\"val3\"]}},\"messageId\":\"1212abcd\"}") .contains("\"message\":\"1212abcd\"") .contains("\"message\":\"Message body = plop and id = \\\"1212abcd\\\"\""); // Reserved keys should be ignored @@ -106,7 +104,7 @@ void shouldLogArgumentsAsJsonWhenUsingKeyValue() { msg.setMessageId("1212abcd"); msg.setBody("plop"); msg.setEventSource("eb"); - msg.setAwsRegion("eu-west-1"); + msg.setAwsRegion("us-east-1"); SQSEvent.MessageAttribute attribute = new SQSEvent.MessageAttribute(); attribute.setStringListValues(Arrays.asList("val1", "val2", "val3")); msg.setMessageAttributes(Collections.singletonMap("keyAttribute", attribute)); @@ -118,7 +116,7 @@ void shouldLogArgumentsAsJsonWhenUsingKeyValue() { File logFile = new File("target/logfile.json"); assertThat(contentOf(logFile)) .contains( - "\"input\":{\"awsRegion\":\"eu-west-1\",\"body\":\"plop\",\"eventSource\":\"eb\",\"messageAttributes\":{\"keyAttribute\":{\"stringListValues\":[\"val1\",\"val2\",\"val3\"]}},\"messageId\":\"1212abcd\"}") + "\"input\":{\"awsRegion\":\"us-east-1\",\"body\":\"plop\",\"eventSource\":\"eb\",\"messageAttributes\":{\"keyAttribute\":{\"stringListValues\":[\"val1\",\"val2\",\"val3\"]}},\"messageId\":\"1212abcd\"}") .contains("\"message\":\"1212abcd\"") .contains("\"message\":\"Message body = plop and id = \\\"1212abcd\\\"\""); @@ -131,11 +129,4 @@ void shouldLogArgumentsAsJsonWhenUsingKeyValue() { }); } - private void setupContext() { - when(context.getFunctionName()).thenReturn("testFunction"); - when(context.getInvokedFunctionArn()).thenReturn("testArn"); - when(context.getFunctionVersion()).thenReturn("1"); - when(context.getMemoryLimitInMB()).thenReturn(10); - when(context.getAwsRequestId()).thenReturn("RequestId"); - } } From e1eb1286b820326785f2973fd77c8fa1c75040ad Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Fri, 15 Aug 2025 15:35:10 +0200 Subject: [PATCH 11/65] Add --initialize-at-build-time=org.junit.platform.launcher.core.DiscoveryIssueNotifier --- powertools-logging/powertools-logging-log4j/pom.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/powertools-logging/powertools-logging-log4j/pom.xml b/powertools-logging/powertools-logging-log4j/pom.xml index da6bd3652..5c29b8666 100644 --- a/powertools-logging/powertools-logging-log4j/pom.xml +++ b/powertools-logging/powertools-logging-log4j/pom.xml @@ -149,6 +149,9 @@ --initialize-at-build-time=org.junit.Ignore --initialize-at-build-time=java.lang.annotation.Annotation --initialize-at-build-time=org.junit.runners.model.FrameworkField + + --initialize-at-build-time=org.junit.platform.launcher.core.DiscoveryIssueNotifier$1 + From 79389a62515c1626edd67ddad8145d469221a251 Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Fri, 15 Aug 2025 15:45:24 +0200 Subject: [PATCH 12/65] Remove mockito from powertools-logging-logback. --- .../powertools-logging-log4j/pom.xml | 1 - .../powertools-logging-logback/pom.xml | 55 ++---- .../jni-config.json | 4 - .../predefined-classes-config.json | 8 + .../proxy-config.json | 2 + .../reflect-config.json | 165 ++++++------------ .../resource-config.json | 14 ++ .../serialization-config.json | 11 ++ .../internal/LambdaEcsEncoderTest.java | 36 ++-- .../internal/LambdaJsonEncoderTest.java | 75 ++++---- 10 files changed, 158 insertions(+), 213 deletions(-) create mode 100644 powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/predefined-classes-config.json create mode 100644 powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/proxy-config.json create mode 100644 powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/serialization-config.json diff --git a/powertools-logging/powertools-logging-log4j/pom.xml b/powertools-logging/powertools-logging-log4j/pom.xml index 5c29b8666..e71f07782 100644 --- a/powertools-logging/powertools-logging-log4j/pom.xml +++ b/powertools-logging/powertools-logging-log4j/pom.xml @@ -211,5 +211,4 @@ - diff --git a/powertools-logging/powertools-logging-logback/pom.xml b/powertools-logging/powertools-logging-logback/pom.xml index b9ea7f8de..2938e9153 100644 --- a/powertools-logging/powertools-logging-logback/pom.xml +++ b/powertools-logging/powertools-logging-logback/pom.xml @@ -1,7 +1,7 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 powertools-parent @@ -49,8 +49,10 @@ test - org.mockito - mockito-core + software.amazon.lambda + powertools-common + ${project.version} + test-jar test @@ -88,13 +90,6 @@ generate-graalvm-files - - - org.mockito - mockito-subclass - test - - @@ -102,7 +97,11 @@ maven-surefire-plugin 3.5.3 - -Dmockito.mock.maker=subclass -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback,experimental-class-define-support + -Dorg.graalvm.nativeimage.imagecode=agent + -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback,experimental-class-define-support + --add-opens java.base/java.util=ALL-UNNAMED + --add-opens java.base/java.lang=ALL-UNNAMED + @@ -110,13 +109,6 @@ graalvm-native - - - org.mockito - mockito-subclass - test - - @@ -134,37 +126,20 @@ - - true - Standard - powertools-logging-logback + --add-opens java.base/java.util=ALL-UNNAMED + --add-opens java.base/java.lang=ALL-UNNAMED --no-fallback -Dorg.graalvm.nativeimage.imagecode=agent - -H:ClassInitialization=net.bytebuddy.ClassFileVersion:rerun - -H:ClassInitialization=net.bytebuddy.utility.dispatcher.JavaDispatcher:rerun - -H:ClassInitialization=net.bytebuddy.utility.Invoker$Dispatcher:rerun - -H:ClassInitialization=net.bytebuddy.utility.GraalImageCode:rerun --initialize-at-build-time=org.slf4j.simple.SimpleLogger --initialize-at-build-time=org.slf4j.LoggerFactory --initialize-at-build-time=org.junit.Ignore --initialize-at-build-time=java.lang.annotation.Annotation --initialize-at-build-time=org.junit.runners.model.FrameworkField - --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase - --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic - --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$1 - --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$2 - --initialize-at-build-time=net.bytebuddy.utility.dispatcher.JavaDispatcher$DynamicClassLoader - --initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable - --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase - --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$ForLoadedType - --initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$ForLoadedMethod - --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Super$Instantiation$2 - --trace-class-initialization=net.bytebuddy.description.type.TypeDescription$ForLoadedType,net.bytebuddy.description.method.MethodDescription$ForLoadedMethod,net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable + --initialize-at-build-time=org.junit.platform.launcher.core.DiscoveryIssueNotifier$1 - --verbose @@ -225,6 +200,4 @@ - - diff --git a/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/jni-config.json b/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/jni-config.json index 2c4de0562..753dafdea 100644 --- a/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/jni-config.json +++ b/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/jni-config.json @@ -15,10 +15,6 @@ "name":"org.apache.maven.surefire.booter.ForkedBooter", "methods":[{"name":"main","parameterTypes":["java.lang.String[]"] }] }, -{ - "name":"sun.instrument.InstrumentationImpl", - "methods":[{"name":"","parameterTypes":["long","boolean","boolean","boolean"] }, {"name":"loadClassAndCallAgentmain","parameterTypes":["java.lang.String","java.lang.String"] }, {"name":"loadClassAndCallPremain","parameterTypes":["java.lang.String","java.lang.String"] }, {"name":"transform","parameterTypes":["java.lang.Module","java.lang.ClassLoader","java.lang.String","java.lang.Class","java.security.ProtectionDomain","byte[]","boolean"] }] -}, { "name":"sun.management.VMManagementImpl", "fields":[{"name":"compTimeMonitoringSupport"}, {"name":"currentThreadCpuTimeSupport"}, {"name":"objectMonitorUsageSupport"}, {"name":"otherThreadCpuTimeSupport"}, {"name":"remoteDiagnosticCommandsSupport"}, {"name":"synchronizerUsageSupport"}, {"name":"threadAllocatedMemorySupport"}, {"name":"threadContentionMonitoringSupport"}] diff --git a/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/predefined-classes-config.json b/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/predefined-classes-config.json new file mode 100644 index 000000000..0e79b2c5d --- /dev/null +++ b/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/predefined-classes-config.json @@ -0,0 +1,8 @@ +[ + { + "type":"agent-extracted", + "classes":[ + ] + } +] + diff --git a/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/proxy-config.json b/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/proxy-config.json new file mode 100644 index 000000000..0d4f101c7 --- /dev/null +++ b/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/proxy-config.json @@ -0,0 +1,2 @@ +[ +] diff --git a/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/reflect-config.json b/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/reflect-config.json index 0d3bdbe7e..efd81020e 100644 --- a/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/reflect-config.json +++ b/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/reflect-config.json @@ -1,4 +1,10 @@ [ +{ + "name":"[Ljava.lang.Object;" +}, +{ + "name":"[Ljava.lang.String;" +}, { "name":"ch.qos.logback.classic.joran.SerializedModelConfigurator", "methods":[{"name":"","parameterTypes":[] }] @@ -21,11 +27,7 @@ "methods":[{"name":"valueOf","parameterTypes":["java.lang.String"] }] }, { - "name":"com.amazonaws.services.lambda.runtime.Context", - "queryAllDeclaredMethods":true, - "queryAllPublicMethods":true, - "queryAllDeclaredConstructors":true, - "methods":[{"name":"getAwsRequestId","parameterTypes":[] }, {"name":"getClientContext","parameterTypes":[] }, {"name":"getFunctionName","parameterTypes":[] }, {"name":"getFunctionVersion","parameterTypes":[] }, {"name":"getIdentity","parameterTypes":[] }, {"name":"getInvokedFunctionArn","parameterTypes":[] }, {"name":"getLogGroupName","parameterTypes":[] }, {"name":"getLogStreamName","parameterTypes":[] }, {"name":"getLogger","parameterTypes":[] }, {"name":"getMemoryLimitInMB","parameterTypes":[] }, {"name":"getRemainingTimeInMillis","parameterTypes":[] }] + "name":"com.amazonaws.services.lambda.runtime.Context" }, { "name":"com.amazonaws.services.lambda.runtime.events.SQSEvent$MessageAttribute", @@ -49,12 +51,6 @@ "name":"com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl", "methods":[{"name":"","parameterTypes":[] }] }, -{ - "name":"com.sun.tools.attach.VirtualMachine" -}, -{ - "name":"java.io.FilePermission" -}, { "name":"java.io.IOException" }, @@ -66,153 +62,110 @@ }, { "name":"java.io.Serializable", - "queryAllDeclaredMethods":true, - "queryAllDeclaredConstructors":true -}, -{ - "name":"java.lang.Class", - "methods":[{"name":"forName","parameterTypes":["java.lang.String"] }, {"name":"getAnnotatedInterfaces","parameterTypes":[] }, {"name":"getAnnotatedSuperclass","parameterTypes":[] }, {"name":"getDeclaredMethod","parameterTypes":["java.lang.String","java.lang.Class[]"] }, {"name":"getMethod","parameterTypes":["java.lang.String","java.lang.Class[]"] }, {"name":"getModule","parameterTypes":[] }, {"name":"getNestHost","parameterTypes":[] }, {"name":"getNestMembers","parameterTypes":[] }, {"name":"getPermittedSubclasses","parameterTypes":[] }, {"name":"getRecordComponents","parameterTypes":[] }, {"name":"isNestmateOf","parameterTypes":["java.lang.Class"] }, {"name":"isRecord","parameterTypes":[] }, {"name":"isSealed","parameterTypes":[] }] -}, -{ - "name":"java.lang.ClassLoader", - "methods":[{"name":"getDefinedPackage","parameterTypes":["java.lang.String"] }, {"name":"getUnnamedModule","parameterTypes":[] }, {"name":"registerAsParallelCapable","parameterTypes":[] }] + "queryAllDeclaredMethods":true }, { "name":"java.lang.Cloneable", "queryAllDeclaredMethods":true }, { - "name":"java.lang.Module", - "methods":[{"name":"addExports","parameterTypes":["java.lang.String","java.lang.Module"] }, {"name":"addReads","parameterTypes":["java.lang.Module"] }, {"name":"canRead","parameterTypes":["java.lang.Module"] }, {"name":"getClassLoader","parameterTypes":[] }, {"name":"getName","parameterTypes":[] }, {"name":"getPackages","parameterTypes":[] }, {"name":"getResourceAsStream","parameterTypes":["java.lang.String"] }, {"name":"isExported","parameterTypes":["java.lang.String"] }, {"name":"isExported","parameterTypes":["java.lang.String","java.lang.Module"] }, {"name":"isNamed","parameterTypes":[] }, {"name":"isOpen","parameterTypes":["java.lang.String","java.lang.Module"] }] -}, -{ - "name":"java.lang.Object", - "queryAllDeclaredMethods":true, - "queryAllDeclaredConstructors":true, - "methods":[{"name":"","parameterTypes":[] }, {"name":"clone","parameterTypes":[] }, {"name":"getClass","parameterTypes":[] }, {"name":"toString","parameterTypes":[] }] -}, -{ - "name":"java.lang.ProcessHandle", - "methods":[{"name":"current","parameterTypes":[] }, {"name":"pid","parameterTypes":[] }] -}, -{ - "name":"java.lang.Runtime", - "methods":[{"name":"version","parameterTypes":[] }] -}, -{ - "name":"java.lang.Runtime$Version", - "methods":[{"name":"feature","parameterTypes":[] }] + "name":"java.lang.Iterable", + "queryAllDeclaredMethods":true }, { - "name":"java.lang.RuntimePermission" + "name":"java.lang.Object" }, { - "name":"java.lang.StackWalker" + "name":"java.lang.String" }, { - "name":"java.lang.String" + "name":"java.util.AbstractCollection", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true }, { - "name":"java.lang.System", - "methods":[{"name":"getSecurityManager","parameterTypes":[] }] + "name":"java.util.AbstractList", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true }, { - "name":"java.lang.annotation.Retention", - "queryAllDeclaredMethods":true, - "queryAllDeclaredConstructors":true + "name":"java.util.AbstractMap", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true }, { - "name":"java.lang.annotation.Target", + "name":"java.util.Arrays$ArrayList", + "allDeclaredFields":true, "queryAllDeclaredMethods":true, "queryAllDeclaredConstructors":true }, { - "name":"java.lang.invoke.MethodHandle", - "methods":[{"name":"bindTo","parameterTypes":["java.lang.Object"] }, {"name":"invokeWithArguments","parameterTypes":["java.lang.Object[]"] }] -}, -{ - "name":"java.lang.invoke.MethodHandles", - "methods":[{"name":"lookup","parameterTypes":[] }] -}, -{ - "name":"java.lang.invoke.MethodHandles$Lookup", - "methods":[{"name":"findVirtual","parameterTypes":["java.lang.Class","java.lang.String","java.lang.invoke.MethodType"] }] -}, -{ - "name":"java.lang.invoke.MethodType", - "methods":[{"name":"methodType","parameterTypes":["java.lang.Class","java.lang.Class[]"] }] -}, -{ - "name":"java.lang.reflect.AccessibleObject", - "methods":[{"name":"setAccessible","parameterTypes":["boolean"] }] -}, -{ - "name":"java.lang.reflect.AnnotatedArrayType", - "methods":[{"name":"getAnnotatedGenericComponentType","parameterTypes":[] }] -}, -{ - "name":"java.lang.reflect.AnnotatedType", - "methods":[{"name":"getType","parameterTypes":[] }] -}, -{ - "name":"java.lang.reflect.Executable", - "methods":[{"name":"getAnnotatedExceptionTypes","parameterTypes":[] }, {"name":"getAnnotatedParameterTypes","parameterTypes":[] }, {"name":"getAnnotatedReceiverType","parameterTypes":[] }, {"name":"getParameterCount","parameterTypes":[] }, {"name":"getParameters","parameterTypes":[] }] + "name":"java.util.Collection", + "queryAllDeclaredMethods":true }, { - "name":"java.lang.reflect.Method", - "methods":[{"name":"getAnnotatedReturnType","parameterTypes":[] }] + "name":"java.util.Collections$SingletonMap", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true }, { - "name":"java.lang.reflect.Parameter", - "methods":[{"name":"getModifiers","parameterTypes":[] }, {"name":"getName","parameterTypes":[] }, {"name":"isNamePresent","parameterTypes":[] }] + "name":"java.util.List", + "queryAllDeclaredMethods":true }, { - "name":"java.net.NetPermission" + "name":"java.util.Map", + "queryAllDeclaredMethods":true }, { - "name":"java.net.SocketPermission" + "name":"java.util.RandomAccess", + "queryAllDeclaredMethods":true }, { - "name":"java.net.URLPermission", - "methods":[{"name":"","parameterTypes":["java.lang.String","java.lang.String"] }] + "name":"java.util.concurrent.atomic.AtomicBoolean", + "fields":[{"name":"value"}] }, { - "name":"java.security.AccessController", - "methods":[{"name":"doPrivileged","parameterTypes":["java.security.PrivilegedAction"] }, {"name":"doPrivileged","parameterTypes":["java.security.PrivilegedExceptionAction"] }] + "name":"java.util.concurrent.atomic.AtomicReference", + "fields":[{"name":"value"}] }, { - "name":"java.security.AllPermission" + "name":"kotlin.Metadata" }, { - "name":"java.security.SecurityPermission" + "name":"org.apache.maven.surefire.junitplatform.JUnitPlatformProvider", + "methods":[{"name":"","parameterTypes":["org.apache.maven.surefire.api.provider.ProviderParameters"] }] }, { - "name":"java.util.PropertyPermission" + "name":"org.apiguardian.api.API", + "queryAllPublicMethods":true }, { - "name":"java.util.concurrent.ForkJoinTask", - "fields":[{"name":"aux"}, {"name":"status"}] + "name":"org.junit.internal.AssumptionViolatedException" }, { - "name":"java.util.concurrent.atomic.AtomicBoolean", - "fields":[{"name":"value"}] + "name":"org.junit.jupiter.api.ClassOrderer$OrderAnnotation", + "methods":[{"name":"","parameterTypes":[] }] }, { - "name":"java.util.concurrent.atomic.AtomicReference", - "fields":[{"name":"value"}] + "name":"org.junit.jupiter.api.Order", + "queryAllPublicMethods":true }, { - "name":"javax.smartcardio.CardPermission" + "name":"org.junit.jupiter.api.Test", + "queryAllPublicMethods":true }, { - "name":"jdk.internal.misc.Unsafe" + "name":"org.junit.platform.commons.annotation.Testable", + "queryAllPublicMethods":true }, { - "name":"kotlin.jvm.JvmInline" + "name":"org.junit.platform.launcher.LauncherSession", + "methods":[{"name":"getLauncher","parameterTypes":[] }] }, { - "name":"org.apiguardian.api.API", - "queryAllPublicMethods":true + "name":"org.junit.platform.launcher.core.LauncherFactory", + "methods":[{"name":"openSession","parameterTypes":[] }] }, { "name":"software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor", @@ -282,9 +235,5 @@ "name":"software.amazon.lambda.powertools.logging.logback.LambdaJsonEncoder", "queryAllPublicMethods":true, "methods":[{"name":"","parameterTypes":[] }] -}, -{ - "name":"sun.reflect.ReflectionFactory", - "methods":[{"name":"getReflectionFactory","parameterTypes":[] }, {"name":"newConstructorForSerialization","parameterTypes":["java.lang.Class","java.lang.reflect.Constructor"] }] } ] diff --git a/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/resource-config.json b/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/resource-config.json index dea71883a..551635098 100644 --- a/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/resource-config.json +++ b/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/resource-config.json @@ -14,10 +14,24 @@ "pattern":"\\QMETA-INF/services/org.assertj.core.configuration.Configuration\\E" }, { "pattern":"\\QMETA-INF/services/org.assertj.core.presentation.Representation\\E" + }, { + "pattern":"\\QMETA-INF/services/org.junit.platform.commons.support.scanning.ClasspathScanner\\E" + }, { + "pattern":"\\QMETA-INF/services/org.junit.platform.engine.TestEngine\\E" + }, { + "pattern":"\\QMETA-INF/services/org.junit.platform.launcher.LauncherDiscoveryListener\\E" + }, { + "pattern":"\\QMETA-INF/services/org.junit.platform.launcher.LauncherSessionListener\\E" + }, { + "pattern":"\\QMETA-INF/services/org.junit.platform.launcher.PostDiscoveryFilter\\E" + }, { + "pattern":"\\QMETA-INF/services/org.junit.platform.launcher.TestExecutionListener\\E" }, { "pattern":"\\QMETA-INF/services/org.slf4j.spi.SLF4JServiceProvider\\E" }, { "pattern":"\\QMETA-INF/services/software.amazon.lambda.powertools.logging.internal.LoggingManager\\E" + }, { + "pattern":"\\Qjunit-platform.properties\\E" }, { "pattern":"\\Qlogback-test.scmo\\E" }, { diff --git a/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/serialization-config.json b/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/serialization-config.json new file mode 100644 index 000000000..fc967f7f8 --- /dev/null +++ b/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/serialization-config.json @@ -0,0 +1,11 @@ +{ + "types":[ + { + "name":"org.junit.platform.launcher.TestIdentifier$SerializedForm" + } + ], + "lambdaCapturingTypes":[ + ], + "proxies":[ + ] +} diff --git a/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaEcsEncoderTest.java b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaEcsEncoderTest.java index 7e8977508..65277e3d6 100644 --- a/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaEcsEncoderTest.java +++ b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaEcsEncoderTest.java @@ -17,8 +17,6 @@ import static org.apache.commons.lang3.reflect.FieldUtils.writeStaticField; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.contentOf; -import static org.mockito.Mockito.when; -import static org.mockito.MockitoAnnotations.openMocks; import ch.qos.logback.classic.Level; import ch.qos.logback.classic.Logger; @@ -36,7 +34,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Test; -import org.mockito.Mock; +import software.amazon.lambda.powertools.common.stubs.TestLambdaContext; import org.slf4j.LoggerFactory; import org.slf4j.MDC; import software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor; @@ -48,16 +46,13 @@ class LambdaEcsEncoderTest { private static final Logger logger = (Logger) LoggerFactory.getLogger(LambdaEcsEncoderTest.class.getName()); - - @Mock private Context context; @BeforeEach void setUp() throws IllegalAccessException, IOException { - openMocks(this); MDC.clear(); writeStaticField(LambdaHandlerProcessor.class, "IS_COLD_START", null, true); - setupContext(); + context = new TestLambdaContext(); // Make sure file is cleaned up before running tests try { FileChannel.open(Paths.get("target/ecslogfile.json"), StandardOpenOption.WRITE).truncate(0).close(); @@ -67,7 +62,7 @@ void setUp() throws IllegalAccessException, IOException { } @AfterEach - void cleanUp() throws IOException{ + void cleanUp() throws IOException { FileChannel.open(Paths.get("target/ecslogfile.json"), StandardOpenOption.WRITE).truncate(0).close(); } @@ -78,7 +73,7 @@ void shouldLogInEcsFormat() { File logFile = new File("target/ecslogfile.json"); assertThat(contentOf(logFile)).contains( - "\"ecs.version\":\"1.2.0\",\"log.level\":\"DEBUG\",\"message\":\"Test debug event\",\"service.name\":\"testLogback\",\"service.version\":\"1\",\"log.logger\":\"software.amazon.lambda.powertools.logging.internal.handler.PowertoolsLogEnabled\",\"process.thread.name\":\"main\",\"cloud.provider\":\"aws\",\"cloud.service.name\":\"lambda\",\"cloud.region\":\"eu-west-1\",\"cloud.account.id\":\"012345678910\",\"faas.id\":\"arn:aws:lambda:eu-west-1:012345678910:function:testFunction:1\",\"faas.name\":\"testFunction\",\"faas.version\":\"1\",\"faas.memory\":\"1024\",\"faas.execution\":\"RequestId\",\"faas.coldstart\":\"true\",\"trace.id\":\"1-63441c4a-abcdef012345678912345678\",\"myKey\":\"myValue\"}\n"); + "\"ecs.version\":\"1.2.0\",\"log.level\":\"DEBUG\",\"message\":\"Test debug event\",\"service.name\":\"testLogback\",\"service.version\":\"1\",\"log.logger\":\"software.amazon.lambda.powertools.logging.internal.handler.PowertoolsLogEnabled\",\"process.thread.name\":\"main\",\"cloud.provider\":\"aws\",\"cloud.service.name\":\"lambda\",\"cloud.region\":\"us-east-1\",\"cloud.account.id\":\"123456789012\",\"faas.id\":\"arn:aws:lambda:us-east-1:123456789012:function:test\",\"faas.name\":\"test-function\",\"faas.version\":\"1\",\"faas.memory\":\"128\",\"faas.execution\":\"test-request-id\",\"faas.coldstart\":\"true\",\"trace.id\":\"1-63441c4a-abcdef012345678912345678\",\"myKey\":\"myValue\"}\n"); } private final LoggingEvent loggingEvent = new LoggingEvent("fqcn", logger, Level.INFO, "message", null, null); @@ -94,7 +89,8 @@ void shouldNotLogFunctionInfo() { String result = new String(encoded, StandardCharsets.UTF_8); // THEN - assertThat(result).contains("\"faas.id\":\"arn:aws:lambda:eu-west-1:012345678910:function:testFunction:1\",\"faas.name\":\"testFunction\",\"faas.version\":\"1\",\"faas.memory\":\"1024\",\"faas.execution\":\"RequestId\",\"faas.coldstart\":\"false\""); + assertThat(result).contains( + "\"faas.id\":\"arn:aws:lambda:us-east-1:123456789012:function:test\",\"faas.name\":\"test-function\",\"faas.version\":\"1\",\"faas.memory\":\"128\",\"faas.execution\":\"test-request-id\",\"faas.coldstart\":\"false\""); // WHEN (includeFaasInfo = false) encoder.setIncludeFaasInfo(false); @@ -116,7 +112,8 @@ void shouldNotLogCloudInfo() { String result = new String(encoded, StandardCharsets.UTF_8); // THEN - assertThat(result).contains("\"cloud.provider\":\"aws\",\"cloud.service.name\":\"lambda\",\"cloud.region\":\"eu-west-1\",\"cloud.account.id\":\"012345678910\""); + assertThat(result).contains( + "\"cloud.provider\":\"aws\",\"cloud.service.name\":\"lambda\",\"cloud.region\":\"us-east-1\",\"cloud.account.id\":\"123456789012\""); // WHEN (includeCloudInfo = false) encoder.setIncludeCloudInfo(false); @@ -132,14 +129,16 @@ void shouldLogException() { // GIVEN LambdaEcsEncoder encoder = new LambdaEcsEncoder(); encoder.start(); - LoggingEvent errorloggingEvent = new LoggingEvent("fqcn", logger, Level.INFO, "Error", new IllegalStateException("Unexpected value"), null); + LoggingEvent errorloggingEvent = new LoggingEvent("fqcn", logger, Level.INFO, "Error", + new IllegalStateException("Unexpected value"), null); // WHEN byte[] encoded = encoder.encode(errorloggingEvent); String result = new String(encoded, StandardCharsets.UTF_8); // THEN - assertThat(result).contains("\"message\":\"Error\",\"error.message\":\"Unexpected value\",\"error.type\":\"java.lang.IllegalStateException\",\"error.stack_trace\":\"[software.amazon.lambda.powertools.logging.internal.LambdaEcsEncoderTest.shouldLogException"); + assertThat(result).contains( + "\"message\":\"Error\",\"error.message\":\"Unexpected value\",\"error.type\":\"java.lang.IllegalStateException\",\"error.stack_trace\":\"[software.amazon.lambda.powertools.logging.internal.LambdaEcsEncoderTest.shouldLogException"); // WHEN (configure a custom throwableConverter) encoder = new LambdaEcsEncoder(); @@ -150,7 +149,8 @@ void shouldLogException() { result = new String(encoded, StandardCharsets.UTF_8); // THEN (stack is logged with root cause first) - assertThat(result).contains("\"message\":\"Error\",\"error.message\":\"Unexpected value\",\"error.type\":\"java.lang.IllegalStateException\",\"error.stack_trace\":\"java.lang.IllegalStateException: Unexpected value\\n"); + assertThat(result).contains( + "\"message\":\"Error\",\"error.message\":\"Unexpected value\",\"error.type\":\"java.lang.IllegalStateException\",\"error.stack_trace\":\"java.lang.IllegalStateException: Unexpected value\\n"); } private void setMDC() { @@ -165,12 +165,4 @@ private void setMDC() { MDC.put(PowertoolsLoggedFields.SERVICE.getName(), "Service"); } - private void setupContext() { - when(context.getFunctionName()).thenReturn("testFunction"); - when(context.getInvokedFunctionArn()).thenReturn( - "arn:aws:lambda:eu-west-1:012345678910:function:testFunction:1"); - when(context.getFunctionVersion()).thenReturn("1"); - when(context.getMemoryLimitInMB()).thenReturn(1024); - when(context.getAwsRequestId()).thenReturn("RequestId"); - } } diff --git a/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaJsonEncoderTest.java b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaJsonEncoderTest.java index c0eecf6f3..fa50bac21 100644 --- a/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaJsonEncoderTest.java +++ b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaJsonEncoderTest.java @@ -19,8 +19,6 @@ import static org.apache.commons.lang3.reflect.FieldUtils.writeStaticField; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.contentOf; -import static org.mockito.Mockito.when; -import static org.mockito.MockitoAnnotations.openMocks; import ch.qos.logback.classic.Level; import ch.qos.logback.classic.Logger; @@ -29,7 +27,6 @@ import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.events.SQSEvent; import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.util.JSONPObject; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; @@ -51,7 +48,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Test; -import org.mockito.Mock; +import software.amazon.lambda.powertools.common.stubs.TestLambdaContext; import org.slf4j.LoggerFactory; import org.slf4j.MDC; import software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor; @@ -70,15 +67,13 @@ class LambdaJsonEncoderTest { private static final Logger logger = (Logger) LoggerFactory.getLogger(LambdaJsonEncoderTest.class.getName()); - @Mock private Context context; @BeforeEach void setUp() throws IllegalAccessException, IOException { - openMocks(this); MDC.clear(); writeStaticField(LambdaHandlerProcessor.class, "IS_COLD_START", null, true); - setupContext(); + context = new TestLambdaContext(); // Make sure file is cleaned up before running tests try { FileChannel.open(Paths.get("target/logfile.json"), StandardOpenOption.WRITE).truncate(0).close(); @@ -88,7 +83,7 @@ void setUp() throws IllegalAccessException, IOException { } @AfterEach - void cleanUp() throws IOException{ + void cleanUp() throws IOException { FileChannel.open(Paths.get("target/logfile.json"), StandardOpenOption.WRITE).truncate(0).close(); } @@ -103,7 +98,7 @@ void shouldLogInJsonFormat() { // THEN File logFile = new File("target/logfile.json"); assertThat(contentOf(logFile)).contains( - "{\"level\":\"DEBUG\",\"message\":\"Test debug event\",\"cold_start\":true,\"function_arn\":\"arn:aws:lambda:eu-west-1:012345678910:function:testFunction:1\",\"function_memory_size\":1024,\"function_name\":\"testFunction\",\"function_request_id\":\"RequestId\",\"function_version\":1,\"service\":\"testLogback\",\"xray_trace_id\":\"1-63441c4a-abcdef012345678912345678\",\"myKey\":\"myValue\",\"timestamp\":"); + "{\"level\":\"DEBUG\",\"message\":\"Test debug event\",\"cold_start\":true,\"function_arn\":\"arn:aws:lambda:us-east-1:123456789012:function:test\",\"function_memory_size\":128,\"function_name\":\"test-function\",\"function_request_id\":\"test-request-id\",\"function_version\":1,\"service\":\"testLogback\",\"xray_trace_id\":\"1-63441c4a-abcdef012345678912345678\",\"myKey\":\"myValue\",\"timestamp\":"); } @Test @@ -114,7 +109,7 @@ void shouldLogArgumentsAsJsonWhenUsingRawJson() { msg.setMessageId("1212abcd"); msg.setBody("plop"); msg.setEventSource("eb"); - msg.setAwsRegion("eu-west-1"); + msg.setAwsRegion("eu-central-1"); SQSEvent.MessageAttribute attribute = new SQSEvent.MessageAttribute(); attribute.setStringListValues(Arrays.asList("val1", "val2", "val3")); msg.setMessageAttributes(Collections.singletonMap("keyAttribute", attribute)); @@ -125,7 +120,8 @@ void shouldLogArgumentsAsJsonWhenUsingRawJson() { // THEN File logFile = new File("target/logfile.json"); assertThat(contentOf(logFile)) - .contains("\"input\":{\"awsRegion\":\"eu-west-1\",\"body\":\"plop\",\"eventSource\":\"eb\",\"messageAttributes\":{\"keyAttribute\":{\"stringListValues\":[\"val1\",\"val2\",\"val3\"]}},\"messageId\":\"1212abcd\"}") + .contains( + "\"input\":{\"awsRegion\":\"eu-central-1\",\"body\":\"plop\",\"eventSource\":\"eb\",\"messageAttributes\":{\"keyAttribute\":{\"stringListValues\":[\"val1\",\"val2\",\"val3\"]}},\"messageId\":\"1212abcd\"}") .contains("\"message\":\"1212abcd\"") // Should auto-escape double quotes around id .contains("\"message\":\"Message body = plop and id = \\\"1212abcd\\\"\""); @@ -146,7 +142,7 @@ void shouldLogArgumentsAsJsonWhenUsingKeyValue() { msg.setMessageId("1212abcd"); msg.setBody("plop"); msg.setEventSource("eb"); - msg.setAwsRegion("eu-west-1"); + msg.setAwsRegion("eu-central-1"); SQSEvent.MessageAttribute attribute = new SQSEvent.MessageAttribute(); attribute.setStringListValues(Arrays.asList("val1", "val2", "val3")); msg.setMessageAttributes(Collections.singletonMap("keyAttribute", attribute)); @@ -157,7 +153,8 @@ void shouldLogArgumentsAsJsonWhenUsingKeyValue() { // THEN File logFile = new File("target/logfile.json"); assertThat(contentOf(logFile)) - .contains("\"input\":{\"awsRegion\":\"eu-west-1\",\"body\":\"plop\",\"eventSource\":\"eb\",\"messageAttributes\":{\"keyAttribute\":{\"stringListValues\":[\"val1\",\"val2\",\"val3\"]}},\"messageId\":\"1212abcd\"}") + .contains( + "\"input\":{\"awsRegion\":\"eu-central-1\",\"body\":\"plop\",\"eventSource\":\"eb\",\"messageAttributes\":{\"keyAttribute\":{\"stringListValues\":[\"val1\",\"val2\",\"val3\"]}},\"messageId\":\"1212abcd\"}") .contains("\"message\":\"1212abcd\"") // Should auto-escape double quotes around id .contains("\"message\":\"Message body = plop and id = \\\"1212abcd\\\"\""); @@ -192,7 +189,8 @@ void shouldNotLogPowertoolsInfo() { String result = new String(encoded, StandardCharsets.UTF_8); // THEN - assertThat(result).contains("{\"level\":\"INFO\",\"message\":\"message\",\"cold_start\":false,\"function_arn\":\"arn:aws:lambda:eu-west-1:012345678910:function:testFunction:1\",\"function_memory_size\":1024,\"function_name\":\"testFunction\",\"function_request_id\":\"RequestId\",\"function_version\":1,\"sampling_rate\":0.2,\"service\":\"Service\",\"timestamp\":"); + assertThat(result).contains( + "{\"level\":\"INFO\",\"message\":\"message\",\"cold_start\":false,\"function_arn\":\"arn:aws:lambda:us-east-1:123456789012:function:test\",\"function_memory_size\":128,\"function_name\":\"test-function\",\"function_request_id\":\"test-request-id\",\"function_version\":1,\"sampling_rate\":0.2,\"service\":\"Service\",\"timestamp\":"); // WHEN (powertoolsInfo = false) encoder.setIncludePowertoolsInfo(false); @@ -200,7 +198,8 @@ void shouldNotLogPowertoolsInfo() { result = new String(encoded, StandardCharsets.UTF_8); // THEN (no powertools info in logs) - assertThat(result).doesNotContain("cold_start", "function_arn", "function_memory_size", "function_name", "function_request_id", "function_version", "sampling_rate", "service"); + assertThat(result).doesNotContain("cold_start", "function_arn", "function_memory_size", "function_name", + "function_request_id", "function_version", "sampling_rate", "service"); } @Test @@ -212,20 +211,22 @@ void shouldLogStructuredArgumentsAsNewEntries() { msg.setMessageId("1212abcd"); msg.setBody("plop"); msg.setEventSource("eb"); - msg.setAwsRegion("eu-west-1"); + msg.setAwsRegion("eu-central-1"); SQSEvent.MessageAttribute attribute = new SQSEvent.MessageAttribute(); attribute.setStringListValues(Arrays.asList("val1", "val2", "val3")); msg.setMessageAttributes(Collections.singletonMap("keyAttribute", attribute)); StructuredArgument argument = StructuredArguments.entry("msg", msg); // WHEN - LoggingEvent loggingEvent = new LoggingEvent("fqcn", logger, Level.INFO, "A message", null, new Object[]{argument}); + LoggingEvent loggingEvent = new LoggingEvent("fqcn", logger, Level.INFO, "A message", null, + new Object[] { argument }); byte[] encoded = encoder.encode(loggingEvent); String result = new String(encoded, StandardCharsets.UTF_8); // THEN (logged as JSON) assertThat(result) - .contains("\"message\":\"A message\",\"msg\":{\"awsRegion\":\"eu-west-1\",\"body\":\"plop\",\"eventSource\":\"eb\",\"messageAttributes\":{\"keyAttribute\":{\"stringListValues\":[\"val1\",\"val2\",\"val3\"]}},\"messageId\":\"1212abcd\"}"); + .contains( + "\"message\":\"A message\",\"msg\":{\"awsRegion\":\"eu-central-1\",\"body\":\"plop\",\"eventSource\":\"eb\",\"messageAttributes\":{\"keyAttribute\":{\"stringListValues\":[\"val1\",\"val2\",\"val3\"]}},\"messageId\":\"1212abcd\"}"); } @Test @@ -252,7 +253,7 @@ void shouldLogEventForHandlerWhenEnvVariableSetToTrue() { SQSEvent.SQSMessage message = new SQSEvent.SQSMessage(); message.setBody("body"); message.setMessageId("1234abcd"); - message.setAwsRegion("eu-west-1"); + message.setAwsRegion("eu-central-1"); // WHEN requestHandler.handleRequest(message, context); @@ -260,8 +261,9 @@ void shouldLogEventForHandlerWhenEnvVariableSetToTrue() { // THEN File logFile = new File("target/logfile.json"); assertThat(contentOf(logFile)) - .contains("\"message\":\"Handler Event\"") - .contains("\"event\":{\"awsRegion\":\"eu-west-1\",\"body\":\"body\",\"messageId\":\"1234abcd\"}"); + .contains("\"message\":\"Handler Event\"") + .contains( + "\"event\":{\"awsRegion\":\"eu-central-1\",\"body\":\"body\",\"messageId\":\"1234abcd\"}"); } finally { LoggingConstants.POWERTOOLS_LOG_EVENT = false; } @@ -288,7 +290,10 @@ void shouldLogEventAsStringForStreamHandler() throws IOException { ByteArrayOutputStream output = new ByteArrayOutputStream(); // WHEN - requestStreamHandler.handleRequest(new ByteArrayInputStream(new ObjectMapper().writeValueAsBytes(Collections.singletonMap("key", "value"))), output, context); + requestStreamHandler.handleRequest( + new ByteArrayInputStream( + new ObjectMapper().writeValueAsBytes(Collections.singletonMap("key", "value"))), + output, context); // THEN assertThat(new String(output.toByteArray(), StandardCharsets.UTF_8)) @@ -345,7 +350,8 @@ void shouldLogResponseForStreamHandler() throws IOException { String input = "BobThe Sponge"; // WHEN - requestStreamHandler.handleRequest(new ByteArrayInputStream(input.getBytes(StandardCharsets.UTF_8)), output, context); + requestStreamHandler.handleRequest(new ByteArrayInputStream(input.getBytes(StandardCharsets.UTF_8)), output, + context); // THEN assertThat(new String(output.toByteArray(), StandardCharsets.UTF_8)) @@ -353,8 +359,8 @@ void shouldLogResponseForStreamHandler() throws IOException { File logFile = new File("target/logfile.json"); assertThat(contentOf(logFile)) - .contains("\"message\":\"Handler Response\"") - .contains("\"response\":\""+input+"\""); + .contains("\"message\":\"Handler Response\"") + .contains("\"response\":\"" + input + "\""); } @Test @@ -368,7 +374,8 @@ void shouldLogThreadInfo() { String result = new String(encoded, StandardCharsets.UTF_8); // THEN - assertThat(result).contains("\"thread\":\"main\",\"thread_id\":"+ Thread.currentThread().getId() +",\"thread_priority\":5"); + assertThat(result).contains( + "\"thread\":\"main\",\"thread_id\":" + Thread.currentThread().getId() + ",\"thread_priority\":5"); } @Test @@ -388,7 +395,7 @@ void shouldLogTimestampDifferently() { // THEN SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern); simpleDateFormat.setTimeZone(TimeZone.getTimeZone(timeZone)); - assertThat(result).contains("\"timestamp\":\""+simpleDateFormat.format(date)+"\""); + assertThat(result).contains("\"timestamp\":\"" + simpleDateFormat.format(date) + "\""); } @Test @@ -396,7 +403,8 @@ void shouldLogException() { // GIVEN LambdaJsonEncoder encoder = new LambdaJsonEncoder(); encoder.start(); - LoggingEvent errorloggingEvent = new LoggingEvent("fqcn", logger, Level.INFO, "Error", new IllegalStateException("Unexpected value"), null); + LoggingEvent errorloggingEvent = new LoggingEvent("fqcn", logger, Level.INFO, "Error", + new IllegalStateException("Unexpected value"), null); // WHEN byte[] encoded = encoder.encode(errorloggingEvent); @@ -406,7 +414,8 @@ void shouldLogException() { assertThat(result).contains("\"message\":\"Error\",\"error\":{") .contains("\"message\":\"Unexpected value\"") .contains("\"name\":\"java.lang.IllegalStateException\"") - .contains("\"stack\":\"[software.amazon.lambda.powertools.logging.internal.LambdaJsonEncoderTest.shouldLogException"); + .contains( + "\"stack\":\"[software.amazon.lambda.powertools.logging.internal.LambdaJsonEncoderTest.shouldLogException"); // WHEN (configure a custom throwableConverter) encoder = new LambdaJsonEncoder(); @@ -422,12 +431,4 @@ void shouldLogException() { .contains("\"stack\":\"java.lang.IllegalStateException: Unexpected value\\n"); } - private void setupContext() { - when(context.getFunctionName()).thenReturn("testFunction"); - when(context.getInvokedFunctionArn()).thenReturn( - "arn:aws:lambda:eu-west-1:012345678910:function:testFunction:1"); - when(context.getFunctionVersion()).thenReturn("1"); - when(context.getMemoryLimitInMB()).thenReturn(1024); - when(context.getAwsRequestId()).thenReturn("RequestId"); - } } From cad65cc4871d88027c5c39663d94a94f72384161 Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Fri, 15 Aug 2025 15:58:35 +0200 Subject: [PATCH 13/65] Remove mockito from powertools-tracing. --- powertools-tracing/pom.xml | 44 +++---------- .../powertools/tracing/TracingUtilsTest.java | 63 +++++-------------- .../internal/LambdaTracingAspectTest.java | 62 ++++++------------ 3 files changed, 41 insertions(+), 128 deletions(-) diff --git a/powertools-tracing/pom.xml b/powertools-tracing/pom.xml index b95caf56b..421028c29 100644 --- a/powertools-tracing/pom.xml +++ b/powertools-tracing/pom.xml @@ -14,8 +14,8 @@ --> + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 powertools-tracing @@ -87,8 +87,10 @@ test - org.mockito - mockito-core + software.amazon.lambda + powertools-common + ${project.version} + test-jar test @@ -121,13 +123,6 @@ generate-graalvm-files - - - org.mockito - mockito-subclass - test - - @@ -135,7 +130,8 @@ maven-surefire-plugin 3.5.3 - -Dmockito.mock.maker=subclass -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-tracing,experimental-class-define-support + -Dorg.graalvm.nativeimage.imagecode=agent + -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-tracing,experimental-class-define-support --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED @@ -146,13 +142,6 @@ graalvm-native - - - org.mockito - mockito-subclass - test - - @@ -177,10 +166,6 @@ --enable-url-protocols=http --no-fallback -Dorg.graalvm.nativeimage.imagecode=agent - -H:ClassInitialization=net.bytebuddy.ClassFileVersion:rerun - -H:ClassInitialization=net.bytebuddy.utility.dispatcher.JavaDispatcher:rerun - -H:ClassInitialization=net.bytebuddy.utility.Invoker$Dispatcher:rerun - -H:ClassInitialization=net.bytebuddy.utility.GraalImageCode:rerun -H:IncludeResources=version.properties -H:IncludeResources=unreadable.properties --initialize-at-build-time=org.slf4j.simple.SimpleLogger @@ -188,19 +173,6 @@ --initialize-at-build-time=org.junit.Ignore --initialize-at-build-time=java.lang.annotation.Annotation --initialize-at-build-time=org.junit.runners.model.FrameworkField - --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase - --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic - --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$1 - --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$2 - --initialize-at-build-time=net.bytebuddy.utility.dispatcher.JavaDispatcher$DynamicClassLoader - --initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable - --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase - --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$ForLoadedType - --initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$ForLoadedMethod - --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Super$Instantiation$2 - - --trace-class-initialization=net.bytebuddy.description.type.TypeDescription$ForLoadedType,net.bytebuddy.description.method.MethodDescription$ForLoadedMethod,net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable - --verbose --native-image-info -H:+UnlockExperimentalVMOptions 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 01f25f37a..db9807dbd 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 @@ -16,17 +16,15 @@ 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; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import com.amazonaws.xray.AWSXRay; +import com.amazonaws.xray.entities.Entity; + class TracingUtilsTest { @BeforeEach void setUp() { @@ -55,8 +53,7 @@ void shouldSetAnnotationOnCurrentSubSegment() { .contains( entry("stringKey", "val"), entry("numberKey", 10), - entry("booleanKey", false) - ); + entry("booleanKey", false)); } @Test @@ -76,10 +73,8 @@ void shouldSetMetadataOnCurrentSubSegment() { assertThat(AWSXRay.getTraceEntity().getMetadata()) .hasSize(1) .containsKey("service_undefined") - .satisfies(map -> - assertThat(map.get("service_undefined")) - .containsEntry("key", "val") - ); + .satisfies(map -> assertThat(map.get("service_undefined")) + .containsEntry("key", "val")); } @Test @@ -92,21 +87,14 @@ void shouldNotSetMetaDataIfNoCurrentSubSegment() { @Test void shouldInvokeCodeBlockWrappedWithinSubsegment() { - Context test = mock(Context.class); - - TracingUtils.withSubsegment("testSubSegment", subsegment -> - { + 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 -> - { + .allSatisfy(subsegment -> { assertThat(subsegment.getName()) .isEqualTo("## testSubSegment"); @@ -142,21 +130,14 @@ void shouldAddAnnotationIfValidCharactersInKey() { @Test void shouldInvokeCodeBlockWrappedWithinNamespacedSubsegment() { - Context test = mock(Context.class); - - TracingUtils.withSubsegment("testNamespace", "testSubSegment", subsegment -> - { + 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 -> - { + .allSatisfy(subsegment -> { assertThat(subsegment.getName()) .isEqualTo("## testSubSegment"); @@ -174,25 +155,18 @@ void shouldInvokeCodeBlockWrappedWithinNamespacedSubsegment() { @Test void shouldInvokeCodeBlockWrappedWithinEntitySubsegment() throws InterruptedException { - Context test = mock(Context.class); - Entity traceEntity = AWSXRay.getTraceEntity(); - Thread thread = new Thread(() -> withEntitySubsegment("testSubSegment", traceEntity, subsegment -> - { + Thread thread = new Thread(() -> withEntitySubsegment("testSubSegment", traceEntity, subsegment -> { subsegment.putAnnotation("key", "val"); - test.getFunctionName(); })); thread.start(); thread.join(); - verify(test).getFunctionName(); - assertThat(AWSXRay.getTraceEntity().getSubsegments()) .hasSize(1) - .allSatisfy(subsegment -> - { + .allSatisfy(subsegment -> { assertThat(subsegment.getName()) .isEqualTo("## testSubSegment"); @@ -207,26 +181,19 @@ void shouldInvokeCodeBlockWrappedWithinEntitySubsegment() throws InterruptedExce @Test void shouldInvokeCodeBlockWrappedWithinNamespacedEntitySubsegment() throws InterruptedException { - Context test = mock(Context.class); - Entity traceEntity = AWSXRay.getTraceEntity(); - Thread thread = - new Thread(() -> withEntitySubsegment("testNamespace", "testSubSegment", traceEntity, subsegment -> - { + Thread thread = new Thread( + () -> withEntitySubsegment("testNamespace", "testSubSegment", traceEntity, subsegment -> { subsegment.putAnnotation("key", "val"); - test.getFunctionName(); })); thread.start(); thread.join(); - verify(test).getFunctionName(); - assertThat(AWSXRay.getTraceEntity().getSubsegments()) .hasSize(1) - .allSatisfy(subsegment -> - { + .allSatisfy(subsegment -> { assertThat(subsegment.getName()) .isEqualTo("## testSubSegment"); 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 1d108ed5f..4d2e481b1 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 @@ -18,8 +18,6 @@ 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.when; -import static org.mockito.MockitoAnnotations.openMocks; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; @@ -29,7 +27,6 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junitpioneer.jupiter.SetEnvironmentVariable; -import org.mockito.Mock; import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestHandler; @@ -37,6 +34,7 @@ import com.amazonaws.xray.AWSXRay; import software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor; +import software.amazon.lambda.powertools.common.stubs.TestLambdaContext; import software.amazon.lambda.powertools.tracing.handlers.PowerToolDisabled; import software.amazon.lambda.powertools.tracing.handlers.PowerToolDisabledForStream; import software.amazon.lambda.powertools.tracing.handlers.PowerTracerToolEnabled; @@ -50,7 +48,6 @@ import software.amazon.lambda.powertools.tracing.handlers.PowerTracerToolEnabledWithNoMetaData; import software.amazon.lambda.powertools.tracing.nonhandler.PowerToolNonHandler; - @SetEnvironmentVariable(key = "POWERTOOLS_TRACER_CAPTURE_RESPONSE", value = "false") @SetEnvironmentVariable(key = "POWERTOOLS_TRACER_CAPTURE_ERROR", value = "false") class LambdaTracingAspectTest { @@ -58,14 +55,12 @@ class LambdaTracingAspectTest { private RequestStreamHandler streamHandler; private PowerToolNonHandler nonHandlerMethod; - @Mock private Context context; @BeforeEach void setUp() throws IllegalAccessException { - openMocks(this); writeStaticField(LambdaHandlerProcessor.class, "IS_COLD_START", null, true); - setupContext(); + context = new TestLambdaContext(); requestHandler = new PowerTracerToolEnabled(); streamHandler = new PowerTracerToolEnabledForStream(); nonHandlerMethod = new PowerToolNonHandler(); @@ -86,8 +81,7 @@ void shouldCaptureNonHandlerMethod() { assertThat(AWSXRay.getTraceEntity().getSubsegmentsCopy()) .hasSize(1) - .anySatisfy(segment -> - assertThat(segment.getName()).isEqualTo("## doSomething")); + .anySatisfy(segment -> assertThat(segment.getName()).isEqualTo("## doSomething")); } @Test @@ -99,8 +93,7 @@ void shouldCaptureNonHandlerMethodWithCustomSegmentName() { assertThat(AWSXRay.getTraceEntity().getSubsegmentsCopy()) .hasSize(1) - .anySatisfy(segment -> - assertThat(segment.getName()).isEqualTo("custom")); + .anySatisfy(segment -> assertThat(segment.getName()).isEqualTo("custom")); } @Test @@ -112,15 +105,14 @@ void shouldCaptureTraces() { assertThat(AWSXRay.getTraceEntity().getSubsegmentsCopy()) .hasSize(1) - .allSatisfy(subsegment -> - { + .allSatisfy(subsegment -> { assertThat(subsegment.getAnnotations()) .hasSize(2) .containsEntry("ColdStart", true) .containsEntry("Service", "lambdaHandler"); assertThat(subsegment.getMetadata()) - .hasSize(0); + .isEmpty(); }); } @@ -134,8 +126,7 @@ void shouldCaptureTracesWithResponseMetadata() { assertThat(AWSXRay.getTraceEntity().getSubsegmentsCopy()) .hasSize(1) - .allSatisfy(subsegment -> - { + .allSatisfy(subsegment -> { assertThat(subsegment.getAnnotations()) .hasSize(2) .containsEntry("ColdStart", true) @@ -159,8 +150,7 @@ void shouldCaptureTracesWithExceptionMetaData() { assertThat(AWSXRay.getTraceEntity().getSubsegmentsCopy()) .hasSize(1) - .allSatisfy(subsegment -> - { + .allSatisfy(subsegment -> { assertThat(subsegment.getAnnotations()) .hasSize(2) .containsEntry("ColdStart", true) @@ -185,8 +175,7 @@ void shouldCaptureTracesForStream() throws IOException { assertThat(AWSXRay.getTraceEntity().getSubsegmentsCopy()) .hasSize(1) - .allSatisfy(subsegment -> - { + .allSatisfy(subsegment -> { assertThat(subsegment.getAnnotations()) .hasSize(2) .containsEntry("ColdStart", true) @@ -204,8 +193,7 @@ void shouldCaptureTracesForStreamWithResponseMetadata() throws IOException { assertThat(AWSXRay.getTraceEntity().getSubsegmentsCopy()) .hasSize(1) - .allSatisfy(subsegment -> - { + .allSatisfy(subsegment -> { assertThat(subsegment.getAnnotations()) .hasSize(2) .containsEntry("ColdStart", true) @@ -246,8 +234,7 @@ void shouldCaptureTracesWithNoMetadata() { assertThat(AWSXRay.getTraceEntity().getSubsegmentsCopy()) .hasSize(1) - .allSatisfy(subsegment -> - { + .allSatisfy(subsegment -> { assertThat(subsegment.getAnnotations()) .hasSize(2) .containsEntry("ColdStart", true) @@ -269,8 +256,7 @@ void shouldCaptureTracesForStreamWithNoMetadata() throws IOException { assertThat(AWSXRay.getTraceEntity().getSubsegmentsCopy()) .hasSize(1) - .allSatisfy(subsegment -> - { + .allSatisfy(subsegment -> { assertThat(subsegment.getAnnotations()) .hasSize(2) .containsEntry("ColdStart", true) @@ -291,8 +277,7 @@ void shouldNotCaptureTracesIfDisabledViaEnvironmentVariable() { assertThat(AWSXRay.getTraceEntity().getSubsegmentsCopy()) .hasSize(1) - .allSatisfy(subsegment -> - { + .allSatisfy(subsegment -> { assertThat(subsegment.getAnnotations()) .hasSize(2) .containsEntry("ColdStart", true) @@ -315,8 +300,7 @@ void shouldCaptureTracesIfExplicitlyEnabledAndEnvironmentVariableIsDisabled() { assertThat(AWSXRay.getTraceEntity().getSubsegmentsCopy()) .hasSize(1) - .allSatisfy(subsegment -> - { + .allSatisfy(subsegment -> { assertThat(subsegment.getAnnotations()) .hasSize(2) .containsEntry("ColdStart", true) @@ -339,8 +323,7 @@ void shouldCaptureTracesForSelfReferencingReturnTypesViaCustomMapper() { assertThat(AWSXRay.getTraceEntity().getSubsegmentsCopy()) .hasSize(1) - .allSatisfy(subsegment -> - { + .allSatisfy(subsegment -> { assertThat(subsegment.getMetadata()) .hasSize(1) .containsKey("lambdaHandler"); @@ -368,8 +351,7 @@ void shouldCaptureTracesIfExplicitlyEnabledBothAndEnvironmentVariableIsDisabled( assertThat(AWSXRay.getTraceEntity().getSubsegmentsCopy()) .hasSize(1) - .allSatisfy(subsegment -> - { + .allSatisfy(subsegment -> { assertThat(subsegment.getAnnotations()) .hasSize(2) .containsEntry("ColdStart", true) @@ -396,8 +378,7 @@ void shouldNotCaptureTracesWithExceptionMetaDataIfDisabledViaEnvironmentVariable assertThat(AWSXRay.getTraceEntity().getSubsegmentsCopy()) .hasSize(1) - .allSatisfy(subsegment -> - { + .allSatisfy(subsegment -> { assertThat(subsegment.getAnnotations()) .hasSize(2) .containsEntry("ColdStart", true) @@ -420,8 +401,7 @@ void shouldCaptureTracesWithExceptionMetaDataEnabledExplicitlyAndEnvironmentVari assertThat(AWSXRay.getTraceEntity().getSubsegmentsCopy()) .hasSize(1) - .allSatisfy(subsegment -> - { + .allSatisfy(subsegment -> { assertThat(subsegment.getAnnotations()) .hasSize(2) .containsEntry("ColdStart", true) @@ -437,10 +417,4 @@ void shouldCaptureTracesWithExceptionMetaDataEnabledExplicitlyAndEnvironmentVari }); } - private void setupContext() { - when(context.getFunctionName()).thenReturn("testFunction"); - when(context.getInvokedFunctionArn()).thenReturn("testArn"); - when(context.getFunctionVersion()).thenReturn("1"); - when(context.getMemoryLimitInMB()).thenReturn(10); - } } From 01a6721365deb1da5ef47ea6087df5a151b0a783 Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Fri, 15 Aug 2025 16:00:43 +0200 Subject: [PATCH 14/65] Build project first to make sure test-jar dependencies are available for graalvm unit tests. --- .github/workflows/check-build.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/check-build.yml b/.github/workflows/check-build.yml index 56fd193c1..f5e66fc6c 100644 --- a/.github/workflows/check-build.yml +++ b/.github/workflows/check-build.yml @@ -99,6 +99,9 @@ jobs: - id: graalvm-native-test name: GraalVM Native Test run: | + # Build the entire project first to ensure test-jar dependencies are available + mvn -B install -DskipTests + # Find modules with graalvm-native profile and run tests. # This will make sure to discover new GraalVM supported modules automatically in the future. for module in powertools-*/pom.xml; do From 88236cc59862161fbebfb2fcf6c0cb55a912000a Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Fri, 15 Aug 2025 16:18:03 +0200 Subject: [PATCH 15/65] Enable maven quite mode and search recursively for graalvm profiles to make sure sub-sub-modules are also covered. --- .github/workflows/check-build.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/check-build.yml b/.github/workflows/check-build.yml index f5e66fc6c..f705ee76a 100644 --- a/.github/workflows/check-build.yml +++ b/.github/workflows/check-build.yml @@ -82,7 +82,7 @@ jobs: - id: build-maven name: Build (Maven) run: | - mvn -B install --file pom.xml + mvn -B -q install --file pom.xml graalvm-build: runs-on: ubuntu-latest @@ -100,16 +100,16 @@ jobs: name: GraalVM Native Test run: | # Build the entire project first to ensure test-jar dependencies are available - mvn -B install -DskipTests + mvn -B -q install -DskipTests - # Find modules with graalvm-native profile and run tests. + # Find modules with graalvm-native profile and run tests recursively. # This will make sure to discover new GraalVM supported modules automatically in the future. - for module in powertools-*/pom.xml; do + find . -name "pom.xml" -path "./powertools-*" | while read module; do if grep -q "graalvm-native" "$module"; then module_dir=$(dirname "$module") echo "Regenerating GraalVM metadata for $module_dir" - mvn -B -f "$module" -Pgenerate-graalvm-files clean test + mvn -B -q -f "$module" -Pgenerate-graalvm-files clean test echo "Running GraalVM native tests for $module_dir" - mvn -B -f "$module" -Pgraalvm-native test + mvn -B -q -f "$module" -Pgraalvm-native test fi done From 1d227da308cce94aeea8c36e28bbbcba772a8da8 Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Mon, 18 Aug 2025 10:42:32 +0200 Subject: [PATCH 16/65] Add back Mockito to powertools-common. --- pom.xml | 4 +- powertools-common/pom.xml | 26 ++++-- .../internal/LambdaHandlerProcessorTest.java | 30 ++++--- .../common/stubs/TestInputStream.java | 24 ----- .../common/stubs/TestOutputStream.java | 23 ----- .../common/stubs/TestProceedingJoinPoint.java | 90 ------------------- .../common/stubs/TestSignature.java | 55 ------------ 7 files changed, 41 insertions(+), 211 deletions(-) delete mode 100644 powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestInputStream.java delete mode 100644 powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestOutputStream.java delete mode 100644 powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestProceedingJoinPoint.java delete mode 100644 powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestSignature.java diff --git a/pom.xml b/pom.xml index c2a792d91..59c5eb2e5 100644 --- a/pom.xml +++ b/pom.xml @@ -113,8 +113,8 @@ 1.12.781 2.18.0 1.7.0 - 5.19.0 - 5.19.0 + 5.19.1-SNAPSHOT + 5.19.1-SNAPSHOT 2.3.0 1.5.0 diff --git a/powertools-common/pom.xml b/powertools-common/pom.xml index bca268359..c19b79c08 100644 --- a/powertools-common/pom.xml +++ b/powertools-common/pom.xml @@ -81,10 +81,22 @@ slf4j-simple test + + org.mockito + mockito-core + test + generate-graalvm-files + + + org.mockito + mockito-subclass + test + + @@ -104,6 +116,13 @@ graalvm-native + + + org.mockito + mockito-subclass + test + + @@ -126,16 +145,11 @@ --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED --no-fallback - -Dorg.graalvm.nativeimage.imagecode=agent - --initialize-at-build-time=org.slf4j.simple.SimpleLogger - --initialize-at-build-time=org.slf4j.LoggerFactory - --initialize-at-build-time=org.junit.Ignore - --initialize-at-build-time=java.lang.annotation.Annotation - --initialize-at-build-time=org.junit.runners.model.FrameworkField --verbose --native-image-info -H:+UnlockExperimentalVMOptions -H:Log=registerResource:5 + -H:+ReportExceptionStackTraces diff --git a/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/LambdaHandlerProcessorTest.java b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/LambdaHandlerProcessorTest.java index 11eac7a4c..17732cdf0 100644 --- a/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/LambdaHandlerProcessorTest.java +++ b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/LambdaHandlerProcessorTest.java @@ -16,10 +16,15 @@ 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.when; +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.junitpioneer.jupiter.ClearEnvironmentVariable; import org.junitpioneer.jupiter.SetEnvironmentVariable; @@ -29,10 +34,6 @@ import com.amazonaws.services.lambda.runtime.RequestStreamHandler; import software.amazon.lambda.powertools.common.stubs.TestLambdaContext; -import software.amazon.lambda.powertools.common.stubs.TestInputStream; -import software.amazon.lambda.powertools.common.stubs.TestOutputStream; -import software.amazon.lambda.powertools.common.stubs.TestProceedingJoinPoint; -import software.amazon.lambda.powertools.common.stubs.TestSignature; class LambdaHandlerProcessorTest { @@ -47,7 +48,7 @@ void isHandlerMethod_shouldRecognizeRequestHandler() { @Test void isHandlerMethod_shouldRecognizeRequestStreamHandler() { - Object[] args = { new TestInputStream(), new TestOutputStream(), new TestLambdaContext() }; + Object[] args = { mock(InputStream.class), mock(OutputStream.class), new TestLambdaContext() }; ProceedingJoinPoint pjpMock = mockRequestHandlerPjp(RequestStreamHandler.class, args); assertThat(LambdaHandlerProcessor.isHandlerMethod(pjpMock)).isTrue(); @@ -72,7 +73,7 @@ void placedOnRequestHandler_shouldRecognizeRequestHandler() { @Test void placedOnStreamHandler_shouldRecognizeRequestStreamHandler() { - Object[] args = { new TestInputStream(), new TestOutputStream(), new TestLambdaContext() }; + Object[] args = { mock(InputStream.class), mock(OutputStream.class), new TestLambdaContext() }; ProceedingJoinPoint pjpMock = mockRequestHandlerPjp(RequestStreamHandler.class, args); assertThat(LambdaHandlerProcessor.placedOnStreamHandler(pjpMock)).isTrue(); @@ -120,7 +121,7 @@ void placedOnStreamHandler_shouldInvalidateOnWrongTypeOfArgs() { @Test void placedOnStreamHandler_shouldInvalidateOnTypeOfArgs_invalidOutputStreamArg() { - Object[] args = { new TestInputStream(), new Object(), new TestLambdaContext() }; + Object[] args = { mock(InputStream.class), new Object(), new TestLambdaContext() }; ProceedingJoinPoint pjpMock = mockRequestHandlerPjp(RequestStreamHandler.class, args); boolean isPlacedOnStreamHandler = LambdaHandlerProcessor.placedOnStreamHandler(pjpMock); @@ -130,7 +131,7 @@ void placedOnStreamHandler_shouldInvalidateOnTypeOfArgs_invalidOutputStreamArg() @Test void placedOnStreamHandler_shouldInvalidateOnTypeOfArgs_invalidContextArg() { - Object[] args = { new TestInputStream(), new TestOutputStream(), new Object() }; + Object[] args = { mock(InputStream.class), mock(OutputStream.class), new Object() }; ProceedingJoinPoint pjpMock = mockRequestHandlerPjp(RequestStreamHandler.class, args); boolean isPlacedOnStreamHandler = LambdaHandlerProcessor.placedOnStreamHandler(pjpMock); @@ -170,7 +171,7 @@ void extractContext_fromRequestHandler() { @Test void extractContext_fromStreamRequestHandler() { - Object[] args = { new TestInputStream(), new TestOutputStream(), new TestLambdaContext() }; + Object[] args = { mock(InputStream.class), mock(OutputStream.class), new TestLambdaContext() }; ProceedingJoinPoint pjpMock = mockRequestHandlerPjp(RequestStreamHandler.class, args); Context context = LambdaHandlerProcessor.extractContext(pjpMock); @@ -230,7 +231,14 @@ void serviceName_Undefined() { } private ProceedingJoinPoint mockRequestHandlerPjp(Class handlerClass, Object[] handlerArgs) { - TestSignature signature = new TestSignature(handlerClass); - return new TestProceedingJoinPoint(signature, handlerArgs); + ProceedingJoinPoint pjp = mock(ProceedingJoinPoint.class); + Signature signature = mock(Signature.class); + + when(signature.getDeclaringType()).thenReturn(handlerClass); + when(signature.getName()).thenReturn("handleRequest"); + when(pjp.getSignature()).thenReturn(signature); + when(pjp.getArgs()).thenReturn(handlerArgs); + + return pjp; } } diff --git a/powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestInputStream.java b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestInputStream.java deleted file mode 100644 index cb9122966..000000000 --- a/powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestInputStream.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * 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.common.stubs; - -import java.io.InputStream; - -public class TestInputStream extends InputStream { - @Override - public int read() { - return -1; - } -} diff --git a/powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestOutputStream.java b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestOutputStream.java deleted file mode 100644 index b64b4759d..000000000 --- a/powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestOutputStream.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * 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.common.stubs; - -import java.io.OutputStream; - -public class TestOutputStream extends OutputStream { - @Override - public void write(int b) { - } -} diff --git a/powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestProceedingJoinPoint.java b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestProceedingJoinPoint.java deleted file mode 100644 index e0285518c..000000000 --- a/powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestProceedingJoinPoint.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * 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.common.stubs; - -import org.aspectj.lang.ProceedingJoinPoint; -import org.aspectj.lang.Signature; -import org.aspectj.lang.reflect.SourceLocation; -import org.aspectj.runtime.internal.AroundClosure; - -public class TestProceedingJoinPoint implements ProceedingJoinPoint { - private final Signature signature; - private final Object[] args; - - public TestProceedingJoinPoint(Signature signature, Object[] args) { - this.signature = signature; - this.args = args; - } - - @Override - public Object[] getArgs() { - return args; - } - - @Override - public Signature getSignature() { - return signature; - } - - @Override - public Object getTarget() { - return null; - } - - @Override - public Object getThis() { - return null; - } - - @Override - public StaticPart getStaticPart() { - return null; - } - - @Override - public String getKind() { - return null; - } - - @Override - public SourceLocation getSourceLocation() { - return null; - } - - @Override - public Object proceed() { - return null; - } - - @Override - public Object proceed(Object[] args) { - return null; - } - - @Override - public void set$AroundClosure(AroundClosure arc) { - // Stubbed method - } - - @Override - public String toLongString() { - return "handleRequest"; - } - - @Override - public String toShortString() { - return "handleRequest"; - } -} diff --git a/powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestSignature.java b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestSignature.java deleted file mode 100644 index 903e4c8fa..000000000 --- a/powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestSignature.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * 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.common.stubs; - -import org.aspectj.lang.Signature; - -public class TestSignature implements Signature { - private final Class declaringType; - - public TestSignature(Class declaringType) { - this.declaringType = declaringType; - } - - @Override - public Class getDeclaringType() { - return declaringType; - } - - @Override - public String getDeclaringTypeName() { - return declaringType.getName(); - } - - @Override - public int getModifiers() { - return 0; - } - - @Override - public String getName() { - return "handleRequest"; - } - - @Override - public String toLongString() { - return "handleRequest"; - } - - @Override - public String toShortString() { - return "handleRequest"; - } -} From e470317d8da6ebfbdcb3982358dbd1fca5cb262a Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Mon, 18 Aug 2025 10:57:29 +0200 Subject: [PATCH 17/65] Simplify graalvm config for logback and log4j modules. --- powertools-common/pom.xml | 3 ++- .../powertools-logging-log4j/pom.xml | 22 +++++++++---------- .../powertools-logging-logback/pom.xml | 20 ++++++++--------- 3 files changed, 23 insertions(+), 22 deletions(-) diff --git a/powertools-common/pom.xml b/powertools-common/pom.xml index c19b79c08..390a4bf02 100644 --- a/powertools-common/pom.xml +++ b/powertools-common/pom.xml @@ -104,7 +104,8 @@ maven-surefire-plugin 3.5.3 - -Dorg.graalvm.nativeimage.imagecode=agent + + -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-common,experimental-class-define-support --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED diff --git a/powertools-logging/powertools-logging-log4j/pom.xml b/powertools-logging/powertools-logging-log4j/pom.xml index e71f07782..ad0c3c373 100644 --- a/powertools-logging/powertools-logging-log4j/pom.xml +++ b/powertools-logging/powertools-logging-log4j/pom.xml @@ -109,7 +109,8 @@ maven-surefire-plugin 3.5.3 - -Dorg.graalvm.nativeimage.imagecode=agent + + -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-log4j,experimental-class-define-support --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED @@ -126,7 +127,7 @@ org.graalvm.buildtools native-maven-plugin - 0.11.0 + 0.11.0 true @@ -140,18 +141,17 @@ powertools-logging-log4j - --add-opens java.base/java.util=ALL-UNNAMED - --add-opens java.base/java.lang=ALL-UNNAMED - --no-fallback - -Dorg.graalvm.nativeimage.imagecode=agent - --initialize-at-build-time=org.slf4j.simple.SimpleLogger - --initialize-at-build-time=org.slf4j.LoggerFactory - --initialize-at-build-time=org.junit.Ignore - --initialize-at-build-time=java.lang.annotation.Annotation - --initialize-at-build-time=org.junit.runners.model.FrameworkField --initialize-at-build-time=org.junit.platform.launcher.core.DiscoveryIssueNotifier$1 + --add-opens java.base/java.util=ALL-UNNAMED + --add-opens java.base/java.lang=ALL-UNNAMED + --no-fallback + --verbose + --native-image-info + -H:+UnlockExperimentalVMOptions + -H:Log=registerResource:5 + -H:+ReportExceptionStackTraces diff --git a/powertools-logging/powertools-logging-logback/pom.xml b/powertools-logging/powertools-logging-logback/pom.xml index 2938e9153..0175e219e 100644 --- a/powertools-logging/powertools-logging-logback/pom.xml +++ b/powertools-logging/powertools-logging-logback/pom.xml @@ -97,7 +97,8 @@ maven-surefire-plugin 3.5.3 - -Dorg.graalvm.nativeimage.imagecode=agent + + -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback,experimental-class-define-support --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED @@ -128,18 +129,17 @@ powertools-logging-logback - --add-opens java.base/java.util=ALL-UNNAMED - --add-opens java.base/java.lang=ALL-UNNAMED - --no-fallback - -Dorg.graalvm.nativeimage.imagecode=agent - --initialize-at-build-time=org.slf4j.simple.SimpleLogger - --initialize-at-build-time=org.slf4j.LoggerFactory - --initialize-at-build-time=org.junit.Ignore - --initialize-at-build-time=java.lang.annotation.Annotation - --initialize-at-build-time=org.junit.runners.model.FrameworkField --initialize-at-build-time=org.junit.platform.launcher.core.DiscoveryIssueNotifier$1 + --add-opens java.base/java.util=ALL-UNNAMED + --add-opens java.base/java.lang=ALL-UNNAMED + --no-fallback + --verbose + --native-image-info + -H:+UnlockExperimentalVMOptions + -H:Log=registerResource:5 + -H:+ReportExceptionStackTraces From d78677b55d3cb39c2ee7c6be4475e9663bd618c0 Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Mon, 18 Aug 2025 11:01:51 +0200 Subject: [PATCH 18/65] Simplify graalvm config in powertools-logging. --- powertools-logging/pom.xml | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/powertools-logging/pom.xml b/powertools-logging/pom.xml index aa4c92555..4312ffbf6 100644 --- a/powertools-logging/pom.xml +++ b/powertools-logging/pom.xml @@ -125,7 +125,8 @@ maven-surefire-plugin 3.5.3 - -Dorg.graalvm.nativeimage.imagecode=agent + + -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging,experimental-class-define-support --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED @@ -159,13 +160,11 @@ --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED --no-fallback - -Dorg.graalvm.nativeimage.imagecode=agent - --initialize-at-build-time=org.slf4j.simple.SimpleLogger - --initialize-at-build-time=org.slf4j.LoggerFactory - --initialize-at-build-time=org.junit.Ignore - --initialize-at-build-time=java.lang.annotation.Annotation - --initialize-at-build-time=org.junit.runners.model.FrameworkField --verbose + --native-image-info + -H:+UnlockExperimentalVMOptions + -H:Log=registerResource:5 + -H:+ReportExceptionStackTraces From 572f2bf00de6b43ccbd0b1c65965ffe5206397e0 Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Mon, 18 Aug 2025 11:09:54 +0200 Subject: [PATCH 19/65] Cleanup GRM files for logback module. --- .../predefined-classes-config.json | 8 ---- .../proxy-config.json | 2 - .../reflect-config.json | 37 ------------------- .../resource-config.json | 24 ------------ .../serialization-config.json | 11 ------ 5 files changed, 82 deletions(-) delete mode 100644 powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/predefined-classes-config.json delete mode 100644 powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/proxy-config.json delete mode 100644 powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/serialization-config.json diff --git a/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/predefined-classes-config.json b/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/predefined-classes-config.json deleted file mode 100644 index 0e79b2c5d..000000000 --- a/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/predefined-classes-config.json +++ /dev/null @@ -1,8 +0,0 @@ -[ - { - "type":"agent-extracted", - "classes":[ - ] - } -] - diff --git a/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/proxy-config.json b/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/proxy-config.json deleted file mode 100644 index 0d4f101c7..000000000 --- a/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/proxy-config.json +++ /dev/null @@ -1,2 +0,0 @@ -[ -] diff --git a/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/reflect-config.json b/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/reflect-config.json index efd81020e..683933a77 100644 --- a/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/reflect-config.json +++ b/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/reflect-config.json @@ -1,10 +1,4 @@ [ -{ - "name":"[Ljava.lang.Object;" -}, -{ - "name":"[Ljava.lang.String;" -}, { "name":"ch.qos.logback.classic.joran.SerializedModelConfigurator", "methods":[{"name":"","parameterTypes":[] }] @@ -132,41 +126,10 @@ { "name":"kotlin.Metadata" }, -{ - "name":"org.apache.maven.surefire.junitplatform.JUnitPlatformProvider", - "methods":[{"name":"","parameterTypes":["org.apache.maven.surefire.api.provider.ProviderParameters"] }] -}, { "name":"org.apiguardian.api.API", "queryAllPublicMethods":true }, -{ - "name":"org.junit.internal.AssumptionViolatedException" -}, -{ - "name":"org.junit.jupiter.api.ClassOrderer$OrderAnnotation", - "methods":[{"name":"","parameterTypes":[] }] -}, -{ - "name":"org.junit.jupiter.api.Order", - "queryAllPublicMethods":true -}, -{ - "name":"org.junit.jupiter.api.Test", - "queryAllPublicMethods":true -}, -{ - "name":"org.junit.platform.commons.annotation.Testable", - "queryAllPublicMethods":true -}, -{ - "name":"org.junit.platform.launcher.LauncherSession", - "methods":[{"name":"getLauncher","parameterTypes":[] }] -}, -{ - "name":"org.junit.platform.launcher.core.LauncherFactory", - "methods":[{"name":"openSession","parameterTypes":[] }] -}, { "name":"software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor", "fields":[{"name":"IS_COLD_START"}] diff --git a/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/resource-config.json b/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/resource-config.json index 551635098..2fc3c56bd 100644 --- a/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/resource-config.json +++ b/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/resource-config.json @@ -8,34 +8,10 @@ "pattern":"\\QMETA-INF/services/java.time.zone.ZoneRulesProvider\\E" }, { "pattern":"\\QMETA-INF/services/javax.xml.parsers.SAXParserFactory\\E" - }, { - "pattern":"\\QMETA-INF/services/org.apache.maven.surefire.spi.MasterProcessChannelProcessorFactory\\E" - }, { - "pattern":"\\QMETA-INF/services/org.assertj.core.configuration.Configuration\\E" - }, { - "pattern":"\\QMETA-INF/services/org.assertj.core.presentation.Representation\\E" - }, { - "pattern":"\\QMETA-INF/services/org.junit.platform.commons.support.scanning.ClasspathScanner\\E" - }, { - "pattern":"\\QMETA-INF/services/org.junit.platform.engine.TestEngine\\E" - }, { - "pattern":"\\QMETA-INF/services/org.junit.platform.launcher.LauncherDiscoveryListener\\E" - }, { - "pattern":"\\QMETA-INF/services/org.junit.platform.launcher.LauncherSessionListener\\E" - }, { - "pattern":"\\QMETA-INF/services/org.junit.platform.launcher.PostDiscoveryFilter\\E" - }, { - "pattern":"\\QMETA-INF/services/org.junit.platform.launcher.TestExecutionListener\\E" }, { "pattern":"\\QMETA-INF/services/org.slf4j.spi.SLF4JServiceProvider\\E" }, { "pattern":"\\QMETA-INF/services/software.amazon.lambda.powertools.logging.internal.LoggingManager\\E" - }, { - "pattern":"\\Qjunit-platform.properties\\E" - }, { - "pattern":"\\Qlogback-test.scmo\\E" - }, { - "pattern":"\\Qlogback-test.xml\\E" }, { "pattern":"\\Qlogback.scmo\\E" }]}, diff --git a/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/serialization-config.json b/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/serialization-config.json deleted file mode 100644 index fc967f7f8..000000000 --- a/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/serialization-config.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "types":[ - { - "name":"org.junit.platform.launcher.TestIdentifier$SerializedForm" - } - ], - "lambdaCapturingTypes":[ - ], - "proxies":[ - ] -} From cbf933098751ed68fc1ff14e37fbe5e48adacae9 Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Mon, 18 Aug 2025 11:34:51 +0200 Subject: [PATCH 20/65] Simplify GraalVM config for powertools-metrics, powertools-serialization, powertools-tracing. --- powertools-metrics/pom.xml | 16 ++++++++-------- powertools-serialization/pom.xml | 16 ++++++---------- powertools-tracing/pom.xml | 12 +++--------- 3 files changed, 17 insertions(+), 27 deletions(-) diff --git a/powertools-metrics/pom.xml b/powertools-metrics/pom.xml index d7aefb1e5..f2ec7dbc9 100644 --- a/powertools-metrics/pom.xml +++ b/powertools-metrics/pom.xml @@ -128,7 +128,8 @@ org.apache.maven.plugins maven-surefire-plugin - -Xlog:class+load=info:classesloaded.txt + + -Xlog:class+load=info:classesloaded.txt --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED @@ -145,7 +146,8 @@ org.apache.maven.plugins maven-surefire-plugin - -Dorg.graalvm.nativeimage.imagecode=agent + + -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-metrics,experimental-class-define-support --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED @@ -179,13 +181,11 @@ --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED --no-fallback - -Dorg.graalvm.nativeimage.imagecode=agent - --initialize-at-build-time=org.slf4j.simple.SimpleLogger - --initialize-at-build-time=org.slf4j.LoggerFactory - --initialize-at-build-time=org.junit.Ignore - --initialize-at-build-time=java.lang.annotation.Annotation - --initialize-at-build-time=org.junit.runners.model.FrameworkField --verbose + --native-image-info + -H:+UnlockExperimentalVMOptions + -H:Log=registerResource:5 + -H:+ReportExceptionStackTraces diff --git a/powertools-serialization/pom.xml b/powertools-serialization/pom.xml index 46f57d040..a7e5bf6c9 100644 --- a/powertools-serialization/pom.xml +++ b/powertools-serialization/pom.xml @@ -132,20 +132,16 @@ - - true - Standard - powertools-serialization + --add-opens java.base/java.util=ALL-UNNAMED + --add-opens java.base/java.lang=ALL-UNNAMED --no-fallback - -Dorg.graalvm.nativeimage.imagecode=agent - --initialize-at-build-time=org.slf4j.simple.SimpleLogger - --initialize-at-build-time=org.slf4j.LoggerFactory - --initialize-at-build-time=org.junit.Ignore - --initialize-at-build-time=java.lang.annotation.Annotation - --initialize-at-build-time=org.junit.runners.model.FrameworkField --verbose + --native-image-info + -H:+UnlockExperimentalVMOptions + -H:Log=registerResource:5 + -H:+ReportExceptionStackTraces diff --git a/powertools-tracing/pom.xml b/powertools-tracing/pom.xml index 421028c29..fb3a5153e 100644 --- a/powertools-tracing/pom.xml +++ b/powertools-tracing/pom.xml @@ -130,7 +130,8 @@ maven-surefire-plugin 3.5.3 - -Dorg.graalvm.nativeimage.imagecode=agent + + -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-tracing,experimental-class-define-support --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED @@ -165,18 +166,11 @@ --add-opens java.base/java.lang=ALL-UNNAMED --enable-url-protocols=http --no-fallback - -Dorg.graalvm.nativeimage.imagecode=agent - -H:IncludeResources=version.properties - -H:IncludeResources=unreadable.properties - --initialize-at-build-time=org.slf4j.simple.SimpleLogger - --initialize-at-build-time=org.slf4j.LoggerFactory - --initialize-at-build-time=org.junit.Ignore - --initialize-at-build-time=java.lang.annotation.Annotation - --initialize-at-build-time=org.junit.runners.model.FrameworkField --verbose --native-image-info -H:+UnlockExperimentalVMOptions -H:Log=registerResource:5 + -H:+ReportExceptionStackTraces From c238eeb537ca6a101811b932cff1f08de94c9dbf Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Mon, 18 Aug 2025 11:39:53 +0200 Subject: [PATCH 21/65] Remove comment. --- powertools-common/pom.xml | 2 +- .../powertools-logging-logback/pom.xml | 2 +- powertools-parameters/pom.xml | 50 +++---------------- .../powertools-parameters-appconfig/pom.xml | 2 +- .../powertools-parameters-dynamodb/pom.xml | 2 +- .../powertools-parameters-secrets/pom.xml | 2 +- .../powertools-parameters-ssm/pom.xml | 2 +- .../powertools-parameters-tests/pom.xml | 2 +- powertools-serialization/pom.xml | 2 +- powertools-tracing/pom.xml | 2 +- 10 files changed, 17 insertions(+), 51 deletions(-) diff --git a/powertools-common/pom.xml b/powertools-common/pom.xml index 390a4bf02..8a9d06460 100644 --- a/powertools-common/pom.xml +++ b/powertools-common/pom.xml @@ -129,7 +129,7 @@ org.graalvm.buildtools native-maven-plugin - 0.11.0 + 0.11.0 true diff --git a/powertools-logging/powertools-logging-logback/pom.xml b/powertools-logging/powertools-logging-logback/pom.xml index 0175e219e..9f0b36dad 100644 --- a/powertools-logging/powertools-logging-logback/pom.xml +++ b/powertools-logging/powertools-logging-logback/pom.xml @@ -115,7 +115,7 @@ org.graalvm.buildtools native-maven-plugin - 0.11.0 + 0.11.0 true diff --git a/powertools-parameters/pom.xml b/powertools-parameters/pom.xml index fec1b8efa..7e28ad556 100644 --- a/powertools-parameters/pom.xml +++ b/powertools-parameters/pom.xml @@ -14,8 +14,8 @@ --> + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 @@ -43,11 +43,11 @@ software.amazon.awssdk url-connection-client - com.fasterxml.jackson.core jackson-databind + org.junit.jupiter @@ -93,13 +93,6 @@ generate-graalvm-files - - - org.mockito - mockito-subclass - test - - @@ -107,7 +100,9 @@ maven-surefire-plugin 3.5.3 - -Dmockito.mock.maker=subclass -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters,experimental-class-define-support + + -Dorg.graalvm.nativeimage.imagecode=agent + -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters,experimental-class-define-support --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED @@ -118,19 +113,12 @@ graalvm-native - - - org.mockito - mockito-subclass - test - - org.graalvm.buildtools native-maven-plugin - 0.11.0 + 0.11.0 true @@ -147,33 +135,11 @@ --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED --no-fallback - -Dorg.graalvm.nativeimage.imagecode=agent - -H:ClassInitialization=net.bytebuddy.ClassFileVersion:rerun - -H:ClassInitialization=net.bytebuddy.utility.dispatcher.JavaDispatcher:rerun - -H:ClassInitialization=net.bytebuddy.utility.Invoker$Dispatcher:rerun - -H:ClassInitialization=net.bytebuddy.utility.GraalImageCode:rerun - --initialize-at-build-time=org.slf4j.simple.SimpleLogger - --initialize-at-build-time=org.slf4j.LoggerFactory - --initialize-at-build-time=org.junit.Ignore - --initialize-at-build-time=java.lang.annotation.Annotation - --initialize-at-build-time=org.junit.runners.model.FrameworkField - --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase - --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic - --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$1 - --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$2 - --initialize-at-build-time=net.bytebuddy.utility.dispatcher.JavaDispatcher$DynamicClassLoader - --initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable - --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase - --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$ForLoadedType - --initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$ForLoadedMethod - --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Super$Instantiation$2 - - --trace-class-initialization=net.bytebuddy.description.type.TypeDescription$ForLoadedType,net.bytebuddy.description.method.MethodDescription$ForLoadedMethod,net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable - --verbose --native-image-info -H:+UnlockExperimentalVMOptions -H:Log=registerResource:5 + -H:+ReportExceptionStackTraces diff --git a/powertools-parameters/powertools-parameters-appconfig/pom.xml b/powertools-parameters/powertools-parameters-appconfig/pom.xml index 0a83d36e2..cc36b5438 100644 --- a/powertools-parameters/powertools-parameters-appconfig/pom.xml +++ b/powertools-parameters/powertools-parameters-appconfig/pom.xml @@ -119,7 +119,7 @@ org.graalvm.buildtools native-maven-plugin - 0.11.0 + 0.11.0 true diff --git a/powertools-parameters/powertools-parameters-dynamodb/pom.xml b/powertools-parameters/powertools-parameters-dynamodb/pom.xml index 9ffca4ad8..436068346 100644 --- a/powertools-parameters/powertools-parameters-dynamodb/pom.xml +++ b/powertools-parameters/powertools-parameters-dynamodb/pom.xml @@ -120,7 +120,7 @@ org.graalvm.buildtools native-maven-plugin - 0.11.0 + 0.11.0 true diff --git a/powertools-parameters/powertools-parameters-secrets/pom.xml b/powertools-parameters/powertools-parameters-secrets/pom.xml index 9b6696900..cfbc38fa5 100644 --- a/powertools-parameters/powertools-parameters-secrets/pom.xml +++ b/powertools-parameters/powertools-parameters-secrets/pom.xml @@ -120,7 +120,7 @@ org.graalvm.buildtools native-maven-plugin - 0.11.0 + 0.11.0 true diff --git a/powertools-parameters/powertools-parameters-ssm/pom.xml b/powertools-parameters/powertools-parameters-ssm/pom.xml index 52b51c1d9..c81dfd67a 100644 --- a/powertools-parameters/powertools-parameters-ssm/pom.xml +++ b/powertools-parameters/powertools-parameters-ssm/pom.xml @@ -134,7 +134,7 @@ org.graalvm.buildtools native-maven-plugin - 0.11.0 + 0.11.0 true diff --git a/powertools-parameters/powertools-parameters-tests/pom.xml b/powertools-parameters/powertools-parameters-tests/pom.xml index f09d79ac9..efde979b5 100644 --- a/powertools-parameters/powertools-parameters-tests/pom.xml +++ b/powertools-parameters/powertools-parameters-tests/pom.xml @@ -130,7 +130,7 @@ org.graalvm.buildtools native-maven-plugin - 0.11.0 + 0.11.0 true diff --git a/powertools-serialization/pom.xml b/powertools-serialization/pom.xml index a7e5bf6c9..911f47850 100644 --- a/powertools-serialization/pom.xml +++ b/powertools-serialization/pom.xml @@ -120,7 +120,7 @@ org.graalvm.buildtools native-maven-plugin - 0.11.0 + 0.11.0 true diff --git a/powertools-tracing/pom.xml b/powertools-tracing/pom.xml index fb3a5153e..b6cac28aa 100644 --- a/powertools-tracing/pom.xml +++ b/powertools-tracing/pom.xml @@ -148,7 +148,7 @@ org.graalvm.buildtools native-maven-plugin - 0.11.0 + 0.11.0 true From 3304fa3d75ed553cb561fc83949681566f754d6a Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Mon, 18 Aug 2025 12:05:47 +0200 Subject: [PATCH 22/65] Simplify powertools-parameters-tests GraalVM config and fix issues in unit tests. --- .../powertools-parameters-tests/pom.xml | 44 ++++++++----------- .../parameters/BaseProviderTest.java | 10 ++--- .../ParamProvidersIntegrationTest.java | 17 +++---- 3 files changed, 31 insertions(+), 40 deletions(-) diff --git a/powertools-parameters/powertools-parameters-tests/pom.xml b/powertools-parameters/powertools-parameters-tests/pom.xml index efde979b5..5db059123 100644 --- a/powertools-parameters/powertools-parameters-tests/pom.xml +++ b/powertools-parameters/powertools-parameters-tests/pom.xml @@ -1,7 +1,7 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 software.amazon.lambda @@ -50,6 +50,11 @@ mockito-core test + + org.mockito + mockito-junit-jupiter + test + org.slf4j slf4j-simple @@ -107,7 +112,9 @@ maven-surefire-plugin 3.5.3 - -Dmockito.mock.maker=subclass -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters,experimental-class-define-support + + -Dorg.graalvm.nativeimage.imagecode=agent + -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters,experimental-class-define-support --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED @@ -124,6 +131,13 @@ mockito-subclass test + + + + org.junit.jupiter + junit-jupiter-params + test + @@ -147,33 +161,11 @@ --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED --no-fallback - -Dorg.graalvm.nativeimage.imagecode=agent - -H:ClassInitialization=net.bytebuddy.ClassFileVersion:rerun - -H:ClassInitialization=net.bytebuddy.utility.dispatcher.JavaDispatcher:rerun - -H:ClassInitialization=net.bytebuddy.utility.Invoker$Dispatcher:rerun - -H:ClassInitialization=net.bytebuddy.utility.GraalImageCode:rerun - --initialize-at-build-time=org.slf4j.simple.SimpleLogger - --initialize-at-build-time=org.slf4j.LoggerFactory - --initialize-at-build-time=org.junit.Ignore - --initialize-at-build-time=java.lang.annotation.Annotation - --initialize-at-build-time=org.junit.runners.model.FrameworkField - --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase - --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic - --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$1 - --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$2 - --initialize-at-build-time=net.bytebuddy.utility.dispatcher.JavaDispatcher$DynamicClassLoader - --initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable - --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase - --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$ForLoadedType - --initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$ForLoadedMethod - --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Super$Instantiation$2 - - --trace-class-initialization=net.bytebuddy.description.type.TypeDescription$ForLoadedType,net.bytebuddy.description.method.MethodDescription$ForLoadedMethod,net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable - --verbose --native-image-info -H:+UnlockExperimentalVMOptions -H:Log=registerResource:5 + -H:+ReportExceptionStackTraces diff --git a/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/BaseProviderTest.java b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/BaseProviderTest.java index 5fa740253..cbc8f5b30 100644 --- a/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/BaseProviderTest.java +++ b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/BaseProviderTest.java @@ -20,7 +20,6 @@ import static java.time.temporal.ChronoUnit.SECONDS; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatIllegalStateException; -import static org.mockito.MockitoAnnotations.openMocks; import static software.amazon.lambda.powertools.parameters.transform.Transformer.base64; import static software.amazon.lambda.powertools.parameters.transform.Transformer.json; @@ -30,8 +29,10 @@ 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; @@ -43,13 +44,10 @@ public class BaseProviderTest { CacheManager cacheManager; TransformationManager transformationManager; BasicProvider provider; - boolean getFromStore = false; @BeforeEach public void setup() { - openMocks(this); - clock = Clock.systemDefaultZone(); cacheManager = new CacheManager(); transformationManager = new TransformationManager(); @@ -197,8 +195,8 @@ 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") diff --git a/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/ParamProvidersIntegrationTest.java b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/ParamProvidersIntegrationTest.java index 7d790d140..6b3cf7641 100644 --- a/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/ParamProvidersIntegrationTest.java +++ b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/ParamProvidersIntegrationTest.java @@ -19,17 +19,19 @@ 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 org.assertj.core.data.MapEntry; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.ArgumentCaptor; import org.mockito.Captor; import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + import software.amazon.awssdk.services.dynamodb.DynamoDbClient; import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient; import software.amazon.awssdk.services.secretsmanager.model.GetSecretValueRequest; @@ -43,27 +45,26 @@ import software.amazon.lambda.powertools.parameters.secrets.SecretsProvider; import software.amazon.lambda.powertools.parameters.ssm.SSMProvider; +@ExtendWith(MockitoExtension.class) public class ParamProvidersIntegrationTest { - @Mock SsmClient ssmClient; @Mock DynamoDbClient ddbClient; + @Captor ArgumentCaptor ssmParamCaptor; + @Captor ArgumentCaptor ssmParamByPathCaptor; + @Mock SecretsManagerClient secretsManagerClient; + @Captor ArgumentCaptor secretsCaptor; - @BeforeEach - public void setup() throws IllegalAccessException { - openMocks(this); - } - @Test public void ssmProvider_get() { SSMProvider ssmProvider = SSMProvider.builder() From 08b0642b467cef7e50a98847a5728392c9bae16c Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Mon, 18 Aug 2025 12:24:32 +0200 Subject: [PATCH 23/65] Simplify powertools-parameters-ssm GraalVM config and fix issues in unit tests. --- .../powertools-parameters-ssm/pom.xml | 44 ++++++++----------- 1 file changed, 18 insertions(+), 26 deletions(-) diff --git a/powertools-parameters/powertools-parameters-ssm/pom.xml b/powertools-parameters/powertools-parameters-ssm/pom.xml index c81dfd67a..a418d3f09 100644 --- a/powertools-parameters/powertools-parameters-ssm/pom.xml +++ b/powertools-parameters/powertools-parameters-ssm/pom.xml @@ -1,7 +1,7 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 @@ -58,6 +58,11 @@ mockito-core test + + org.mockito + mockito-junit-jupiter + test + org.slf4j slf4j-simple @@ -111,7 +116,9 @@ maven-surefire-plugin 3.5.3 - -Dmockito.mock.maker=subclass -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-ssm,experimental-class-define-support + + -Dorg.graalvm.nativeimage.imagecode=agent + -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-ssm,experimental-class-define-support --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED @@ -128,6 +135,13 @@ mockito-subclass test + + + + org.junit.jupiter + junit-jupiter-params + test + @@ -151,33 +165,11 @@ --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED --no-fallback - -Dorg.graalvm.nativeimage.imagecode=agent - -H:ClassInitialization=net.bytebuddy.ClassFileVersion:rerun - -H:ClassInitialization=net.bytebuddy.utility.dispatcher.JavaDispatcher:rerun - -H:ClassInitialization=net.bytebuddy.utility.Invoker$Dispatcher:rerun - -H:ClassInitialization=net.bytebuddy.utility.GraalImageCode:rerun - --initialize-at-build-time=org.slf4j.simple.SimpleLogger - --initialize-at-build-time=org.slf4j.LoggerFactory - --initialize-at-build-time=org.junit.Ignore - --initialize-at-build-time=java.lang.annotation.Annotation - --initialize-at-build-time=org.junit.runners.model.FrameworkField - --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase - --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic - --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$1 - --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$2 - --initialize-at-build-time=net.bytebuddy.utility.dispatcher.JavaDispatcher$DynamicClassLoader - --initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable - --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase - --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$ForLoadedType - --initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$ForLoadedMethod - --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Super$Instantiation$2 - - --trace-class-initialization=net.bytebuddy.description.type.TypeDescription$ForLoadedType,net.bytebuddy.description.method.MethodDescription$ForLoadedMethod,net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable - --verbose --native-image-info -H:+UnlockExperimentalVMOptions -H:Log=registerResource:5 + -H:+ReportExceptionStackTraces From c7bb6ec9de654b389ad5c6d9532b6b109faa6812 Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Mon, 18 Aug 2025 12:35:26 +0200 Subject: [PATCH 24/65] Simplify powertools-parameters-secrets GraalVM config and fix issues in unit tests. --- .../powertools-parameters-secrets/pom.xml | 44 ++++++++----------- .../secrets/SecretsProviderTest.java | 16 +++---- 2 files changed, 25 insertions(+), 35 deletions(-) diff --git a/powertools-parameters/powertools-parameters-secrets/pom.xml b/powertools-parameters/powertools-parameters-secrets/pom.xml index cfbc38fa5..cf262b8d6 100644 --- a/powertools-parameters/powertools-parameters-secrets/pom.xml +++ b/powertools-parameters/powertools-parameters-secrets/pom.xml @@ -1,7 +1,7 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 @@ -58,6 +58,11 @@ mockito-core test + + org.mockito + mockito-junit-jupiter + test + org.slf4j slf4j-simple @@ -97,7 +102,9 @@ maven-surefire-plugin 3.5.3 - -Dmockito.mock.maker=subclass -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-secrets,experimental-class-define-support + + -Dorg.graalvm.nativeimage.imagecode=agent + -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-secrets,experimental-class-define-support --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED @@ -114,6 +121,13 @@ mockito-subclass test + + + + org.junit.jupiter + junit-jupiter-params + test + @@ -137,33 +151,11 @@ --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED --no-fallback - -Dorg.graalvm.nativeimage.imagecode=agent - -H:ClassInitialization=net.bytebuddy.ClassFileVersion:rerun - -H:ClassInitialization=net.bytebuddy.utility.dispatcher.JavaDispatcher:rerun - -H:ClassInitialization=net.bytebuddy.utility.Invoker$Dispatcher:rerun - -H:ClassInitialization=net.bytebuddy.utility.GraalImageCode:rerun - --initialize-at-build-time=org.slf4j.simple.SimpleLogger - --initialize-at-build-time=org.slf4j.LoggerFactory - --initialize-at-build-time=org.junit.Ignore - --initialize-at-build-time=java.lang.annotation.Annotation - --initialize-at-build-time=org.junit.runners.model.FrameworkField - --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase - --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic - --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$1 - --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$2 - --initialize-at-build-time=net.bytebuddy.utility.dispatcher.JavaDispatcher$DynamicClassLoader - --initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable - --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase - --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$ForLoadedType - --initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$ForLoadedMethod - --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Super$Instantiation$2 - - --trace-class-initialization=net.bytebuddy.description.type.TypeDescription$ForLoadedType,net.bytebuddy.description.method.MethodDescription$ForLoadedMethod,net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable - --verbose --native-image-info -H:+UnlockExperimentalVMOptions -H:Log=registerResource:5 + -H:+ReportExceptionStackTraces diff --git a/powertools-parameters/powertools-parameters-secrets/src/test/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProviderTest.java b/powertools-parameters/powertools-parameters-secrets/src/test/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProviderTest.java index a2607dd2c..d0b32874a 100644 --- a/powertools-parameters/powertools-parameters-secrets/src/test/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProviderTest.java +++ b/powertools-parameters/powertools-parameters-secrets/src/test/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProviderTest.java @@ -25,11 +25,13 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.ArgumentCaptor; import org.mockito.Captor; import org.mockito.Mock; import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.jupiter.MockitoExtension; + import software.amazon.awssdk.core.SdkBytes; import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient; import software.amazon.awssdk.services.secretsmanager.model.GetSecretValueRequest; @@ -37,6 +39,7 @@ import software.amazon.lambda.powertools.parameters.cache.CacheManager; import software.amazon.lambda.powertools.parameters.transform.TransformationManager; +@ExtendWith(MockitoExtension.class) public class SecretsProviderTest { @Mock @@ -54,7 +57,6 @@ public class SecretsProviderTest { @BeforeEach public void init() { - MockitoAnnotations.openMocks(this); cacheManager = new CacheManager(); provider = new SecretsProvider(cacheManager, transformationManager, client); } @@ -78,8 +80,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); @@ -90,16 +92,13 @@ public void getValueBase64() { @Test public void getMultipleValuesThrowsException() { - // Act & Assert assertThatRuntimeException().isThrownBy(() -> provider.getMultipleValues("path")) .withMessage("Impossible to get multiple values from AWS Secrets Manager"); - } @Test public void testGetSecretsProvider_withoutParameter_shouldCreateDefaultClient() { - // Act SecretsProvider secretsProvider = SecretsProvider.builder() .build(); @@ -111,11 +110,10 @@ public void testGetSecretsProvider_withoutParameter_shouldCreateDefaultClient() @Test public void testGetSecretsProvider_withoutParameter_shouldHaveDefaultTransformationManager() { - // Act SecretsProvider secretsProvider = SecretsProvider.builder() .build(); // Assert - assertDoesNotThrow(()->secretsProvider.withTransformation(json)); + assertDoesNotThrow(() -> secretsProvider.withTransformation(json)); } } From a596cfdf5af2a1fc498bbd14ac9d031cf56e68de Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Mon, 18 Aug 2025 12:43:48 +0200 Subject: [PATCH 25/65] Simplify powertools-parameters-dynamodb GraalVM config and fix issues in unit tests. --- .../powertools-parameters-dynamodb/pom.xml | 44 ++++++++----------- .../dynamodb/DynamoDbProviderTest.java | 25 ++++++----- 2 files changed, 33 insertions(+), 36 deletions(-) diff --git a/powertools-parameters/powertools-parameters-dynamodb/pom.xml b/powertools-parameters/powertools-parameters-dynamodb/pom.xml index 436068346..c4ff00a38 100644 --- a/powertools-parameters/powertools-parameters-dynamodb/pom.xml +++ b/powertools-parameters/powertools-parameters-dynamodb/pom.xml @@ -1,7 +1,7 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 @@ -58,6 +58,11 @@ mockito-core test + + org.mockito + mockito-junit-jupiter + test + org.slf4j slf4j-simple @@ -97,7 +102,9 @@ maven-surefire-plugin 3.5.3 - -Dmockito.mock.maker=subclass -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-dynamodb,experimental-class-define-support + + -Dorg.graalvm.nativeimage.imagecode=agent + -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-dynamodb,experimental-class-define-support --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED @@ -114,6 +121,13 @@ mockito-subclass test + + + + org.junit.jupiter + junit-jupiter-params + test + @@ -137,33 +151,11 @@ --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED --no-fallback - -Dorg.graalvm.nativeimage.imagecode=agent - -H:ClassInitialization=net.bytebuddy.ClassFileVersion:rerun - -H:ClassInitialization=net.bytebuddy.utility.dispatcher.JavaDispatcher:rerun - -H:ClassInitialization=net.bytebuddy.utility.Invoker$Dispatcher:rerun - -H:ClassInitialization=net.bytebuddy.utility.GraalImageCode:rerun - --initialize-at-build-time=org.slf4j.simple.SimpleLogger - --initialize-at-build-time=org.slf4j.LoggerFactory - --initialize-at-build-time=org.junit.Ignore - --initialize-at-build-time=java.lang.annotation.Annotation - --initialize-at-build-time=org.junit.runners.model.FrameworkField - --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase - --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic - --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$1 - --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$2 - --initialize-at-build-time=net.bytebuddy.utility.dispatcher.JavaDispatcher$DynamicClassLoader - --initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable - --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase - --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$ForLoadedType - --initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$ForLoadedMethod - --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Super$Instantiation$2 - - --trace-class-initialization=net.bytebuddy.description.type.TypeDescription$ForLoadedType,net.bytebuddy.description.method.MethodDescription$ForLoadedMethod,net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable - --verbose --native-image-info -H:+UnlockExperimentalVMOptions -H:Log=registerResource:5 + -H:+ReportExceptionStackTraces diff --git a/powertools-parameters/powertools-parameters-dynamodb/src/test/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderTest.java b/powertools-parameters/powertools-parameters-dynamodb/src/test/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderTest.java index 10d756c69..68d48b01c 100644 --- a/powertools-parameters/powertools-parameters-dynamodb/src/test/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderTest.java +++ b/powertools-parameters/powertools-parameters-dynamodb/src/test/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderTest.java @@ -23,13 +23,17 @@ 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; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.ArgumentCaptor; import org.mockito.Captor; import org.mockito.Mock; import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; + import software.amazon.awssdk.services.dynamodb.DynamoDbClient; import software.amazon.awssdk.services.dynamodb.model.AttributeValue; import software.amazon.awssdk.services.dynamodb.model.GetItemRequest; @@ -40,17 +44,23 @@ import software.amazon.lambda.powertools.parameters.dynamodb.exception.DynamoDbProviderSchemaException; import software.amazon.lambda.powertools.parameters.transform.TransformationManager; +@ExtendWith(MockitoExtension.class) 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; @BeforeEach @@ -60,7 +70,6 @@ public void init() { provider = new DynamoDbProvider(cacheManager, transformationManager, client, tableName); } - @Test public void getValue() { @@ -84,7 +93,6 @@ public void getValue() { assertThat(getItemValueCaptor.getValue().key().get("id").s()).isEqualTo(key); } - @Test public void getValueWithNullResultsReturnsNull() { // Arrange @@ -124,13 +132,11 @@ public void getValueWithMalformedRowThrows() { .item(responseData) .build()); // Act - Assertions.assertThrows(DynamoDbProviderSchemaException.class, () -> - { + Assertions.assertThrows(DynamoDbProviderSchemaException.class, () -> { provider.getValue(key); }); } - @Test public void getValues() { @@ -191,8 +197,7 @@ public void getMultipleValuesMissingSortKey_throwsException() { Mockito.when(client.query(queryRequestCaptor.capture())).thenReturn(response); // Assert - Assertions.assertThrows(DynamoDbProviderSchemaException.class, () -> - { + Assertions.assertThrows(DynamoDbProviderSchemaException.class, () -> { // Act provider.getMultipleValues(key); }); @@ -212,8 +217,7 @@ public void getValuesWithMalformedRowThrows() { Mockito.when(client.query(queryRequestCaptor.capture())).thenReturn(response); // Assert - Assertions.assertThrows(DynamoDbProviderSchemaException.class, () -> - { + Assertions.assertThrows(DynamoDbProviderSchemaException.class, () -> { // Act provider.getMultipleValues(key); }); @@ -227,6 +231,7 @@ public void testDynamoDBBuilderMissingTable_throwsException() { .withCacheManager(new CacheManager()) .build()); } + @Test public void testDynamoDBBuilder_withoutParameter_shouldHaveDefaultTransformationManager() { @@ -234,7 +239,7 @@ public void testDynamoDBBuilder_withoutParameter_shouldHaveDefaultTransformation DynamoDbProvider dynamoDbProvider = DynamoDbProvider.builder().withTable("test-table") .build(); // Assert - assertDoesNotThrow(()->dynamoDbProvider.withTransformation(json)); + assertDoesNotThrow(() -> dynamoDbProvider.withTransformation(json)); } } From d2893c8173a75ec5707f0a559c53d8198a50e191 Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Mon, 18 Aug 2025 12:52:27 +0200 Subject: [PATCH 26/65] Simplify powertools-parameters-appconfig GraalVM config and fix issues in unit tests. --- .../powertools-parameters-appconfig/pom.xml | 44 ++++++++----------- .../appconfig/AppConfigParamAspectTest.java | 1 + .../appconfig/AppConfigProviderTest.java | 6 +-- 3 files changed, 22 insertions(+), 29 deletions(-) diff --git a/powertools-parameters/powertools-parameters-appconfig/pom.xml b/powertools-parameters/powertools-parameters-appconfig/pom.xml index cc36b5438..c32bb4d12 100644 --- a/powertools-parameters/powertools-parameters-appconfig/pom.xml +++ b/powertools-parameters/powertools-parameters-appconfig/pom.xml @@ -1,7 +1,7 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 @@ -57,6 +57,11 @@ mockito-core test + + org.mockito + mockito-junit-jupiter + test + org.slf4j slf4j-simple @@ -96,7 +101,9 @@ maven-surefire-plugin 3.5.3 - -Dmockito.mock.maker=subclass -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-appconfig,experimental-class-define-support + + -Dorg.graalvm.nativeimage.imagecode=agent + -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-appconfig,experimental-class-define-support --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED @@ -113,6 +120,13 @@ mockito-subclass test + + + + org.junit.jupiter + junit-jupiter-params + test + @@ -136,33 +150,11 @@ --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED --no-fallback - -Dorg.graalvm.nativeimage.imagecode=agent - -H:ClassInitialization=net.bytebuddy.ClassFileVersion:rerun - -H:ClassInitialization=net.bytebuddy.utility.dispatcher.JavaDispatcher:rerun - -H:ClassInitialization=net.bytebuddy.utility.Invoker$Dispatcher:rerun - -H:ClassInitialization=net.bytebuddy.utility.GraalImageCode:rerun - --initialize-at-build-time=org.slf4j.simple.SimpleLogger - --initialize-at-build-time=org.slf4j.LoggerFactory - --initialize-at-build-time=org.junit.Ignore - --initialize-at-build-time=java.lang.annotation.Annotation - --initialize-at-build-time=org.junit.runners.model.FrameworkField - --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase - --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic - --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$1 - --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$2 - --initialize-at-build-time=net.bytebuddy.utility.dispatcher.JavaDispatcher$DynamicClassLoader - --initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable - --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase - --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$ForLoadedType - --initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$ForLoadedMethod - --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Super$Instantiation$2 - - --trace-class-initialization=net.bytebuddy.description.type.TypeDescription$ForLoadedType,net.bytebuddy.description.method.MethodDescription$ForLoadedMethod,net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable - --verbose --native-image-info -H:+UnlockExperimentalVMOptions -H:Log=registerResource:5 + -H:+ReportExceptionStackTraces diff --git a/powertools-parameters/powertools-parameters-appconfig/src/test/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParamAspectTest.java b/powertools-parameters/powertools-parameters-appconfig/src/test/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParamAspectTest.java index f50e88ec5..df3191632 100644 --- a/powertools-parameters/powertools-parameters-appconfig/src/test/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParamAspectTest.java +++ b/powertools-parameters/powertools-parameters-appconfig/src/test/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParamAspectTest.java @@ -18,6 +18,7 @@ import static org.assertj.core.api.Assertions.assertThat; import java.util.function.BiFunction; + import org.junit.jupiter.api.Test; import org.mockito.Mockito; diff --git a/powertools-parameters/powertools-parameters-appconfig/src/test/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProviderTest.java b/powertools-parameters/powertools-parameters-appconfig/src/test/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProviderTest.java index da01d7d9a..7f06ed412 100644 --- a/powertools-parameters/powertools-parameters-appconfig/src/test/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProviderTest.java +++ b/powertools-parameters/powertools-parameters-appconfig/src/test/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProviderTest.java @@ -18,15 +18,16 @@ import static org.assertj.core.api.Assertions.assertThatIllegalStateException; import static org.assertj.core.api.Assertions.assertThatRuntimeException; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; -import static org.mockito.MockitoAnnotations.openMocks; import static software.amazon.lambda.powertools.parameters.transform.Transformer.json; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.ArgumentCaptor; import org.mockito.Captor; import org.mockito.Mock; import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; import software.amazon.awssdk.core.SdkBytes; import software.amazon.awssdk.services.appconfigdata.AppConfigDataClient; @@ -37,6 +38,7 @@ import software.amazon.lambda.powertools.parameters.cache.CacheManager; import software.amazon.lambda.powertools.parameters.transform.TransformationManager; +@ExtendWith(MockitoExtension.class) class AppConfigProviderTest { private static final String ENVIRONMENT_NAME = "test"; @@ -55,8 +57,6 @@ class AppConfigProviderTest { @BeforeEach void init() { - openMocks(this); - provider = AppConfigProvider.builder() .withClient(client) .withApplication(APPLICATION_NAME) From a8dd7ff18b421f55804cf617a387df665523d3e0 Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Mon, 18 Aug 2025 13:01:12 +0200 Subject: [PATCH 27/65] Fix SonarCube finding. --- .../powertools/logging/internal/LambdaJsonEncoderTest.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaJsonEncoderTest.java b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaJsonEncoderTest.java index fa50bac21..912e2fde9 100644 --- a/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaJsonEncoderTest.java +++ b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaJsonEncoderTest.java @@ -66,6 +66,7 @@ @Order(2) class LambdaJsonEncoderTest { private static final Logger logger = (Logger) LoggerFactory.getLogger(LambdaJsonEncoderTest.class.getName()); + private final LoggingEvent loggingEvent = new LoggingEvent("fqcn", logger, Level.INFO, "message", null, null); private Context context; @@ -167,8 +168,6 @@ void shouldLogArgumentsAsJsonWhenUsingKeyValue() { }); } - private final LoggingEvent loggingEvent = new LoggingEvent("fqcn", logger, Level.INFO, "message", null, null); - @Test void shouldNotLogPowertoolsInfo() { // GIVEN @@ -218,9 +217,9 @@ void shouldLogStructuredArgumentsAsNewEntries() { StructuredArgument argument = StructuredArguments.entry("msg", msg); // WHEN - LoggingEvent loggingEvent = new LoggingEvent("fqcn", logger, Level.INFO, "A message", null, + LoggingEvent structuredLoggingEvent = new LoggingEvent("fqcn", logger, Level.INFO, "A message", null, new Object[] { argument }); - byte[] encoded = encoder.encode(loggingEvent); + byte[] encoded = encoder.encode(structuredLoggingEvent); String result = new String(encoded, StandardCharsets.UTF_8); // THEN (logged as JSON) From 54f352e029584fa87793f46e19618cc4ea1a831b Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Tue, 19 Aug 2025 10:12:05 +0200 Subject: [PATCH 28/65] Allowlist UPL-1.0 license. --- .github/dependency-review-config.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/dependency-review-config.yml b/.github/dependency-review-config.yml index 6d737ee55..8390cfb5b 100644 --- a/.github/dependency-review-config.yml +++ b/.github/dependency-review-config.yml @@ -27,4 +27,5 @@ allow-licenses: - 'BSD-3-Clause-No-Nuclear-License-2014' - 'BSD-3-Clause-No-Nuclear-Warranty' - 'BSD-3-Clause-Open-MPI' -comment-summary-in-pr: on-failure \ No newline at end of file + - 'UPL-1.0' +comment-summary-in-pr: on-failure From c0f991af55e50adb0e61a26c357c2cb2bce92c6f Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Tue, 19 Aug 2025 11:17:27 +0200 Subject: [PATCH 29/65] Add TT ID to UPL license. --- .github/dependency-review-config.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/dependency-review-config.yml b/.github/dependency-review-config.yml index 8390cfb5b..2ea218503 100644 --- a/.github/dependency-review-config.yml +++ b/.github/dependency-review-config.yml @@ -27,5 +27,6 @@ allow-licenses: - 'BSD-3-Clause-No-Nuclear-License-2014' - 'BSD-3-Clause-No-Nuclear-Warranty' - 'BSD-3-Clause-Open-MPI' + # TT: D290816995 - 'UPL-1.0' comment-summary-in-pr: on-failure From 6c8d6c66885ce147b64f0a2a4726bcca0de2f011 Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Wed, 20 Aug 2025 16:25:33 +0200 Subject: [PATCH 30/65] Add native maven profiles to idempotency-core. --- .../powertools-idempotency-core/pom.xml | 96 ++++++++++++++++++- .../internal/IdempotencyAspectTest.java | 21 +--- .../test/resources/simplelogger.properties | 7 ++ 3 files changed, 107 insertions(+), 17 deletions(-) create mode 100644 powertools-idempotency/powertools-idempotency-core/src/test/resources/simplelogger.properties diff --git a/powertools-idempotency/powertools-idempotency-core/pom.xml b/powertools-idempotency/powertools-idempotency-core/pom.xml index 6f15bfc3d..ba04019aa 100644 --- a/powertools-idempotency/powertools-idempotency-core/pom.xml +++ b/powertools-idempotency/powertools-idempotency-core/pom.xml @@ -37,16 +37,110 @@ software.amazon.lambda powertools-serialization + + + org.junit.jupiter + junit-jupiter-api + test + + + org.junit.jupiter + junit-jupiter-engine + test + org.mockito mockito-core test + + org.mockito + mockito-junit-jupiter + test + org.slf4j slf4j-simple test + + software.amazon.lambda + powertools-common + ${project.version} + test-jar + test + - \ No newline at end of file + + + + generate-graalvm-files + + + org.mockito + mockito-subclass + test + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + -Dorg.graalvm.nativeimage.imagecode=agent + -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-idempotency-core,experimental-class-define-support + --add-opens java.base/java.util=ALL-UNNAMED + --add-opens java.base/java.lang=ALL-UNNAMED + + + + + + + + graalvm-native + + + org.mockito + mockito-subclass + test + + + + + + org.graalvm.buildtools + native-maven-plugin + 0.11.0 + true + + + test-native + + test + + test + + + + powertools-idempotency-core + + --add-opens java.base/java.util=ALL-UNNAMED + --add-opens java.base/java.lang=ALL-UNNAMED + --no-fallback + --verbose + --native-image-info + -H:+UnlockExperimentalVMOptions + -H:Log=registerResource:5 + -H:+ReportExceptionStackTraces + + + + + + + + diff --git a/powertools-idempotency/powertools-idempotency-core/src/test/java/software/amazon/lambda/powertools/idempotency/internal/IdempotencyAspectTest.java b/powertools-idempotency/powertools-idempotency-core/src/test/java/software/amazon/lambda/powertools/idempotency/internal/IdempotencyAspectTest.java index 12113fc9e..398beee2c 100644 --- a/powertools-idempotency/powertools-idempotency-core/src/test/java/software/amazon/lambda/powertools/idempotency/internal/IdempotencyAspectTest.java +++ b/powertools-idempotency/powertools-idempotency-core/src/test/java/software/amazon/lambda/powertools/idempotency/internal/IdempotencyAspectTest.java @@ -24,20 +24,20 @@ import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoInteractions; -import static org.mockito.Mockito.when; import java.time.Instant; import java.util.OptionalInt; import java.util.OptionalLong; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.junitpioneer.jupiter.SetEnvironmentVariable; import org.mockito.ArgumentCaptor; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.jupiter.MockitoExtension; import com.amazonaws.services.lambda.runtime.Context; +import software.amazon.lambda.powertools.common.stubs.TestLambdaContext; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; @@ -61,19 +61,14 @@ import software.amazon.lambda.powertools.idempotency.persistence.DataRecord; import software.amazon.lambda.powertools.utilities.JsonConfig; +@ExtendWith(MockitoExtension.class) public class IdempotencyAspectTest { - @Mock - private Context context; + private Context context = new TestLambdaContext(); @Mock private BasePersistenceStore store; - @BeforeEach - void setUp() { - MockitoAnnotations.openMocks(this); - } - @Test public void firstCall_shouldPutInStore() { Idempotency.config() @@ -85,8 +80,6 @@ public void firstCall_shouldPutInStore() { IdempotencyEnabledFunction function = new IdempotencyEnabledFunction(); - when(context.getRemainingTimeInMillis()).thenReturn(30000); - Product p = new Product(42, "fake product", 12); Basket basket = function.handleRequest(p, context); assertThat(basket.getProducts()).hasSize(1); @@ -124,8 +117,6 @@ public void firstCall_shouldPutInStoreAndNotApplyResponseHook() { IdempotencyEnabledFunction function = new IdempotencyEnabledFunction(); - when(context.getRemainingTimeInMillis()).thenReturn(30000); - Product p = new Product(42, "fake product", 12); Basket basket = function.handleRequest(p, context); assertThat(basket.getProducts()).hasSize(1); // Size should be 1 because response hook should not run @@ -393,8 +384,6 @@ public void idempotencyOnSubMethodAnnotated_firstCall_shouldPutInStore() { // WHEN boolean registerContext = true; - when(context.getRemainingTimeInMillis()).thenReturn(30000); - IdempotencyInternalFunction function = new IdempotencyInternalFunction(registerContext); Product p = new Product(42, "fake product", 12); Basket basket = function.handleRequest(p, context); diff --git a/powertools-idempotency/powertools-idempotency-core/src/test/resources/simplelogger.properties b/powertools-idempotency/powertools-idempotency-core/src/test/resources/simplelogger.properties new file mode 100644 index 000000000..78b3d6ad4 --- /dev/null +++ b/powertools-idempotency/powertools-idempotency-core/src/test/resources/simplelogger.properties @@ -0,0 +1,7 @@ +org.slf4j.simpleLogger.logFile=target/idempotency-core-test.log +org.slf4j.simpleLogger.defaultLogLevel=warn +org.slf4j.simpleLogger.showDateTime=true +org.slf4j.simpleLogger.dateTimeFormat=yyyy-MM-dd HH:mm:ss:SSS +org.slf4j.simpleLogger.showThreadName=false +org.slf4j.simpleLogger.showLogName=true +org.slf4j.simpleLogger.showShortLogName=false \ No newline at end of file From 115169919122a8f0342e346095a6c343057fae2d Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Wed, 20 Aug 2025 19:25:31 +0200 Subject: [PATCH 31/65] Configure GraalVM profile for idempotency-dynamodb. Refactor unit tests to treat DynamoDBLocal as external process instead of starting it via JVM which is not compatible with GraalVM. --- pom.xml | 5 + .../powertools-idempotency-dynamodb/pom.xml | 156 +++++++++++++- .../persistence/dynamodb/DynamoDBConfig.java | 69 ++----- .../DynamoDBPersistenceStoreTest.java | 192 ++++++++---------- .../persistence/dynamodb/IdempotencyTest.java | 16 +- .../test/resources/simplelogger.properties | 7 + 6 files changed, 264 insertions(+), 181 deletions(-) create mode 100644 powertools-idempotency/powertools-idempotency-dynamodb/src/test/resources/simplelogger.properties diff --git a/pom.xml b/pom.xml index 59c5eb2e5..7d953509f 100644 --- a/pom.xml +++ b/pom.xml @@ -443,6 +443,11 @@ maven-gpg-plugin ${maven-gpg-plugin.version} + + org.codehaus.mojo + exec-maven-plugin + 3.5.1 + diff --git a/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml b/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml index ed5b8d5c0..e3d935e1a 100644 --- a/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml +++ b/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml @@ -63,6 +63,29 @@ + + org.junit.jupiter + junit-jupiter-api + test + + + org.junit.jupiter + junit-jupiter-engine + test + + + org.slf4j + slf4j-simple + test + + + software.amazon.lambda + powertools-common + ${project.version} + test-jar + test + + com.amazonaws DynamoDBLocal @@ -71,17 +94,124 @@ 2.2.0 test - - - io.github.ganadist.sqlite4java - libsqlite4java-osx-aarch64 - 1.0.392 - test - dylib - + + + + generate-graalvm-files + + + + org.apache.maven.plugins + maven-surefire-plugin + + + -Dorg.graalvm.nativeimage.imagecode=agent + -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-idempotency-dynamodb,experimental-class-define-support + --add-opens java.base/java.util=ALL-UNNAMED + --add-opens java.base/java.lang=ALL-UNNAMED + + + + + + + + graalvm-native + + + + org.graalvm.buildtools + native-maven-plugin + 0.11.0 + true + + + test-native + + test + + test + + + + powertools-idempotency-dynamodb + + + com.amazonaws + DynamoDBLocal + + + + --add-opens java.base/java.util=ALL-UNNAMED + --add-opens java.base/java.lang=ALL-UNNAMED + --enable-url-protocols=http + --no-fallback + --verbose + --native-image-info + -H:+UnlockExperimentalVMOptions + -H:Log=registerResource:5 + -H:+ReportExceptionStackTraces + + + + + + + + + + + org.apache.maven.plugins + maven-dependency-plugin + + + copy-dynamodb-local + generate-test-resources + + copy-dependencies + + + test + false + + com.amazonaws,software.amazon.awssdk,org.eclipse.jetty,com.fasterxml.jackson.core,com.fasterxml.jackson.dataformat,com.fasterxml.jackson.datatype,com.almworks.sqlite4java,commons-cli,org.apache.commons,commons-logging,org.apache.logging.log4j,org.slf4j,org.reactivestreams,org.antlr,com.google.guava,jakarta.transaction + ${project.build.directory}/dynamodb-local + + + + + + + org.codehaus.mojo + exec-maven-plugin + + + start-dynamodb-local + process-test-classes + + exec + + + java + ${project.build.directory}/dynamodb-local + + -Djava.library.path=${project.build.directory}/dynamodb-local + -cp + ${project.build.directory}/dynamodb-local/* + com.amazonaws.services.dynamodbv2.local.main.ServerRunner + -inMemory + -port + 8000 + + true + true + + + + org.apache.maven.plugins maven-jar-plugin @@ -94,6 +224,16 @@ + + + org.apache.maven.plugins + maven-surefire-plugin + + + http://localhost:8000 + + + dev.aspectj aspectj-maven-plugin diff --git a/powertools-idempotency/powertools-idempotency-dynamodb/src/test/java/software/amazon/lambda/powertools/idempotency/persistence/dynamodb/DynamoDBConfig.java b/powertools-idempotency/powertools-idempotency-dynamodb/src/test/java/software/amazon/lambda/powertools/idempotency/persistence/dynamodb/DynamoDBConfig.java index 289b0f1cd..9f6875689 100644 --- a/powertools-idempotency/powertools-idempotency-dynamodb/src/test/java/software/amazon/lambda/powertools/idempotency/persistence/dynamodb/DynamoDBConfig.java +++ b/powertools-idempotency/powertools-idempotency-dynamodb/src/test/java/software/amazon/lambda/powertools/idempotency/persistence/dynamodb/DynamoDBConfig.java @@ -14,16 +14,10 @@ package software.amazon.lambda.powertools.idempotency.persistence.dynamodb; -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 com.amazonaws.services.dynamodbv2.local.main.ServerRunner; -import com.amazonaws.services.dynamodbv2.local.server.DynamoDBProxyServer; - import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient; @@ -32,71 +26,40 @@ 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.ResourceInUseException; import software.amazon.awssdk.services.dynamodb.model.ScalarAttributeType; -public class DynamoDBConfig { +class DynamoDBConfig { protected static final String TABLE_NAME = "idempotency_table"; - protected static DynamoDBProxyServer dynamoProxy; protected static DynamoDbClient client; @BeforeAll - public static void setupDynamo() { - int port = getFreePort(); - try { - dynamoProxy = ServerRunner.createServerFromCommandLineArgs(new String[] { - "-inMemory", - "-port", - Integer.toString(port) - }); - dynamoProxy.start(); - } catch (Exception e) { - throw new RuntimeException(); - } + static void setupDynamo() { + String endpoint = System.getProperty("dynamodb.endpoint", "http://localhost:8000"); client = DynamoDbClient.builder() .httpClient(UrlConnectionHttpClient.builder().build()) .region(Region.EU_WEST_1) - .endpointOverride(URI.create("http://localhost:" + port)) + .endpointOverride(URI.create(endpoint)) .credentialsProvider(StaticCredentialsProvider.create( AwsBasicCredentials.create("FAKE", "FAKE"))) .build(); - client.createTable(CreateTableRequest.builder() - .tableName(TABLE_NAME) - .keySchema(KeySchemaElement.builder().keyType(KeyType.HASH).attributeName("id").build()) - .attributeDefinitions( - AttributeDefinition.builder().attributeName("id").attributeType(ScalarAttributeType.S).build()) - .billingMode(BillingMode.PAY_PER_REQUEST) - .build()); - - DescribeTableResponse response = client - .describeTable(DescribeTableRequest.builder().tableName(TABLE_NAME).build()); - if (response == null) { - throw new RuntimeException("Table was not created within expected time"); - } - } - - @AfterAll - public static void teardownDynamo() { try { - dynamoProxy.stop(); + client.createTable(CreateTableRequest.builder() + .tableName(TABLE_NAME) + .keySchema(KeySchemaElement.builder().keyType(KeyType.HASH).attributeName("id").build()) + .attributeDefinitions( + AttributeDefinition.builder().attributeName("id").attributeType(ScalarAttributeType.S) + .build()) + .billingMode(BillingMode.PAY_PER_REQUEST) + .build()); + } catch (ResourceInUseException e) { + // Table already exists, ignore } catch (Exception e) { - throw new RuntimeException(); - } - } - - private static int getFreePort() { - try { - ServerSocket socket = new ServerSocket(0); - int port = socket.getLocalPort(); - socket.close(); - return port; - } catch (IOException ioe) { - throw new RuntimeException(ioe); + throw new RuntimeException("Failed to create DynamoDB table", e); } } } diff --git a/powertools-idempotency/powertools-idempotency-dynamodb/src/test/java/software/amazon/lambda/powertools/idempotency/persistence/dynamodb/DynamoDBPersistenceStoreTest.java b/powertools-idempotency/powertools-idempotency-dynamodb/src/test/java/software/amazon/lambda/powertools/idempotency/persistence/dynamodb/DynamoDBPersistenceStoreTest.java index 56b32c4f9..b5c816286 100644 --- a/powertools-idempotency/powertools-idempotency-dynamodb/src/test/java/software/amazon/lambda/powertools/idempotency/persistence/dynamodb/DynamoDBPersistenceStoreTest.java +++ b/powertools-idempotency/powertools-idempotency-dynamodb/src/test/java/software/amazon/lambda/powertools/idempotency/persistence/dynamodb/DynamoDBPersistenceStoreTest.java @@ -14,10 +14,20 @@ package software.amazon.lambda.powertools.idempotency.persistence.dynamodb; +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.AttributeDefinition; import software.amazon.awssdk.services.dynamodb.model.AttributeValue; import software.amazon.awssdk.services.dynamodb.model.BillingMode; @@ -32,47 +42,35 @@ import software.amazon.awssdk.services.dynamodb.model.ScanRequest; import software.amazon.lambda.powertools.idempotency.Constants; 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.persistence.DataRecord; -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 */ -public class DynamoDBPersistenceStoreTest extends DynamoDBConfig { +class DynamoDBPersistenceStoreTest extends DynamoDBConfig { protected static final String TABLE_NAME_CUSTOM = "idempotency_table_custom"; private Map key; private DynamoDBPersistenceStore dynamoDBPersistenceStore; - // ================================================================= - // @Test - public void putRecord_shouldCreateRecordInDynamoDB() throws IdempotencyItemAlreadyExistsException { + void putRecord_shouldCreateRecordInDynamoDB() throws IdempotencyItemAlreadyExistsException { Instant now = Instant.now(); long expiry = now.plus(3600, ChronoUnit.SECONDS).getEpochSecond(); 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)); } @Test - public void putRecord_shouldCreateRecordInDynamoDB_IfPreviousExpired() { + void putRecord_shouldCreateRecordInDynamoDB_IfPreviousExpired() { key = Collections.singletonMap("id", AttributeValue.builder().s("key").build()); // GIVEN: Insert a fake item with same id and expired @@ -91,22 +89,23 @@ public void putRecord_shouldCreateRecordInDynamoDB_IfPreviousExpired() { DataRecord.Status.INPROGRESS, expiry2, null, - null - ), now); + null), + 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)); } @Test - public void putRecord_shouldCreateRecordInDynamoDB_IfLambdaWasInProgressAndTimedOut() { + void putRecord_shouldCreateRecordInDynamoDB_IfLambdaWasInProgressAndTimedOut() { key = Collections.singletonMap("id", AttributeValue.builder().s("key").build()); - // GIVEN: Insert a fake item with same id and progress expired (Lambda timed out before and we allow a new execution) + // GIVEN: Insert a fake item with same id and progress expired (Lambda timed out before and we allow a new + // execution) Map item = new HashMap<>(key); Instant now = Instant.now(); long expiry = now.plus(30, ChronoUnit.SECONDS).getEpochSecond(); @@ -124,19 +123,19 @@ public void putRecord_shouldCreateRecordInDynamoDB_IfLambdaWasInProgressAndTimed DataRecord.Status.INPROGRESS, expiry2, null, - null - ), now); + null), + 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)); } @Test - public void putRecord_shouldThrowIdempotencyItemAlreadyExistsException_IfRecordAlreadyExist() { + void putRecord_shouldThrowIdempotencyItemAlreadyExistsException_IfRecordAlreadyExist() { key = Collections.singletonMap("id", AttributeValue.builder().s("key").build()); // GIVEN: Insert a fake item with same id @@ -150,15 +149,15 @@ public void putRecord_shouldThrowIdempotencyItemAlreadyExistsException_IfRecordA // WHEN: call putRecord long expiry2 = now.plus(3600, ChronoUnit.SECONDS).getEpochSecond(); - assertThatThrownBy(() -> dynamoDBPersistenceStore.putRecord( - new DataRecord("key", - DataRecord.Status.INPROGRESS, - expiry2, - null, - null), - now)).isInstanceOf(IdempotencyItemAlreadyExistsException.class) - // DataRecord should be present due to returnValuesOnConditionCheckFailure("ALL_OLD") - .matches(e -> ((IdempotencyItemAlreadyExistsException) e).getDataRecord().isPresent()); + DataRecord recordToInsert = new DataRecord("key", + DataRecord.Status.INPROGRESS, + expiry2, + null, + null); + assertThatThrownBy(() -> dynamoDBPersistenceStore.putRecord(recordToInsert, now)) + .isInstanceOf(IdempotencyItemAlreadyExistsException.class) + // DataRecord should be present due to returnValuesOnConditionCheckFailure("ALL_OLD") + .matches(e -> ((IdempotencyItemAlreadyExistsException) e).getDataRecord().isPresent()); // THEN: item was not updated, retrieve the initial one Map itemInDb = client @@ -170,7 +169,7 @@ public void putRecord_shouldThrowIdempotencyItemAlreadyExistsException_IfRecordA } @Test - public void putRecord_shouldBlockUpdate_IfRecordAlreadyExistAndProgressNotExpiredAfterLambdaTimedOut() { + void putRecord_shouldBlockUpdate_IfRecordAlreadyExistAndProgressNotExpiredAfterLambdaTimedOut() { key = Collections.singletonMap("id", AttributeValue.builder().s("key").build()); // GIVEN: Insert a fake item with same id @@ -186,17 +185,15 @@ public void putRecord_shouldBlockUpdate_IfRecordAlreadyExistAndProgressNotExpire // WHEN: call putRecord long expiry2 = now.plus(3600, ChronoUnit.SECONDS).getEpochSecond(); - assertThatThrownBy(() -> dynamoDBPersistenceStore.putRecord( - new DataRecord("key", - DataRecord.Status.INPROGRESS, - expiry2, - "Fake Data 2", - null), - now)) - .isInstanceOf(IdempotencyItemAlreadyExistsException.class) - // DataRecord should be present due to returnValuesOnConditionCheckFailure("ALL_OLD") - .matches(e -> ((IdempotencyItemAlreadyExistsException) e).getDataRecord().isPresent()); - ; + DataRecord recordToInsert = new DataRecord("key", + DataRecord.Status.INPROGRESS, + expiry2, + "Fake Data 2", + null); + assertThatThrownBy(() -> dynamoDBPersistenceStore.putRecord(recordToInsert, now)) + .isInstanceOf(IdempotencyItemAlreadyExistsException.class) + // DataRecord should be present due to returnValuesOnConditionCheckFailure("ALL_OLD") + .matches(e -> ((IdempotencyItemAlreadyExistsException) e).getDataRecord().isPresent()); // THEN: item was not updated, retrieve the initial one Map itemInDb = client @@ -207,15 +204,8 @@ public void putRecord_shouldBlockUpdate_IfRecordAlreadyExistAndProgressNotExpire assertThat(itemInDb.get("data").s()).isEqualTo("Fake Data"); } - - // - // ================================================================= - - // ================================================================= - // - @Test - public void getRecord_shouldReturnExistingRecord() throws IdempotencyItemNotFoundException { + void getRecord_shouldReturnExistingRecord() throws IdempotencyItemNotFoundException { key = Collections.singletonMap("id", AttributeValue.builder().s("key").build()); // GIVEN: Insert a fake item with same id @@ -228,29 +218,23 @@ public void getRecord_shouldReturnExistingRecord() throws IdempotencyItemNotFoun client.putItem(PutItemRequest.builder().tableName(TABLE_NAME).item(item).build()); // WHEN - DataRecord record = dynamoDBPersistenceStore.getRecord("key"); + DataRecord dr = dynamoDBPersistenceStore.getRecord("key"); // THEN - assertThat(record.getIdempotencyKey()).isEqualTo("key"); - assertThat(record.getStatus()).isEqualTo(DataRecord.Status.COMPLETED); - assertThat(record.getResponseData()).isEqualTo("Fake Data"); - assertThat(record.getExpiryTimestamp()).isEqualTo(expiry); + assertThat(dr.getIdempotencyKey()).isEqualTo("key"); + assertThat(dr.getStatus()).isEqualTo(DataRecord.Status.COMPLETED); + assertThat(dr.getResponseData()).isEqualTo("Fake Data"); + assertThat(dr.getExpiryTimestamp()).isEqualTo(expiry); } @Test - public void getRecord_shouldThrowException_whenRecordIsAbsent() { - assertThatThrownBy(() -> dynamoDBPersistenceStore.getRecord("key")).isInstanceOf( - IdempotencyItemNotFoundException.class); + void getRecord_shouldThrowException_whenRecordIsAbsent() { + assertThatThrownBy(() -> dynamoDBPersistenceStore.getRecord("key")) + .isInstanceOf(IdempotencyItemNotFoundException.class); } - // - // ================================================================= - - // ================================================================= - // - @Test - public void updateRecord_shouldUpdateRecord() { + void updateRecord_shouldUpdateRecord() { // GIVEN: Insert a fake item with same id key = Collections.singletonMap("id", AttributeValue.builder().s("key").build()); Map item = new HashMap<>(key); @@ -265,26 +249,20 @@ public void updateRecord_shouldUpdateRecord() { // WHEN expiry = now.plus(3600, ChronoUnit.SECONDS).getEpochSecond(); - DataRecord record = new DataRecord("key", DataRecord.Status.COMPLETED, expiry, "Fake result", "hash"); - dynamoDBPersistenceStore.updateRecord(record); + DataRecord dr = new DataRecord("key", DataRecord.Status.COMPLETED, expiry, "Fake result", "hash"); + dynamoDBPersistenceStore.updateRecord(dr); // 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"); assertThat(itemInDb.get("validation").s()).isEqualTo("hash"); } - // - // ================================================================= - - // ================================================================= - // - @Test - public void deleteRecord_shouldDeleteRecord() { + void deleteRecord_shouldDeleteRecord() { // GIVEN: Insert a fake item with same id key = Collections.singletonMap("id", AttributeValue.builder().s("key").build()); Map item = new HashMap<>(key); @@ -299,27 +277,22 @@ public void deleteRecord_shouldDeleteRecord() { dynamoDBPersistenceStore.deleteRecord("key"); // THEN - assertThat(client.scan(ScanRequest.builder().tableName(TABLE_NAME).build()).count()).isEqualTo(0); + assertThat(client.scan(ScanRequest.builder().tableName(TABLE_NAME).build()).count()).isZero(); } - // - // ================================================================= - @Test - public void endToEndWithCustomAttrNamesAndSortKey() throws IdempotencyItemNotFoundException { + void endToEndWithCustomAttrNamesAndSortKey() throws IdempotencyItemNotFoundException { try { client.createTable(CreateTableRequest.builder() .tableName(TABLE_NAME_CUSTOM) .keySchema( KeySchemaElement.builder().keyType(KeyType.HASH).attributeName("key").build(), - KeySchemaElement.builder().keyType(KeyType.RANGE).attributeName("sortkey").build() - ) + 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() - ) + .build()) .billingMode(BillingMode.PAY_PER_REQUEST) .build()); @@ -336,22 +309,21 @@ public void endToEndWithCustomAttrNamesAndSortKey() throws IdempotencyItemNotFou .build(); Instant now = Instant.now(); - DataRecord record = new DataRecord( + DataRecord dr = new DataRecord( "mykey", DataRecord.Status.INPROGRESS, now.plus(400, ChronoUnit.SECONDS).getEpochSecond(), null, - null - ); + null); // PUT - persistenceStore.putRecord(record, now); + persistenceStore.putRecord(dr, now); Map customKey = new HashMap<>(); 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"); @@ -368,8 +340,7 @@ public void endToEndWithCustomAttrNamesAndSortKey() throws IdempotencyItemNotFou DataRecord.Status.COMPLETED, now.plus(500, ChronoUnit.SECONDS).getEpochSecond(), "response", - null - ); + null); persistenceStore.updateRecord(updatedRecord); recordInDb = persistenceStore.getRecord("mykey"); assertThat(recordInDb).isEqualTo(updatedRecord); @@ -389,13 +360,14 @@ public void endToEndWithCustomAttrNamesAndSortKey() throws IdempotencyItemNotFou @Test @SetEnvironmentVariable(key = Constants.IDEMPOTENCY_DISABLED_ENV, value = "true") - public void idempotencyDisabled_noClientShouldBeCreated() { + void idempotencyDisabled_noClientShouldBeCreated() { DynamoDBPersistenceStore store = DynamoDBPersistenceStore.builder().withTableName(TABLE_NAME).build(); - assertThatThrownBy(() -> store.getRecord("fake")).isInstanceOf(NullPointerException.class); + assertThatThrownBy(() -> store.getRecord("fake")) + .isInstanceOf(NullPointerException.class); } @BeforeEach - public void setup() { + void setup() { dynamoDBPersistenceStore = DynamoDBPersistenceStore.builder() .withTableName(TABLE_NAME) .withDynamoDbClient(client) @@ -403,10 +375,14 @@ public void setup() { } @AfterEach - public void emptyDB() { - if (key != null) { - client.deleteItem(DeleteItemRequest.builder().tableName(TABLE_NAME).key(key).build()); - key = null; - } + void emptyDB() { + // Clear all items from the table + client.scan(ScanRequest.builder().tableName(TABLE_NAME).build()) + .items() + .forEach(item -> { + Map itemKey = Collections.singletonMap("id", item.get("id")); + client.deleteItem(DeleteItemRequest.builder().tableName(TABLE_NAME).key(itemKey).build()); + }); + key = null; } } diff --git a/powertools-idempotency/powertools-idempotency-dynamodb/src/test/java/software/amazon/lambda/powertools/idempotency/persistence/dynamodb/IdempotencyTest.java b/powertools-idempotency/powertools-idempotency-dynamodb/src/test/java/software/amazon/lambda/powertools/idempotency/persistence/dynamodb/IdempotencyTest.java index 7b43542c8..e85614580 100644 --- a/powertools-idempotency/powertools-idempotency-dynamodb/src/test/java/software/amazon/lambda/powertools/idempotency/persistence/dynamodb/IdempotencyTest.java +++ b/powertools-idempotency/powertools-idempotency-dynamodb/src/test/java/software/amazon/lambda/powertools/idempotency/persistence/dynamodb/IdempotencyTest.java @@ -16,30 +16,22 @@ import static org.assertj.core.api.Assertions.assertThat; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; import com.amazonaws.services.lambda.runtime.tests.EventLoader; import software.amazon.awssdk.services.dynamodb.model.ScanRequest; +import software.amazon.lambda.powertools.common.stubs.TestLambdaContext; import software.amazon.lambda.powertools.idempotency.persistence.dynamodb.handlers.IdempotencyFunction; -public class IdempotencyTest extends DynamoDBConfig { +class IdempotencyTest extends DynamoDBConfig { - @Mock - private Context context; - - @BeforeEach - void setUp() { - MockitoAnnotations.openMocks(this); - } + private Context context = new TestLambdaContext(); @Test - public void endToEndTest() { + void endToEndTest() { IdempotencyFunction function = new IdempotencyFunction(client); APIGatewayProxyResponseEvent response = function diff --git a/powertools-idempotency/powertools-idempotency-dynamodb/src/test/resources/simplelogger.properties b/powertools-idempotency/powertools-idempotency-dynamodb/src/test/resources/simplelogger.properties new file mode 100644 index 000000000..6d188691f --- /dev/null +++ b/powertools-idempotency/powertools-idempotency-dynamodb/src/test/resources/simplelogger.properties @@ -0,0 +1,7 @@ +org.slf4j.simpleLogger.logFile=target/idempotency-dynamodb-test.log +org.slf4j.simpleLogger.defaultLogLevel=warn +org.slf4j.simpleLogger.showDateTime=true +org.slf4j.simpleLogger.dateTimeFormat=yyyy-MM-dd HH:mm:ss:SSS +org.slf4j.simpleLogger.showThreadName=false +org.slf4j.simpleLogger.showLogName=true +org.slf4j.simpleLogger.showShortLogName=false \ No newline at end of file From 7957a34e199c1226032044f61b5dccb88469a773 Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Thu, 21 Aug 2025 09:05:49 +0000 Subject: [PATCH 32/65] Add GRM data for idempotency dynamodb. --- .../powertools-idempotency-dynamodb/pom.xml | 11 + .../reflect-config.json | 325 ++++++++++++++++++ .../resource-config.json | 27 ++ 3 files changed, 363 insertions(+) create mode 100644 powertools-idempotency/powertools-idempotency-dynamodb/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-idempotency-dynamodb/reflect-config.json create mode 100644 powertools-idempotency/powertools-idempotency-dynamodb/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-idempotency-dynamodb/resource-config.json diff --git a/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml b/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml index e3d935e1a..ef5a3d6eb 100644 --- a/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml +++ b/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml @@ -99,6 +99,17 @@ generate-graalvm-files + + + + com.amazonaws + aws-xray-recorder-sdk-aws-sdk-v2-instrumentor + test + + diff --git a/powertools-idempotency/powertools-idempotency-dynamodb/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-idempotency-dynamodb/reflect-config.json b/powertools-idempotency/powertools-idempotency-dynamodb/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-idempotency-dynamodb/reflect-config.json new file mode 100644 index 000000000..f0ba9c4c2 --- /dev/null +++ b/powertools-idempotency/powertools-idempotency-dynamodb/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-idempotency-dynamodb/reflect-config.json @@ -0,0 +1,325 @@ +[ +{ + "name":"[Lcom.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.Deserializers;" +}, +{ + "name":"[Lcom.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.KeyDeserializers;" +}, +{ + "name":"[Lcom.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.ValueInstantiators;" +}, +{ + "name":"[Lcom.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.Serializers;" +}, +{ + "name":"[Lcom.fasterxml.jackson.databind.deser.Deserializers;" +}, +{ + "name":"com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.Java7HandlersImpl", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.Java7SupportImpl", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.amazonaws.services.lambda.runtime.Context" +}, +{ + "name":"com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"getBody","parameterTypes":[] }, {"name":"getHeaders","parameterTypes":[] }, {"name":"getHttpMethod","parameterTypes":[] }, {"name":"getIsBase64Encoded","parameterTypes":[] }, {"name":"getMultiValueHeaders","parameterTypes":[] }, {"name":"getMultiValueQueryStringParameters","parameterTypes":[] }, {"name":"getPath","parameterTypes":[] }, {"name":"getPathParameters","parameterTypes":[] }, {"name":"getQueryStringParameters","parameterTypes":[] }, {"name":"getRequestContext","parameterTypes":[] }, {"name":"getResource","parameterTypes":[] }, {"name":"getStageVariables","parameterTypes":[] }, {"name":"getVersion","parameterTypes":[] }, {"name":"setBody","parameterTypes":["java.lang.String"] }, {"name":"setHeaders","parameterTypes":["java.util.Map"] }, {"name":"setHttpMethod","parameterTypes":["java.lang.String"] }, {"name":"setIsBase64Encoded","parameterTypes":["java.lang.Boolean"] }, {"name":"setPath","parameterTypes":["java.lang.String"] }, {"name":"setPathParameters","parameterTypes":["java.util.Map"] }, {"name":"setQueryStringParameters","parameterTypes":["java.util.Map"] }, {"name":"setRequestContext","parameterTypes":["com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent$ProxyRequestContext"] }, {"name":"setResource","parameterTypes":["java.lang.String"] }, {"name":"setStageVariables","parameterTypes":["java.util.Map"] }] +}, +{ + "name":"com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent$ProxyRequestContext", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"getAccountId","parameterTypes":[] }, {"name":"getApiId","parameterTypes":[] }, {"name":"getAuthorizer","parameterTypes":[] }, {"name":"getDomainName","parameterTypes":[] }, {"name":"getDomainPrefix","parameterTypes":[] }, {"name":"getExtendedRequestId","parameterTypes":[] }, {"name":"getHttpMethod","parameterTypes":[] }, {"name":"getIdentity","parameterTypes":[] }, {"name":"getOperationName","parameterTypes":[] }, {"name":"getPath","parameterTypes":[] }, {"name":"getProtocol","parameterTypes":[] }, {"name":"getRequestId","parameterTypes":[] }, {"name":"getRequestTime","parameterTypes":[] }, {"name":"getRequestTimeEpoch","parameterTypes":[] }, {"name":"getResourceId","parameterTypes":[] }, {"name":"getResourcePath","parameterTypes":[] }, {"name":"getStage","parameterTypes":[] }, {"name":"setAccountId","parameterTypes":["java.lang.String"] }, {"name":"setApiId","parameterTypes":["java.lang.String"] }, {"name":"setHttpMethod","parameterTypes":["java.lang.String"] }, {"name":"setIdentity","parameterTypes":["com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent$RequestIdentity"] }, {"name":"setPath","parameterTypes":["java.lang.String"] }, {"name":"setProtocol","parameterTypes":["java.lang.String"] }, {"name":"setRequestId","parameterTypes":["java.lang.String"] }, {"name":"setRequestTime","parameterTypes":["java.lang.String"] }, {"name":"setRequestTimeEpoch","parameterTypes":["java.lang.Long"] }, {"name":"setResourceId","parameterTypes":["java.lang.String"] }, {"name":"setResourcePath","parameterTypes":["java.lang.String"] }, {"name":"setStage","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent$RequestIdentity", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"getAccessKey","parameterTypes":[] }, {"name":"getAccountId","parameterTypes":[] }, {"name":"getApiKey","parameterTypes":[] }, {"name":"getCaller","parameterTypes":[] }, {"name":"getCognitoAuthenticationProvider","parameterTypes":[] }, {"name":"getCognitoAuthenticationType","parameterTypes":[] }, {"name":"getCognitoIdentityId","parameterTypes":[] }, {"name":"getCognitoIdentityPoolId","parameterTypes":[] }, {"name":"getPrincipalOrgId","parameterTypes":[] }, {"name":"getSourceIp","parameterTypes":[] }, {"name":"getUser","parameterTypes":[] }, {"name":"getUserAgent","parameterTypes":[] }, {"name":"getUserArn","parameterTypes":[] }, {"name":"setAccessKey","parameterTypes":["java.lang.String"] }, {"name":"setAccountId","parameterTypes":["java.lang.String"] }, {"name":"setCaller","parameterTypes":["java.lang.String"] }, {"name":"setCognitoAuthenticationProvider","parameterTypes":["java.lang.String"] }, {"name":"setCognitoAuthenticationType","parameterTypes":["java.lang.String"] }, {"name":"setCognitoIdentityId","parameterTypes":["java.lang.String"] }, {"name":"setCognitoIdentityPoolId","parameterTypes":["java.lang.String"] }, {"name":"setSourceIp","parameterTypes":["java.lang.String"] }, {"name":"setUser","parameterTypes":["java.lang.String"] }, {"name":"setUserAgent","parameterTypes":["java.lang.String"] }, {"name":"setUserArn","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"getBody","parameterTypes":[] }, {"name":"getHeaders","parameterTypes":[] }, {"name":"getIsBase64Encoded","parameterTypes":[] }, {"name":"getMultiValueHeaders","parameterTypes":[] }, {"name":"getStatusCode","parameterTypes":[] }, {"name":"setBody","parameterTypes":["java.lang.String"] }, {"name":"setHeaders","parameterTypes":["java.util.Map"] }, {"name":"setStatusCode","parameterTypes":["java.lang.Integer"] }] +}, +{ + "name":"com.amazonaws.xray.handlers.config.AWSOperationHandler", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.amazonaws.xray.handlers.config.AWSOperationHandlerManifest", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.amazonaws.xray.handlers.config.AWSOperationHandlerRequestDescriptor", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.amazonaws.xray.handlers.config.AWSOperationHandlerResponseDescriptor", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.amazonaws.xray.handlers.config.AWSServiceHandlerManifest", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.amazonaws.xray.interceptors.TracingInterceptor", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.amazonaws.xray.strategy.sampling.manifest.SamplingRuleManifest", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"setDefaultRule","parameterTypes":["com.amazonaws.xray.strategy.sampling.rule.SamplingRule"] }, {"name":"setRules","parameterTypes":["java.util.List"] }, {"name":"setVersion","parameterTypes":["int"] }] +}, +{ + "name":"com.amazonaws.xray.strategy.sampling.reservoir.Reservoir", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"com.amazonaws.xray.strategy.sampling.rule.SamplingRule", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"setFixedTarget","parameterTypes":["int"] }, {"name":"setRate","parameterTypes":["float"] }] +}, +{ + "name":"com.fasterxml.jackson.databind.ext.Java7SupportImpl", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.sun.crypto.provider.AESCipher$General", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.sun.crypto.provider.ARCFOURCipher", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.sun.crypto.provider.ChaCha20Cipher$ChaCha20Poly1305", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.sun.crypto.provider.DESCipher", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.sun.crypto.provider.DESedeCipher", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.sun.crypto.provider.GaloisCounterMode$AESGCM", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.sun.crypto.provider.HmacCore$HmacSHA256", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"java.io.IOException", + "methods":[{"name":"","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"java.io.Serializable", + "queryAllDeclaredMethods":true +}, +{ + "name":"java.lang.Cloneable", + "queryAllDeclaredMethods":true +}, +{ + "name":"java.lang.ProcessEnvironment", + "fields":[{"name":"theCaseInsensitiveEnvironment"}, {"name":"theEnvironment"}] +}, +{ + "name":"java.lang.String" +}, +{ + "name":"java.lang.Thread", + "fields":[{"name":"threadLocalRandomProbe"}], + "methods":[{"name":"getContextClassLoader","parameterTypes":[] }] +}, +{ + "name":"java.security.AlgorithmParametersSpi" +}, +{ + "name":"java.security.KeyStoreSpi" +}, +{ + "name":"java.security.SecureRandomParameters" +}, +{ + "name":"java.util.Collections$UnmodifiableMap", + "fields":[{"name":"m"}] +}, +{ + "name":"java.util.concurrent.atomic.AtomicBoolean", + "fields":[{"name":"value"}] +}, +{ + "name":"java.util.concurrent.atomic.AtomicReference", + "fields":[{"name":"value"}] +}, +{ + "name":"java.util.concurrent.atomic.Striped64", + "fields":[{"name":"base"}, {"name":"cellsBusy"}] +}, +{ + "name":"javax.crac.Resource" +}, +{ + "name":"javax.security.auth.x500.X500Principal", + "fields":[{"name":"thisX500Name"}], + "methods":[{"name":"","parameterTypes":["sun.security.x509.X500Name"] }] +}, +{ + "name":"jdk.crac.Resource" +}, +{ + "name":"kotlin.Metadata" +}, +{ + "name":"kotlin.Unit" +}, +{ + "name":"org.apache.commons.logging.LogFactory" +}, +{ + "name":"org.apache.commons.logging.impl.Jdk14Logger", + "methods":[{"name":"","parameterTypes":["java.lang.String"] }, {"name":"setLogFactory","parameterTypes":["org.apache.commons.logging.LogFactory"] }] +}, +{ + "name":"org.apache.commons.logging.impl.Log4JLogger" +}, +{ + "name":"org.apache.commons.logging.impl.LogFactoryImpl", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.apache.commons.logging.impl.WeakHashtable", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.apiguardian.api.API", + "queryAllPublicMethods":true +}, +{ + "name":"org.joda.time.DateTime" +}, +{ + "name":"scala.util.Properties" +}, +{ + "name":"software.amazon.awssdk.enhanced.dynamodb.internal.ApplyUserAgentInterceptor", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sun.security.pkcs12.PKCS12KeyStore", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sun.security.pkcs12.PKCS12KeyStore$DualFormatPKCS12", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sun.security.provider.MD5", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sun.security.provider.NativePRNG", + "methods":[{"name":"","parameterTypes":[] }, {"name":"","parameterTypes":["java.security.SecureRandomParameters"] }] +}, +{ + "name":"sun.security.provider.SHA", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sun.security.provider.SHA2$SHA256", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sun.security.provider.X509Factory", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sun.security.rsa.RSAKeyFactory$Legacy", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sun.security.ssl.SSLContextImpl$TLSContext", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sun.security.ssl.TrustManagerFactoryImpl$PKIXFactory", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sun.security.x509.AuthorityInfoAccessExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.AuthorityKeyIdentifierExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.BasicConstraintsExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.CRLDistributionPointsExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.CertificatePoliciesExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.ExtendedKeyUsageExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.KeyUsageExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.NetscapeCertTypeExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.PrivateKeyUsageExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.SubjectKeyIdentifierExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +} +] diff --git a/powertools-idempotency/powertools-idempotency-dynamodb/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-idempotency-dynamodb/resource-config.json b/powertools-idempotency/powertools-idempotency-dynamodb/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-idempotency-dynamodb/resource-config.json new file mode 100644 index 000000000..98e775bb6 --- /dev/null +++ b/powertools-idempotency/powertools-idempotency-dynamodb/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-idempotency-dynamodb/resource-config.json @@ -0,0 +1,27 @@ +{ + "resources":{ + "includes":[{ + "pattern":"\\QMETA-INF/services/java.lang.System$LoggerFinder\\E" + }, { + "pattern":"\\QMETA-INF/services/java.net.spi.InetAddressResolverProvider\\E" + }, { + "pattern":"\\QMETA-INF/services/java.net.spi.URLStreamHandlerProvider\\E" + }, { + "pattern":"\\QMETA-INF/services/org.apache.commons.logging.LogFactory\\E" + }, { + "pattern":"\\QMETA-INF/services/org.slf4j.spi.SLF4JServiceProvider\\E" + }, { + "pattern":"\\Qcom/amazonaws/xray/interceptors/DefaultOperationParameterWhitelist.json\\E" + }, { + "pattern":"\\Qcom/amazonaws/xray/sdk.properties\\E" + }, { + "pattern":"\\Qcom/amazonaws/xray/strategy/sampling/DefaultSamplingRules.json\\E" + }, { + "pattern":"\\Qcommons-logging.properties\\E" + }, { + "pattern":"\\Qsoftware/amazon/awssdk/global/handlers/execution.interceptors\\E" + }, { + "pattern":"\\Qsoftware/amazon/awssdk/services/dynamodb/execution.interceptors\\E" + }]}, + "bundles":[] +} From 9008aac3e0aaadda8870b8af82d3e87bfd7f2143 Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Thu, 21 Aug 2025 09:05:59 +0000 Subject: [PATCH 33/65] Revert "PoC for Metrics and Logging UA Configuration." This reverts commit 1681e19f352d899a651ba870f826aa8f43a99652. --- .../sam/pom.xml | 5 --- .../sam/src/main/java/helloworld/App.java | 26 ------------- .../sam/template.yaml | 11 ------ .../internal/UserAgentConfigurator.java | 20 +++------- .../internal/UserAgentConfiguratorTest.java | 16 ++------ .../powertools-logging-log4j/pom.xml | 9 +---- .../internal/LoggingUserAgentInterceptor.java | 37 ------------------- .../global/handlers/execution.interceptors | 1 - powertools-metrics/pom.xml | 5 --- .../internal/MetricsUserAgentInterceptor.java | 37 ------------------- .../global/handlers/execution.interceptors | 1 - 11 files changed, 12 insertions(+), 156 deletions(-) delete mode 100644 powertools-logging/powertools-logging-log4j/src/main/java/software/amazon/lambda/powertools/logging/log4/internal/LoggingUserAgentInterceptor.java delete mode 100644 powertools-logging/powertools-logging-log4j/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors delete mode 100644 powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/MetricsUserAgentInterceptor.java delete mode 100644 powertools-metrics/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors diff --git a/examples/powertools-examples-core-utilities/sam/pom.xml b/examples/powertools-examples-core-utilities/sam/pom.xml index b184f402f..3df44f441 100644 --- a/examples/powertools-examples-core-utilities/sam/pom.xml +++ b/examples/powertools-examples-core-utilities/sam/pom.xml @@ -45,11 +45,6 @@ aspectjrt ${aspectj.version} - - software.amazon.awssdk - s3 - 2.32.8 - diff --git a/examples/powertools-examples-core-utilities/sam/src/main/java/helloworld/App.java b/examples/powertools-examples-core-utilities/sam/src/main/java/helloworld/App.java index 4a1d86205..2675c96eb 100644 --- a/examples/powertools-examples-core-utilities/sam/src/main/java/helloworld/App.java +++ b/examples/powertools-examples-core-utilities/sam/src/main/java/helloworld/App.java @@ -34,13 +34,6 @@ import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; -import software.amazon.awssdk.auth.credentials.EnvironmentVariableCredentialsProvider; -import software.amazon.awssdk.core.SdkSystemSetting; -import software.amazon.awssdk.core.interceptor.ExecutionAttributes; -import software.amazon.awssdk.core.interceptor.ExecutionInterceptor; -import software.amazon.awssdk.http.SdkHttpRequest; -import software.amazon.awssdk.regions.Region; -import software.amazon.awssdk.services.s3.S3Client; import software.amazon.lambda.powertools.logging.Logging; import software.amazon.lambda.powertools.metrics.FlushMetrics; import software.amazon.lambda.powertools.metrics.Metrics; @@ -57,32 +50,13 @@ */ public class App implements RequestHandler { private static final Logger log = LoggerFactory.getLogger(App.class); - private static final S3Client s3Client = S3Client.builder() - .region(Region.of(System.getenv(SdkSystemSetting.AWS_REGION.environmentVariable()))) - .credentialsProvider(EnvironmentVariableCredentialsProvider.create()) - .overrideConfiguration(c -> c.addExecutionInterceptor(new ExecutionInterceptor() { - @Override - public void beforeTransmission( - software.amazon.awssdk.core.interceptor.Context.BeforeTransmission context, - ExecutionAttributes executionAttributes) { - SdkHttpRequest request = context.httpRequest(); - log.info("User-Agent header: {}", request.headers().get("User-Agent")); - } - })) - .build(); private static final Metrics metrics = MetricsFactory.getMetricsInstance(); - public App() { - log.info("sdk.ua.appId system property: {}", System.getProperty("sdk.ua.appId")); - s3Client.listBuckets(); - } - @Logging(logEvent = true, samplingRate = 0.7) @Tracing(captureMode = CaptureMode.RESPONSE_AND_ERROR) @FlushMetrics(namespace = "ServerlessAirline", service = "payment", captureColdStart = true) public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) { Map headers = new HashMap<>(); - s3Client.listBuckets(); headers.put("Content-Type", "application/json"); headers.put("X-Custom-Header", "application/json"); diff --git a/examples/powertools-examples-core-utilities/sam/template.yaml b/examples/powertools-examples-core-utilities/sam/template.yaml index af0a553fb..9a51a1ba9 100644 --- a/examples/powertools-examples-core-utilities/sam/template.yaml +++ b/examples/powertools-examples-core-utilities/sam/template.yaml @@ -19,22 +19,11 @@ Globals: POWERTOOLS_METRICS_NAMESPACE: Coreutilities Resources: - TestBucket: - Type: AWS::S3::Bucket - HelloWorldFunction: Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction Properties: CodeUri: . Handler: helloworld.App::handleRequest - Policies: - - S3ReadPolicy: - BucketName: !Ref TestBucket - - Statement: - - Effect: Allow - Action: - - s3:ListAllMyBuckets - Resource: "*" Environment: # More info about Env Vars: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#environment-object Variables: POWERTOOLS_SERVICE_NAME: hello diff --git a/powertools-common/src/main/java/software/amazon/lambda/powertools/common/internal/UserAgentConfigurator.java b/powertools-common/src/main/java/software/amazon/lambda/powertools/common/internal/UserAgentConfigurator.java index 264598788..d2e592902 100644 --- a/powertools-common/src/main/java/software/amazon/lambda/powertools/common/internal/UserAgentConfigurator.java +++ b/powertools-common/src/main/java/software/amazon/lambda/powertools/common/internal/UserAgentConfigurator.java @@ -19,14 +19,14 @@ import java.io.IOException; import java.io.InputStream; import java.util.Properties; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; + /** * Can be used to create a string that can server as a User-Agent suffix in requests made with the AWS SDK clients */ -public final class UserAgentConfigurator { +public class UserAgentConfigurator { public static final String NA = "NA"; public static final String VERSION_KEY = "powertools.version"; @@ -37,7 +37,7 @@ public final class UserAgentConfigurator { private static final Logger LOG = LoggerFactory.getLogger(UserAgentConfigurator.class); private static final String NO_OP = "no-op"; private static final String POWERTOOLS_VERSION = getProjectVersion(); - private static final String USER_AGENT_PATTERN = "PT/" + PT_FEATURE_VARIABLE + "/" + POWERTOOLS_VERSION + " PTENV/" + private static final String USER_AGENT_PATTERN = "PT/" + PT_FEATURE_VARIABLE + "/" + POWERTOOLS_VERSION + " PTEnv/" + PT_EXEC_ENV_VARIABLE; private UserAgentConfigurator() { @@ -53,6 +53,7 @@ static String getProjectVersion() { return getVersionFromProperties(VERSION_PROPERTIES_FILENAME, VERSION_KEY); } + /** * Retrieves the project version from a properties file. * The file should be in the resources folder. @@ -82,18 +83,9 @@ static String getVersionFromProperties(String propertyFileName, String versionKe return NA; } - /** - * Configures the AWS SDK to use Powertools user agent by setting the sdk.ua.appId system property. - * This should be called during library initialization to ensure the user agent is properly configured. - */ - public static void configureUserAgent(String ptFeature) { - System.out.println("CONFIGURE UA " + ptFeature); - System.setProperty("sdk.ua.appId", getUserAgent(ptFeature)); - } - /** * Retrieves the user agent string for the Powertools for AWS Lambda. - * It follows the pattern PT/{PT_FEATURE}/{PT_VERSION} PTENV/{PT_EXEC_ENV} + * It follows the pattern PT/{PT_FEATURE}/{PT_VERSION} PTEnv/{PT_EXEC_ENV} * The version of the project is automatically retrieved. * The PT_EXEC_ENV is automatically retrieved from the AWS_EXECUTION_ENV environment variable. * If it AWS_EXECUTION_ENV is not set, PT_EXEC_ENV defaults to "NA" @@ -113,7 +105,7 @@ public static String getUserAgent(String ptFeature) { ptFeature = NO_OP; } return userAgent - .replace(PT_FEATURE_VARIABLE, ptFeature.toUpperCase()) + .replace(PT_FEATURE_VARIABLE, ptFeature) .replace(PT_EXEC_ENV_VARIABLE, ptExecEnv); } } diff --git a/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/UserAgentConfiguratorTest.java b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/UserAgentConfiguratorTest.java index ba33de49a..0c7935a55 100644 --- a/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/UserAgentConfiguratorTest.java +++ b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/UserAgentConfiguratorTest.java @@ -91,7 +91,7 @@ void testGetUserAgent() { assertThat(userAgent) .isNotNull() - .isEqualTo("PT/TEST-FEATURE/" + VERSION + " PTENV/NA"); + .isEqualTo("PT/test-feature/" + VERSION + " PTEnv/NA"); } @@ -101,7 +101,7 @@ void testGetUserAgent_NoFeature() { assertThat(userAgent) .isNotNull() - .isEqualTo("PT/NO-OP/" + VERSION + " PTENV/NA"); + .isEqualTo("PT/no-op/" + VERSION + " PTEnv/NA"); } @Test @@ -110,7 +110,7 @@ void testGetUserAgent_NullFeature() { assertThat(userAgent) .isNotNull() - .isEqualTo("PT/NO-OP/" + VERSION + " PTENV/NA"); + .isEqualTo("PT/no-op/" + VERSION + " PTEnv/NA"); } @Test @@ -120,15 +120,7 @@ void testGetUserAgent_SetAWSExecutionEnv() { assertThat(userAgent) .isNotNull() - .isEqualTo("PT/TEST-FEATURE/" + VERSION + " PTENV/AWS_Lambda_java8"); - } - - @Test - void testConfigureUserAgent() { - UserAgentConfigurator.configureUserAgent("test-feature"); - - assertThat(System.getProperty("sdk.ua.appId")) - .isEqualTo("PT/TEST-FEATURE/" + VERSION + " PTENV/NA"); + .isEqualTo("PT/test-feature/" + VERSION + " PTEnv/AWS_Lambda_java8"); } } diff --git a/powertools-logging/powertools-logging-log4j/pom.xml b/powertools-logging/powertools-logging-log4j/pom.xml index ad0c3c373..be8e4bc62 100644 --- a/powertools-logging/powertools-logging-log4j/pom.xml +++ b/powertools-logging/powertools-logging-log4j/pom.xml @@ -1,7 +1,7 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 @@ -39,11 +39,6 @@ org.apache.logging.log4j log4j-layout-template-json - - software.amazon.awssdk - sdk-core - provided - diff --git a/powertools-logging/powertools-logging-log4j/src/main/java/software/amazon/lambda/powertools/logging/log4/internal/LoggingUserAgentInterceptor.java b/powertools-logging/powertools-logging-log4j/src/main/java/software/amazon/lambda/powertools/logging/log4/internal/LoggingUserAgentInterceptor.java deleted file mode 100644 index a4d19363e..000000000 --- a/powertools-logging/powertools-logging-log4j/src/main/java/software/amazon/lambda/powertools/logging/log4/internal/LoggingUserAgentInterceptor.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * 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.logging.log4.internal; - -import software.amazon.awssdk.core.SdkRequest; -import software.amazon.awssdk.core.interceptor.Context; -import software.amazon.awssdk.core.interceptor.ExecutionAttributes; -import software.amazon.awssdk.core.interceptor.ExecutionInterceptor; -import software.amazon.lambda.powertools.common.internal.UserAgentConfigurator; - -/** - * Global interceptor that configures the User-Agent for all AWS SDK clients - * when the metrics module is on the classpath. - */ -public final class LoggingUserAgentInterceptor implements ExecutionInterceptor { - static { - UserAgentConfigurator.configureUserAgent("logging"); - } - - @Override - public SdkRequest modifyRequest(Context.ModifyRequest context, ExecutionAttributes executionAttributes) { - // This is a no-op interceptor. We use this class to configure the PT User-Agent in the static block. It is - // loaded by AWS SDK Global Interceptors. - return context.request(); - } -} diff --git a/powertools-logging/powertools-logging-log4j/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors b/powertools-logging/powertools-logging-log4j/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors deleted file mode 100644 index 7917018f2..000000000 --- a/powertools-logging/powertools-logging-log4j/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors +++ /dev/null @@ -1 +0,0 @@ -software.amazon.lambda.powertools.logging.log4.internal.LoggingUserAgentInterceptor diff --git a/powertools-metrics/pom.xml b/powertools-metrics/pom.xml index f2ec7dbc9..525e7cbea 100644 --- a/powertools-metrics/pom.xml +++ b/powertools-metrics/pom.xml @@ -73,11 +73,6 @@ org.apache.commons commons-lang3 - - software.amazon.awssdk - sdk-core - provided - diff --git a/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/MetricsUserAgentInterceptor.java b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/MetricsUserAgentInterceptor.java deleted file mode 100644 index 5a466cc3a..000000000 --- a/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/MetricsUserAgentInterceptor.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * 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 software.amazon.awssdk.core.SdkRequest; -import software.amazon.awssdk.core.interceptor.Context; -import software.amazon.awssdk.core.interceptor.ExecutionAttributes; -import software.amazon.awssdk.core.interceptor.ExecutionInterceptor; -import software.amazon.lambda.powertools.common.internal.UserAgentConfigurator; - -/** - * Global interceptor that configures the User-Agent for all AWS SDK clients - * when the metrics module is on the classpath. - */ -public final class MetricsUserAgentInterceptor implements ExecutionInterceptor { - static { - UserAgentConfigurator.configureUserAgent("metrics"); - } - - @Override - public SdkRequest modifyRequest(Context.ModifyRequest context, ExecutionAttributes executionAttributes) { - // This is a no-op interceptor. We use this class to configure the PT User-Agent in the static block. It is - // loaded by AWS SDK Global Interceptors. - return context.request(); - } -} diff --git a/powertools-metrics/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors b/powertools-metrics/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors deleted file mode 100644 index 544bd8ead..000000000 --- a/powertools-metrics/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors +++ /dev/null @@ -1 +0,0 @@ -software.amazon.lambda.powertools.metrics.internal.MetricsUserAgentInterceptor \ No newline at end of file From 16544eac74f08c5fae356de4b7e9d21607800c07 Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Thu, 14 Aug 2025 14:07:15 +0200 Subject: [PATCH 34/65] chore(ci): Run unit tests for GraalVM as well during build. --- .github/workflows/check-build.yml | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/.github/workflows/check-build.yml b/.github/workflows/check-build.yml index 32cd87011..a9bc60899 100644 --- a/.github/workflows/check-build.yml +++ b/.github/workflows/check-build.yml @@ -82,7 +82,7 @@ jobs: - id: build-maven name: Build (Maven) run: | - mvn -B -q install --file pom.xml + mvn -B install --file pom.xml graalvm-build: runs-on: ubuntu-latest @@ -99,17 +99,14 @@ jobs: - id: graalvm-native-test name: GraalVM Native Test run: | - # Build the entire project first to ensure test-jar dependencies are available - mvn -B -q install -DskipTests - - # Find modules with graalvm-native profile and run tests recursively. + # Find modules with graalvm-native profile and run tests. # This will make sure to discover new GraalVM supported modules automatically in the future. - find . -name "pom.xml" -path "./powertools-*" | while read module; do + for module in powertools-*/pom.xml; do if grep -q "graalvm-native" "$module"; then module_dir=$(dirname "$module") echo "Regenerating GraalVM metadata for $module_dir" - mvn -B -q -f "$module" -Pgenerate-graalvm-files clean test + mvn -B -f "$module" -Pgenerate-graalvm-files clean test echo "Running GraalVM native tests for $module_dir" - mvn -B -q -f "$module" -Pgraalvm-native test + mvn -B -f "$module" -Pgraalvm-native test fi done From 74026bada7d630431018b271ec42fca4d1aecc72 Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Thu, 14 Aug 2025 18:07:29 +0200 Subject: [PATCH 35/65] Test GraalVM unit tests on Mockito 5.16.0. --- pom.xml | 4 ++-- powertools-logging/pom.xml | 14 ++++++++++++++ .../powertools-logging-log4j/pom.xml | 14 ++++++++++++++ .../powertools-logging-logback/pom.xml | 14 ++++++++++++++ powertools-parameters/pom.xml | 14 ++++++++++++++ .../powertools-parameters-appconfig/pom.xml | 7 ------- .../powertools-parameters-dynamodb/pom.xml | 7 ------- .../powertools-parameters-secrets/pom.xml | 7 ------- .../powertools-parameters-ssm/pom.xml | 7 ------- .../powertools-parameters-tests/pom.xml | 7 ------- powertools-serialization/pom.xml | 14 ++++++++++++++ powertools-tracing/pom.xml | 14 ++++++++++++++ 12 files changed, 86 insertions(+), 37 deletions(-) diff --git a/pom.xml b/pom.xml index 1347603c7..53868c4c4 100644 --- a/pom.xml +++ b/pom.xml @@ -114,8 +114,8 @@ 1.12.781 2.18.0 1.7.0 - 5.19.1-SNAPSHOT - 5.19.1-SNAPSHOT + 5.16.0 + 5.16.0 2.3.0 1.5.0 diff --git a/powertools-logging/pom.xml b/powertools-logging/pom.xml index 4312ffbf6..0302f0bd0 100644 --- a/powertools-logging/pom.xml +++ b/powertools-logging/pom.xml @@ -118,6 +118,13 @@ generate-graalvm-files + + + org.mockito + mockito-subclass + test + + @@ -138,6 +145,13 @@ graalvm-native + + + org.mockito + mockito-subclass + test + + diff --git a/powertools-logging/powertools-logging-log4j/pom.xml b/powertools-logging/powertools-logging-log4j/pom.xml index be8e4bc62..a186a2e0d 100644 --- a/powertools-logging/powertools-logging-log4j/pom.xml +++ b/powertools-logging/powertools-logging-log4j/pom.xml @@ -97,6 +97,13 @@ generate-graalvm-files + + + org.mockito + mockito-subclass + test + + @@ -117,6 +124,13 @@ graalvm-native + + + org.mockito + mockito-subclass + test + + diff --git a/powertools-logging/powertools-logging-logback/pom.xml b/powertools-logging/powertools-logging-logback/pom.xml index 9f0b36dad..8b5ed98a7 100644 --- a/powertools-logging/powertools-logging-logback/pom.xml +++ b/powertools-logging/powertools-logging-logback/pom.xml @@ -90,6 +90,13 @@ generate-graalvm-files + + + org.mockito + mockito-subclass + test + + @@ -110,6 +117,13 @@ graalvm-native + + + org.mockito + mockito-subclass + test + + diff --git a/powertools-parameters/pom.xml b/powertools-parameters/pom.xml index 7e28ad556..d71bca681 100644 --- a/powertools-parameters/pom.xml +++ b/powertools-parameters/pom.xml @@ -93,6 +93,13 @@ generate-graalvm-files + + + org.mockito + mockito-subclass + test + + @@ -113,6 +120,13 @@ graalvm-native + + + org.mockito + mockito-subclass + test + + diff --git a/powertools-parameters/powertools-parameters-appconfig/pom.xml b/powertools-parameters/powertools-parameters-appconfig/pom.xml index c32bb4d12..adc8eac77 100644 --- a/powertools-parameters/powertools-parameters-appconfig/pom.xml +++ b/powertools-parameters/powertools-parameters-appconfig/pom.xml @@ -120,13 +120,6 @@ mockito-subclass test - - - - org.junit.jupiter - junit-jupiter-params - test - diff --git a/powertools-parameters/powertools-parameters-dynamodb/pom.xml b/powertools-parameters/powertools-parameters-dynamodb/pom.xml index c4ff00a38..bfe6f8398 100644 --- a/powertools-parameters/powertools-parameters-dynamodb/pom.xml +++ b/powertools-parameters/powertools-parameters-dynamodb/pom.xml @@ -121,13 +121,6 @@ mockito-subclass test - - - - org.junit.jupiter - junit-jupiter-params - test - diff --git a/powertools-parameters/powertools-parameters-secrets/pom.xml b/powertools-parameters/powertools-parameters-secrets/pom.xml index cf262b8d6..5b18d0b92 100644 --- a/powertools-parameters/powertools-parameters-secrets/pom.xml +++ b/powertools-parameters/powertools-parameters-secrets/pom.xml @@ -121,13 +121,6 @@ mockito-subclass test - - - - org.junit.jupiter - junit-jupiter-params - test - diff --git a/powertools-parameters/powertools-parameters-ssm/pom.xml b/powertools-parameters/powertools-parameters-ssm/pom.xml index a418d3f09..86fb4fea2 100644 --- a/powertools-parameters/powertools-parameters-ssm/pom.xml +++ b/powertools-parameters/powertools-parameters-ssm/pom.xml @@ -135,13 +135,6 @@ mockito-subclass test - - - - org.junit.jupiter - junit-jupiter-params - test - diff --git a/powertools-parameters/powertools-parameters-tests/pom.xml b/powertools-parameters/powertools-parameters-tests/pom.xml index 5db059123..386703808 100644 --- a/powertools-parameters/powertools-parameters-tests/pom.xml +++ b/powertools-parameters/powertools-parameters-tests/pom.xml @@ -131,13 +131,6 @@ mockito-subclass test - - - - org.junit.jupiter - junit-jupiter-params - test - diff --git a/powertools-serialization/pom.xml b/powertools-serialization/pom.xml index 911f47850..afb77b6d8 100644 --- a/powertools-serialization/pom.xml +++ b/powertools-serialization/pom.xml @@ -98,6 +98,13 @@ generate-graalvm-files + + + org.mockito + mockito-subclass + test + + @@ -115,6 +122,13 @@ graalvm-native + + + org.mockito + mockito-subclass + test + + diff --git a/powertools-tracing/pom.xml b/powertools-tracing/pom.xml index b6cac28aa..229ec96a1 100644 --- a/powertools-tracing/pom.xml +++ b/powertools-tracing/pom.xml @@ -123,6 +123,13 @@ generate-graalvm-files + + + org.mockito + mockito-subclass + test + + @@ -143,6 +150,13 @@ graalvm-native + + + org.mockito + mockito-subclass + test + + From 91d1a57683bf93ef3ad6e3c92b5b1cb27502ffda Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Thu, 14 Aug 2025 14:07:15 +0200 Subject: [PATCH 36/65] chore(ci): Run unit tests for GraalVM as well during build. --- .github/workflows/check-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/check-build.yml b/.github/workflows/check-build.yml index a9bc60899..f121a8003 100644 --- a/.github/workflows/check-build.yml +++ b/.github/workflows/check-build.yml @@ -74,7 +74,7 @@ jobs: name: Checkout repository uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Setup Java - uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 + uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 with: distribution: corretto java-version: ${{ matrix.java }} From fb50fed932441b23f2925d01b05dede495635d15 Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Mon, 25 Aug 2025 13:59:00 +0200 Subject: [PATCH 37/65] chore(ci): Run unit tests for GraalVM as well during build. (#2047) * chore(ci): Run unit tests for GraalVM as well during build. * Test GraalVM unit tests on Mockito 5.16.0. * Fix native tests in powertools-serialization. Remove mockito dependency there. * Remove mockito from powertools-common. * Remove mockito from powertools-metrics and re-use TestLamdaContext from powertools-common. * Remove mockito from powertools-serialization. * Remove mockito from powertools-logging. * Remove mockito from powertools-logging-log4j. * Add --initialize-at-build-time=org.junit.platform.launcher.core.DiscoveryIssueNotifier * Remove mockito from powertools-logging-logback. * Remove mockito from powertools-tracing. * Build project first to make sure test-jar dependencies are available for graalvm unit tests. * Enable maven quite mode and search recursively for graalvm profiles to make sure sub-sub-modules are also covered. * Add back Mockito to powertools-common. * Simplify graalvm config for logback and log4j modules. * Simplify graalvm config in powertools-logging. * Cleanup GRM files for logback module. * Simplify GraalVM config for powertools-metrics, powertools-serialization, powertools-tracing. * Remove comment. * Simplify powertools-parameters-tests GraalVM config and fix issues in unit tests. * Simplify powertools-parameters-ssm GraalVM config and fix issues in unit tests. * Simplify powertools-parameters-secrets GraalVM config and fix issues in unit tests. * Simplify powertools-parameters-dynamodb GraalVM config and fix issues in unit tests. * Simplify powertools-parameters-appconfig GraalVM config and fix issues in unit tests. * Fix SonarCube finding. * Allowlist UPL-1.0 license. * Add TT ID to UPL license. * Enable Maven Central snapshot repo temporarily. * Potential fix for code scanning alert no. 54: Workflow does not contain permissions Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> * Disable verbose resource registration logs. --------- Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> --- .github/workflows/check-build.yml | 15 ++++++++++----- pom.xml | 19 +++++++++++++++++-- powertools-common/pom.xml | 1 - powertools-logging/pom.xml | 15 --------------- .../powertools-logging-log4j/pom.xml | 19 ++----------------- .../powertools-logging-logback/pom.xml | 15 --------------- powertools-metrics/pom.xml | 1 - powertools-parameters/pom.xml | 15 --------------- .../powertools-parameters-appconfig/pom.xml | 8 +++++++- .../powertools-parameters-dynamodb/pom.xml | 8 +++++++- .../powertools-parameters-secrets/pom.xml | 8 +++++++- .../powertools-parameters-ssm/pom.xml | 8 +++++++- .../powertools-parameters-tests/pom.xml | 8 +++++++- powertools-serialization/pom.xml | 15 --------------- powertools-tracing/pom.xml | 15 --------------- 15 files changed, 64 insertions(+), 106 deletions(-) diff --git a/.github/workflows/check-build.yml b/.github/workflows/check-build.yml index f121a8003..72070ed9e 100644 --- a/.github/workflows/check-build.yml +++ b/.github/workflows/check-build.yml @@ -58,6 +58,8 @@ on: - '.github/workflows/**' name: Build +permissions: + contents: read run-name: Build - ${{ github.event_name }} jobs: @@ -82,7 +84,7 @@ jobs: - id: build-maven name: Build (Maven) run: | - mvn -B install --file pom.xml + mvn -B -q install --file pom.xml graalvm-build: runs-on: ubuntu-latest @@ -99,14 +101,17 @@ jobs: - id: graalvm-native-test name: GraalVM Native Test run: | - # Find modules with graalvm-native profile and run tests. + # Build the entire project first to ensure test-jar dependencies are available + mvn -B -q install -DskipTests + + # Find modules with graalvm-native profile and run tests recursively. # This will make sure to discover new GraalVM supported modules automatically in the future. - for module in powertools-*/pom.xml; do + find . -name "pom.xml" -path "./powertools-*" | while read module; do if grep -q "graalvm-native" "$module"; then module_dir=$(dirname "$module") echo "Regenerating GraalVM metadata for $module_dir" - mvn -B -f "$module" -Pgenerate-graalvm-files clean test + mvn -B -q -f "$module" -Pgenerate-graalvm-files clean test echo "Running GraalVM native tests for $module_dir" - mvn -B -f "$module" -Pgraalvm-native test + mvn -B -q -f "$module" -Pgraalvm-native test fi done diff --git a/pom.xml b/pom.xml index 53868c4c4..bdafe88e1 100644 --- a/pom.xml +++ b/pom.xml @@ -114,8 +114,8 @@ 1.12.781 2.18.0 1.7.0 - 5.16.0 - 5.16.0 + 5.19.1-SNAPSHOT + 5.19.1-SNAPSHOT 2.3.0 1.5.0 @@ -131,6 +131,21 @@ + + + + Central Portal Snapshots + central-portal-snapshots + https://central.sonatype.com/repository/maven-snapshots/ + + false + + + true + + + + diff --git a/powertools-common/pom.xml b/powertools-common/pom.xml index 8a9d06460..ea9baa98c 100644 --- a/powertools-common/pom.xml +++ b/powertools-common/pom.xml @@ -149,7 +149,6 @@ --verbose --native-image-info -H:+UnlockExperimentalVMOptions - -H:Log=registerResource:5 -H:+ReportExceptionStackTraces diff --git a/powertools-logging/pom.xml b/powertools-logging/pom.xml index 0302f0bd0..7a288870a 100644 --- a/powertools-logging/pom.xml +++ b/powertools-logging/pom.xml @@ -118,13 +118,6 @@ generate-graalvm-files - - - org.mockito - mockito-subclass - test - - @@ -145,13 +138,6 @@ graalvm-native - - - org.mockito - mockito-subclass - test - - @@ -177,7 +163,6 @@ --verbose --native-image-info -H:+UnlockExperimentalVMOptions - -H:Log=registerResource:5 -H:+ReportExceptionStackTraces diff --git a/powertools-logging/powertools-logging-log4j/pom.xml b/powertools-logging/powertools-logging-log4j/pom.xml index a186a2e0d..836f8c53f 100644 --- a/powertools-logging/powertools-logging-log4j/pom.xml +++ b/powertools-logging/powertools-logging-log4j/pom.xml @@ -1,7 +1,7 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 @@ -97,13 +97,6 @@ generate-graalvm-files - - - org.mockito - mockito-subclass - test - - @@ -124,13 +117,6 @@ graalvm-native - - - org.mockito - mockito-subclass - test - - @@ -159,7 +145,6 @@ --verbose --native-image-info -H:+UnlockExperimentalVMOptions - -H:Log=registerResource:5 -H:+ReportExceptionStackTraces diff --git a/powertools-logging/powertools-logging-logback/pom.xml b/powertools-logging/powertools-logging-logback/pom.xml index 8b5ed98a7..433a3774a 100644 --- a/powertools-logging/powertools-logging-logback/pom.xml +++ b/powertools-logging/powertools-logging-logback/pom.xml @@ -90,13 +90,6 @@ generate-graalvm-files - - - org.mockito - mockito-subclass - test - - @@ -117,13 +110,6 @@ graalvm-native - - - org.mockito - mockito-subclass - test - - @@ -152,7 +138,6 @@ --verbose --native-image-info -H:+UnlockExperimentalVMOptions - -H:Log=registerResource:5 -H:+ReportExceptionStackTraces diff --git a/powertools-metrics/pom.xml b/powertools-metrics/pom.xml index 525e7cbea..4bccab505 100644 --- a/powertools-metrics/pom.xml +++ b/powertools-metrics/pom.xml @@ -179,7 +179,6 @@ --verbose --native-image-info -H:+UnlockExperimentalVMOptions - -H:Log=registerResource:5 -H:+ReportExceptionStackTraces diff --git a/powertools-parameters/pom.xml b/powertools-parameters/pom.xml index d71bca681..617e0cc00 100644 --- a/powertools-parameters/pom.xml +++ b/powertools-parameters/pom.xml @@ -93,13 +93,6 @@ generate-graalvm-files - - - org.mockito - mockito-subclass - test - - @@ -120,13 +113,6 @@ graalvm-native - - - org.mockito - mockito-subclass - test - - @@ -152,7 +138,6 @@ --verbose --native-image-info -H:+UnlockExperimentalVMOptions - -H:Log=registerResource:5 -H:+ReportExceptionStackTraces diff --git a/powertools-parameters/powertools-parameters-appconfig/pom.xml b/powertools-parameters/powertools-parameters-appconfig/pom.xml index adc8eac77..ed92930fc 100644 --- a/powertools-parameters/powertools-parameters-appconfig/pom.xml +++ b/powertools-parameters/powertools-parameters-appconfig/pom.xml @@ -120,6 +120,13 @@ mockito-subclass test + + + + org.junit.jupiter + junit-jupiter-params + test + @@ -146,7 +153,6 @@ --verbose --native-image-info -H:+UnlockExperimentalVMOptions - -H:Log=registerResource:5 -H:+ReportExceptionStackTraces diff --git a/powertools-parameters/powertools-parameters-dynamodb/pom.xml b/powertools-parameters/powertools-parameters-dynamodb/pom.xml index bfe6f8398..b8857b0c9 100644 --- a/powertools-parameters/powertools-parameters-dynamodb/pom.xml +++ b/powertools-parameters/powertools-parameters-dynamodb/pom.xml @@ -121,6 +121,13 @@ mockito-subclass test + + + + org.junit.jupiter + junit-jupiter-params + test + @@ -147,7 +154,6 @@ --verbose --native-image-info -H:+UnlockExperimentalVMOptions - -H:Log=registerResource:5 -H:+ReportExceptionStackTraces diff --git a/powertools-parameters/powertools-parameters-secrets/pom.xml b/powertools-parameters/powertools-parameters-secrets/pom.xml index 5b18d0b92..b486a1bb3 100644 --- a/powertools-parameters/powertools-parameters-secrets/pom.xml +++ b/powertools-parameters/powertools-parameters-secrets/pom.xml @@ -121,6 +121,13 @@ mockito-subclass test + + + + org.junit.jupiter + junit-jupiter-params + test + @@ -147,7 +154,6 @@ --verbose --native-image-info -H:+UnlockExperimentalVMOptions - -H:Log=registerResource:5 -H:+ReportExceptionStackTraces diff --git a/powertools-parameters/powertools-parameters-ssm/pom.xml b/powertools-parameters/powertools-parameters-ssm/pom.xml index 86fb4fea2..709ea6634 100644 --- a/powertools-parameters/powertools-parameters-ssm/pom.xml +++ b/powertools-parameters/powertools-parameters-ssm/pom.xml @@ -135,6 +135,13 @@ mockito-subclass test + + + + org.junit.jupiter + junit-jupiter-params + test + @@ -161,7 +168,6 @@ --verbose --native-image-info -H:+UnlockExperimentalVMOptions - -H:Log=registerResource:5 -H:+ReportExceptionStackTraces diff --git a/powertools-parameters/powertools-parameters-tests/pom.xml b/powertools-parameters/powertools-parameters-tests/pom.xml index 386703808..6dcf2c4ae 100644 --- a/powertools-parameters/powertools-parameters-tests/pom.xml +++ b/powertools-parameters/powertools-parameters-tests/pom.xml @@ -131,6 +131,13 @@ mockito-subclass test + + + + org.junit.jupiter + junit-jupiter-params + test + @@ -157,7 +164,6 @@ --verbose --native-image-info -H:+UnlockExperimentalVMOptions - -H:Log=registerResource:5 -H:+ReportExceptionStackTraces diff --git a/powertools-serialization/pom.xml b/powertools-serialization/pom.xml index afb77b6d8..7e4e2af15 100644 --- a/powertools-serialization/pom.xml +++ b/powertools-serialization/pom.xml @@ -98,13 +98,6 @@ generate-graalvm-files - - - org.mockito - mockito-subclass - test - - @@ -122,13 +115,6 @@ graalvm-native - - - org.mockito - mockito-subclass - test - - @@ -154,7 +140,6 @@ --verbose --native-image-info -H:+UnlockExperimentalVMOptions - -H:Log=registerResource:5 -H:+ReportExceptionStackTraces diff --git a/powertools-tracing/pom.xml b/powertools-tracing/pom.xml index 229ec96a1..67de0be7d 100644 --- a/powertools-tracing/pom.xml +++ b/powertools-tracing/pom.xml @@ -123,13 +123,6 @@ generate-graalvm-files - - - org.mockito - mockito-subclass - test - - @@ -150,13 +143,6 @@ graalvm-native - - - org.mockito - mockito-subclass - test - - @@ -183,7 +169,6 @@ --verbose --native-image-info -H:+UnlockExperimentalVMOptions - -H:Log=registerResource:5 -H:+ReportExceptionStackTraces From a42e1fb8a7769b1f5b74df54b1eabf775f0a2de5 Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Tue, 19 Aug 2025 11:05:25 +0200 Subject: [PATCH 38/65] PoC for Metrics and Logging UA Configuration. --- .../sam/pom.xml | 5 +++ .../sam/src/main/java/helloworld/App.java | 26 +++++++++++++ .../sam/template.yaml | 11 ++++++ .../internal/UserAgentConfigurator.java | 20 +++++++--- .../internal/UserAgentConfiguratorTest.java | 16 ++++++-- .../powertools-logging-log4j/pom.xml | 5 +++ .../internal/LoggingUserAgentInterceptor.java | 37 +++++++++++++++++++ .../global/handlers/execution.interceptors | 1 + powertools-metrics/pom.xml | 5 +++ .../internal/MetricsUserAgentInterceptor.java | 37 +++++++++++++++++++ .../global/handlers/execution.interceptors | 1 + 11 files changed, 154 insertions(+), 10 deletions(-) create mode 100644 powertools-logging/powertools-logging-log4j/src/main/java/software/amazon/lambda/powertools/logging/log4/internal/LoggingUserAgentInterceptor.java create mode 100644 powertools-logging/powertools-logging-log4j/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors create mode 100644 powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/MetricsUserAgentInterceptor.java create mode 100644 powertools-metrics/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors diff --git a/examples/powertools-examples-core-utilities/sam/pom.xml b/examples/powertools-examples-core-utilities/sam/pom.xml index 3df44f441..b184f402f 100644 --- a/examples/powertools-examples-core-utilities/sam/pom.xml +++ b/examples/powertools-examples-core-utilities/sam/pom.xml @@ -45,6 +45,11 @@ aspectjrt ${aspectj.version} + + software.amazon.awssdk + s3 + 2.32.8 + diff --git a/examples/powertools-examples-core-utilities/sam/src/main/java/helloworld/App.java b/examples/powertools-examples-core-utilities/sam/src/main/java/helloworld/App.java index 2675c96eb..4a1d86205 100644 --- a/examples/powertools-examples-core-utilities/sam/src/main/java/helloworld/App.java +++ b/examples/powertools-examples-core-utilities/sam/src/main/java/helloworld/App.java @@ -34,6 +34,13 @@ import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; +import software.amazon.awssdk.auth.credentials.EnvironmentVariableCredentialsProvider; +import software.amazon.awssdk.core.SdkSystemSetting; +import software.amazon.awssdk.core.interceptor.ExecutionAttributes; +import software.amazon.awssdk.core.interceptor.ExecutionInterceptor; +import software.amazon.awssdk.http.SdkHttpRequest; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.s3.S3Client; import software.amazon.lambda.powertools.logging.Logging; import software.amazon.lambda.powertools.metrics.FlushMetrics; import software.amazon.lambda.powertools.metrics.Metrics; @@ -50,13 +57,32 @@ */ public class App implements RequestHandler { private static final Logger log = LoggerFactory.getLogger(App.class); + private static final S3Client s3Client = S3Client.builder() + .region(Region.of(System.getenv(SdkSystemSetting.AWS_REGION.environmentVariable()))) + .credentialsProvider(EnvironmentVariableCredentialsProvider.create()) + .overrideConfiguration(c -> c.addExecutionInterceptor(new ExecutionInterceptor() { + @Override + public void beforeTransmission( + software.amazon.awssdk.core.interceptor.Context.BeforeTransmission context, + ExecutionAttributes executionAttributes) { + SdkHttpRequest request = context.httpRequest(); + log.info("User-Agent header: {}", request.headers().get("User-Agent")); + } + })) + .build(); private static final Metrics metrics = MetricsFactory.getMetricsInstance(); + public App() { + log.info("sdk.ua.appId system property: {}", System.getProperty("sdk.ua.appId")); + s3Client.listBuckets(); + } + @Logging(logEvent = true, samplingRate = 0.7) @Tracing(captureMode = CaptureMode.RESPONSE_AND_ERROR) @FlushMetrics(namespace = "ServerlessAirline", service = "payment", captureColdStart = true) public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) { Map headers = new HashMap<>(); + s3Client.listBuckets(); headers.put("Content-Type", "application/json"); headers.put("X-Custom-Header", "application/json"); diff --git a/examples/powertools-examples-core-utilities/sam/template.yaml b/examples/powertools-examples-core-utilities/sam/template.yaml index 9a51a1ba9..af0a553fb 100644 --- a/examples/powertools-examples-core-utilities/sam/template.yaml +++ b/examples/powertools-examples-core-utilities/sam/template.yaml @@ -19,11 +19,22 @@ Globals: POWERTOOLS_METRICS_NAMESPACE: Coreutilities Resources: + TestBucket: + Type: AWS::S3::Bucket + HelloWorldFunction: Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction Properties: CodeUri: . Handler: helloworld.App::handleRequest + Policies: + - S3ReadPolicy: + BucketName: !Ref TestBucket + - Statement: + - Effect: Allow + Action: + - s3:ListAllMyBuckets + Resource: "*" Environment: # More info about Env Vars: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#environment-object Variables: POWERTOOLS_SERVICE_NAME: hello diff --git a/powertools-common/src/main/java/software/amazon/lambda/powertools/common/internal/UserAgentConfigurator.java b/powertools-common/src/main/java/software/amazon/lambda/powertools/common/internal/UserAgentConfigurator.java index d2e592902..264598788 100644 --- a/powertools-common/src/main/java/software/amazon/lambda/powertools/common/internal/UserAgentConfigurator.java +++ b/powertools-common/src/main/java/software/amazon/lambda/powertools/common/internal/UserAgentConfigurator.java @@ -19,14 +19,14 @@ import java.io.IOException; import java.io.InputStream; import java.util.Properties; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; - /** * Can be used to create a string that can server as a User-Agent suffix in requests made with the AWS SDK clients */ -public class UserAgentConfigurator { +public final class UserAgentConfigurator { public static final String NA = "NA"; public static final String VERSION_KEY = "powertools.version"; @@ -37,7 +37,7 @@ public class UserAgentConfigurator { private static final Logger LOG = LoggerFactory.getLogger(UserAgentConfigurator.class); private static final String NO_OP = "no-op"; private static final String POWERTOOLS_VERSION = getProjectVersion(); - private static final String USER_AGENT_PATTERN = "PT/" + PT_FEATURE_VARIABLE + "/" + POWERTOOLS_VERSION + " PTEnv/" + private static final String USER_AGENT_PATTERN = "PT/" + PT_FEATURE_VARIABLE + "/" + POWERTOOLS_VERSION + " PTENV/" + PT_EXEC_ENV_VARIABLE; private UserAgentConfigurator() { @@ -53,7 +53,6 @@ static String getProjectVersion() { return getVersionFromProperties(VERSION_PROPERTIES_FILENAME, VERSION_KEY); } - /** * Retrieves the project version from a properties file. * The file should be in the resources folder. @@ -83,9 +82,18 @@ static String getVersionFromProperties(String propertyFileName, String versionKe return NA; } + /** + * Configures the AWS SDK to use Powertools user agent by setting the sdk.ua.appId system property. + * This should be called during library initialization to ensure the user agent is properly configured. + */ + public static void configureUserAgent(String ptFeature) { + System.out.println("CONFIGURE UA " + ptFeature); + System.setProperty("sdk.ua.appId", getUserAgent(ptFeature)); + } + /** * Retrieves the user agent string for the Powertools for AWS Lambda. - * It follows the pattern PT/{PT_FEATURE}/{PT_VERSION} PTEnv/{PT_EXEC_ENV} + * It follows the pattern PT/{PT_FEATURE}/{PT_VERSION} PTENV/{PT_EXEC_ENV} * The version of the project is automatically retrieved. * The PT_EXEC_ENV is automatically retrieved from the AWS_EXECUTION_ENV environment variable. * If it AWS_EXECUTION_ENV is not set, PT_EXEC_ENV defaults to "NA" @@ -105,7 +113,7 @@ public static String getUserAgent(String ptFeature) { ptFeature = NO_OP; } return userAgent - .replace(PT_FEATURE_VARIABLE, ptFeature) + .replace(PT_FEATURE_VARIABLE, ptFeature.toUpperCase()) .replace(PT_EXEC_ENV_VARIABLE, ptExecEnv); } } diff --git a/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/UserAgentConfiguratorTest.java b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/UserAgentConfiguratorTest.java index 0c7935a55..ba33de49a 100644 --- a/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/UserAgentConfiguratorTest.java +++ b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/UserAgentConfiguratorTest.java @@ -91,7 +91,7 @@ void testGetUserAgent() { assertThat(userAgent) .isNotNull() - .isEqualTo("PT/test-feature/" + VERSION + " PTEnv/NA"); + .isEqualTo("PT/TEST-FEATURE/" + VERSION + " PTENV/NA"); } @@ -101,7 +101,7 @@ void testGetUserAgent_NoFeature() { assertThat(userAgent) .isNotNull() - .isEqualTo("PT/no-op/" + VERSION + " PTEnv/NA"); + .isEqualTo("PT/NO-OP/" + VERSION + " PTENV/NA"); } @Test @@ -110,7 +110,7 @@ void testGetUserAgent_NullFeature() { assertThat(userAgent) .isNotNull() - .isEqualTo("PT/no-op/" + VERSION + " PTEnv/NA"); + .isEqualTo("PT/NO-OP/" + VERSION + " PTENV/NA"); } @Test @@ -120,7 +120,15 @@ void testGetUserAgent_SetAWSExecutionEnv() { assertThat(userAgent) .isNotNull() - .isEqualTo("PT/test-feature/" + VERSION + " PTEnv/AWS_Lambda_java8"); + .isEqualTo("PT/TEST-FEATURE/" + VERSION + " PTENV/AWS_Lambda_java8"); + } + + @Test + void testConfigureUserAgent() { + UserAgentConfigurator.configureUserAgent("test-feature"); + + assertThat(System.getProperty("sdk.ua.appId")) + .isEqualTo("PT/TEST-FEATURE/" + VERSION + " PTENV/NA"); } } diff --git a/powertools-logging/powertools-logging-log4j/pom.xml b/powertools-logging/powertools-logging-log4j/pom.xml index 836f8c53f..92b412834 100644 --- a/powertools-logging/powertools-logging-log4j/pom.xml +++ b/powertools-logging/powertools-logging-log4j/pom.xml @@ -39,6 +39,11 @@ org.apache.logging.log4j log4j-layout-template-json + + software.amazon.awssdk + sdk-core + provided + diff --git a/powertools-logging/powertools-logging-log4j/src/main/java/software/amazon/lambda/powertools/logging/log4/internal/LoggingUserAgentInterceptor.java b/powertools-logging/powertools-logging-log4j/src/main/java/software/amazon/lambda/powertools/logging/log4/internal/LoggingUserAgentInterceptor.java new file mode 100644 index 000000000..a4d19363e --- /dev/null +++ b/powertools-logging/powertools-logging-log4j/src/main/java/software/amazon/lambda/powertools/logging/log4/internal/LoggingUserAgentInterceptor.java @@ -0,0 +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.logging.log4.internal; + +import software.amazon.awssdk.core.SdkRequest; +import software.amazon.awssdk.core.interceptor.Context; +import software.amazon.awssdk.core.interceptor.ExecutionAttributes; +import software.amazon.awssdk.core.interceptor.ExecutionInterceptor; +import software.amazon.lambda.powertools.common.internal.UserAgentConfigurator; + +/** + * Global interceptor that configures the User-Agent for all AWS SDK clients + * when the metrics module is on the classpath. + */ +public final class LoggingUserAgentInterceptor implements ExecutionInterceptor { + static { + UserAgentConfigurator.configureUserAgent("logging"); + } + + @Override + public SdkRequest modifyRequest(Context.ModifyRequest context, ExecutionAttributes executionAttributes) { + // This is a no-op interceptor. We use this class to configure the PT User-Agent in the static block. It is + // loaded by AWS SDK Global Interceptors. + return context.request(); + } +} diff --git a/powertools-logging/powertools-logging-log4j/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors b/powertools-logging/powertools-logging-log4j/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors new file mode 100644 index 000000000..7917018f2 --- /dev/null +++ b/powertools-logging/powertools-logging-log4j/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors @@ -0,0 +1 @@ +software.amazon.lambda.powertools.logging.log4.internal.LoggingUserAgentInterceptor diff --git a/powertools-metrics/pom.xml b/powertools-metrics/pom.xml index 4bccab505..58b37a232 100644 --- a/powertools-metrics/pom.xml +++ b/powertools-metrics/pom.xml @@ -73,6 +73,11 @@ org.apache.commons commons-lang3 + + software.amazon.awssdk + sdk-core + provided + diff --git a/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/MetricsUserAgentInterceptor.java b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/MetricsUserAgentInterceptor.java new file mode 100644 index 000000000..5a466cc3a --- /dev/null +++ b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/MetricsUserAgentInterceptor.java @@ -0,0 +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.metrics.internal; + +import software.amazon.awssdk.core.SdkRequest; +import software.amazon.awssdk.core.interceptor.Context; +import software.amazon.awssdk.core.interceptor.ExecutionAttributes; +import software.amazon.awssdk.core.interceptor.ExecutionInterceptor; +import software.amazon.lambda.powertools.common.internal.UserAgentConfigurator; + +/** + * Global interceptor that configures the User-Agent for all AWS SDK clients + * when the metrics module is on the classpath. + */ +public final class MetricsUserAgentInterceptor implements ExecutionInterceptor { + static { + UserAgentConfigurator.configureUserAgent("metrics"); + } + + @Override + public SdkRequest modifyRequest(Context.ModifyRequest context, ExecutionAttributes executionAttributes) { + // This is a no-op interceptor. We use this class to configure the PT User-Agent in the static block. It is + // loaded by AWS SDK Global Interceptors. + return context.request(); + } +} diff --git a/powertools-metrics/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors b/powertools-metrics/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors new file mode 100644 index 000000000..544bd8ead --- /dev/null +++ b/powertools-metrics/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors @@ -0,0 +1 @@ +software.amazon.lambda.powertools.metrics.internal.MetricsUserAgentInterceptor \ No newline at end of file From a737a79c19d9d9e07b0a78cd62222615c5a279c7 Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Thu, 14 Aug 2025 14:07:15 +0200 Subject: [PATCH 39/65] chore(ci): Run unit tests for GraalVM as well during build. --- .github/workflows/check-build.yml | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/.github/workflows/check-build.yml b/.github/workflows/check-build.yml index 72070ed9e..02920d6e7 100644 --- a/.github/workflows/check-build.yml +++ b/.github/workflows/check-build.yml @@ -84,7 +84,7 @@ jobs: - id: build-maven name: Build (Maven) run: | - mvn -B -q install --file pom.xml + mvn -B install --file pom.xml graalvm-build: runs-on: ubuntu-latest @@ -101,17 +101,14 @@ jobs: - id: graalvm-native-test name: GraalVM Native Test run: | - # Build the entire project first to ensure test-jar dependencies are available - mvn -B -q install -DskipTests - - # Find modules with graalvm-native profile and run tests recursively. + # Find modules with graalvm-native profile and run tests. # This will make sure to discover new GraalVM supported modules automatically in the future. - find . -name "pom.xml" -path "./powertools-*" | while read module; do + for module in powertools-*/pom.xml; do if grep -q "graalvm-native" "$module"; then module_dir=$(dirname "$module") echo "Regenerating GraalVM metadata for $module_dir" - mvn -B -q -f "$module" -Pgenerate-graalvm-files clean test + mvn -B -f "$module" -Pgenerate-graalvm-files clean test echo "Running GraalVM native tests for $module_dir" - mvn -B -q -f "$module" -Pgraalvm-native test + mvn -B -f "$module" -Pgraalvm-native test fi done From dd29088facfa124d3ef1abf9c4096eb98a330743 Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Fri, 15 Aug 2025 09:03:05 +0200 Subject: [PATCH 40/65] Fix native tests in powertools-serialization. Remove mockito dependency there. --- powertools-serialization/pom.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/powertools-serialization/pom.xml b/powertools-serialization/pom.xml index 7e4e2af15..e729020d2 100644 --- a/powertools-serialization/pom.xml +++ b/powertools-serialization/pom.xml @@ -137,6 +137,12 @@ --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED --no-fallback + -Dorg.graalvm.nativeimage.imagecode=agent + --initialize-at-build-time=org.slf4j.simple.SimpleLogger + --initialize-at-build-time=org.slf4j.LoggerFactory + --initialize-at-build-time=org.junit.Ignore + --initialize-at-build-time=java.lang.annotation.Annotation + --initialize-at-build-time=org.junit.runners.model.FrameworkField --verbose --native-image-info -H:+UnlockExperimentalVMOptions From 023eed76a26e93c329bab57cdea67b3538ba0ff3 Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Fri, 15 Aug 2025 11:26:32 +0200 Subject: [PATCH 41/65] Remove mockito from powertools-common. --- pom.xml | 4 +- powertools-common/pom.xml | 28 ++---- .../internal/LambdaHandlerProcessorTest.java | 30 +++---- .../common/stubs/TestInputStream.java | 24 +++++ .../common/stubs/TestOutputStream.java | 23 +++++ .../common/stubs/TestProceedingJoinPoint.java | 90 +++++++++++++++++++ .../common/stubs/TestSignature.java | 55 ++++++++++++ 7 files changed, 212 insertions(+), 42 deletions(-) create mode 100644 powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestInputStream.java create mode 100644 powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestOutputStream.java create mode 100644 powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestProceedingJoinPoint.java create mode 100644 powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestSignature.java diff --git a/pom.xml b/pom.xml index bdafe88e1..ba4b8f3b0 100644 --- a/pom.xml +++ b/pom.xml @@ -114,8 +114,8 @@ 1.12.781 2.18.0 1.7.0 - 5.19.1-SNAPSHOT - 5.19.1-SNAPSHOT + 5.19.0 + 5.19.0 2.3.0 1.5.0 diff --git a/powertools-common/pom.xml b/powertools-common/pom.xml index ea9baa98c..2e3832a90 100644 --- a/powertools-common/pom.xml +++ b/powertools-common/pom.xml @@ -81,22 +81,10 @@ slf4j-simple test - - org.mockito - mockito-core - test - generate-graalvm-files - - - org.mockito - mockito-subclass - test - - @@ -104,8 +92,7 @@ maven-surefire-plugin 3.5.3 - - -Dorg.graalvm.nativeimage.imagecode=agent + -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-common,experimental-class-define-support --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED @@ -117,13 +104,6 @@ graalvm-native - - - org.mockito - mockito-subclass - test - - @@ -146,6 +126,12 @@ --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED --no-fallback + -Dorg.graalvm.nativeimage.imagecode=agent + --initialize-at-build-time=org.slf4j.simple.SimpleLogger + --initialize-at-build-time=org.slf4j.LoggerFactory + --initialize-at-build-time=org.junit.Ignore + --initialize-at-build-time=java.lang.annotation.Annotation + --initialize-at-build-time=org.junit.runners.model.FrameworkField --verbose --native-image-info -H:+UnlockExperimentalVMOptions diff --git a/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/LambdaHandlerProcessorTest.java b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/LambdaHandlerProcessorTest.java index 17732cdf0..11eac7a4c 100644 --- a/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/LambdaHandlerProcessorTest.java +++ b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/LambdaHandlerProcessorTest.java @@ -16,15 +16,10 @@ 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.when; -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.junitpioneer.jupiter.ClearEnvironmentVariable; import org.junitpioneer.jupiter.SetEnvironmentVariable; @@ -34,6 +29,10 @@ import com.amazonaws.services.lambda.runtime.RequestStreamHandler; import software.amazon.lambda.powertools.common.stubs.TestLambdaContext; +import software.amazon.lambda.powertools.common.stubs.TestInputStream; +import software.amazon.lambda.powertools.common.stubs.TestOutputStream; +import software.amazon.lambda.powertools.common.stubs.TestProceedingJoinPoint; +import software.amazon.lambda.powertools.common.stubs.TestSignature; class LambdaHandlerProcessorTest { @@ -48,7 +47,7 @@ void isHandlerMethod_shouldRecognizeRequestHandler() { @Test void isHandlerMethod_shouldRecognizeRequestStreamHandler() { - Object[] args = { mock(InputStream.class), mock(OutputStream.class), new TestLambdaContext() }; + Object[] args = { new TestInputStream(), new TestOutputStream(), new TestLambdaContext() }; ProceedingJoinPoint pjpMock = mockRequestHandlerPjp(RequestStreamHandler.class, args); assertThat(LambdaHandlerProcessor.isHandlerMethod(pjpMock)).isTrue(); @@ -73,7 +72,7 @@ void placedOnRequestHandler_shouldRecognizeRequestHandler() { @Test void placedOnStreamHandler_shouldRecognizeRequestStreamHandler() { - Object[] args = { mock(InputStream.class), mock(OutputStream.class), new TestLambdaContext() }; + Object[] args = { new TestInputStream(), new TestOutputStream(), new TestLambdaContext() }; ProceedingJoinPoint pjpMock = mockRequestHandlerPjp(RequestStreamHandler.class, args); assertThat(LambdaHandlerProcessor.placedOnStreamHandler(pjpMock)).isTrue(); @@ -121,7 +120,7 @@ void placedOnStreamHandler_shouldInvalidateOnWrongTypeOfArgs() { @Test void placedOnStreamHandler_shouldInvalidateOnTypeOfArgs_invalidOutputStreamArg() { - Object[] args = { mock(InputStream.class), new Object(), new TestLambdaContext() }; + Object[] args = { new TestInputStream(), new Object(), new TestLambdaContext() }; ProceedingJoinPoint pjpMock = mockRequestHandlerPjp(RequestStreamHandler.class, args); boolean isPlacedOnStreamHandler = LambdaHandlerProcessor.placedOnStreamHandler(pjpMock); @@ -131,7 +130,7 @@ void placedOnStreamHandler_shouldInvalidateOnTypeOfArgs_invalidOutputStreamArg() @Test void placedOnStreamHandler_shouldInvalidateOnTypeOfArgs_invalidContextArg() { - Object[] args = { mock(InputStream.class), mock(OutputStream.class), new Object() }; + Object[] args = { new TestInputStream(), new TestOutputStream(), new Object() }; ProceedingJoinPoint pjpMock = mockRequestHandlerPjp(RequestStreamHandler.class, args); boolean isPlacedOnStreamHandler = LambdaHandlerProcessor.placedOnStreamHandler(pjpMock); @@ -171,7 +170,7 @@ void extractContext_fromRequestHandler() { @Test void extractContext_fromStreamRequestHandler() { - Object[] args = { mock(InputStream.class), mock(OutputStream.class), new TestLambdaContext() }; + Object[] args = { new TestInputStream(), new TestOutputStream(), new TestLambdaContext() }; ProceedingJoinPoint pjpMock = mockRequestHandlerPjp(RequestStreamHandler.class, args); Context context = LambdaHandlerProcessor.extractContext(pjpMock); @@ -231,14 +230,7 @@ void serviceName_Undefined() { } private ProceedingJoinPoint mockRequestHandlerPjp(Class handlerClass, Object[] handlerArgs) { - ProceedingJoinPoint pjp = mock(ProceedingJoinPoint.class); - Signature signature = mock(Signature.class); - - when(signature.getDeclaringType()).thenReturn(handlerClass); - when(signature.getName()).thenReturn("handleRequest"); - when(pjp.getSignature()).thenReturn(signature); - when(pjp.getArgs()).thenReturn(handlerArgs); - - return pjp; + TestSignature signature = new TestSignature(handlerClass); + return new TestProceedingJoinPoint(signature, handlerArgs); } } diff --git a/powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestInputStream.java b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestInputStream.java new file mode 100644 index 000000000..cb9122966 --- /dev/null +++ b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestInputStream.java @@ -0,0 +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.common.stubs; + +import java.io.InputStream; + +public class TestInputStream extends InputStream { + @Override + public int read() { + return -1; + } +} diff --git a/powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestOutputStream.java b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestOutputStream.java new file mode 100644 index 000000000..b64b4759d --- /dev/null +++ b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestOutputStream.java @@ -0,0 +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.common.stubs; + +import java.io.OutputStream; + +public class TestOutputStream extends OutputStream { + @Override + public void write(int b) { + } +} diff --git a/powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestProceedingJoinPoint.java b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestProceedingJoinPoint.java new file mode 100644 index 000000000..e0285518c --- /dev/null +++ b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestProceedingJoinPoint.java @@ -0,0 +1,90 @@ +/* + * 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.common.stubs; + +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.Signature; +import org.aspectj.lang.reflect.SourceLocation; +import org.aspectj.runtime.internal.AroundClosure; + +public class TestProceedingJoinPoint implements ProceedingJoinPoint { + private final Signature signature; + private final Object[] args; + + public TestProceedingJoinPoint(Signature signature, Object[] args) { + this.signature = signature; + this.args = args; + } + + @Override + public Object[] getArgs() { + return args; + } + + @Override + public Signature getSignature() { + return signature; + } + + @Override + public Object getTarget() { + return null; + } + + @Override + public Object getThis() { + return null; + } + + @Override + public StaticPart getStaticPart() { + return null; + } + + @Override + public String getKind() { + return null; + } + + @Override + public SourceLocation getSourceLocation() { + return null; + } + + @Override + public Object proceed() { + return null; + } + + @Override + public Object proceed(Object[] args) { + return null; + } + + @Override + public void set$AroundClosure(AroundClosure arc) { + // Stubbed method + } + + @Override + public String toLongString() { + return "handleRequest"; + } + + @Override + public String toShortString() { + return "handleRequest"; + } +} diff --git a/powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestSignature.java b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestSignature.java new file mode 100644 index 000000000..903e4c8fa --- /dev/null +++ b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestSignature.java @@ -0,0 +1,55 @@ +/* + * 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.common.stubs; + +import org.aspectj.lang.Signature; + +public class TestSignature implements Signature { + private final Class declaringType; + + public TestSignature(Class declaringType) { + this.declaringType = declaringType; + } + + @Override + public Class getDeclaringType() { + return declaringType; + } + + @Override + public String getDeclaringTypeName() { + return declaringType.getName(); + } + + @Override + public int getModifiers() { + return 0; + } + + @Override + public String getName() { + return "handleRequest"; + } + + @Override + public String toLongString() { + return "handleRequest"; + } + + @Override + public String toShortString() { + return "handleRequest"; + } +} From 5ac77c6aef0bff60f1e13556c1d5ee0403d40637 Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Fri, 15 Aug 2025 11:49:06 +0200 Subject: [PATCH 42/65] Remove mockito from powertools-metrics and re-use TestLamdaContext from powertools-common. --- powertools-metrics/pom.xml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/powertools-metrics/pom.xml b/powertools-metrics/pom.xml index 58b37a232..8542400db 100644 --- a/powertools-metrics/pom.xml +++ b/powertools-metrics/pom.xml @@ -146,8 +146,7 @@ org.apache.maven.plugins maven-surefire-plugin - - -Dorg.graalvm.nativeimage.imagecode=agent + -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-metrics,experimental-class-define-support --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED @@ -181,6 +180,12 @@ --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED --no-fallback + -Dorg.graalvm.nativeimage.imagecode=agent + --initialize-at-build-time=org.slf4j.simple.SimpleLogger + --initialize-at-build-time=org.slf4j.LoggerFactory + --initialize-at-build-time=org.junit.Ignore + --initialize-at-build-time=java.lang.annotation.Annotation + --initialize-at-build-time=org.junit.runners.model.FrameworkField --verbose --native-image-info -H:+UnlockExperimentalVMOptions From 69e653613c82d35ed3c276cb95fb38d700905c85 Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Fri, 15 Aug 2025 12:03:35 +0200 Subject: [PATCH 43/65] Remove mockito from powertools-logging. --- powertools-logging/pom.xml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/powertools-logging/pom.xml b/powertools-logging/pom.xml index 7a288870a..aaa9587fd 100644 --- a/powertools-logging/pom.xml +++ b/powertools-logging/pom.xml @@ -125,8 +125,7 @@ maven-surefire-plugin 3.5.3 - - -Dorg.graalvm.nativeimage.imagecode=agent + -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging,experimental-class-define-support --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED @@ -160,6 +159,12 @@ --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED --no-fallback + -Dorg.graalvm.nativeimage.imagecode=agent + --initialize-at-build-time=org.slf4j.simple.SimpleLogger + --initialize-at-build-time=org.slf4j.LoggerFactory + --initialize-at-build-time=org.junit.Ignore + --initialize-at-build-time=java.lang.annotation.Annotation + --initialize-at-build-time=org.junit.runners.model.FrameworkField --verbose --native-image-info -H:+UnlockExperimentalVMOptions From d3bf13fd29881a711e776420a1a8adf3967137d7 Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Fri, 15 Aug 2025 14:49:47 +0200 Subject: [PATCH 44/65] Remove mockito from powertools-logging-log4j. --- powertools-logging/powertools-logging-log4j/pom.xml | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/powertools-logging/powertools-logging-log4j/pom.xml b/powertools-logging/powertools-logging-log4j/pom.xml index 92b412834..3e0fc471e 100644 --- a/powertools-logging/powertools-logging-log4j/pom.xml +++ b/powertools-logging/powertools-logging-log4j/pom.xml @@ -109,8 +109,7 @@ maven-surefire-plugin 3.5.3 - - -Dorg.graalvm.nativeimage.imagecode=agent + -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-log4j,experimental-class-define-support --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED @@ -147,10 +146,12 @@ --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED --no-fallback - --verbose - --native-image-info - -H:+UnlockExperimentalVMOptions - -H:+ReportExceptionStackTraces + -Dorg.graalvm.nativeimage.imagecode=agent + --initialize-at-build-time=org.slf4j.simple.SimpleLogger + --initialize-at-build-time=org.slf4j.LoggerFactory + --initialize-at-build-time=org.junit.Ignore + --initialize-at-build-time=java.lang.annotation.Annotation + --initialize-at-build-time=org.junit.runners.model.FrameworkField From 8547658d77a090c6dec41a0c29b479da8310793a Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Fri, 15 Aug 2025 15:45:24 +0200 Subject: [PATCH 45/65] Remove mockito from powertools-logging-logback. --- .../powertools-logging-logback/pom.xml | 19 +++++----- .../predefined-classes-config.json | 8 ++++ .../proxy-config.json | 2 + .../reflect-config.json | 37 +++++++++++++++++++ .../resource-config.json | 24 ++++++++++++ .../serialization-config.json | 11 ++++++ .../internal/LambdaJsonEncoderTest.java | 4 +- 7 files changed, 94 insertions(+), 11 deletions(-) create mode 100644 powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/predefined-classes-config.json create mode 100644 powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/proxy-config.json create mode 100644 powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/serialization-config.json diff --git a/powertools-logging/powertools-logging-logback/pom.xml b/powertools-logging/powertools-logging-logback/pom.xml index 433a3774a..f6aac3096 100644 --- a/powertools-logging/powertools-logging-logback/pom.xml +++ b/powertools-logging/powertools-logging-logback/pom.xml @@ -97,8 +97,7 @@ maven-surefire-plugin 3.5.3 - - -Dorg.graalvm.nativeimage.imagecode=agent + -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback,experimental-class-define-support --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED @@ -129,16 +128,18 @@ powertools-logging-logback - - --initialize-at-build-time=org.junit.platform.launcher.core.DiscoveryIssueNotifier$1 - --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED --no-fallback - --verbose - --native-image-info - -H:+UnlockExperimentalVMOptions - -H:+ReportExceptionStackTraces + -Dorg.graalvm.nativeimage.imagecode=agent + --initialize-at-build-time=org.slf4j.simple.SimpleLogger + --initialize-at-build-time=org.slf4j.LoggerFactory + --initialize-at-build-time=org.junit.Ignore + --initialize-at-build-time=java.lang.annotation.Annotation + --initialize-at-build-time=org.junit.runners.model.FrameworkField + + --initialize-at-build-time=org.junit.platform.launcher.core.DiscoveryIssueNotifier$1 + diff --git a/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/predefined-classes-config.json b/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/predefined-classes-config.json new file mode 100644 index 000000000..0e79b2c5d --- /dev/null +++ b/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/predefined-classes-config.json @@ -0,0 +1,8 @@ +[ + { + "type":"agent-extracted", + "classes":[ + ] + } +] + diff --git a/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/proxy-config.json b/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/proxy-config.json new file mode 100644 index 000000000..0d4f101c7 --- /dev/null +++ b/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/proxy-config.json @@ -0,0 +1,2 @@ +[ +] diff --git a/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/reflect-config.json b/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/reflect-config.json index 683933a77..efd81020e 100644 --- a/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/reflect-config.json +++ b/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/reflect-config.json @@ -1,4 +1,10 @@ [ +{ + "name":"[Ljava.lang.Object;" +}, +{ + "name":"[Ljava.lang.String;" +}, { "name":"ch.qos.logback.classic.joran.SerializedModelConfigurator", "methods":[{"name":"","parameterTypes":[] }] @@ -126,10 +132,41 @@ { "name":"kotlin.Metadata" }, +{ + "name":"org.apache.maven.surefire.junitplatform.JUnitPlatformProvider", + "methods":[{"name":"","parameterTypes":["org.apache.maven.surefire.api.provider.ProviderParameters"] }] +}, { "name":"org.apiguardian.api.API", "queryAllPublicMethods":true }, +{ + "name":"org.junit.internal.AssumptionViolatedException" +}, +{ + "name":"org.junit.jupiter.api.ClassOrderer$OrderAnnotation", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.junit.jupiter.api.Order", + "queryAllPublicMethods":true +}, +{ + "name":"org.junit.jupiter.api.Test", + "queryAllPublicMethods":true +}, +{ + "name":"org.junit.platform.commons.annotation.Testable", + "queryAllPublicMethods":true +}, +{ + "name":"org.junit.platform.launcher.LauncherSession", + "methods":[{"name":"getLauncher","parameterTypes":[] }] +}, +{ + "name":"org.junit.platform.launcher.core.LauncherFactory", + "methods":[{"name":"openSession","parameterTypes":[] }] +}, { "name":"software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor", "fields":[{"name":"IS_COLD_START"}] diff --git a/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/resource-config.json b/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/resource-config.json index 2fc3c56bd..551635098 100644 --- a/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/resource-config.json +++ b/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/resource-config.json @@ -8,10 +8,34 @@ "pattern":"\\QMETA-INF/services/java.time.zone.ZoneRulesProvider\\E" }, { "pattern":"\\QMETA-INF/services/javax.xml.parsers.SAXParserFactory\\E" + }, { + "pattern":"\\QMETA-INF/services/org.apache.maven.surefire.spi.MasterProcessChannelProcessorFactory\\E" + }, { + "pattern":"\\QMETA-INF/services/org.assertj.core.configuration.Configuration\\E" + }, { + "pattern":"\\QMETA-INF/services/org.assertj.core.presentation.Representation\\E" + }, { + "pattern":"\\QMETA-INF/services/org.junit.platform.commons.support.scanning.ClasspathScanner\\E" + }, { + "pattern":"\\QMETA-INF/services/org.junit.platform.engine.TestEngine\\E" + }, { + "pattern":"\\QMETA-INF/services/org.junit.platform.launcher.LauncherDiscoveryListener\\E" + }, { + "pattern":"\\QMETA-INF/services/org.junit.platform.launcher.LauncherSessionListener\\E" + }, { + "pattern":"\\QMETA-INF/services/org.junit.platform.launcher.PostDiscoveryFilter\\E" + }, { + "pattern":"\\QMETA-INF/services/org.junit.platform.launcher.TestExecutionListener\\E" }, { "pattern":"\\QMETA-INF/services/org.slf4j.spi.SLF4JServiceProvider\\E" }, { "pattern":"\\QMETA-INF/services/software.amazon.lambda.powertools.logging.internal.LoggingManager\\E" + }, { + "pattern":"\\Qjunit-platform.properties\\E" + }, { + "pattern":"\\Qlogback-test.scmo\\E" + }, { + "pattern":"\\Qlogback-test.xml\\E" }, { "pattern":"\\Qlogback.scmo\\E" }]}, diff --git a/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/serialization-config.json b/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/serialization-config.json new file mode 100644 index 000000000..fc967f7f8 --- /dev/null +++ b/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/serialization-config.json @@ -0,0 +1,11 @@ +{ + "types":[ + { + "name":"org.junit.platform.launcher.TestIdentifier$SerializedForm" + } + ], + "lambdaCapturingTypes":[ + ], + "proxies":[ + ] +} diff --git a/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaJsonEncoderTest.java b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaJsonEncoderTest.java index 912e2fde9..398811d54 100644 --- a/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaJsonEncoderTest.java +++ b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaJsonEncoderTest.java @@ -217,9 +217,9 @@ void shouldLogStructuredArgumentsAsNewEntries() { StructuredArgument argument = StructuredArguments.entry("msg", msg); // WHEN - LoggingEvent structuredLoggingEvent = new LoggingEvent("fqcn", logger, Level.INFO, "A message", null, + LoggingEvent loggingEvent = new LoggingEvent("fqcn", logger, Level.INFO, "A message", null, new Object[] { argument }); - byte[] encoded = encoder.encode(structuredLoggingEvent); + byte[] encoded = encoder.encode(loggingEvent); String result = new String(encoded, StandardCharsets.UTF_8); // THEN (logged as JSON) From bf44487f4e0664179c9f55c63f50971e88a4b0d3 Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Fri, 15 Aug 2025 15:58:35 +0200 Subject: [PATCH 46/65] Remove mockito from powertools-tracing. --- powertools-tracing/pom.xml | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/powertools-tracing/pom.xml b/powertools-tracing/pom.xml index 67de0be7d..983212dd1 100644 --- a/powertools-tracing/pom.xml +++ b/powertools-tracing/pom.xml @@ -130,8 +130,7 @@ maven-surefire-plugin 3.5.3 - - -Dorg.graalvm.nativeimage.imagecode=agent + -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-tracing,experimental-class-define-support --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED @@ -166,6 +165,14 @@ --add-opens java.base/java.lang=ALL-UNNAMED --enable-url-protocols=http --no-fallback + -Dorg.graalvm.nativeimage.imagecode=agent + -H:IncludeResources=version.properties + -H:IncludeResources=unreadable.properties + --initialize-at-build-time=org.slf4j.simple.SimpleLogger + --initialize-at-build-time=org.slf4j.LoggerFactory + --initialize-at-build-time=org.junit.Ignore + --initialize-at-build-time=java.lang.annotation.Annotation + --initialize-at-build-time=org.junit.runners.model.FrameworkField --verbose --native-image-info -H:+UnlockExperimentalVMOptions From 51cadc7dd2599bf29cf486a082b67653fedd6a71 Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Mon, 18 Aug 2025 10:42:32 +0200 Subject: [PATCH 47/65] Add back Mockito to powertools-common. --- pom.xml | 4 +- powertools-common/pom.xml | 26 ++++-- .../internal/LambdaHandlerProcessorTest.java | 30 ++++--- .../common/stubs/TestInputStream.java | 24 ----- .../common/stubs/TestOutputStream.java | 23 ----- .../common/stubs/TestProceedingJoinPoint.java | 90 ------------------- .../common/stubs/TestSignature.java | 55 ------------ 7 files changed, 41 insertions(+), 211 deletions(-) delete mode 100644 powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestInputStream.java delete mode 100644 powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestOutputStream.java delete mode 100644 powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestProceedingJoinPoint.java delete mode 100644 powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestSignature.java diff --git a/pom.xml b/pom.xml index ba4b8f3b0..bdafe88e1 100644 --- a/pom.xml +++ b/pom.xml @@ -114,8 +114,8 @@ 1.12.781 2.18.0 1.7.0 - 5.19.0 - 5.19.0 + 5.19.1-SNAPSHOT + 5.19.1-SNAPSHOT 2.3.0 1.5.0 diff --git a/powertools-common/pom.xml b/powertools-common/pom.xml index 2e3832a90..53145d4a4 100644 --- a/powertools-common/pom.xml +++ b/powertools-common/pom.xml @@ -81,10 +81,22 @@ slf4j-simple test + + org.mockito + mockito-core + test + generate-graalvm-files + + + org.mockito + mockito-subclass + test + + @@ -104,6 +116,13 @@ graalvm-native + + + org.mockito + mockito-subclass + test + + @@ -126,15 +145,10 @@ --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED --no-fallback - -Dorg.graalvm.nativeimage.imagecode=agent - --initialize-at-build-time=org.slf4j.simple.SimpleLogger - --initialize-at-build-time=org.slf4j.LoggerFactory - --initialize-at-build-time=org.junit.Ignore - --initialize-at-build-time=java.lang.annotation.Annotation - --initialize-at-build-time=org.junit.runners.model.FrameworkField --verbose --native-image-info -H:+UnlockExperimentalVMOptions + -H:Log=registerResource:5 -H:+ReportExceptionStackTraces diff --git a/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/LambdaHandlerProcessorTest.java b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/LambdaHandlerProcessorTest.java index 11eac7a4c..17732cdf0 100644 --- a/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/LambdaHandlerProcessorTest.java +++ b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/LambdaHandlerProcessorTest.java @@ -16,10 +16,15 @@ 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.when; +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.junitpioneer.jupiter.ClearEnvironmentVariable; import org.junitpioneer.jupiter.SetEnvironmentVariable; @@ -29,10 +34,6 @@ import com.amazonaws.services.lambda.runtime.RequestStreamHandler; import software.amazon.lambda.powertools.common.stubs.TestLambdaContext; -import software.amazon.lambda.powertools.common.stubs.TestInputStream; -import software.amazon.lambda.powertools.common.stubs.TestOutputStream; -import software.amazon.lambda.powertools.common.stubs.TestProceedingJoinPoint; -import software.amazon.lambda.powertools.common.stubs.TestSignature; class LambdaHandlerProcessorTest { @@ -47,7 +48,7 @@ void isHandlerMethod_shouldRecognizeRequestHandler() { @Test void isHandlerMethod_shouldRecognizeRequestStreamHandler() { - Object[] args = { new TestInputStream(), new TestOutputStream(), new TestLambdaContext() }; + Object[] args = { mock(InputStream.class), mock(OutputStream.class), new TestLambdaContext() }; ProceedingJoinPoint pjpMock = mockRequestHandlerPjp(RequestStreamHandler.class, args); assertThat(LambdaHandlerProcessor.isHandlerMethod(pjpMock)).isTrue(); @@ -72,7 +73,7 @@ void placedOnRequestHandler_shouldRecognizeRequestHandler() { @Test void placedOnStreamHandler_shouldRecognizeRequestStreamHandler() { - Object[] args = { new TestInputStream(), new TestOutputStream(), new TestLambdaContext() }; + Object[] args = { mock(InputStream.class), mock(OutputStream.class), new TestLambdaContext() }; ProceedingJoinPoint pjpMock = mockRequestHandlerPjp(RequestStreamHandler.class, args); assertThat(LambdaHandlerProcessor.placedOnStreamHandler(pjpMock)).isTrue(); @@ -120,7 +121,7 @@ void placedOnStreamHandler_shouldInvalidateOnWrongTypeOfArgs() { @Test void placedOnStreamHandler_shouldInvalidateOnTypeOfArgs_invalidOutputStreamArg() { - Object[] args = { new TestInputStream(), new Object(), new TestLambdaContext() }; + Object[] args = { mock(InputStream.class), new Object(), new TestLambdaContext() }; ProceedingJoinPoint pjpMock = mockRequestHandlerPjp(RequestStreamHandler.class, args); boolean isPlacedOnStreamHandler = LambdaHandlerProcessor.placedOnStreamHandler(pjpMock); @@ -130,7 +131,7 @@ void placedOnStreamHandler_shouldInvalidateOnTypeOfArgs_invalidOutputStreamArg() @Test void placedOnStreamHandler_shouldInvalidateOnTypeOfArgs_invalidContextArg() { - Object[] args = { new TestInputStream(), new TestOutputStream(), new Object() }; + Object[] args = { mock(InputStream.class), mock(OutputStream.class), new Object() }; ProceedingJoinPoint pjpMock = mockRequestHandlerPjp(RequestStreamHandler.class, args); boolean isPlacedOnStreamHandler = LambdaHandlerProcessor.placedOnStreamHandler(pjpMock); @@ -170,7 +171,7 @@ void extractContext_fromRequestHandler() { @Test void extractContext_fromStreamRequestHandler() { - Object[] args = { new TestInputStream(), new TestOutputStream(), new TestLambdaContext() }; + Object[] args = { mock(InputStream.class), mock(OutputStream.class), new TestLambdaContext() }; ProceedingJoinPoint pjpMock = mockRequestHandlerPjp(RequestStreamHandler.class, args); Context context = LambdaHandlerProcessor.extractContext(pjpMock); @@ -230,7 +231,14 @@ void serviceName_Undefined() { } private ProceedingJoinPoint mockRequestHandlerPjp(Class handlerClass, Object[] handlerArgs) { - TestSignature signature = new TestSignature(handlerClass); - return new TestProceedingJoinPoint(signature, handlerArgs); + ProceedingJoinPoint pjp = mock(ProceedingJoinPoint.class); + Signature signature = mock(Signature.class); + + when(signature.getDeclaringType()).thenReturn(handlerClass); + when(signature.getName()).thenReturn("handleRequest"); + when(pjp.getSignature()).thenReturn(signature); + when(pjp.getArgs()).thenReturn(handlerArgs); + + return pjp; } } diff --git a/powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestInputStream.java b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestInputStream.java deleted file mode 100644 index cb9122966..000000000 --- a/powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestInputStream.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * 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.common.stubs; - -import java.io.InputStream; - -public class TestInputStream extends InputStream { - @Override - public int read() { - return -1; - } -} diff --git a/powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestOutputStream.java b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestOutputStream.java deleted file mode 100644 index b64b4759d..000000000 --- a/powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestOutputStream.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * 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.common.stubs; - -import java.io.OutputStream; - -public class TestOutputStream extends OutputStream { - @Override - public void write(int b) { - } -} diff --git a/powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestProceedingJoinPoint.java b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestProceedingJoinPoint.java deleted file mode 100644 index e0285518c..000000000 --- a/powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestProceedingJoinPoint.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * 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.common.stubs; - -import org.aspectj.lang.ProceedingJoinPoint; -import org.aspectj.lang.Signature; -import org.aspectj.lang.reflect.SourceLocation; -import org.aspectj.runtime.internal.AroundClosure; - -public class TestProceedingJoinPoint implements ProceedingJoinPoint { - private final Signature signature; - private final Object[] args; - - public TestProceedingJoinPoint(Signature signature, Object[] args) { - this.signature = signature; - this.args = args; - } - - @Override - public Object[] getArgs() { - return args; - } - - @Override - public Signature getSignature() { - return signature; - } - - @Override - public Object getTarget() { - return null; - } - - @Override - public Object getThis() { - return null; - } - - @Override - public StaticPart getStaticPart() { - return null; - } - - @Override - public String getKind() { - return null; - } - - @Override - public SourceLocation getSourceLocation() { - return null; - } - - @Override - public Object proceed() { - return null; - } - - @Override - public Object proceed(Object[] args) { - return null; - } - - @Override - public void set$AroundClosure(AroundClosure arc) { - // Stubbed method - } - - @Override - public String toLongString() { - return "handleRequest"; - } - - @Override - public String toShortString() { - return "handleRequest"; - } -} diff --git a/powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestSignature.java b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestSignature.java deleted file mode 100644 index 903e4c8fa..000000000 --- a/powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestSignature.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * 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.common.stubs; - -import org.aspectj.lang.Signature; - -public class TestSignature implements Signature { - private final Class declaringType; - - public TestSignature(Class declaringType) { - this.declaringType = declaringType; - } - - @Override - public Class getDeclaringType() { - return declaringType; - } - - @Override - public String getDeclaringTypeName() { - return declaringType.getName(); - } - - @Override - public int getModifiers() { - return 0; - } - - @Override - public String getName() { - return "handleRequest"; - } - - @Override - public String toLongString() { - return "handleRequest"; - } - - @Override - public String toShortString() { - return "handleRequest"; - } -} From 0a26c32e13999934ba6c5a33e3422feb1175c0fc Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Mon, 18 Aug 2025 10:57:29 +0200 Subject: [PATCH 48/65] Simplify graalvm config for logback and log4j modules. --- powertools-common/pom.xml | 3 ++- .../powertools-logging-log4j/pom.xml | 14 ++++++------- .../powertools-logging-logback/pom.xml | 20 +++++++++---------- 3 files changed, 19 insertions(+), 18 deletions(-) diff --git a/powertools-common/pom.xml b/powertools-common/pom.xml index 53145d4a4..8a9d06460 100644 --- a/powertools-common/pom.xml +++ b/powertools-common/pom.xml @@ -104,7 +104,8 @@ maven-surefire-plugin 3.5.3 - -Dorg.graalvm.nativeimage.imagecode=agent + + -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-common,experimental-class-define-support --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED diff --git a/powertools-logging/powertools-logging-log4j/pom.xml b/powertools-logging/powertools-logging-log4j/pom.xml index 3e0fc471e..ad0c3c373 100644 --- a/powertools-logging/powertools-logging-log4j/pom.xml +++ b/powertools-logging/powertools-logging-log4j/pom.xml @@ -109,7 +109,8 @@ maven-surefire-plugin 3.5.3 - -Dorg.graalvm.nativeimage.imagecode=agent + + -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-log4j,experimental-class-define-support --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED @@ -146,12 +147,11 @@ --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED --no-fallback - -Dorg.graalvm.nativeimage.imagecode=agent - --initialize-at-build-time=org.slf4j.simple.SimpleLogger - --initialize-at-build-time=org.slf4j.LoggerFactory - --initialize-at-build-time=org.junit.Ignore - --initialize-at-build-time=java.lang.annotation.Annotation - --initialize-at-build-time=org.junit.runners.model.FrameworkField + --verbose + --native-image-info + -H:+UnlockExperimentalVMOptions + -H:Log=registerResource:5 + -H:+ReportExceptionStackTraces diff --git a/powertools-logging/powertools-logging-logback/pom.xml b/powertools-logging/powertools-logging-logback/pom.xml index f6aac3096..9f0b36dad 100644 --- a/powertools-logging/powertools-logging-logback/pom.xml +++ b/powertools-logging/powertools-logging-logback/pom.xml @@ -97,7 +97,8 @@ maven-surefire-plugin 3.5.3 - -Dorg.graalvm.nativeimage.imagecode=agent + + -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback,experimental-class-define-support --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED @@ -128,18 +129,17 @@ powertools-logging-logback - --add-opens java.base/java.util=ALL-UNNAMED - --add-opens java.base/java.lang=ALL-UNNAMED - --no-fallback - -Dorg.graalvm.nativeimage.imagecode=agent - --initialize-at-build-time=org.slf4j.simple.SimpleLogger - --initialize-at-build-time=org.slf4j.LoggerFactory - --initialize-at-build-time=org.junit.Ignore - --initialize-at-build-time=java.lang.annotation.Annotation - --initialize-at-build-time=org.junit.runners.model.FrameworkField --initialize-at-build-time=org.junit.platform.launcher.core.DiscoveryIssueNotifier$1 + --add-opens java.base/java.util=ALL-UNNAMED + --add-opens java.base/java.lang=ALL-UNNAMED + --no-fallback + --verbose + --native-image-info + -H:+UnlockExperimentalVMOptions + -H:Log=registerResource:5 + -H:+ReportExceptionStackTraces From 1677d1a5d2132b56298eca1e734d676129ff274b Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Mon, 18 Aug 2025 11:01:51 +0200 Subject: [PATCH 49/65] Simplify graalvm config in powertools-logging. --- powertools-logging/pom.xml | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/powertools-logging/pom.xml b/powertools-logging/pom.xml index aaa9587fd..4312ffbf6 100644 --- a/powertools-logging/pom.xml +++ b/powertools-logging/pom.xml @@ -125,7 +125,8 @@ maven-surefire-plugin 3.5.3 - -Dorg.graalvm.nativeimage.imagecode=agent + + -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging,experimental-class-define-support --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED @@ -159,15 +160,10 @@ --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED --no-fallback - -Dorg.graalvm.nativeimage.imagecode=agent - --initialize-at-build-time=org.slf4j.simple.SimpleLogger - --initialize-at-build-time=org.slf4j.LoggerFactory - --initialize-at-build-time=org.junit.Ignore - --initialize-at-build-time=java.lang.annotation.Annotation - --initialize-at-build-time=org.junit.runners.model.FrameworkField --verbose --native-image-info -H:+UnlockExperimentalVMOptions + -H:Log=registerResource:5 -H:+ReportExceptionStackTraces From 20778809d9346b8b352c815493abec710d3eaf9a Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Mon, 18 Aug 2025 11:34:51 +0200 Subject: [PATCH 50/65] Simplify GraalVM config for powertools-metrics, powertools-serialization, powertools-tracing. --- powertools-metrics/pom.xml | 10 +++------- powertools-serialization/pom.xml | 7 +------ powertools-tracing/pom.xml | 12 +++--------- 3 files changed, 7 insertions(+), 22 deletions(-) diff --git a/powertools-metrics/pom.xml b/powertools-metrics/pom.xml index 8542400db..f2ec7dbc9 100644 --- a/powertools-metrics/pom.xml +++ b/powertools-metrics/pom.xml @@ -146,7 +146,8 @@ org.apache.maven.plugins maven-surefire-plugin - -Dorg.graalvm.nativeimage.imagecode=agent + + -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-metrics,experimental-class-define-support --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED @@ -180,15 +181,10 @@ --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED --no-fallback - -Dorg.graalvm.nativeimage.imagecode=agent - --initialize-at-build-time=org.slf4j.simple.SimpleLogger - --initialize-at-build-time=org.slf4j.LoggerFactory - --initialize-at-build-time=org.junit.Ignore - --initialize-at-build-time=java.lang.annotation.Annotation - --initialize-at-build-time=org.junit.runners.model.FrameworkField --verbose --native-image-info -H:+UnlockExperimentalVMOptions + -H:Log=registerResource:5 -H:+ReportExceptionStackTraces diff --git a/powertools-serialization/pom.xml b/powertools-serialization/pom.xml index e729020d2..911f47850 100644 --- a/powertools-serialization/pom.xml +++ b/powertools-serialization/pom.xml @@ -137,15 +137,10 @@ --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED --no-fallback - -Dorg.graalvm.nativeimage.imagecode=agent - --initialize-at-build-time=org.slf4j.simple.SimpleLogger - --initialize-at-build-time=org.slf4j.LoggerFactory - --initialize-at-build-time=org.junit.Ignore - --initialize-at-build-time=java.lang.annotation.Annotation - --initialize-at-build-time=org.junit.runners.model.FrameworkField --verbose --native-image-info -H:+UnlockExperimentalVMOptions + -H:Log=registerResource:5 -H:+ReportExceptionStackTraces diff --git a/powertools-tracing/pom.xml b/powertools-tracing/pom.xml index 983212dd1..b6cac28aa 100644 --- a/powertools-tracing/pom.xml +++ b/powertools-tracing/pom.xml @@ -130,7 +130,8 @@ maven-surefire-plugin 3.5.3 - -Dorg.graalvm.nativeimage.imagecode=agent + + -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-tracing,experimental-class-define-support --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED @@ -165,17 +166,10 @@ --add-opens java.base/java.lang=ALL-UNNAMED --enable-url-protocols=http --no-fallback - -Dorg.graalvm.nativeimage.imagecode=agent - -H:IncludeResources=version.properties - -H:IncludeResources=unreadable.properties - --initialize-at-build-time=org.slf4j.simple.SimpleLogger - --initialize-at-build-time=org.slf4j.LoggerFactory - --initialize-at-build-time=org.junit.Ignore - --initialize-at-build-time=java.lang.annotation.Annotation - --initialize-at-build-time=org.junit.runners.model.FrameworkField --verbose --native-image-info -H:+UnlockExperimentalVMOptions + -H:Log=registerResource:5 -H:+ReportExceptionStackTraces From 078376b2020cd27c9810773693ddb8f886c74d0f Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Mon, 18 Aug 2025 11:39:53 +0200 Subject: [PATCH 51/65] Remove comment. --- powertools-parameters/pom.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/powertools-parameters/pom.xml b/powertools-parameters/pom.xml index 617e0cc00..7e28ad556 100644 --- a/powertools-parameters/pom.xml +++ b/powertools-parameters/pom.xml @@ -138,6 +138,7 @@ --verbose --native-image-info -H:+UnlockExperimentalVMOptions + -H:Log=registerResource:5 -H:+ReportExceptionStackTraces From 37fa06243289022772e3e5921236837932a81e77 Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Mon, 18 Aug 2025 12:05:47 +0200 Subject: [PATCH 52/65] Simplify powertools-parameters-tests GraalVM config and fix issues in unit tests. --- powertools-parameters/powertools-parameters-tests/pom.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/powertools-parameters/powertools-parameters-tests/pom.xml b/powertools-parameters/powertools-parameters-tests/pom.xml index 6dcf2c4ae..5db059123 100644 --- a/powertools-parameters/powertools-parameters-tests/pom.xml +++ b/powertools-parameters/powertools-parameters-tests/pom.xml @@ -164,6 +164,7 @@ --verbose --native-image-info -H:+UnlockExperimentalVMOptions + -H:Log=registerResource:5 -H:+ReportExceptionStackTraces From 80844f65c645eedcefcd0b0aba9e72ac857280c1 Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Mon, 18 Aug 2025 12:24:32 +0200 Subject: [PATCH 53/65] Simplify powertools-parameters-ssm GraalVM config and fix issues in unit tests. --- powertools-parameters/powertools-parameters-ssm/pom.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/powertools-parameters/powertools-parameters-ssm/pom.xml b/powertools-parameters/powertools-parameters-ssm/pom.xml index 709ea6634..a418d3f09 100644 --- a/powertools-parameters/powertools-parameters-ssm/pom.xml +++ b/powertools-parameters/powertools-parameters-ssm/pom.xml @@ -168,6 +168,7 @@ --verbose --native-image-info -H:+UnlockExperimentalVMOptions + -H:Log=registerResource:5 -H:+ReportExceptionStackTraces From 0f7bd00b1579b5d87970e083d7de924f3fc1bff4 Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Mon, 18 Aug 2025 12:35:26 +0200 Subject: [PATCH 54/65] Simplify powertools-parameters-secrets GraalVM config and fix issues in unit tests. --- powertools-parameters/powertools-parameters-secrets/pom.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/powertools-parameters/powertools-parameters-secrets/pom.xml b/powertools-parameters/powertools-parameters-secrets/pom.xml index b486a1bb3..cf262b8d6 100644 --- a/powertools-parameters/powertools-parameters-secrets/pom.xml +++ b/powertools-parameters/powertools-parameters-secrets/pom.xml @@ -154,6 +154,7 @@ --verbose --native-image-info -H:+UnlockExperimentalVMOptions + -H:Log=registerResource:5 -H:+ReportExceptionStackTraces From 4ab6efab21a3464502684d461361c8d483272b7c Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Mon, 18 Aug 2025 12:43:48 +0200 Subject: [PATCH 55/65] Simplify powertools-parameters-dynamodb GraalVM config and fix issues in unit tests. --- powertools-parameters/powertools-parameters-dynamodb/pom.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/powertools-parameters/powertools-parameters-dynamodb/pom.xml b/powertools-parameters/powertools-parameters-dynamodb/pom.xml index b8857b0c9..c4ff00a38 100644 --- a/powertools-parameters/powertools-parameters-dynamodb/pom.xml +++ b/powertools-parameters/powertools-parameters-dynamodb/pom.xml @@ -154,6 +154,7 @@ --verbose --native-image-info -H:+UnlockExperimentalVMOptions + -H:Log=registerResource:5 -H:+ReportExceptionStackTraces From 537a4222505bb6d3afdfd9d85616e413b6c07681 Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Mon, 18 Aug 2025 12:52:27 +0200 Subject: [PATCH 56/65] Simplify powertools-parameters-appconfig GraalVM config and fix issues in unit tests. --- powertools-parameters/powertools-parameters-appconfig/pom.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/powertools-parameters/powertools-parameters-appconfig/pom.xml b/powertools-parameters/powertools-parameters-appconfig/pom.xml index ed92930fc..c32bb4d12 100644 --- a/powertools-parameters/powertools-parameters-appconfig/pom.xml +++ b/powertools-parameters/powertools-parameters-appconfig/pom.xml @@ -153,6 +153,7 @@ --verbose --native-image-info -H:+UnlockExperimentalVMOptions + -H:Log=registerResource:5 -H:+ReportExceptionStackTraces From 3de875d0929677553309fd1dba73cc64babf7491 Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Mon, 18 Aug 2025 13:01:12 +0200 Subject: [PATCH 57/65] Fix SonarCube finding. --- .../powertools/logging/internal/LambdaJsonEncoderTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaJsonEncoderTest.java b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaJsonEncoderTest.java index 398811d54..912e2fde9 100644 --- a/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaJsonEncoderTest.java +++ b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaJsonEncoderTest.java @@ -217,9 +217,9 @@ void shouldLogStructuredArgumentsAsNewEntries() { StructuredArgument argument = StructuredArguments.entry("msg", msg); // WHEN - LoggingEvent loggingEvent = new LoggingEvent("fqcn", logger, Level.INFO, "A message", null, + LoggingEvent structuredLoggingEvent = new LoggingEvent("fqcn", logger, Level.INFO, "A message", null, new Object[] { argument }); - byte[] encoded = encoder.encode(loggingEvent); + byte[] encoded = encoder.encode(structuredLoggingEvent); String result = new String(encoded, StandardCharsets.UTF_8); // THEN (logged as JSON) From 5952a925f1803a44ec367b7e7421182d0e1e0a12 Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Tue, 19 Aug 2025 10:12:05 +0200 Subject: [PATCH 58/65] Allowlist UPL-1.0 license. --- .github/dependency-review-config.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/dependency-review-config.yml b/.github/dependency-review-config.yml index 2ea218503..8390cfb5b 100644 --- a/.github/dependency-review-config.yml +++ b/.github/dependency-review-config.yml @@ -27,6 +27,5 @@ allow-licenses: - 'BSD-3-Clause-No-Nuclear-License-2014' - 'BSD-3-Clause-No-Nuclear-Warranty' - 'BSD-3-Clause-Open-MPI' - # TT: D290816995 - 'UPL-1.0' comment-summary-in-pr: on-failure From 6c293c62ebe31eeb817a7b2a689f12cd77a1f3dd Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Fri, 15 Aug 2025 09:03:05 +0200 Subject: [PATCH 59/65] Fix native tests in powertools-serialization. Remove mockito dependency there. --- powertools-serialization/pom.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/powertools-serialization/pom.xml b/powertools-serialization/pom.xml index 911f47850..b82a56af5 100644 --- a/powertools-serialization/pom.xml +++ b/powertools-serialization/pom.xml @@ -137,6 +137,12 @@ --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED --no-fallback + -Dorg.graalvm.nativeimage.imagecode=agent + --initialize-at-build-time=org.slf4j.simple.SimpleLogger + --initialize-at-build-time=org.slf4j.LoggerFactory + --initialize-at-build-time=org.junit.Ignore + --initialize-at-build-time=java.lang.annotation.Annotation + --initialize-at-build-time=org.junit.runners.model.FrameworkField --verbose --native-image-info -H:+UnlockExperimentalVMOptions From c6f53ded5fa07b73e4c41817c9d5fa4ece7cd47a Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Fri, 15 Aug 2025 11:26:32 +0200 Subject: [PATCH 60/65] Remove mockito from powertools-common. --- powertools-common/pom.xml | 28 ++---- .../internal/LambdaHandlerProcessorTest.java | 30 +++---- .../common/stubs/TestInputStream.java | 24 +++++ .../common/stubs/TestOutputStream.java | 23 +++++ .../common/stubs/TestProceedingJoinPoint.java | 90 +++++++++++++++++++ .../common/stubs/TestSignature.java | 55 ++++++++++++ 6 files changed, 210 insertions(+), 40 deletions(-) create mode 100644 powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestInputStream.java create mode 100644 powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestOutputStream.java create mode 100644 powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestProceedingJoinPoint.java create mode 100644 powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestSignature.java diff --git a/powertools-common/pom.xml b/powertools-common/pom.xml index 8a9d06460..c4da617ca 100644 --- a/powertools-common/pom.xml +++ b/powertools-common/pom.xml @@ -81,22 +81,10 @@ slf4j-simple test - - org.mockito - mockito-core - test - generate-graalvm-files - - - org.mockito - mockito-subclass - test - - @@ -104,8 +92,7 @@ maven-surefire-plugin 3.5.3 - - -Dorg.graalvm.nativeimage.imagecode=agent + -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-common,experimental-class-define-support --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED @@ -117,13 +104,6 @@ graalvm-native - - - org.mockito - mockito-subclass - test - - @@ -146,6 +126,12 @@ --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED --no-fallback + -Dorg.graalvm.nativeimage.imagecode=agent + --initialize-at-build-time=org.slf4j.simple.SimpleLogger + --initialize-at-build-time=org.slf4j.LoggerFactory + --initialize-at-build-time=org.junit.Ignore + --initialize-at-build-time=java.lang.annotation.Annotation + --initialize-at-build-time=org.junit.runners.model.FrameworkField --verbose --native-image-info -H:+UnlockExperimentalVMOptions diff --git a/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/LambdaHandlerProcessorTest.java b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/LambdaHandlerProcessorTest.java index 17732cdf0..11eac7a4c 100644 --- a/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/LambdaHandlerProcessorTest.java +++ b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/LambdaHandlerProcessorTest.java @@ -16,15 +16,10 @@ 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.when; -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.junitpioneer.jupiter.ClearEnvironmentVariable; import org.junitpioneer.jupiter.SetEnvironmentVariable; @@ -34,6 +29,10 @@ import com.amazonaws.services.lambda.runtime.RequestStreamHandler; import software.amazon.lambda.powertools.common.stubs.TestLambdaContext; +import software.amazon.lambda.powertools.common.stubs.TestInputStream; +import software.amazon.lambda.powertools.common.stubs.TestOutputStream; +import software.amazon.lambda.powertools.common.stubs.TestProceedingJoinPoint; +import software.amazon.lambda.powertools.common.stubs.TestSignature; class LambdaHandlerProcessorTest { @@ -48,7 +47,7 @@ void isHandlerMethod_shouldRecognizeRequestHandler() { @Test void isHandlerMethod_shouldRecognizeRequestStreamHandler() { - Object[] args = { mock(InputStream.class), mock(OutputStream.class), new TestLambdaContext() }; + Object[] args = { new TestInputStream(), new TestOutputStream(), new TestLambdaContext() }; ProceedingJoinPoint pjpMock = mockRequestHandlerPjp(RequestStreamHandler.class, args); assertThat(LambdaHandlerProcessor.isHandlerMethod(pjpMock)).isTrue(); @@ -73,7 +72,7 @@ void placedOnRequestHandler_shouldRecognizeRequestHandler() { @Test void placedOnStreamHandler_shouldRecognizeRequestStreamHandler() { - Object[] args = { mock(InputStream.class), mock(OutputStream.class), new TestLambdaContext() }; + Object[] args = { new TestInputStream(), new TestOutputStream(), new TestLambdaContext() }; ProceedingJoinPoint pjpMock = mockRequestHandlerPjp(RequestStreamHandler.class, args); assertThat(LambdaHandlerProcessor.placedOnStreamHandler(pjpMock)).isTrue(); @@ -121,7 +120,7 @@ void placedOnStreamHandler_shouldInvalidateOnWrongTypeOfArgs() { @Test void placedOnStreamHandler_shouldInvalidateOnTypeOfArgs_invalidOutputStreamArg() { - Object[] args = { mock(InputStream.class), new Object(), new TestLambdaContext() }; + Object[] args = { new TestInputStream(), new Object(), new TestLambdaContext() }; ProceedingJoinPoint pjpMock = mockRequestHandlerPjp(RequestStreamHandler.class, args); boolean isPlacedOnStreamHandler = LambdaHandlerProcessor.placedOnStreamHandler(pjpMock); @@ -131,7 +130,7 @@ void placedOnStreamHandler_shouldInvalidateOnTypeOfArgs_invalidOutputStreamArg() @Test void placedOnStreamHandler_shouldInvalidateOnTypeOfArgs_invalidContextArg() { - Object[] args = { mock(InputStream.class), mock(OutputStream.class), new Object() }; + Object[] args = { new TestInputStream(), new TestOutputStream(), new Object() }; ProceedingJoinPoint pjpMock = mockRequestHandlerPjp(RequestStreamHandler.class, args); boolean isPlacedOnStreamHandler = LambdaHandlerProcessor.placedOnStreamHandler(pjpMock); @@ -171,7 +170,7 @@ void extractContext_fromRequestHandler() { @Test void extractContext_fromStreamRequestHandler() { - Object[] args = { mock(InputStream.class), mock(OutputStream.class), new TestLambdaContext() }; + Object[] args = { new TestInputStream(), new TestOutputStream(), new TestLambdaContext() }; ProceedingJoinPoint pjpMock = mockRequestHandlerPjp(RequestStreamHandler.class, args); Context context = LambdaHandlerProcessor.extractContext(pjpMock); @@ -231,14 +230,7 @@ void serviceName_Undefined() { } private ProceedingJoinPoint mockRequestHandlerPjp(Class handlerClass, Object[] handlerArgs) { - ProceedingJoinPoint pjp = mock(ProceedingJoinPoint.class); - Signature signature = mock(Signature.class); - - when(signature.getDeclaringType()).thenReturn(handlerClass); - when(signature.getName()).thenReturn("handleRequest"); - when(pjp.getSignature()).thenReturn(signature); - when(pjp.getArgs()).thenReturn(handlerArgs); - - return pjp; + TestSignature signature = new TestSignature(handlerClass); + return new TestProceedingJoinPoint(signature, handlerArgs); } } diff --git a/powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestInputStream.java b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestInputStream.java new file mode 100644 index 000000000..cb9122966 --- /dev/null +++ b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestInputStream.java @@ -0,0 +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.common.stubs; + +import java.io.InputStream; + +public class TestInputStream extends InputStream { + @Override + public int read() { + return -1; + } +} diff --git a/powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestOutputStream.java b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestOutputStream.java new file mode 100644 index 000000000..b64b4759d --- /dev/null +++ b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestOutputStream.java @@ -0,0 +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.common.stubs; + +import java.io.OutputStream; + +public class TestOutputStream extends OutputStream { + @Override + public void write(int b) { + } +} diff --git a/powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestProceedingJoinPoint.java b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestProceedingJoinPoint.java new file mode 100644 index 000000000..e0285518c --- /dev/null +++ b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestProceedingJoinPoint.java @@ -0,0 +1,90 @@ +/* + * 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.common.stubs; + +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.Signature; +import org.aspectj.lang.reflect.SourceLocation; +import org.aspectj.runtime.internal.AroundClosure; + +public class TestProceedingJoinPoint implements ProceedingJoinPoint { + private final Signature signature; + private final Object[] args; + + public TestProceedingJoinPoint(Signature signature, Object[] args) { + this.signature = signature; + this.args = args; + } + + @Override + public Object[] getArgs() { + return args; + } + + @Override + public Signature getSignature() { + return signature; + } + + @Override + public Object getTarget() { + return null; + } + + @Override + public Object getThis() { + return null; + } + + @Override + public StaticPart getStaticPart() { + return null; + } + + @Override + public String getKind() { + return null; + } + + @Override + public SourceLocation getSourceLocation() { + return null; + } + + @Override + public Object proceed() { + return null; + } + + @Override + public Object proceed(Object[] args) { + return null; + } + + @Override + public void set$AroundClosure(AroundClosure arc) { + // Stubbed method + } + + @Override + public String toLongString() { + return "handleRequest"; + } + + @Override + public String toShortString() { + return "handleRequest"; + } +} diff --git a/powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestSignature.java b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestSignature.java new file mode 100644 index 000000000..903e4c8fa --- /dev/null +++ b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestSignature.java @@ -0,0 +1,55 @@ +/* + * 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.common.stubs; + +import org.aspectj.lang.Signature; + +public class TestSignature implements Signature { + private final Class declaringType; + + public TestSignature(Class declaringType) { + this.declaringType = declaringType; + } + + @Override + public Class getDeclaringType() { + return declaringType; + } + + @Override + public String getDeclaringTypeName() { + return declaringType.getName(); + } + + @Override + public int getModifiers() { + return 0; + } + + @Override + public String getName() { + return "handleRequest"; + } + + @Override + public String toLongString() { + return "handleRequest"; + } + + @Override + public String toShortString() { + return "handleRequest"; + } +} From a314cff0ec49a2dd50c12ea4082500e86d3f5bf6 Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Fri, 15 Aug 2025 12:03:35 +0200 Subject: [PATCH 61/65] Remove mockito from powertools-logging. --- powertools-logging/pom.xml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/powertools-logging/pom.xml b/powertools-logging/pom.xml index 4312ffbf6..1ed628678 100644 --- a/powertools-logging/pom.xml +++ b/powertools-logging/pom.xml @@ -125,8 +125,7 @@ maven-surefire-plugin 3.5.3 - - -Dorg.graalvm.nativeimage.imagecode=agent + -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging,experimental-class-define-support --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED @@ -160,6 +159,12 @@ --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED --no-fallback + -Dorg.graalvm.nativeimage.imagecode=agent + --initialize-at-build-time=org.slf4j.simple.SimpleLogger + --initialize-at-build-time=org.slf4j.LoggerFactory + --initialize-at-build-time=org.junit.Ignore + --initialize-at-build-time=java.lang.annotation.Annotation + --initialize-at-build-time=org.junit.runners.model.FrameworkField --verbose --native-image-info -H:+UnlockExperimentalVMOptions From 4f02496c83e8cef090dda31ee29d0d0b77b20569 Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Fri, 15 Aug 2025 14:49:47 +0200 Subject: [PATCH 62/65] Remove mockito from powertools-logging-log4j. --- powertools-logging/powertools-logging-log4j/pom.xml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/powertools-logging/powertools-logging-log4j/pom.xml b/powertools-logging/powertools-logging-log4j/pom.xml index ad0c3c373..6a2dd3328 100644 --- a/powertools-logging/powertools-logging-log4j/pom.xml +++ b/powertools-logging/powertools-logging-log4j/pom.xml @@ -109,8 +109,7 @@ maven-surefire-plugin 3.5.3 - - -Dorg.graalvm.nativeimage.imagecode=agent + -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-log4j,experimental-class-define-support --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED From 623d4809b466b222616c2a9c7bb7ec118ccd9cce Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Fri, 15 Aug 2025 15:45:24 +0200 Subject: [PATCH 63/65] Remove mockito from powertools-logging-logback. --- powertools-logging/powertools-logging-logback/pom.xml | 6 +----- .../powertools/logging/internal/LambdaJsonEncoderTest.java | 4 ++-- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/powertools-logging/powertools-logging-logback/pom.xml b/powertools-logging/powertools-logging-logback/pom.xml index 9f0b36dad..af71dbfc4 100644 --- a/powertools-logging/powertools-logging-logback/pom.xml +++ b/powertools-logging/powertools-logging-logback/pom.xml @@ -97,8 +97,7 @@ maven-surefire-plugin 3.5.3 - - -Dorg.graalvm.nativeimage.imagecode=agent + -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback,experimental-class-define-support --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED @@ -129,9 +128,6 @@ powertools-logging-logback - - --initialize-at-build-time=org.junit.platform.launcher.core.DiscoveryIssueNotifier$1 - --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED --no-fallback diff --git a/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaJsonEncoderTest.java b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaJsonEncoderTest.java index 912e2fde9..398811d54 100644 --- a/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaJsonEncoderTest.java +++ b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaJsonEncoderTest.java @@ -217,9 +217,9 @@ void shouldLogStructuredArgumentsAsNewEntries() { StructuredArgument argument = StructuredArguments.entry("msg", msg); // WHEN - LoggingEvent structuredLoggingEvent = new LoggingEvent("fqcn", logger, Level.INFO, "A message", null, + LoggingEvent loggingEvent = new LoggingEvent("fqcn", logger, Level.INFO, "A message", null, new Object[] { argument }); - byte[] encoded = encoder.encode(structuredLoggingEvent); + byte[] encoded = encoder.encode(loggingEvent); String result = new String(encoded, StandardCharsets.UTF_8); // THEN (logged as JSON) From e0b8f3b72903790c802663e1b7cbaaf54fc705bb Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Fri, 15 Aug 2025 15:58:35 +0200 Subject: [PATCH 64/65] Remove mockito from powertools-tracing. --- powertools-tracing/pom.xml | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/powertools-tracing/pom.xml b/powertools-tracing/pom.xml index b6cac28aa..4d6f40511 100644 --- a/powertools-tracing/pom.xml +++ b/powertools-tracing/pom.xml @@ -130,8 +130,7 @@ maven-surefire-plugin 3.5.3 - - -Dorg.graalvm.nativeimage.imagecode=agent + -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-tracing,experimental-class-define-support --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED @@ -166,6 +165,14 @@ --add-opens java.base/java.lang=ALL-UNNAMED --enable-url-protocols=http --no-fallback + -Dorg.graalvm.nativeimage.imagecode=agent + -H:IncludeResources=version.properties + -H:IncludeResources=unreadable.properties + --initialize-at-build-time=org.slf4j.simple.SimpleLogger + --initialize-at-build-time=org.slf4j.LoggerFactory + --initialize-at-build-time=org.junit.Ignore + --initialize-at-build-time=java.lang.annotation.Annotation + --initialize-at-build-time=org.junit.runners.model.FrameworkField --verbose --native-image-info -H:+UnlockExperimentalVMOptions From 5ced0c90a50ca1500f7339d4af6898d14431a3b5 Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Mon, 18 Aug 2025 10:57:29 +0200 Subject: [PATCH 65/65] Simplify graalvm config for logback and log4j modules. --- powertools-common/pom.xml | 3 ++- powertools-logging/powertools-logging-log4j/pom.xml | 3 ++- powertools-logging/powertools-logging-logback/pom.xml | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/powertools-common/pom.xml b/powertools-common/pom.xml index c4da617ca..f4c4a6a7c 100644 --- a/powertools-common/pom.xml +++ b/powertools-common/pom.xml @@ -92,7 +92,8 @@ maven-surefire-plugin 3.5.3 - -Dorg.graalvm.nativeimage.imagecode=agent + + -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-common,experimental-class-define-support --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED diff --git a/powertools-logging/powertools-logging-log4j/pom.xml b/powertools-logging/powertools-logging-log4j/pom.xml index 6a2dd3328..ad0c3c373 100644 --- a/powertools-logging/powertools-logging-log4j/pom.xml +++ b/powertools-logging/powertools-logging-log4j/pom.xml @@ -109,7 +109,8 @@ maven-surefire-plugin 3.5.3 - -Dorg.graalvm.nativeimage.imagecode=agent + + -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-log4j,experimental-class-define-support --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED diff --git a/powertools-logging/powertools-logging-logback/pom.xml b/powertools-logging/powertools-logging-logback/pom.xml index af71dbfc4..470a8d728 100644 --- a/powertools-logging/powertools-logging-logback/pom.xml +++ b/powertools-logging/powertools-logging-logback/pom.xml @@ -97,7 +97,8 @@ maven-surefire-plugin 3.5.3 - -Dorg.graalvm.nativeimage.imagecode=agent + + -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback,experimental-class-define-support --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED