From a4d019aa779177e59f7f36bcd5ed636696d0e950 Mon Sep 17 00:00:00 2001
From: Scott Gerring <gerrings@amazon.com>
Date: Tue, 29 Aug 2023 13:27:36 +0200
Subject: [PATCH 01/45] Starting by splitting SSM provider out

---
 .../powertools-examples-parameters/pom.xml    |   2 +-
 .../demo/parameters/ParametersFunction.java   |   6 +-
 pom.xml                                       |   2 +
 powertools-parameters/pom.xml                 |  19 +--
 .../powertools-parameters-ssm/pom.xml         | 116 ++++++++++++++++++
 .../parameters/ssm}/SSMProvider.java          |  22 ++--
 .../parameters/ssm}/SSMProviderTest.java      |  64 +++++-----
 .../powertools-parameters-tests/pom.xml       |  64 ++++++++++
 .../parameters/AppConfigProviderTest.java     |   0
 .../parameters/BaseProviderTest.java          |   0
 .../parameters/DynamoDbProviderE2ETest.java   |   0
 .../parameters/DynamoDbProviderTest.java      |   0
 .../LambdaParametersAspectTest.java           |  33 ++---
 .../ParamManagerIntegrationTest.java          |  10 +-
 .../parameters/ParamManagerTest.java          |  10 --
 .../parameters/SecretsProviderTest.java       |   0
 .../parameters/cache/CacheManagerTest.java    |   0
 .../parameters/cache/DataStoreTest.java       |   0
 .../parameters/internal/AnotherObject.java    |   0
 .../parameters/internal/CustomProvider.java   |   0
 .../transform/Base64TransformerTest.java      |   0
 .../transform/JsonTransformerTest.java        |   0
 .../transform/ObjectToDeserialize.java        |   0
 .../transform/TransformationManagerTest.java  |   0
 .../lambda/powertools/parameters/Param.java   |   2 +-
 .../powertools/parameters/ParamManager.java   |  27 +---
 26 files changed, 258 insertions(+), 119 deletions(-)
 create mode 100644 powertools-parameters/powertools-parameters-ssm/pom.xml
 rename powertools-parameters/{src/main/java/software/amazon/lambda/powertools/parameters => powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm}/SSMProvider.java (95%)
 rename powertools-parameters/{src/test/java/software/amazon/lambda/powertools/parameters => powertools-parameters-ssm/src/test/java/software/amazon/lambda/powertools/parameters/ssm}/SSMProviderTest.java (74%)
 create mode 100644 powertools-parameters/powertools-parameters-tests/pom.xml
 rename powertools-parameters/{ => powertools-parameters-tests}/src/test/java/software/amazon/lambda/powertools/parameters/AppConfigProviderTest.java (100%)
 rename powertools-parameters/{ => powertools-parameters-tests}/src/test/java/software/amazon/lambda/powertools/parameters/BaseProviderTest.java (100%)
 rename powertools-parameters/{ => powertools-parameters-tests}/src/test/java/software/amazon/lambda/powertools/parameters/DynamoDbProviderE2ETest.java (100%)
 rename powertools-parameters/{ => powertools-parameters-tests}/src/test/java/software/amazon/lambda/powertools/parameters/DynamoDbProviderTest.java (100%)
 rename powertools-parameters/{src/test/java/software/amazon/lambda/powertools/parameters/internal => powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters}/LambdaParametersAspectTest.java (74%)
 rename powertools-parameters/{ => powertools-parameters-tests}/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerIntegrationTest.java (93%)
 rename powertools-parameters/{ => powertools-parameters-tests}/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerTest.java (92%)
 rename powertools-parameters/{ => powertools-parameters-tests}/src/test/java/software/amazon/lambda/powertools/parameters/SecretsProviderTest.java (100%)
 rename powertools-parameters/{ => powertools-parameters-tests}/src/test/java/software/amazon/lambda/powertools/parameters/cache/CacheManagerTest.java (100%)
 rename powertools-parameters/{ => powertools-parameters-tests}/src/test/java/software/amazon/lambda/powertools/parameters/cache/DataStoreTest.java (100%)
 rename powertools-parameters/{ => powertools-parameters-tests}/src/test/java/software/amazon/lambda/powertools/parameters/internal/AnotherObject.java (100%)
 rename powertools-parameters/{ => powertools-parameters-tests}/src/test/java/software/amazon/lambda/powertools/parameters/internal/CustomProvider.java (100%)
 rename powertools-parameters/{ => powertools-parameters-tests}/src/test/java/software/amazon/lambda/powertools/parameters/transform/Base64TransformerTest.java (100%)
 rename powertools-parameters/{ => powertools-parameters-tests}/src/test/java/software/amazon/lambda/powertools/parameters/transform/JsonTransformerTest.java (100%)
 rename powertools-parameters/{ => powertools-parameters-tests}/src/test/java/software/amazon/lambda/powertools/parameters/transform/ObjectToDeserialize.java (100%)
 rename powertools-parameters/{ => powertools-parameters-tests}/src/test/java/software/amazon/lambda/powertools/parameters/transform/TransformationManagerTest.java (100%)

diff --git a/examples/powertools-examples-parameters/pom.xml b/examples/powertools-examples-parameters/pom.xml
index 19be585a5..03b9e4dad 100644
--- a/examples/powertools-examples-parameters/pom.xml
+++ b/examples/powertools-examples-parameters/pom.xml
@@ -21,7 +21,7 @@
         </dependency>
         <dependency>
             <groupId>software.amazon.lambda</groupId>
-            <artifactId>powertools-parameters</artifactId>
+            <artifactId>powertools-parameters-ssm</artifactId>
             <version>${project.version}</version>
         </dependency>
         <dependency>
diff --git a/examples/powertools-examples-parameters/src/main/java/org/demo/parameters/ParametersFunction.java b/examples/powertools-examples-parameters/src/main/java/org/demo/parameters/ParametersFunction.java
index 5b691cfd9..5dfec8031 100644
--- a/examples/powertools-examples-parameters/src/main/java/org/demo/parameters/ParametersFunction.java
+++ b/examples/powertools-examples-parameters/src/main/java/org/demo/parameters/ParametersFunction.java
@@ -32,13 +32,15 @@
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 import software.amazon.lambda.powertools.parameters.ParamManager;
-import software.amazon.lambda.powertools.parameters.SSMProvider;
+import software.amazon.lambda.powertools.parameters.ssm.SSMProvider;
 import software.amazon.lambda.powertools.parameters.SecretsProvider;
 
 public class ParametersFunction implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {
     private final static Logger log = LogManager.getLogger(ParametersFunction.class);
 
-    SSMProvider ssmProvider = ParamManager.getSsmProvider();
+    SSMProvider ssmProvider = SSMProvider
+            .builder()
+            .build();
     SecretsProvider secretsProvider = ParamManager.getSecretsProvider();
 
     String simpleValue = ssmProvider.defaultMaxAge(30, SECONDS).get("/powertools-java/sample/simplekey");
diff --git a/pom.xml b/pom.xml
index 17fb1a712..e9465fd41 100644
--- a/pom.xml
+++ b/pom.xml
@@ -54,6 +54,8 @@
         <module>powertools-e2e-tests</module>
         <module>powertools-batch</module>
         <module>examples</module>
+        <module>powertools-parameters/powertools-parameters-ssm</module>
+        <module>powertools-parameters/powertools-parameters-tests</module>
     </modules>
 
     <scm>
diff --git a/powertools-parameters/pom.xml b/powertools-parameters/pom.xml
index a703bf36b..95ec9cd6b 100644
--- a/powertools-parameters/pom.xml
+++ b/powertools-parameters/pom.xml
@@ -28,9 +28,8 @@
 
     <name>Powertools for AWS Lambda (Java) library Parameters</name>
 
-    <description>
-        Set of utilities to retrieve parameters from Secrets Manager or SSM Parameter Store
-    </description>
+    <description>Set of utilities to retrieve parameters - common interface</description>
+
     <url>https://aws.amazon.com/lambda/</url>
     <issueManagement>
         <system>GitHub Issues</system>
@@ -59,20 +58,6 @@
             <groupId>software.amazon.lambda</groupId>
             <artifactId>powertools-common</artifactId>
         </dependency>
-        <dependency>
-            <groupId>software.amazon.awssdk</groupId>
-            <artifactId>ssm</artifactId>
-            <exclusions>
-                <exclusion>
-                    <groupId>software.amazon.awssdk</groupId>
-                    <artifactId>apache-client</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>software.amazon.awssdk</groupId>
-                    <artifactId>netty-nio-client</artifactId>
-                </exclusion>
-            </exclusions>
-        </dependency>
         <dependency>
             <groupId>software.amazon.awssdk</groupId>
             <artifactId>secretsmanager</artifactId>
diff --git a/powertools-parameters/powertools-parameters-ssm/pom.xml b/powertools-parameters/powertools-parameters-ssm/pom.xml
new file mode 100644
index 000000000..fae952999
--- /dev/null
+++ b/powertools-parameters/powertools-parameters-ssm/pom.xml
@@ -0,0 +1,116 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         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">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>software.amazon.lambda</groupId>
+        <artifactId>powertools-parent</artifactId>
+        <version>2.0.0-SNAPSHOT</version>
+        <relativePath>../../pom.xml</relativePath>
+    </parent>
+
+    <artifactId>powertools-parameters-ssm</artifactId>
+    <name>Powertools for AWS Lambda (Java) library Parameters - SSM</name>
+    <description>SSM Parameter Store implementation for the Parameters module</description>
+
+    <issueManagement>
+        <system>GitHub Issues</system>
+        <url>https://github.com/aws-powertools/powertools-lambda-java/issues</url>
+    </issueManagement>
+    <scm>
+        <url>https://github.com/aws-powertools/powertools-lambda-java.git</url>
+    </scm>
+    <developers>
+        <developer>
+            <name>Powertools for AWS Lambda team</name>
+            <organization>Amazon Web Services</organization>
+            <organizationUrl>https://aws.amazon.com/</organizationUrl>
+        </developer>
+    </developers>
+
+    <distributionManagement>
+        <snapshotRepository>
+            <id>ossrh</id>
+            <url>https://aws.oss.sonatype.org/content/repositories/snapshots</url>
+        </snapshotRepository>
+    </distributionManagement>
+
+    <dependencies>
+        <dependency>
+            <groupId>software.amazon.lambda</groupId>
+            <artifactId>powertools-parameters</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <!-- Test dependencies -->
+        <dependency>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter-api</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter-engine</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-core</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-inline</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.assertj</groupId>
+            <artifactId>assertj-core</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.aspectj</groupId>
+            <artifactId>aspectjweaver</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>software.amazon.awssdk</groupId>
+            <artifactId>ssm</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>software.amazon.awssdk</groupId>
+                    <artifactId>apache-client</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>software.amazon.awssdk</groupId>
+                    <artifactId>netty-nio-client</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <version>3.1.2</version>
+                <configuration>
+                    <environmentVariables>
+                        <AWS_REGION>eu-central-1</AWS_REGION>
+                    </environmentVariables>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-checkstyle-plugin</artifactId>
+            </plugin>
+        </plugins>
+    </build>
+</project>
\ No newline at end of file
diff --git a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/SSMProvider.java b/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMProvider.java
similarity index 95%
rename from powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/SSMProvider.java
rename to powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMProvider.java
index 10bb70c15..7f308228d 100644
--- a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/SSMProvider.java
+++ b/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMProvider.java
@@ -12,7 +12,7 @@
  *
  */
 
-package software.amazon.lambda.powertools.parameters;
+package software.amazon.lambda.powertools.parameters.ssm;
 
 import java.time.temporal.ChronoUnit;
 import java.util.HashMap;
@@ -28,6 +28,8 @@
 import software.amazon.awssdk.services.ssm.model.GetParametersByPathResponse;
 import software.amazon.awssdk.utils.StringUtils;
 import software.amazon.lambda.powertools.common.internal.UserAgentConfigurator;
+import software.amazon.lambda.powertools.parameters.BaseProvider;
+import software.amazon.lambda.powertools.parameters.ParamManager;
 import software.amazon.lambda.powertools.parameters.cache.CacheManager;
 import software.amazon.lambda.powertools.parameters.transform.TransformationManager;
 import software.amazon.lambda.powertools.parameters.transform.Transformer;
@@ -89,17 +91,6 @@ public class SSMProvider extends BaseProvider {
         this.client = client;
     }
 
-    /**
-     * Constructor with only a CacheManager<br/>
-     * <p>
-     * Used in {@link ParamManager#createProvider(Class)}
-     *
-     * @param cacheManager handles the parameter caching
-     */
-    SSMProvider(CacheManager cacheManager) {
-        this(cacheManager, Builder.createClient());
-    }
-
     /**
      * Create a builder that can be used to configure and create a {@link SSMProvider}.
      *
@@ -242,7 +233,7 @@ SsmClient getClient() {
         return client;
     }
 
-    static class Builder {
+    public static class Builder {
         private SsmClient client;
         private CacheManager cacheManager;
         private TransformationManager transformationManager;
@@ -253,7 +244,7 @@ private static SsmClient createClient() {
                     .region(Region.of(System.getenv(SdkSystemSetting.AWS_REGION.environmentVariable())))
                     .overrideConfiguration(ClientOverrideConfiguration.builder()
                             .putAdvancedOption(SdkAdvancedClientOption.USER_AGENT_SUFFIX,
-                                    UserAgentConfigurator.getUserAgent(PARAMETERS)).build())
+                                    UserAgentConfigurator.getUserAgent(BaseProvider.PARAMETERS)).build())
                     .build();
         }
 
@@ -264,7 +255,8 @@ private static SsmClient createClient() {
          */
         public SSMProvider build() {
             if (cacheManager == null) {
-                throw new IllegalStateException("No CacheManager provided, please provide one");
+                // TODO - do we want to share this somehow?
+                cacheManager = new CacheManager();
             }
             SSMProvider provider;
             if (client == null) {
diff --git a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/SSMProviderTest.java b/powertools-parameters/powertools-parameters-ssm/src/test/java/software/amazon/lambda/powertools/parameters/ssm/SSMProviderTest.java
similarity index 74%
rename from powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/SSMProviderTest.java
rename to powertools-parameters/powertools-parameters-ssm/src/test/java/software/amazon/lambda/powertools/parameters/ssm/SSMProviderTest.java
index 2a4f8f927..a85f71727 100644
--- a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/SSMProviderTest.java
+++ b/powertools-parameters/powertools-parameters-ssm/src/test/java/software/amazon/lambda/powertools/parameters/ssm/SSMProviderTest.java
@@ -12,7 +12,7 @@
  *
  */
 
-package software.amazon.lambda.powertools.parameters;
+package software.amazon.lambda.powertools.parameters.ssm;
 
 import static java.util.Arrays.asList;
 import static org.assertj.core.api.Assertions.assertThat;
@@ -27,12 +27,16 @@
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
+import org.assertj.core.api.Assertions;
 import org.assertj.core.data.MapEntry;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.mockito.ArgumentCaptor;
+import org.mockito.ArgumentMatchers;
 import org.mockito.Captor;
 import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
 import software.amazon.awssdk.services.ssm.SsmClient;
 import software.amazon.awssdk.services.ssm.model.GetParameterRequest;
 import software.amazon.awssdk.services.ssm.model.GetParameterResponse;
@@ -62,7 +66,7 @@ public class SSMProviderTest {
 
     @BeforeEach
     public void init() {
-        openMocks(this);
+        MockitoAnnotations.openMocks(this);
         cacheManager = new CacheManager();
         provider = new SSMProvider(cacheManager, client);
     }
@@ -75,9 +79,9 @@ public void getValue() {
 
         String value = provider.getValue(key);
 
-        assertThat(value).isEqualTo(expectedValue);
-        assertThat(paramCaptor.getValue().name()).isEqualTo(key);
-        assertThat(paramCaptor.getValue().withDecryption()).isFalse();
+        Assertions.assertThat(value).isEqualTo(expectedValue);
+        Assertions.assertThat(paramCaptor.getValue().name()).isEqualTo(key);
+        Assertions.assertThat(paramCaptor.getValue().withDecryption()).isFalse();
     }
 
     @Test
@@ -88,9 +92,9 @@ public void getValueDecrypted() {
 
         String value = provider.withDecryption().getValue(key);
 
-        assertThat(value).isEqualTo(expectedValue);
-        assertThat(paramCaptor.getValue().name()).isEqualTo(key);
-        assertThat(paramCaptor.getValue().withDecryption()).isTrue();
+        Assertions.assertThat(value).isEqualTo(expectedValue);
+        Assertions.assertThat(paramCaptor.getValue().name()).isEqualTo(key);
+        Assertions.assertThat(paramCaptor.getValue().withDecryption()).isTrue();
     }
 
     @Test
@@ -100,10 +104,10 @@ public void getMultiple() {
         parameters.add(Parameter.builder().name("/prod/app1/key2").value("foo2").build());
         parameters.add(Parameter.builder().name("/prod/app1/key3").value("foo3").build());
         GetParametersByPathResponse response = GetParametersByPathResponse.builder().parameters(parameters).build();
-        when(client.getParametersByPath(paramByPathCaptor.capture())).thenReturn(response);
+        Mockito.when(client.getParametersByPath(paramByPathCaptor.capture())).thenReturn(response);
 
         Map<String, String> params = provider.getMultiple("/prod/app1");
-        assertThat(params).contains(
+        Assertions.assertThat(params).contains(
                 MapEntry.entry("key1", "foo1"),
                 MapEntry.entry("key2", "foo2"),
                 MapEntry.entry("key3", "foo3"));
@@ -111,9 +115,9 @@ public void getMultiple() {
         assertThat(provider.get("/prod/app1/key2")).isEqualTo("foo2");
         assertThat(provider.get("/prod/app1/key3")).isEqualTo("foo3");
 
-        assertThat(paramByPathCaptor.getValue().path()).isEqualTo("/prod/app1");
-        assertThat(paramByPathCaptor.getValue().withDecryption()).isFalse();
-        assertThat(paramByPathCaptor.getValue().recursive()).isFalse();
+        Assertions.assertThat(paramByPathCaptor.getValue().path()).isEqualTo("/prod/app1");
+        Assertions.assertThat(paramByPathCaptor.getValue().withDecryption()).isFalse();
+        Assertions.assertThat(paramByPathCaptor.getValue().recursive()).isFalse();
     }
 
     @Test
@@ -123,10 +127,10 @@ public void getMultipleWithTrailingSlash() {
         parameters.add(Parameter.builder().name("/prod/app1/key2").value("foo2").build());
         parameters.add(Parameter.builder().name("/prod/app1/key3").value("foo3").build());
         GetParametersByPathResponse response = GetParametersByPathResponse.builder().parameters(parameters).build();
-        when(client.getParametersByPath(paramByPathCaptor.capture())).thenReturn(response);
+        Mockito.when(client.getParametersByPath(paramByPathCaptor.capture())).thenReturn(response);
 
         Map<String, String> params = provider.getMultiple("/prod/app1/");
-        assertThat(params).contains(
+        Assertions.assertThat(params).contains(
                 MapEntry.entry("key1", "foo1"),
                 MapEntry.entry("key2", "foo2"),
                 MapEntry.entry("key3", "foo3"));
@@ -134,9 +138,9 @@ public void getMultipleWithTrailingSlash() {
         assertThat(provider.get("/prod/app1/key2")).isEqualTo("foo2");
         assertThat(provider.get("/prod/app1/key3")).isEqualTo("foo3");
 
-        assertThat(paramByPathCaptor.getValue().path()).isEqualTo("/prod/app1");
-        assertThat(paramByPathCaptor.getValue().withDecryption()).isFalse();
-        assertThat(paramByPathCaptor.getValue().recursive()).isFalse();
+        Assertions.assertThat(paramByPathCaptor.getValue().path()).isEqualTo("/prod/app1");
+        Assertions.assertThat(paramByPathCaptor.getValue().withDecryption()).isFalse();
+        Assertions.assertThat(paramByPathCaptor.getValue().recursive()).isFalse();
     }
 
     @Test
@@ -146,7 +150,7 @@ public void getMultiple_cached_shouldNotCallSSM() {
         parameters.add(Parameter.builder().name("/prod/app1/key2").value("foo2").build());
         parameters.add(Parameter.builder().name("/prod/app1/key3").value("foo3").build());
         GetParametersByPathResponse response = GetParametersByPathResponse.builder().parameters(parameters).build();
-        when(client.getParametersByPath(paramByPathCaptor.capture())).thenReturn(response);
+        Mockito.when(client.getParametersByPath(paramByPathCaptor.capture())).thenReturn(response);
 
         provider.getMultiple("/prod/app1");
 
@@ -156,7 +160,7 @@ public void getMultiple_cached_shouldNotCallSSM() {
         provider.get("/prod/app1/key2");
         provider.get("/prod/app1/key3");
 
-        verify(client, times(1)).getParametersByPath(any(GetParametersByPathRequest.class));
+        Mockito.verify(client, Mockito.times(1)).getParametersByPath(ArgumentMatchers.any(GetParametersByPathRequest.class));
 
     }
 
@@ -172,11 +176,11 @@ public void getMultipleWithNextToken() {
         parameters2.add(Parameter.builder().name("/prod/app1/key3").value("foo3").build());
         GetParametersByPathResponse response2 = GetParametersByPathResponse.builder().parameters(parameters2).build();
 
-        when(client.getParametersByPath(paramByPathCaptor.capture())).thenReturn(response1, response2);
+        Mockito.when(client.getParametersByPath(paramByPathCaptor.capture())).thenReturn(response1, response2);
 
         Map<String, String> params = provider.getMultiple("/prod/app1");
 
-        assertThat(params).contains(
+        Assertions.assertThat(params).contains(
                 MapEntry.entry("key1", "foo1"),
                 MapEntry.entry("key2", "foo2"),
                 MapEntry.entry("key3", "foo3"));
@@ -185,22 +189,22 @@ public void getMultipleWithNextToken() {
         GetParametersByPathRequest request1 = requestParams.get(0);
         GetParametersByPathRequest request2 = requestParams.get(1);
 
-        assertThat(asList(request1, request2)).allSatisfy(req ->
+        Assertions.assertThat(asList(request1, request2)).allSatisfy(req ->
         {
-            assertThat(req.path()).isEqualTo("/prod/app1");
-            assertThat(req.withDecryption()).isFalse();
-            assertThat(req.recursive()).isFalse();
+            Assertions.assertThat(req.path()).isEqualTo("/prod/app1");
+            Assertions.assertThat(req.withDecryption()).isFalse();
+            Assertions.assertThat(req.recursive()).isFalse();
         });
 
-        assertThat(request1.nextToken()).isNull();
-        assertThat(request2.nextToken()).isEqualTo("123abc");
+        Assertions.assertThat(request1.nextToken()).isNull();
+        Assertions.assertThat(request2.nextToken()).isEqualTo("123abc");
     }
 
     @Test
     public void testSecretsProviderBuilderMissingCacheManager_throwsException() {
 
         // Act & Assert
-        assertThatIllegalStateException().isThrownBy(() -> SSMProvider.builder()
+        Assertions.assertThatIllegalStateException().isThrownBy(() -> SSMProvider.builder()
                         .withClient(client)
                         .withTransformationManager(transformationManager)
                         .build())
@@ -210,7 +214,7 @@ public void testSecretsProviderBuilderMissingCacheManager_throwsException() {
     private void initMock(String expectedValue) {
         Parameter parameter = Parameter.builder().value(expectedValue).build();
         GetParameterResponse result = GetParameterResponse.builder().parameter(parameter).build();
-        when(client.getParameter(paramCaptor.capture())).thenReturn(result);
+        Mockito.when(client.getParameter(paramCaptor.capture())).thenReturn(result);
         provider.defaultMaxAge(1, ChronoUnit.DAYS);
         provider.withMaxAge(2, ChronoUnit.DAYS);
         provider.recursive();
diff --git a/powertools-parameters/powertools-parameters-tests/pom.xml b/powertools-parameters/powertools-parameters-tests/pom.xml
new file mode 100644
index 000000000..cff5a6324
--- /dev/null
+++ b/powertools-parameters/powertools-parameters-tests/pom.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         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">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>software.amazon.lambda</groupId>
+        <artifactId>powertools-parent</artifactId>
+        <version>2.0.0-SNAPSHOT</version>
+        <relativePath>../../pom.xml</relativePath>
+    </parent>
+
+    <artifactId>powertools-parameters-tests</artifactId>
+    <description>Powertools parameters tests that cut across all the parameters providers</description>
+    <properties>
+        <!-- Don't deploy the examples -->
+        <maven.deploy.skip>true</maven.deploy.skip>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>software.amazon.lambda</groupId>
+            <artifactId>powertools-parameters-ssm</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <!-- Test dependencies -->
+        <dependency>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter-api</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter-engine</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-core</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-inline</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.assertj</groupId>
+            <artifactId>assertj-core</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.aspectj</groupId>
+            <artifactId>aspectjweaver</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+</project>
\ No newline at end of file
diff --git a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/AppConfigProviderTest.java b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/AppConfigProviderTest.java
similarity index 100%
rename from powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/AppConfigProviderTest.java
rename to powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/AppConfigProviderTest.java
diff --git a/powertools-parameters/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
similarity index 100%
rename from powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/BaseProviderTest.java
rename to powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/BaseProviderTest.java
diff --git a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/DynamoDbProviderE2ETest.java b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/DynamoDbProviderE2ETest.java
similarity index 100%
rename from powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/DynamoDbProviderE2ETest.java
rename to powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/DynamoDbProviderE2ETest.java
diff --git a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/DynamoDbProviderTest.java b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/DynamoDbProviderTest.java
similarity index 100%
rename from powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/DynamoDbProviderTest.java
rename to powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/DynamoDbProviderTest.java
diff --git a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/internal/LambdaParametersAspectTest.java b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/LambdaParametersAspectTest.java
similarity index 74%
rename from powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/internal/LambdaParametersAspectTest.java
rename to powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/LambdaParametersAspectTest.java
index 2c246336b..0e978d274 100644
--- a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/internal/LambdaParametersAspectTest.java
+++ b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/LambdaParametersAspectTest.java
@@ -1,4 +1,4 @@
-/*
+package software.amazon.lambda.powertools.parameters;/*
  * Copyright 2023 Amazon.com, Inc. or its affiliates.
  * Licensed under the Apache License, Version 2.0 (the
  * "License"); you may not use this file except in compliance
@@ -12,8 +12,6 @@
  *
  */
 
-package software.amazon.lambda.powertools.parameters.internal;
-
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
 import static org.mockito.Mockito.mockStatic;
@@ -22,14 +20,19 @@
 import static org.mockito.Mockito.when;
 import static org.mockito.MockitoAnnotations.openMocks;
 
+import org.assertj.core.api.Assertions;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.mockito.Mock;
 import org.mockito.MockedStatic;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
 import software.amazon.lambda.powertools.parameters.Param;
 import software.amazon.lambda.powertools.parameters.ParamManager;
-import software.amazon.lambda.powertools.parameters.SSMProvider;
 import software.amazon.lambda.powertools.parameters.exception.TransformationException;
+import software.amazon.lambda.powertools.parameters.internal.AnotherObject;
+import software.amazon.lambda.powertools.parameters.internal.CustomProvider;
+import software.amazon.lambda.powertools.parameters.ssm.SSMProvider;
 import software.amazon.lambda.powertools.parameters.transform.Base64Transformer;
 import software.amazon.lambda.powertools.parameters.transform.JsonTransformer;
 import software.amazon.lambda.powertools.parameters.transform.ObjectToDeserialize;
@@ -39,7 +42,7 @@ public class LambdaParametersAspectTest {
     @Mock
     private SSMProvider defaultProvider;
 
-    @Param(key = "/default")
+    @Param(key = "/default", provider = SSMProvider.class)
     private String defaultValue;
 
     @Param(key = "/simple", provider = CustomProvider.class)
@@ -56,18 +59,18 @@ public class LambdaParametersAspectTest {
 
     @BeforeEach
     public void init() {
-        openMocks(this);
+        MockitoAnnotations.openMocks(this);
     }
 
     @Test
     public void testDefault_ShouldUseSSMProvider() {
-        try (MockedStatic<ParamManager> mocked = mockStatic(ParamManager.class)) {
+        try (MockedStatic<ParamManager> mocked = Mockito.mockStatic(ParamManager.class)) {
             mocked.when(() -> ParamManager.getProvider(SSMProvider.class)).thenReturn(defaultProvider);
-            when(defaultProvider.get("/default")).thenReturn("value");
+            Mockito.when(defaultProvider.get("/default")).thenReturn("value");
 
-            assertThat(defaultValue).isEqualTo("value");
-            mocked.verify(() -> ParamManager.getProvider(SSMProvider.class), times(1));
-            verify(defaultProvider, times(1)).get("/default");
+            Assertions.assertThat(defaultValue).isEqualTo("value");
+            mocked.verify(() -> ParamManager.getProvider(SSMProvider.class), Mockito.times(1));
+            Mockito.verify(defaultProvider, Mockito.times(1)).get("/default");
 
             mocked.reset();
         }
@@ -75,17 +78,17 @@ public void testDefault_ShouldUseSSMProvider() {
 
     @Test
     public void testSimple() {
-        assertThat(param).isEqualTo("value");
+        Assertions.assertThat(param).isEqualTo("value");
     }
 
     @Test
     public void testWithBasicTransform() {
-        assertThat(basicTransform).isEqualTo("value");
+        Assertions.assertThat(basicTransform).isEqualTo("value");
     }
 
     @Test
     public void testWithComplexTransform() {
-        assertThat(complexTransform)
+        Assertions.assertThat(complexTransform)
                 .isInstanceOf(ObjectToDeserialize.class)
                 .matches(
                         o -> o.getFoo().equals("Foo") &&
@@ -95,7 +98,7 @@ public void testWithComplexTransform() {
 
     @Test
     public void testWithComplexTransformWrongTargetClass_ShouldThrowException() {
-        assertThatExceptionOfType(TransformationException.class)
+        Assertions.assertThatExceptionOfType(TransformationException.class)
                 .isThrownBy(() ->
                 {
                     AnotherObject obj = wrongTransform;
diff --git a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerIntegrationTest.java b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerIntegrationTest.java
similarity index 93%
rename from powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerIntegrationTest.java
rename to powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerIntegrationTest.java
index d6fbe66f0..67ea03618 100644
--- a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerIntegrationTest.java
+++ b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerIntegrationTest.java
@@ -43,6 +43,8 @@
 import software.amazon.awssdk.services.ssm.model.GetParametersByPathRequest;
 import software.amazon.awssdk.services.ssm.model.GetParametersByPathResponse;
 import software.amazon.awssdk.services.ssm.model.Parameter;
+import software.amazon.lambda.powertools.parameters.cache.CacheManager;
+import software.amazon.lambda.powertools.parameters.ssm.SSMProvider;
 
 public class ParamManagerIntegrationTest {
 
@@ -71,7 +73,9 @@ public void setup() throws IllegalAccessException {
 
     @Test
     public void ssmProvider_get() {
-        SSMProvider ssmProvider = ParamManager.getSsmProvider(ssmClient);
+        SSMProvider ssmProvider = SSMProvider.builder()
+                .withClient(ssmClient)
+                .build();
 
         String expectedValue = "value";
         Parameter parameter = Parameter.builder().value(expectedValue).build();
@@ -87,7 +91,9 @@ public void ssmProvider_get() {
 
     @Test
     public void ssmProvider_getMultiple() {
-        SSMProvider ssmProvider = ParamManager.getSsmProvider(ssmClient);
+        SSMProvider ssmProvider = SSMProvider.builder()
+                .withClient(ssmClient)
+                .build();
 
         List<Parameter> parameters = new ArrayList<>();
         parameters.add(Parameter.builder().name("/prod/app1/key1").value("foo1").build());
diff --git a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerTest.java b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerTest.java
similarity index 92%
rename from powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerTest.java
rename to powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerTest.java
index b84fcf743..dbfcb1007 100644
--- a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerTest.java
+++ b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerTest.java
@@ -91,16 +91,6 @@ public void testGetSecretsProvider_withoutParameter_shouldCreateDefaultClient()
         assertNotNull(secretsProvider.getClient());
     }
 
-    @Test
-    public void testGetSSMProvider_withoutParameter_shouldCreateDefaultClient() {
-
-        // Act
-        SSMProvider ssmProvider = ParamManager.getSsmProvider();
-
-        // Assert
-        assertNotNull(ssmProvider);
-        assertNotNull(ssmProvider.getClient());
-    }
 
     @Test
     public void testGetDynamoDBProvider_requireOtherParameters_throwException() {
diff --git a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/SecretsProviderTest.java b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/SecretsProviderTest.java
similarity index 100%
rename from powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/SecretsProviderTest.java
rename to powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/SecretsProviderTest.java
diff --git a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/cache/CacheManagerTest.java b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/cache/CacheManagerTest.java
similarity index 100%
rename from powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/cache/CacheManagerTest.java
rename to powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/cache/CacheManagerTest.java
diff --git a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/cache/DataStoreTest.java b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/cache/DataStoreTest.java
similarity index 100%
rename from powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/cache/DataStoreTest.java
rename to powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/cache/DataStoreTest.java
diff --git a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/internal/AnotherObject.java b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/internal/AnotherObject.java
similarity index 100%
rename from powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/internal/AnotherObject.java
rename to powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/internal/AnotherObject.java
diff --git a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/internal/CustomProvider.java b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/internal/CustomProvider.java
similarity index 100%
rename from powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/internal/CustomProvider.java
rename to powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/internal/CustomProvider.java
diff --git a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/transform/Base64TransformerTest.java b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/transform/Base64TransformerTest.java
similarity index 100%
rename from powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/transform/Base64TransformerTest.java
rename to powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/transform/Base64TransformerTest.java
diff --git a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/transform/JsonTransformerTest.java b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/transform/JsonTransformerTest.java
similarity index 100%
rename from powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/transform/JsonTransformerTest.java
rename to powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/transform/JsonTransformerTest.java
diff --git a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/transform/ObjectToDeserialize.java b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/transform/ObjectToDeserialize.java
similarity index 100%
rename from powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/transform/ObjectToDeserialize.java
rename to powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/transform/ObjectToDeserialize.java
diff --git a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/transform/TransformationManagerTest.java b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/transform/TransformationManagerTest.java
similarity index 100%
rename from powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/transform/TransformationManagerTest.java
rename to powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/transform/TransformationManagerTest.java
diff --git a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/Param.java b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/Param.java
index 7ffb0310c..d456cbd99 100644
--- a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/Param.java
+++ b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/Param.java
@@ -39,7 +39,7 @@
 public @interface Param {
     String key();
 
-    Class<? extends BaseProvider> provider() default SSMProvider.class;
+    Class<? extends BaseProvider> provider();
 
     Class<? extends Transformer> transformer() default Transformer.class;
 }
diff --git a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/ParamManager.java b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/ParamManager.java
index 6fee0f114..33f93779c 100644
--- a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/ParamManager.java
+++ b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/ParamManager.java
@@ -19,7 +19,6 @@
 import software.amazon.awssdk.services.appconfigdata.AppConfigDataClient;
 import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
 import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient;
-import software.amazon.awssdk.services.ssm.SsmClient;
 import software.amazon.lambda.powertools.parameters.cache.CacheManager;
 import software.amazon.lambda.powertools.parameters.transform.TransformationManager;
 
@@ -37,7 +36,6 @@ public final class ParamManager {
 
     /**
      * Get a concrete implementation of {@link BaseProvider}.<br/>
-     * You can specify {@link SecretsProvider}, {@link SSMProvider} or create your
      * custom provider by extending {@link BaseProvider} if you need to integrate with a different parameter store.
      *
      * @return a {@link SecretsProvider}
@@ -65,15 +63,6 @@ public static SecretsProvider getSecretsProvider() {
         return getProvider(SecretsProvider.class);
     }
 
-    /**
-     * Get a {@link SSMProvider} with default {@link SsmClient}.<br/>
-     * If you need to customize the region, or other part of the client, use {@link ParamManager#getSsmProvider(SsmClient)} instead.
-     *
-     * @return a {@link SSMProvider}
-     */
-    public static SSMProvider getSsmProvider() {
-        return getProvider(SSMProvider.class);
-    }
 
     /**
      * Get a {@link DynamoDbProvider} with default {@link DynamoDbClient} <br/>
@@ -111,7 +100,7 @@ public static AppConfigProvider getAppConfigProvider(String environment, String
 
     /**
      * Get a {@link SecretsProvider} with your custom {@link SecretsManagerClient}.<br/>
-     * Use this to configure region or other part of the client. Use {@link ParamManager#getSsmProvider()} if you don't need this customization.
+     * Use this to configure region or other part of the client. Use {@link ParamManager#getSecretsProvider()}  if you don't need this customization.
      *
      * @return a {@link SecretsProvider}
      */
@@ -123,20 +112,6 @@ public static SecretsProvider getSecretsProvider(SecretsManagerClient client) {
                 .build());
     }
 
-    /**
-     * Get a {@link SSMProvider} with your custom {@link SsmClient}.<br/>
-     * Use this to configure region or other part of the client. Use {@link ParamManager#getSsmProvider()} if you don't need this customization.
-     *
-     * @return a {@link SSMProvider}
-     */
-    public static SSMProvider getSsmProvider(SsmClient client) {
-        return (SSMProvider) providers.computeIfAbsent(SSMProvider.class, (k) -> SSMProvider.builder()
-                .withClient(client)
-                .withCacheManager(cacheManager)
-                .withTransformationManager(transformationManager)
-                .build());
-    }
-
     /**
      * Get a {@link DynamoDbProvider} with your custom {@link DynamoDbClient}.<br/>
      * Use this to configure region or other part of the client. Use {@link ParamManager#getDynamoDbProvider(String)} )} if you don't need this customization.

From a357255707dad469fd14d092ec2a88ad2a68e7bb Mon Sep 17 00:00:00 2001
From: Scott Gerring <gerrings@amazon.com>
Date: Tue, 29 Aug 2023 14:12:58 +0200
Subject: [PATCH 02/45] Move secrets out

---
 .../powertools-examples-parameters/pom.xml    |   6 +
 .../demo/parameters/ParametersFunction.java   |   6 +-
 pom.xml                                       |   1 +
 powertools-parameters/pom.xml                 |  14 ---
 .../powertools-parameters-secrets/pom.xml     | 117 ++++++++++++++++++
 .../parameters/secrets}/SecretsProvider.java  |  10 +-
 .../secrets}/SecretsProviderTest.java         |  32 ++---
 .../powertools-parameters-ssm/pom.xml         |  29 ++---
 .../powertools-parameters-tests/pom.xml       |   5 +
 .../LambdaParametersAspectTest.java           |  25 ++--
 .../ParamManagerIntegrationTest.java          |   6 +-
 .../parameters/ParamManagerTest.java          |  12 +-
 .../powertools/parameters/ParamManager.java   |  25 ----
 13 files changed, 190 insertions(+), 98 deletions(-)
 create mode 100644 powertools-parameters/powertools-parameters-secrets/pom.xml
 rename powertools-parameters/{src/main/java/software/amazon/lambda/powertools/parameters => powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets}/SecretsProvider.java (96%)
 rename powertools-parameters/{powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters => powertools-parameters-secrets/src/test/java/software/amazon/lambda/powertools/parameters/secrets}/SecretsProviderTest.java (77%)

diff --git a/examples/powertools-examples-parameters/pom.xml b/examples/powertools-examples-parameters/pom.xml
index 03b9e4dad..27ac69373 100644
--- a/examples/powertools-examples-parameters/pom.xml
+++ b/examples/powertools-examples-parameters/pom.xml
@@ -24,6 +24,12 @@
             <artifactId>powertools-parameters-ssm</artifactId>
             <version>${project.version}</version>
         </dependency>
+        <dependency>
+            <groupId>software.amazon.lambda</groupId>
+            <artifactId>powertools-parameters-secrets</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
         <dependency>
             <groupId>com.amazonaws</groupId>
             <artifactId>aws-lambda-java-core</artifactId>
diff --git a/examples/powertools-examples-parameters/src/main/java/org/demo/parameters/ParametersFunction.java b/examples/powertools-examples-parameters/src/main/java/org/demo/parameters/ParametersFunction.java
index 5dfec8031..6eb52a165 100644
--- a/examples/powertools-examples-parameters/src/main/java/org/demo/parameters/ParametersFunction.java
+++ b/examples/powertools-examples-parameters/src/main/java/org/demo/parameters/ParametersFunction.java
@@ -32,8 +32,8 @@
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 import software.amazon.lambda.powertools.parameters.ParamManager;
+import software.amazon.lambda.powertools.parameters.secrets.SecretsProvider;
 import software.amazon.lambda.powertools.parameters.ssm.SSMProvider;
-import software.amazon.lambda.powertools.parameters.SecretsProvider;
 
 public class ParametersFunction implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {
     private final static Logger log = LogManager.getLogger(ParametersFunction.class);
@@ -41,7 +41,9 @@ public class ParametersFunction implements RequestHandler<APIGatewayProxyRequest
     SSMProvider ssmProvider = SSMProvider
             .builder()
             .build();
-    SecretsProvider secretsProvider = ParamManager.getSecretsProvider();
+    SecretsProvider secretsProvider = SecretsProvider
+            .builder()
+            .build();
 
     String simpleValue = ssmProvider.defaultMaxAge(30, SECONDS).get("/powertools-java/sample/simplekey");
     String listValue = ssmProvider.withMaxAge(60, SECONDS).get("/powertools-java/sample/keylist");
diff --git a/pom.xml b/pom.xml
index e9465fd41..19f7c93fd 100644
--- a/pom.xml
+++ b/pom.xml
@@ -56,6 +56,7 @@
         <module>examples</module>
         <module>powertools-parameters/powertools-parameters-ssm</module>
         <module>powertools-parameters/powertools-parameters-tests</module>
+        <module>powertools-parameters/powertools-parameters-secrets</module>
     </modules>
 
     <scm>
diff --git a/powertools-parameters/pom.xml b/powertools-parameters/pom.xml
index 95ec9cd6b..7accdce6b 100644
--- a/powertools-parameters/pom.xml
+++ b/powertools-parameters/pom.xml
@@ -58,20 +58,6 @@
             <groupId>software.amazon.lambda</groupId>
             <artifactId>powertools-common</artifactId>
         </dependency>
-        <dependency>
-            <groupId>software.amazon.awssdk</groupId>
-            <artifactId>secretsmanager</artifactId>
-            <exclusions>
-                <exclusion>
-                    <groupId>software.amazon.awssdk</groupId>
-                    <artifactId>apache-client</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>software.amazon.awssdk</groupId>
-                    <artifactId>netty-nio-client</artifactId>
-                </exclusion>
-            </exclusions>
-        </dependency>
         <dependency>
             <groupId>software.amazon.awssdk</groupId>
             <artifactId>url-connection-client</artifactId>
diff --git a/powertools-parameters/powertools-parameters-secrets/pom.xml b/powertools-parameters/powertools-parameters-secrets/pom.xml
new file mode 100644
index 000000000..5b4dfad34
--- /dev/null
+++ b/powertools-parameters/powertools-parameters-secrets/pom.xml
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         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">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>software.amazon.lambda</groupId>
+        <artifactId>powertools-parent</artifactId>
+        <version>2.0.0-SNAPSHOT</version>
+        <relativePath>../../pom.xml</relativePath>
+    </parent>
+
+    <artifactId>powertools-parameters-secrets</artifactId>
+    <name>Powertools for AWS Lambda (Java) library Parameters - Secrets Manager</name>
+    <description>Secrets Manager implementation for the Parameters module</description>
+
+    <issueManagement>
+        <system>GitHub Issues</system>
+        <url>https://github.com/aws-powertools/powertools-lambda-java/issues</url>
+    </issueManagement>
+    <scm>
+        <url>https://github.com/aws-powertools/powertools-lambda-java.git</url>
+    </scm>
+    <developers>
+        <developer>
+            <name>Powertools for AWS Lambda team</name>
+            <organization>Amazon Web Services</organization>
+            <organizationUrl>https://aws.amazon.com/</organizationUrl>
+        </developer>
+    </developers>
+
+    <distributionManagement>
+        <snapshotRepository>
+            <id>ossrh</id>
+            <url>https://aws.oss.sonatype.org/content/repositories/snapshots</url>
+        </snapshotRepository>
+    </distributionManagement>
+
+    <dependencies>
+        <dependency>
+            <groupId>software.amazon.lambda</groupId>
+            <artifactId>powertools-parameters</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>software.amazon.awssdk</groupId>
+            <artifactId>secretsmanager</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>software.amazon.awssdk</groupId>
+                    <artifactId>apache-client</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>software.amazon.awssdk</groupId>
+                    <artifactId>netty-nio-client</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+        <!-- Test dependencies -->
+        <dependency>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter-api</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter-engine</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-core</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-inline</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.assertj</groupId>
+            <artifactId>assertj-core</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.aspectj</groupId>
+            <artifactId>aspectjweaver</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <version>3.1.2</version>
+                <configuration>
+                    <environmentVariables>
+                        <AWS_REGION>eu-central-1</AWS_REGION>
+                    </environmentVariables>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-checkstyle-plugin</artifactId>
+            </plugin>
+        </plugins>
+    </build>
+</project>
\ No newline at end of file
diff --git a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/SecretsProvider.java b/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProvider.java
similarity index 96%
rename from powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/SecretsProvider.java
rename to powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProvider.java
index b77f501f2..0cdb05a62 100644
--- a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/SecretsProvider.java
+++ b/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProvider.java
@@ -12,7 +12,7 @@
  *
  */
 
-package software.amazon.lambda.powertools.parameters;
+package software.amazon.lambda.powertools.parameters.secrets;
 
 import static java.nio.charset.StandardCharsets.UTF_8;
 
@@ -27,6 +27,7 @@
 import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient;
 import software.amazon.awssdk.services.secretsmanager.model.GetSecretValueRequest;
 import software.amazon.lambda.powertools.common.internal.UserAgentConfigurator;
+import software.amazon.lambda.powertools.parameters.BaseProvider;
 import software.amazon.lambda.powertools.parameters.cache.CacheManager;
 import software.amazon.lambda.powertools.parameters.transform.TransformationManager;
 import software.amazon.lambda.powertools.parameters.transform.Transformer;
@@ -151,7 +152,7 @@ SecretsManagerClient getClient() {
         return client;
     }
 
-    static class Builder {
+    public static class Builder {
 
         private SecretsManagerClient client;
         private CacheManager cacheManager;
@@ -163,7 +164,7 @@ private static SecretsManagerClient createClient() {
                     .region(Region.of(System.getenv(SdkSystemSetting.AWS_REGION.environmentVariable())))
                     .overrideConfiguration(ClientOverrideConfiguration.builder()
                             .putAdvancedOption(SdkAdvancedClientOption.USER_AGENT_SUFFIX,
-                                    UserAgentConfigurator.getUserAgent(PARAMETERS)).build())
+                                    UserAgentConfigurator.getUserAgent(BaseProvider.PARAMETERS)).build())
                     .build();
         }
 
@@ -174,7 +175,8 @@ private static SecretsManagerClient createClient() {
          */
         public SecretsProvider build() {
             if (cacheManager == null) {
-                throw new IllegalStateException("No CacheManager provided, please provide one");
+                // TODO - what should we do with this
+                cacheManager = new CacheManager();
             }
             SecretsProvider provider;
             if (client == null) {
diff --git a/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/SecretsProviderTest.java b/powertools-parameters/powertools-parameters-secrets/src/test/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProviderTest.java
similarity index 77%
rename from powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/SecretsProviderTest.java
rename to powertools-parameters/powertools-parameters-secrets/src/test/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProviderTest.java
index f4f2d9bee..1b4cc4306 100644
--- a/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/SecretsProviderTest.java
+++ b/powertools-parameters/powertools-parameters-secrets/src/test/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProviderTest.java
@@ -12,21 +12,24 @@
  *
  */
 
-package software.amazon.lambda.powertools.parameters;
+package software.amazon.lambda.powertools.parameters.secrets;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
 import static org.assertj.core.api.Assertions.assertThatRuntimeException;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.mockito.MockitoAnnotations.openMocks;
 
 import java.time.temporal.ChronoUnit;
 import java.util.Base64;
+import org.assertj.core.api.Assertions;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Captor;
 import org.mockito.Mock;
 import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
 import software.amazon.awssdk.core.SdkBytes;
 import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient;
 import software.amazon.awssdk.services.secretsmanager.model.GetSecretValueRequest;
@@ -51,7 +54,7 @@ public class SecretsProviderTest {
 
     @BeforeEach
     public void init() {
-        openMocks(this);
+        MockitoAnnotations.openMocks(this);
         cacheManager = new CacheManager();
         provider = new SecretsProvider(cacheManager, client);
     }
@@ -67,8 +70,8 @@ public void getValue() {
 
         String value = provider.getValue(key);
 
-        assertThat(value).isEqualTo(expectedValue);
-        assertThat(paramCaptor.getValue().secretId()).isEqualTo(key);
+        Assertions.assertThat(value).isEqualTo(expectedValue);
+        Assertions.assertThat(paramCaptor.getValue().secretId()).isEqualTo(key);
     }
 
     @Test
@@ -82,27 +85,28 @@ public void getValueBase64() {
 
         String value = provider.getValue(key);
 
-        assertThat(value).isEqualTo(expectedValue);
-        assertThat(paramCaptor.getValue().secretId()).isEqualTo(key);
+        Assertions.assertThat(value).isEqualTo(expectedValue);
+        Assertions.assertThat(paramCaptor.getValue().secretId()).isEqualTo(key);
     }
 
     @Test
     public void getMultipleValuesThrowsException() {
 
         // Act & Assert
-        assertThatRuntimeException().isThrownBy(() -> provider.getMultipleValues("path"))
+        Assertions.assertThatRuntimeException().isThrownBy(() -> provider.getMultipleValues("path"))
                 .withMessage("Impossible to get multiple values from AWS Secrets Manager");
 
     }
 
     @Test
-    public void testSecretsProviderBuilderMissingCacheManager_throwsException() {
+    public void testGetSecretsProvider_withoutParameter_shouldCreateDefaultClient() {
 
-        // Act & Assert
-        assertThatIllegalStateException().isThrownBy(() -> SecretsProvider.builder()
-                        .withClient(client)
-                        .withTransformationManager(transformationManager)
-                        .build())
-                .withMessage("No CacheManager provided, please provide one");
+        // Act
+        SecretsProvider secretsProvider = SecretsProvider.builder()
+                .build();
+
+        // Assert
+        assertNotNull(secretsProvider);
+        assertNotNull(secretsProvider.getClient());
     }
 }
diff --git a/powertools-parameters/powertools-parameters-ssm/pom.xml b/powertools-parameters/powertools-parameters-ssm/pom.xml
index fae952999..47acd5906 100644
--- a/powertools-parameters/powertools-parameters-ssm/pom.xml
+++ b/powertools-parameters/powertools-parameters-ssm/pom.xml
@@ -44,6 +44,21 @@
             <version>${project.version}</version>
         </dependency>
 
+        <dependency>
+            <groupId>software.amazon.awssdk</groupId>
+            <artifactId>ssm</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>software.amazon.awssdk</groupId>
+                    <artifactId>apache-client</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>software.amazon.awssdk</groupId>
+                    <artifactId>netty-nio-client</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
         <!-- Test dependencies -->
         <dependency>
             <groupId>org.junit.jupiter</groupId>
@@ -80,20 +95,6 @@
             <artifactId>aspectjweaver</artifactId>
             <scope>test</scope>
         </dependency>
-        <dependency>
-            <groupId>software.amazon.awssdk</groupId>
-            <artifactId>ssm</artifactId>
-            <exclusions>
-                <exclusion>
-                    <groupId>software.amazon.awssdk</groupId>
-                    <artifactId>apache-client</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>software.amazon.awssdk</groupId>
-                    <artifactId>netty-nio-client</artifactId>
-                </exclusion>
-            </exclusions>
-        </dependency>
     </dependencies>
 
     <build>
diff --git a/powertools-parameters/powertools-parameters-tests/pom.xml b/powertools-parameters/powertools-parameters-tests/pom.xml
index cff5a6324..b527b9e46 100644
--- a/powertools-parameters/powertools-parameters-tests/pom.xml
+++ b/powertools-parameters/powertools-parameters-tests/pom.xml
@@ -23,6 +23,11 @@
             <artifactId>powertools-parameters-ssm</artifactId>
             <version>${project.version}</version>
         </dependency>
+        <dependency>
+            <groupId>software.amazon.lambda</groupId>
+            <artifactId>powertools-parameters-secrets</artifactId>
+            <version>${project.version}</version>
+        </dependency>
 
         <!-- Test dependencies -->
         <dependency>
diff --git a/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/LambdaParametersAspectTest.java b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/LambdaParametersAspectTest.java
index 0e978d274..c99608d57 100644
--- a/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/LambdaParametersAspectTest.java
+++ b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/LambdaParametersAspectTest.java
@@ -63,18 +63,19 @@ public void init() {
     }
 
     @Test
-    public void testDefault_ShouldUseSSMProvider() {
-        try (MockedStatic<ParamManager> mocked = Mockito.mockStatic(ParamManager.class)) {
-            mocked.when(() -> ParamManager.getProvider(SSMProvider.class)).thenReturn(defaultProvider);
-            Mockito.when(defaultProvider.get("/default")).thenReturn("value");
-
-            Assertions.assertThat(defaultValue).isEqualTo("value");
-            mocked.verify(() -> ParamManager.getProvider(SSMProvider.class), Mockito.times(1));
-            Mockito.verify(defaultProvider, Mockito.times(1)).get("/default");
-
-            mocked.reset();
-        }
-    }
+    // TODO - no more defaults!
+//    public void testDefault_ShouldUseSSMProvider() {
+//        try (MockedStatic<ParamManager> mocked = Mockito.mockStatic(ParamManager.class)) {
+//            mocked.when(() -> ParamManager.getProvider(SSMProvider.class)).thenReturn(defaultProvider);
+//            Mockito.when(defaultProvider.get("/default")).thenReturn("value");
+//
+//            Assertions.assertThat(defaultValue).isEqualTo("value");
+//            mocked.verify(() -> ParamManager.getProvider(SSMProvider.class), Mockito.times(1));
+//            Mockito.verify(defaultProvider, Mockito.times(1)).get("/default");
+//
+//            mocked.reset();
+//        }
+//    }
 
     @Test
     public void testSimple() {
diff --git a/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerIntegrationTest.java b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerIntegrationTest.java
index 67ea03618..807aae1ef 100644
--- a/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerIntegrationTest.java
+++ b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerIntegrationTest.java
@@ -43,7 +43,7 @@
 import software.amazon.awssdk.services.ssm.model.GetParametersByPathRequest;
 import software.amazon.awssdk.services.ssm.model.GetParametersByPathResponse;
 import software.amazon.awssdk.services.ssm.model.Parameter;
-import software.amazon.lambda.powertools.parameters.cache.CacheManager;
+import software.amazon.lambda.powertools.parameters.secrets.SecretsProvider;
 import software.amazon.lambda.powertools.parameters.ssm.SSMProvider;
 
 public class ParamManagerIntegrationTest {
@@ -118,7 +118,9 @@ public void ssmProvider_getMultiple() {
 
     @Test
     public void secretsProvider_get() {
-        SecretsProvider secretsProvider = ParamManager.getSecretsProvider(secretsManagerClient);
+        SecretsProvider secretsProvider = SecretsProvider.builder()
+                .withClient(secretsManagerClient)
+                .build();
 
         String expectedValue = "Value1";
         GetSecretValueResponse response = GetSecretValueResponse.builder().secretString(expectedValue).build();
diff --git a/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerTest.java b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerTest.java
index dbfcb1007..e4c7daabb 100644
--- a/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerTest.java
+++ b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerTest.java
@@ -22,6 +22,7 @@
 import org.junit.jupiter.api.Test;
 import software.amazon.lambda.powertools.parameters.cache.CacheManager;
 import software.amazon.lambda.powertools.parameters.internal.CustomProvider;
+import software.amazon.lambda.powertools.parameters.secrets.SecretsProvider;
 import software.amazon.lambda.powertools.parameters.transform.TransformationManager;
 
 public class ParamManagerTest {
@@ -80,17 +81,6 @@ public void testGetProviderWithProviderClass_throwsException() {
         assertThatIllegalStateException().isThrownBy(() -> ParamManager.getProvider(null));
     }
 
-    @Test
-    public void testGetSecretsProvider_withoutParameter_shouldCreateDefaultClient() {
-
-        // Act
-        SecretsProvider secretsProvider = ParamManager.getSecretsProvider();
-
-        // Assert
-        assertNotNull(secretsProvider);
-        assertNotNull(secretsProvider.getClient());
-    }
-
 
     @Test
     public void testGetDynamoDBProvider_requireOtherParameters_throwException() {
diff --git a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/ParamManager.java b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/ParamManager.java
index 33f93779c..d3aaefaa5 100644
--- a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/ParamManager.java
+++ b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/ParamManager.java
@@ -53,17 +53,6 @@ public static <T extends BaseProvider> T getProvider(Class<T> providerClass) {
         return (T) providers.computeIfAbsent(providerClass, ParamManager::createProvider);
     }
 
-    /**
-     * Get a {@link SecretsProvider} with default {@link SecretsManagerClient}.<br/>
-     * If you need to customize the region, or other part of the client, use {@link ParamManager#getSecretsProvider(SecretsManagerClient)} instead.
-     *
-     * @return a {@link SecretsProvider}
-     */
-    public static SecretsProvider getSecretsProvider() {
-        return getProvider(SecretsProvider.class);
-    }
-
-
     /**
      * Get a {@link DynamoDbProvider} with default {@link DynamoDbClient} <br/>
      * If you need to customize the region, or other part of the client, use {@link ParamManager#getDynamoDbProvider(DynamoDbClient, String)}
@@ -98,20 +87,6 @@ public static AppConfigProvider getAppConfigProvider(String environment, String
     }
 
 
-    /**
-     * Get a {@link SecretsProvider} with your custom {@link SecretsManagerClient}.<br/>
-     * Use this to configure region or other part of the client. Use {@link ParamManager#getSecretsProvider()}  if you don't need this customization.
-     *
-     * @return a {@link SecretsProvider}
-     */
-    public static SecretsProvider getSecretsProvider(SecretsManagerClient client) {
-        return (SecretsProvider) providers.computeIfAbsent(SecretsProvider.class, (k) -> SecretsProvider.builder()
-                .withClient(client)
-                .withCacheManager(cacheManager)
-                .withTransformationManager(transformationManager)
-                .build());
-    }
-
     /**
      * Get a {@link DynamoDbProvider} with your custom {@link DynamoDbClient}.<br/>
      * Use this to configure region or other part of the client. Use {@link ParamManager#getDynamoDbProvider(String)} )} if you don't need this customization.

From 7dd85d234ab519c7e232252d92a7e804449eb40d Mon Sep 17 00:00:00 2001
From: Scott Gerring <gerrings@amazon.com>
Date: Tue, 29 Aug 2023 14:32:51 +0200
Subject: [PATCH 03/45] Move DDB out

---
 pom.xml                                       |   3 +-
 powertools-parameters/pom.xml                 |   4 -
 .../powertools-parameters-dynamodb/pom.xml    | 117 ++++++++++++++++++
 .../dynamodb}/DynamoDbProvider.java           |   4 +-
 .../dynamodb}/DynamoDbProviderE2ETest.java    |   2 +-
 .../dynamodb}/DynamoDbProviderTest.java       |   2 +-
 .../powertools-parameters-tests/pom.xml       |   5 +
 .../LambdaParametersAspectTest.java           |   2 +-
 .../ParamManagerIntegrationTest.java          |  10 --
 .../parameters/ParamManagerTest.java          |   1 +
 .../powertools/parameters/ParamManager.java   |  35 +-----
 11 files changed, 132 insertions(+), 53 deletions(-)
 create mode 100644 powertools-parameters/powertools-parameters-dynamodb/pom.xml
 rename powertools-parameters/{src/main/java/software/amazon/lambda/powertools/parameters => powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb}/DynamoDbProvider.java (97%)
 rename powertools-parameters/{powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters => powertools-parameters-dynamodb/src/test/java/software/amazon/lambda/powertools/parameters/dynamodb}/DynamoDbProviderE2ETest.java (98%)
 rename powertools-parameters/{powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters => powertools-parameters-dynamodb/src/test/java/software/amazon/lambda/powertools/parameters/dynamodb}/DynamoDbProviderTest.java (99%)

diff --git a/pom.xml b/pom.xml
index 19f7c93fd..f6ecf8814 100644
--- a/pom.xml
+++ b/pom.xml
@@ -55,8 +55,9 @@
         <module>powertools-batch</module>
         <module>examples</module>
         <module>powertools-parameters/powertools-parameters-ssm</module>
-        <module>powertools-parameters/powertools-parameters-tests</module>
         <module>powertools-parameters/powertools-parameters-secrets</module>
+        <module>powertools-parameters/powertools-parameters-dynamodb</module>
+        <module>powertools-parameters/powertools-parameters-tests</module>
     </modules>
 
     <scm>
diff --git a/powertools-parameters/pom.xml b/powertools-parameters/pom.xml
index 7accdce6b..684083798 100644
--- a/powertools-parameters/pom.xml
+++ b/powertools-parameters/pom.xml
@@ -62,10 +62,6 @@
             <groupId>software.amazon.awssdk</groupId>
             <artifactId>url-connection-client</artifactId>
         </dependency>
-        <dependency>
-            <groupId>software.amazon.awssdk</groupId>
-            <artifactId>dynamodb</artifactId>
-        </dependency>
         <dependency>
             <groupId>software.amazon.awssdk</groupId>
             <artifactId>appconfigdata</artifactId>
diff --git a/powertools-parameters/powertools-parameters-dynamodb/pom.xml b/powertools-parameters/powertools-parameters-dynamodb/pom.xml
new file mode 100644
index 000000000..71126f6b5
--- /dev/null
+++ b/powertools-parameters/powertools-parameters-dynamodb/pom.xml
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         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">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>software.amazon.lambda</groupId>
+        <artifactId>powertools-parent</artifactId>
+        <version>2.0.0-SNAPSHOT</version>
+        <relativePath>../../pom.xml</relativePath>
+    </parent>
+
+    <artifactId>powertools-parameters-dynamodb</artifactId>
+    <name>Powertools for AWS Lambda (Java) library Parameters - DynamoDB</name>
+    <description>DynamoDB implementation for the Parameters module</description>
+
+    <issueManagement>
+        <system>GitHub Issues</system>
+        <url>https://github.com/aws-powertools/powertools-lambda-java/issues</url>
+    </issueManagement>
+    <scm>
+        <url>https://github.com/aws-powertools/powertools-lambda-java.git</url>
+    </scm>
+    <developers>
+        <developer>
+            <name>Powertools for AWS Lambda team</name>
+            <organization>Amazon Web Services</organization>
+            <organizationUrl>https://aws.amazon.com/</organizationUrl>
+        </developer>
+    </developers>
+
+    <distributionManagement>
+        <snapshotRepository>
+            <id>ossrh</id>
+            <url>https://aws.oss.sonatype.org/content/repositories/snapshots</url>
+        </snapshotRepository>
+    </distributionManagement>
+
+    <dependencies>
+        <dependency>
+            <groupId>software.amazon.lambda</groupId>
+            <artifactId>powertools-parameters</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>software.amazon.awssdk</groupId>
+            <artifactId>dynamodb</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>software.amazon.awssdk</groupId>
+                    <artifactId>apache-client</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>software.amazon.awssdk</groupId>
+                    <artifactId>netty-nio-client</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+        <!-- Test dependencies -->
+        <dependency>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter-api</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter-engine</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-core</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-inline</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.assertj</groupId>
+            <artifactId>assertj-core</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.aspectj</groupId>
+            <artifactId>aspectjweaver</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <version>3.1.2</version>
+                <configuration>
+                    <environmentVariables>
+                        <AWS_REGION>eu-central-1</AWS_REGION>
+                    </environmentVariables>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-checkstyle-plugin</artifactId>
+            </plugin>
+        </plugins>
+    </build>
+</project>
\ No newline at end of file
diff --git a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/DynamoDbProvider.java b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProvider.java
similarity index 97%
rename from powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/DynamoDbProvider.java
rename to powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProvider.java
index 363f39d7c..27daf780e 100644
--- a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/DynamoDbProvider.java
+++ b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProvider.java
@@ -12,7 +12,7 @@
  *
  */
 
-package software.amazon.lambda.powertools.parameters;
+package software.amazon.lambda.powertools.parameters.dynamodb;
 
 import java.util.Collections;
 import java.util.Map;
@@ -29,6 +29,8 @@
 import software.amazon.awssdk.services.dynamodb.model.QueryRequest;
 import software.amazon.awssdk.services.dynamodb.model.QueryResponse;
 import software.amazon.lambda.powertools.common.internal.UserAgentConfigurator;
+import software.amazon.lambda.powertools.parameters.BaseProvider;
+import software.amazon.lambda.powertools.parameters.ParamProvider;
 import software.amazon.lambda.powertools.parameters.cache.CacheManager;
 import software.amazon.lambda.powertools.parameters.exception.DynamoDbProviderSchemaException;
 import software.amazon.lambda.powertools.parameters.transform.TransformationManager;
diff --git a/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/DynamoDbProviderE2ETest.java b/powertools-parameters/powertools-parameters-dynamodb/src/test/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderE2ETest.java
similarity index 98%
rename from powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/DynamoDbProviderE2ETest.java
rename to powertools-parameters/powertools-parameters-dynamodb/src/test/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderE2ETest.java
index 18212b45c..c7530e1b7 100644
--- a/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/DynamoDbProviderE2ETest.java
+++ b/powertools-parameters/powertools-parameters-dynamodb/src/test/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderE2ETest.java
@@ -12,7 +12,7 @@
  *
  */
 
-package software.amazon.lambda.powertools.parameters;
+package software.amazon.lambda.powertools.parameters.dynamodb;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
diff --git a/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/DynamoDbProviderTest.java b/powertools-parameters/powertools-parameters-dynamodb/src/test/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderTest.java
similarity index 99%
rename from powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/DynamoDbProviderTest.java
rename to powertools-parameters/powertools-parameters-dynamodb/src/test/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderTest.java
index 2cf84dad4..7e5b5f631 100644
--- a/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/DynamoDbProviderTest.java
+++ b/powertools-parameters/powertools-parameters-dynamodb/src/test/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderTest.java
@@ -12,7 +12,7 @@
  *
  */
 
-package software.amazon.lambda.powertools.parameters;
+package software.amazon.lambda.powertools.parameters.dynamodb;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
diff --git a/powertools-parameters/powertools-parameters-tests/pom.xml b/powertools-parameters/powertools-parameters-tests/pom.xml
index b527b9e46..b0bbfdf74 100644
--- a/powertools-parameters/powertools-parameters-tests/pom.xml
+++ b/powertools-parameters/powertools-parameters-tests/pom.xml
@@ -28,6 +28,11 @@
             <artifactId>powertools-parameters-secrets</artifactId>
             <version>${project.version}</version>
         </dependency>
+        <dependency>
+            <groupId>software.amazon.lambda</groupId>
+            <artifactId>powertools-parameters-dynamodb</artifactId>
+            <version>${project.version}</version>
+        </dependency>
 
         <!-- Test dependencies -->
         <dependency>
diff --git a/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/LambdaParametersAspectTest.java b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/LambdaParametersAspectTest.java
index c99608d57..db4c17b50 100644
--- a/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/LambdaParametersAspectTest.java
+++ b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/LambdaParametersAspectTest.java
@@ -62,7 +62,7 @@ public void init() {
         MockitoAnnotations.openMocks(this);
     }
 
-    @Test
+    // @Test
     // TODO - no more defaults!
 //    public void testDefault_ShouldUseSSMProvider() {
 //        try (MockedStatic<ParamManager> mocked = Mockito.mockStatic(ParamManager.class)) {
diff --git a/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerIntegrationTest.java b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerIntegrationTest.java
index 807aae1ef..ff125666e 100644
--- a/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerIntegrationTest.java
+++ b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerIntegrationTest.java
@@ -133,16 +133,6 @@ public void secretsProvider_get() {
         verify(secretsManagerClient, times(1)).getSecretValue(any(GetSecretValueRequest.class));
     }
 
-    @Test
-    public void getDynamoDbProvider() {
-
-        // Act
-        DynamoDbProvider provider = ParamManager.getDynamoDbProvider(ddbClient, "test-table");
-
-        // Assert
-        assertThat(provider).isNotNull();
-    }
-
     @Test
     public void getAppConfigProvider() {
 
diff --git a/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerTest.java b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerTest.java
index e4c7daabb..ad512e563 100644
--- a/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerTest.java
+++ b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerTest.java
@@ -21,6 +21,7 @@
 
 import org.junit.jupiter.api.Test;
 import software.amazon.lambda.powertools.parameters.cache.CacheManager;
+import software.amazon.lambda.powertools.parameters.dynamodb.DynamoDbProvider;
 import software.amazon.lambda.powertools.parameters.internal.CustomProvider;
 import software.amazon.lambda.powertools.parameters.secrets.SecretsProvider;
 import software.amazon.lambda.powertools.parameters.transform.TransformationManager;
diff --git a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/ParamManager.java b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/ParamManager.java
index d3aaefaa5..6c0a5e72e 100644
--- a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/ParamManager.java
+++ b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/ParamManager.java
@@ -17,8 +17,6 @@
 import java.lang.reflect.Constructor;
 import java.util.concurrent.ConcurrentHashMap;
 import software.amazon.awssdk.services.appconfigdata.AppConfigDataClient;
-import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
-import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient;
 import software.amazon.lambda.powertools.parameters.cache.CacheManager;
 import software.amazon.lambda.powertools.parameters.transform.TransformationManager;
 
@@ -46,28 +44,13 @@ public static <T extends BaseProvider> T getProvider(Class<T> providerClass) {
         if (providerClass == null) {
             throw new IllegalStateException("providerClass cannot be null.");
         }
-        if (providerClass == DynamoDbProvider.class || providerClass == AppConfigProvider.class) {
+        if (providerClass == AppConfigProvider.class) {
             throw new IllegalArgumentException(
                     providerClass + " cannot be instantiated like this, additional parameters are required");
         }
         return (T) providers.computeIfAbsent(providerClass, ParamManager::createProvider);
     }
 
-    /**
-     * Get a {@link DynamoDbProvider} with default {@link DynamoDbClient} <br/>
-     * If you need to customize the region, or other part of the client, use {@link ParamManager#getDynamoDbProvider(DynamoDbClient, String)}
-     */
-    public static DynamoDbProvider getDynamoDbProvider(String tableName) {
-        // Because we need a DDB table name to configure our client, we can't use
-        // ParamManager#getProvider. This means that we need to make sure we do the same stuff -
-        // set transformation manager and cache manager.
-        return DynamoDbProvider.builder()
-                .withCacheManager(cacheManager)
-                .withTable(tableName)
-                .withTransformationManager(transformationManager)
-                .build();
-    }
-
     /**
      * Get a {@link AppConfigProvider} with default {@link AppConfigDataClient}.<br/>
      * If you need to customize the region, or other part of the client, use {@link ParamManager#getAppConfigProvider(AppConfigDataClient, String, String)} instead.
@@ -86,22 +69,6 @@ public static AppConfigProvider getAppConfigProvider(String environment, String
                 .build();
     }
 
-
-    /**
-     * Get a {@link DynamoDbProvider} with your custom {@link DynamoDbClient}.<br/>
-     * Use this to configure region or other part of the client. Use {@link ParamManager#getDynamoDbProvider(String)} )} if you don't need this customization.
-     *
-     * @return a {@link DynamoDbProvider}
-     */
-    public static DynamoDbProvider getDynamoDbProvider(DynamoDbClient client, String table) {
-        return (DynamoDbProvider) providers.computeIfAbsent(DynamoDbProvider.class, (k) -> DynamoDbProvider.builder()
-                .withClient(client)
-                .withTable(table)
-                .withCacheManager(cacheManager)
-                .withTransformationManager(transformationManager)
-                .build());
-    }
-
     /**
      * Get a {@link AppConfigProvider} with your custom {@link AppConfigDataClient}.<br/>
      * Use this to configure region or other part of the client. Use {@link ParamManager#getAppConfigProvider(String, String)} if you don't need this customization.

From 058fb139ecab7d315eb4c10fbb69a9736938ed00 Mon Sep 17 00:00:00 2001
From: Scott Gerring <gerrings@amazon.com>
Date: Tue, 29 Aug 2023 14:47:35 +0200
Subject: [PATCH 04/45] Moved AppConfig out

---
 pom.xml                                       |   1 +
 powertools-parameters/pom.xml                 |   4 -
 .../powertools-parameters-appconfig/pom.xml   | 117 ++++++++++++++++++
 .../appconfig}/AppConfigProvider.java         |   5 +-
 .../appconfig}/AppConfigProviderTest.java     |  51 ++++----
 .../ParamManagerIntegrationTest.java          |  10 --
 .../parameters/ParamManagerTest.java          |   6 -
 .../powertools/parameters/ParamManager.java   |  40 ------
 8 files changed, 145 insertions(+), 89 deletions(-)
 create mode 100644 powertools-parameters/powertools-parameters-appconfig/pom.xml
 rename powertools-parameters/{src/main/java/software/amazon/lambda/powertools/parameters => powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig}/AppConfigProvider.java (98%)
 rename powertools-parameters/{powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters => powertools-parameters-appconfig/src/test/java/software/amazon/lambda/powertools/parameters/appconfig}/AppConfigProviderTest.java (78%)

diff --git a/pom.xml b/pom.xml
index f6ecf8814..47cc228db 100644
--- a/pom.xml
+++ b/pom.xml
@@ -58,6 +58,7 @@
         <module>powertools-parameters/powertools-parameters-secrets</module>
         <module>powertools-parameters/powertools-parameters-dynamodb</module>
         <module>powertools-parameters/powertools-parameters-tests</module>
+        <module>powertools-parameters/powertools-parameters-appconfig</module>
     </modules>
 
     <scm>
diff --git a/powertools-parameters/pom.xml b/powertools-parameters/pom.xml
index 684083798..433226f81 100644
--- a/powertools-parameters/pom.xml
+++ b/powertools-parameters/pom.xml
@@ -62,10 +62,6 @@
             <groupId>software.amazon.awssdk</groupId>
             <artifactId>url-connection-client</artifactId>
         </dependency>
-        <dependency>
-            <groupId>software.amazon.awssdk</groupId>
-            <artifactId>appconfigdata</artifactId>
-        </dependency>
 
         <dependency>
             <groupId>com.fasterxml.jackson.core</groupId>
diff --git a/powertools-parameters/powertools-parameters-appconfig/pom.xml b/powertools-parameters/powertools-parameters-appconfig/pom.xml
new file mode 100644
index 000000000..46c0dcd01
--- /dev/null
+++ b/powertools-parameters/powertools-parameters-appconfig/pom.xml
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         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">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>software.amazon.lambda</groupId>
+        <artifactId>powertools-parent</artifactId>
+        <version>2.0.0-SNAPSHOT</version>
+        <relativePath>../../pom.xml</relativePath>
+    </parent>
+
+    <artifactId>powertools-parameters-appconfig</artifactId>
+    <name>Powertools for AWS Lambda (Java) library Parameters - AppConfig</name>
+    <description>AppConfig implementation for the Parameters module</description>
+
+    <issueManagement>
+        <system>GitHub Issues</system>
+        <url>https://github.com/aws-powertools/powertools-lambda-java/issues</url>
+    </issueManagement>
+    <scm>
+        <url>https://github.com/aws-powertools/powertools-lambda-java.git</url>
+    </scm>
+    <developers>
+        <developer>
+            <name>Powertools for AWS Lambda team</name>
+            <organization>Amazon Web Services</organization>
+            <organizationUrl>https://aws.amazon.com/</organizationUrl>
+        </developer>
+    </developers>
+
+    <distributionManagement>
+        <snapshotRepository>
+            <id>ossrh</id>
+            <url>https://aws.oss.sonatype.org/content/repositories/snapshots</url>
+        </snapshotRepository>
+    </distributionManagement>
+
+    <dependencies>
+        <dependency>
+            <groupId>software.amazon.lambda</groupId>
+            <artifactId>powertools-parameters</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>software.amazon.awssdk</groupId>
+            <artifactId>appconfigdata</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>software.amazon.awssdk</groupId>
+                    <artifactId>apache-client</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>software.amazon.awssdk</groupId>
+                    <artifactId>netty-nio-client</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+        <!-- Test dependencies -->
+        <dependency>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter-api</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter-engine</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-core</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-inline</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.assertj</groupId>
+            <artifactId>assertj-core</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.aspectj</groupId>
+            <artifactId>aspectjweaver</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <version>3.1.2</version>
+                <configuration>
+                    <environmentVariables>
+                        <AWS_REGION>eu-central-1</AWS_REGION>
+                    </environmentVariables>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-checkstyle-plugin</artifactId>
+            </plugin>
+        </plugins>
+    </build>
+</project>
\ No newline at end of file
diff --git a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/AppConfigProvider.java b/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProvider.java
similarity index 98%
rename from powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/AppConfigProvider.java
rename to powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProvider.java
index 5a1e575dd..cf35f27a9 100644
--- a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/AppConfigProvider.java
+++ b/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProvider.java
@@ -12,7 +12,7 @@
  *
  */
 
-package software.amazon.lambda.powertools.parameters;
+package software.amazon.lambda.powertools.parameters.appconfig;
 
 import java.util.HashMap;
 import java.util.Map;
@@ -26,6 +26,7 @@
 import software.amazon.awssdk.services.appconfigdata.model.GetLatestConfigurationResponse;
 import software.amazon.awssdk.services.appconfigdata.model.StartConfigurationSessionRequest;
 import software.amazon.lambda.powertools.common.internal.UserAgentConfigurator;
+import software.amazon.lambda.powertools.parameters.BaseProvider;
 import software.amazon.lambda.powertools.parameters.cache.CacheManager;
 import software.amazon.lambda.powertools.parameters.transform.TransformationManager;
 
@@ -158,7 +159,7 @@ public AppConfigProvider build() {
                         .region(Region.of(System.getenv(SdkSystemSetting.AWS_REGION.environmentVariable())))
                         .overrideConfiguration(ClientOverrideConfiguration.builder()
                                 .putAdvancedOption(SdkAdvancedClientOption.USER_AGENT_SUFFIX,
-                                        UserAgentConfigurator.getUserAgent(PARAMETERS)).build())
+                                        UserAgentConfigurator.getUserAgent(BaseProvider.PARAMETERS)).build())
                         .build();
             }
 
diff --git a/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/AppConfigProviderTest.java b/powertools-parameters/powertools-parameters-appconfig/src/test/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProviderTest.java
similarity index 78%
rename from powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/AppConfigProviderTest.java
rename to powertools-parameters/powertools-parameters-appconfig/src/test/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProviderTest.java
index f467dca72..780e3cb37 100644
--- a/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/AppConfigProviderTest.java
+++ b/powertools-parameters/powertools-parameters-appconfig/src/test/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProviderTest.java
@@ -12,19 +12,16 @@
  *
  */
 
-package software.amazon.lambda.powertools.parameters;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
-import static org.assertj.core.api.Assertions.assertThatRuntimeException;
-import static org.mockito.MockitoAnnotations.openMocks;
+package software.amazon.lambda.powertools.parameters.appconfig;
 
+import org.assertj.core.api.Assertions;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Captor;
 import org.mockito.Mock;
 import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
 import software.amazon.awssdk.core.SdkBytes;
 import software.amazon.awssdk.services.appconfigdata.AppConfigDataClient;
 import software.amazon.awssdk.services.appconfigdata.model.GetLatestConfigurationRequest;
@@ -52,7 +49,7 @@ public class AppConfigProviderTest {
 
     @BeforeEach
     public void init() {
-        openMocks(this);
+        MockitoAnnotations.openMocks(this);
 
         provider = AppConfigProvider.builder()
                 .withClient(client)
@@ -101,18 +98,18 @@ public void getValueRetrievesValue() {
         String returnedValue3 = provider.getValue(defaultTestKey);
 
         // Assert
-        assertThat(returnedValue1).isEqualTo(firstResponse.configuration().asUtf8String());
-        assertThat(returnedValue2).isEqualTo(secondResponse.configuration().asUtf8String());
-        assertThat(returnedValue3).isEqualTo(secondResponse.configuration()
+        Assertions.assertThat(returnedValue1).isEqualTo(firstResponse.configuration().asUtf8String());
+        Assertions.assertThat(returnedValue2).isEqualTo(secondResponse.configuration().asUtf8String());
+        Assertions.assertThat(returnedValue3).isEqualTo(secondResponse.configuration()
                 .asUtf8String()); // Third response is mocked to return null and should re-use previous value
-        assertThat(startSessionRequestCaptor.getValue().applicationIdentifier()).isEqualTo(applicationName);
-        assertThat(startSessionRequestCaptor.getValue().environmentIdentifier()).isEqualTo(environmentName);
-        assertThat(startSessionRequestCaptor.getValue().configurationProfileIdentifier()).isEqualTo(defaultTestKey);
-        assertThat(getLatestConfigurationRequestCaptor.getAllValues().get(0).configurationToken()).isEqualTo(
+        Assertions.assertThat(startSessionRequestCaptor.getValue().applicationIdentifier()).isEqualTo(applicationName);
+        Assertions.assertThat(startSessionRequestCaptor.getValue().environmentIdentifier()).isEqualTo(environmentName);
+        Assertions.assertThat(startSessionRequestCaptor.getValue().configurationProfileIdentifier()).isEqualTo(defaultTestKey);
+        Assertions.assertThat(getLatestConfigurationRequestCaptor.getAllValues().get(0).configurationToken()).isEqualTo(
                 firstSession.initialConfigurationToken());
-        assertThat(getLatestConfigurationRequestCaptor.getAllValues().get(1).configurationToken()).isEqualTo(
+        Assertions.assertThat(getLatestConfigurationRequestCaptor.getAllValues().get(1).configurationToken()).isEqualTo(
                 firstResponse.nextPollConfigurationToken());
-        assertThat(getLatestConfigurationRequestCaptor.getAllValues().get(2).configurationToken()).isEqualTo(
+        Assertions.assertThat(getLatestConfigurationRequestCaptor.getAllValues().get(2).configurationToken()).isEqualTo(
                 secondResponse.nextPollConfigurationToken());
     }
 
@@ -136,7 +133,7 @@ public void getValueNoValueExists() {
 
 
         // Assert
-        assertThat(returnedValue).isEqualTo(null);
+        Assertions.assertThat(returnedValue).isEqualTo(null);
     }
 
     /**
@@ -172,15 +169,15 @@ public void multipleKeysRetrievalWorks() {
         String secondKeyValue = provider.getValue(param2Key);
 
         // Assert
-        assertThat(firstKeyValue).isEqualTo(param1Response.configuration().asUtf8String());
-        assertThat(secondKeyValue).isEqualTo(param2Response.configuration().asUtf8String());
-        assertThat(startSessionRequestCaptor.getAllValues().get(0).configurationProfileIdentifier()).isEqualTo(
+        Assertions.assertThat(firstKeyValue).isEqualTo(param1Response.configuration().asUtf8String());
+        Assertions.assertThat(secondKeyValue).isEqualTo(param2Response.configuration().asUtf8String());
+        Assertions.assertThat(startSessionRequestCaptor.getAllValues().get(0).configurationProfileIdentifier()).isEqualTo(
                 param1Key);
-        assertThat(startSessionRequestCaptor.getAllValues().get(1).configurationProfileIdentifier()).isEqualTo(
+        Assertions.assertThat(startSessionRequestCaptor.getAllValues().get(1).configurationProfileIdentifier()).isEqualTo(
                 param2Key);
-        assertThat(getLatestConfigurationRequestCaptor.getAllValues().get(0).configurationToken()).isEqualTo(
+        Assertions.assertThat(getLatestConfigurationRequestCaptor.getAllValues().get(0).configurationToken()).isEqualTo(
                 param1Session.initialConfigurationToken());
-        assertThat(getLatestConfigurationRequestCaptor.getAllValues().get(1).configurationToken()).isEqualTo(
+        Assertions.assertThat(getLatestConfigurationRequestCaptor.getAllValues().get(1).configurationToken()).isEqualTo(
                 param2Session.initialConfigurationToken());
 
     }
@@ -189,7 +186,7 @@ public void multipleKeysRetrievalWorks() {
     public void getMultipleValuesThrowsException() {
 
         // Act & Assert
-        assertThatRuntimeException().isThrownBy(() -> provider.getMultipleValues("path"))
+        Assertions.assertThatRuntimeException().isThrownBy(() -> provider.getMultipleValues("path"))
                 .withMessage("Retrieving multiple parameter values is not supported with the AWS App Config Provider");
     }
 
@@ -197,7 +194,7 @@ public void getMultipleValuesThrowsException() {
     public void testAppConfigProviderBuilderMissingCacheManager_throwsException() {
 
         // Act & Assert
-        assertThatIllegalStateException().isThrownBy(() -> AppConfigProvider.builder()
+        Assertions.assertThatIllegalStateException().isThrownBy(() -> AppConfigProvider.builder()
                         .withEnvironment(environmentName)
                         .withApplication(applicationName)
                         .withClient(client)
@@ -209,7 +206,7 @@ public void testAppConfigProviderBuilderMissingCacheManager_throwsException() {
     public void testAppConfigProviderBuilderMissingEnvironment_throwsException() {
 
         // Act & Assert
-        assertThatIllegalStateException().isThrownBy(() -> AppConfigProvider.builder()
+        Assertions.assertThatIllegalStateException().isThrownBy(() -> AppConfigProvider.builder()
                         .withCacheManager(new CacheManager())
                         .withApplication(applicationName)
                         .withClient(client)
@@ -221,7 +218,7 @@ public void testAppConfigProviderBuilderMissingEnvironment_throwsException() {
     public void testAppConfigProviderBuilderMissingApplication_throwsException() {
 
         // Act & Assert
-        assertThatIllegalStateException().isThrownBy(() -> AppConfigProvider.builder()
+        Assertions.assertThatIllegalStateException().isThrownBy(() -> AppConfigProvider.builder()
                         .withCacheManager(new CacheManager())
                         .withEnvironment(environmentName)
                         .withClient(client)
diff --git a/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerIntegrationTest.java b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerIntegrationTest.java
index ff125666e..032a11d0d 100644
--- a/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerIntegrationTest.java
+++ b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerIntegrationTest.java
@@ -133,14 +133,4 @@ public void secretsProvider_get() {
         verify(secretsManagerClient, times(1)).getSecretValue(any(GetSecretValueRequest.class));
     }
 
-    @Test
-    public void getAppConfigProvider() {
-
-        // Act
-        AppConfigProvider provider = ParamManager.getAppConfigProvider(appConfigDataClient, "test-env", "test-app");
-
-        // Assert
-        assertThat(provider).isNotNull();
-
-    }
 }
diff --git a/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerTest.java b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerTest.java
index ad512e563..db64c31fd 100644
--- a/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerTest.java
+++ b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerTest.java
@@ -90,10 +90,4 @@ public void testGetDynamoDBProvider_requireOtherParameters_throwException() {
         assertThatIllegalArgumentException().isThrownBy(() -> ParamManager.getProvider(DynamoDbProvider.class));
     }
 
-    @Test
-    public void testGetAppConfigProvider_requireOtherParameters_throwException() {
-
-        // Act & Assert
-        assertThatIllegalArgumentException().isThrownBy(() -> ParamManager.getProvider(AppConfigProvider.class));
-    }
 }
diff --git a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/ParamManager.java b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/ParamManager.java
index 6c0a5e72e..1a5f47ce2 100644
--- a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/ParamManager.java
+++ b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/ParamManager.java
@@ -16,7 +16,6 @@
 
 import java.lang.reflect.Constructor;
 import java.util.concurrent.ConcurrentHashMap;
-import software.amazon.awssdk.services.appconfigdata.AppConfigDataClient;
 import software.amazon.lambda.powertools.parameters.cache.CacheManager;
 import software.amazon.lambda.powertools.parameters.transform.TransformationManager;
 
@@ -44,48 +43,9 @@ public static <T extends BaseProvider> T getProvider(Class<T> providerClass) {
         if (providerClass == null) {
             throw new IllegalStateException("providerClass cannot be null.");
         }
-        if (providerClass == AppConfigProvider.class) {
-            throw new IllegalArgumentException(
-                    providerClass + " cannot be instantiated like this, additional parameters are required");
-        }
         return (T) providers.computeIfAbsent(providerClass, ParamManager::createProvider);
     }
 
-    /**
-     * Get a {@link AppConfigProvider} with default {@link AppConfigDataClient}.<br/>
-     * If you need to customize the region, or other part of the client, use {@link ParamManager#getAppConfigProvider(AppConfigDataClient, String, String)} instead.
-     *
-     * @return a {@link AppConfigProvider}
-     */
-    public static AppConfigProvider getAppConfigProvider(String environment, String application) {
-        // Because we need a DDB table name to configure our client, we can't use
-        // ParamManager#getProvider. This means that we need to make sure we do the same stuff -
-        // set transformation manager and cache manager.
-        return AppConfigProvider.builder()
-                .withCacheManager(cacheManager)
-                .withTransformationManager(transformationManager)
-                .withEnvironment(environment)
-                .withApplication(application)
-                .build();
-    }
-
-    /**
-     * Get a {@link AppConfigProvider} with your custom {@link AppConfigDataClient}.<br/>
-     * Use this to configure region or other part of the client. Use {@link ParamManager#getAppConfigProvider(String, String)} if you don't need this customization.
-     *
-     * @return a {@link AppConfigProvider}
-     */
-    public static AppConfigProvider getAppConfigProvider(AppConfigDataClient client, String environment,
-                                                         String application) {
-        return (AppConfigProvider) providers.computeIfAbsent(AppConfigProvider.class, (k) -> AppConfigProvider.builder()
-                .withClient(client)
-                .withCacheManager(cacheManager)
-                .withTransformationManager(transformationManager)
-                .withEnvironment(environment)
-                .withApplication(application)
-                .build());
-    }
-
 
     public static CacheManager getCacheManager() {
         return cacheManager;

From 2f79e7ca12bba5bb2c4b9b850165001fa8800687 Mon Sep 17 00:00:00 2001
From: Scott Gerring <gerrings@amazon.com>
Date: Wed, 30 Aug 2023 16:34:29 +0200
Subject: [PATCH 05/45] Gutting ParamManager

---
 .../parameters/appconfig/AppConfigParam.java  | 22 +++++++
 .../appconfig/AppConfigParametersAspect.java  | 59 +++++++++++++++++++
 .../parameters/secrets/SecretsProvider.java   |  4 +-
 .../LambdaParametersAspectTest.java           | 16 +----
 .../ParamManagerIntegrationTest.java          |  3 -
 .../LambdaParametersAspect.java               |  2 +-
 .../powertools/parameters/ParamManager.java   | 33 -----------
 7 files changed, 86 insertions(+), 53 deletions(-)
 create mode 100644 powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParam.java
 create mode 100644 powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParametersAspect.java
 rename powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/{internal => }/LambdaParametersAspect.java (97%)

diff --git a/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParam.java b/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParam.java
new file mode 100644
index 000000000..a13c85496
--- /dev/null
+++ b/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParam.java
@@ -0,0 +1,22 @@
+package software.amazon.lambda.powertools.parameters.appconfig;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import software.amazon.lambda.powertools.parameters.BaseProvider;
+import software.amazon.lambda.powertools.parameters.transform.Transformer;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.FIELD)
+public @interface AppConfigParam {
+    String key();
+
+    String environment();
+
+    String application();
+
+    Class<? extends BaseProvider> provider();
+
+    Class<? extends Transformer> transformer() default Transformer.class;
+}
diff --git a/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParametersAspect.java b/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParametersAspect.java
new file mode 100644
index 000000000..d9596e64f
--- /dev/null
+++ b/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParametersAspect.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package software.amazon.lambda.powertools.parameters.appconfig;
+
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Pointcut;
+import org.aspectj.lang.reflect.FieldSignature;
+import software.amazon.lambda.powertools.parameters.BaseProvider;
+import software.amazon.lambda.powertools.parameters.Param;
+import software.amazon.lambda.powertools.parameters.ParamManager;
+
+@Aspect
+public class AppConfigParametersAspect {
+
+    @Pointcut("get(* *) && @annotation(appConfigParamAnnotation)")
+    public void getParam(AppConfigParam appConfigParamAnnotation) {
+    }
+
+    @Around("getParam(appConfigParamAnnotation)")
+    public Object injectParam(final ProceedingJoinPoint joinPoint, final AppConfigParam appConfigParamAnnotation) {
+        AppConfigProvider provider = AppConfigProvider.builder()
+                .withEnvironment(appConfigParamAnnotation.environment())
+                .withApplication(appConfigParamAnnotation.application())
+                .build();
+
+        if (appConfigParamAnnotation.transformer().isInterface()) {
+            // No transformation
+            return provider.get(appConfigParamAnnotation.key());
+        } else {
+            FieldSignature s = (FieldSignature) joinPoint.getSignature();
+            if (String.class.isAssignableFrom(s.getFieldType())) {
+                // Basic transformation
+                return provider
+                        .withTransformation(appConfigParamAnnotation.transformer())
+                        .get(appConfigParamAnnotation.key());
+            } else {
+                // Complex transformation
+                return provider
+                        .withTransformation(appConfigParamAnnotation.transformer())
+                        .get(appConfigParamAnnotation.key(), s.getFieldType());
+            }
+        }
+    }
+
+}
diff --git a/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProvider.java b/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProvider.java
index 0cdb05a62..326c5ef36 100644
--- a/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProvider.java
+++ b/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProvider.java
@@ -68,7 +68,7 @@ public class SecretsProvider extends BaseProvider {
      *
      * @param client custom client you would like to use.
      */
-    SecretsProvider(CacheManager cacheManager, SecretsManagerClient client) {
+    public SecretsProvider(CacheManager cacheManager, SecretsManagerClient client) {
         super(cacheManager);
         this.client = client;
     }
@@ -80,7 +80,7 @@ public class SecretsProvider extends BaseProvider {
      *
      * @param cacheManager handles the parameter caching
      */
-    SecretsProvider(CacheManager cacheManager) {
+    public SecretsProvider(CacheManager cacheManager) {
         this(cacheManager, Builder.createClient());
     }
 
diff --git a/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/LambdaParametersAspectTest.java b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/LambdaParametersAspectTest.java
index db4c17b50..0fb945554 100644
--- a/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/LambdaParametersAspectTest.java
+++ b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/LambdaParametersAspectTest.java
@@ -12,23 +12,11 @@
  *
  */
 
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
-import static org.mockito.Mockito.mockStatic;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-import static org.mockito.MockitoAnnotations.openMocks;
-
 import org.assertj.core.api.Assertions;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.mockito.Mock;
-import org.mockito.MockedStatic;
-import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
-import software.amazon.lambda.powertools.parameters.Param;
-import software.amazon.lambda.powertools.parameters.ParamManager;
 import software.amazon.lambda.powertools.parameters.exception.TransformationException;
 import software.amazon.lambda.powertools.parameters.internal.AnotherObject;
 import software.amazon.lambda.powertools.parameters.internal.CustomProvider;
@@ -42,8 +30,8 @@ public class LambdaParametersAspectTest {
     @Mock
     private SSMProvider defaultProvider;
 
-    @Param(key = "/default", provider = SSMProvider.class)
-    private String defaultValue;
+//    @Param(key = "/default", provider = SSMProvider.class)
+//    private String defaultValue;
 
     @Param(key = "/simple", provider = CustomProvider.class)
     private String param;
diff --git a/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerIntegrationTest.java b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerIntegrationTest.java
index 032a11d0d..e06dd7e13 100644
--- a/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerIntegrationTest.java
+++ b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerIntegrationTest.java
@@ -32,7 +32,6 @@
 import org.mockito.ArgumentCaptor;
 import org.mockito.Captor;
 import org.mockito.Mock;
-import software.amazon.awssdk.services.appconfigdata.AppConfigDataClient;
 import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
 import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient;
 import software.amazon.awssdk.services.secretsmanager.model.GetSecretValueRequest;
@@ -61,8 +60,6 @@ public class ParamManagerIntegrationTest {
     SecretsManagerClient secretsManagerClient;
     @Captor
     ArgumentCaptor<GetSecretValueRequest> secretsCaptor;
-    @Mock
-    private AppConfigDataClient appConfigDataClient;
 
     @BeforeEach
     public void setup() throws IllegalAccessException {
diff --git a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/internal/LambdaParametersAspect.java b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/LambdaParametersAspect.java
similarity index 97%
rename from powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/internal/LambdaParametersAspect.java
rename to powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/LambdaParametersAspect.java
index 081af108d..4fad5ff8f 100644
--- a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/internal/LambdaParametersAspect.java
+++ b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/LambdaParametersAspect.java
@@ -12,7 +12,7 @@
  *
  */
 
-package software.amazon.lambda.powertools.parameters.internal;
+package software.amazon.lambda.powertools.parameters;
 
 import org.aspectj.lang.ProceedingJoinPoint;
 import org.aspectj.lang.annotation.Around;
diff --git a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/ParamManager.java b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/ParamManager.java
index 1a5f47ce2..79eb796e8 100644
--- a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/ParamManager.java
+++ b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/ParamManager.java
@@ -14,8 +14,6 @@
 
 package software.amazon.lambda.powertools.parameters;
 
-import java.lang.reflect.Constructor;
-import java.util.concurrent.ConcurrentHashMap;
 import software.amazon.lambda.powertools.parameters.cache.CacheManager;
 import software.amazon.lambda.powertools.parameters.transform.TransformationManager;
 
@@ -28,25 +26,6 @@ public final class ParamManager {
     private static final CacheManager cacheManager = new CacheManager();
     private static final TransformationManager transformationManager = new TransformationManager();
 
-    // NOTE: For testing purposes `providers` cannot be final
-    private static ConcurrentHashMap<Class<? extends BaseProvider>, BaseProvider> providers = new ConcurrentHashMap<>();
-
-    /**
-     * Get a concrete implementation of {@link BaseProvider}.<br/>
-     * custom provider by extending {@link BaseProvider} if you need to integrate with a different parameter store.
-     *
-     * @return a {@link SecretsProvider}
-     * @deprecated You should not use this method directly but a typed one (getSecretsProvider, getSsmProvider, getDynamoDbProvider, getAppConfigProvider), will be removed in v2
-     */
-    // TODO in v2: remove public access to this and review how we get providers (it was not designed for DDB and AppConfig in mind initially)
-    public static <T extends BaseProvider> T getProvider(Class<T> providerClass) {
-        if (providerClass == null) {
-            throw new IllegalStateException("providerClass cannot be null.");
-        }
-        return (T) providers.computeIfAbsent(providerClass, ParamManager::createProvider);
-    }
-
-
     public static CacheManager getCacheManager() {
         return cacheManager;
     }
@@ -55,17 +34,5 @@ public static TransformationManager getTransformationManager() {
         return transformationManager;
     }
 
-    static <T extends BaseProvider> T createProvider(Class<T> providerClass) {
-        try {
-            Constructor<T> constructor = providerClass.getDeclaredConstructor(CacheManager.class);
-            T provider =
-                    constructor.newInstance(cacheManager); // FIXME: avoid reflection here as we may have issues (#1280)
-            provider.setTransformationManager(transformationManager);
-            return provider;
-        } catch (ReflectiveOperationException e) {
-            throw new RuntimeException("Unexpected error occurred. Please raise issue at " +
-                    "https://github.com/aws-powertools/powertools-lambda-java/issues", e);
-        }
-    }
 
 }

From 65501c3f64d06d07ad19d5ce3a51c785e176427e Mon Sep 17 00:00:00 2001
From: Scott Gerring <gerrings@amazon.com>
Date: Fri, 8 Sep 2023 13:13:09 +0200
Subject: [PATCH 06/45] Breaking up aspects

---
 .../gradle/README.md                          |  38 +++
 .../gradle/build.gradle                       |  35 +++
 .../gradle/events/event.json                  |  62 +++++
 .../gradle/gradle/wrapper/.gitignore          |   2 +
 .../gradle/gradle/wrapper/gradle-wrapper.jar  | Bin 0 -> 63375 bytes
 .../gradle/wrapper/gradle-wrapper.properties  |   7 +
 .../gradle/gradlew                            | 248 ++++++++++++++++++
 .../gradle/gradlew.bat                        |  92 +++++++
 .../gradle/src/main/java/helloworld/App.java  | 107 ++++++++
 .../src/main/java/helloworld/AppStream.java   |  38 +++
 .../src/test/java/helloworld/AppTest.java     |  24 ++
 .../gradle/template.yaml                      |  71 +++++
 .../.gradle/7.3.3/checksums/checksums.lock    | Bin 0 -> 17 bytes
 .../.gradle/7.3.3/fileChanges/last-build.bin  | Bin 0 -> 1 bytes
 .../.gradle/7.3.3/fileHashes/fileHashes.lock  | Bin 0 -> 17 bytes
 .../gradle/.gradle/7.3.3/gc.properties        |   0
 .../gradle/.gradle/vcs-1/gc.properties        |   0
 .../parameters/appconfig/AppConfigParam.java  |   2 -
 .../appconfig/AppConfigParametersAspect.java  |   3 +
 .../appconfig/AppConfigProvider.java          |   2 +-
 .../appconfig/AppConfigParamAspectTest.java   |  20 ++
 .../appconfig/AppConfigProviderTest.java      |  12 -
 .../parameters/dynamodb/DynamoDbParam.java    |  17 ++
 .../dynamodb/DynamoDbParamAspect.java         |  58 ++++
 .../parameters/dynamodb/DynamoDbProvider.java |   2 +-
 .../parameters/secrets/SecretsParam.java      |  15 ++
 .../secrets/SecretsParamAspect.java           |  57 ++++
 .../powertools/parameters/ssm/SSMParam.java   |  15 ++
 .../parameters/ssm/SSMParamAspect.java        |  57 ++++
 .../parameters/ParamManagerTest.java          |  80 +++---
 .../parameters/LambdaParametersAspect.java    |  44 ++--
 31 files changed, 1031 insertions(+), 77 deletions(-)
 create mode 100644 examples/powertools-examples-core-utilities/gradle/README.md
 create mode 100644 examples/powertools-examples-core-utilities/gradle/build.gradle
 create mode 100644 examples/powertools-examples-core-utilities/gradle/events/event.json
 create mode 100644 examples/powertools-examples-core-utilities/gradle/gradle/wrapper/.gitignore
 create mode 100644 examples/powertools-examples-core-utilities/gradle/gradle/wrapper/gradle-wrapper.jar
 create mode 100644 examples/powertools-examples-core-utilities/gradle/gradle/wrapper/gradle-wrapper.properties
 create mode 100755 examples/powertools-examples-core-utilities/gradle/gradlew
 create mode 100644 examples/powertools-examples-core-utilities/gradle/gradlew.bat
 create mode 100644 examples/powertools-examples-core-utilities/gradle/src/main/java/helloworld/App.java
 create mode 100644 examples/powertools-examples-core-utilities/gradle/src/main/java/helloworld/AppStream.java
 create mode 100644 examples/powertools-examples-core-utilities/gradle/src/test/java/helloworld/AppTest.java
 create mode 100644 examples/powertools-examples-core-utilities/gradle/template.yaml
 create mode 100644 examples/powertools-examples-core/gradle/.gradle/7.3.3/checksums/checksums.lock
 create mode 100644 examples/powertools-examples-core/gradle/.gradle/7.3.3/fileChanges/last-build.bin
 create mode 100644 examples/powertools-examples-core/gradle/.gradle/7.3.3/fileHashes/fileHashes.lock
 create mode 100644 examples/powertools-examples-core/gradle/.gradle/7.3.3/gc.properties
 create mode 100644 examples/powertools-examples-core/gradle/.gradle/vcs-1/gc.properties
 create mode 100644 powertools-parameters/powertools-parameters-appconfig/src/test/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParamAspectTest.java
 create mode 100644 powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbParam.java
 create mode 100644 powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbParamAspect.java
 create mode 100644 powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsParam.java
 create mode 100644 powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsParamAspect.java
 create mode 100644 powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMParam.java
 create mode 100644 powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMParamAspect.java

diff --git a/examples/powertools-examples-core-utilities/gradle/README.md b/examples/powertools-examples-core-utilities/gradle/README.md
new file mode 100644
index 000000000..cd6107151
--- /dev/null
+++ b/examples/powertools-examples-core-utilities/gradle/README.md
@@ -0,0 +1,38 @@
+#  Powertools for AWS Lambda (Java) - Core Utilities Example with Gradle
+
+This project demonstrates the Lambda for Powertools Java module deployed using [Serverless Application Model](https://aws.amazon.com/serverless/sam/) with
+[Gradle](https://gradle.org/) running the build. This example is configured for Java 1.8 only; in order to use a newer version, check out the Gradle 
+configuration guide [in the main project README](../../../README.md).
+
+You can also use `sam init` to create a new Gradle-powered Powertools application - choose to use the **AWS Quick Start Templates**,
+and then **Hello World Example with Powertools for AWS Lambda**, **Java 17** runtime, and finally **gradle**.
+
+
+For general information on the deployed example itself, you can refer to the parent [README](../../powertools-examples-core/README.md)
+
+## Configuration
+SAM uses [template.yaml](template.yaml) to define the application's AWS resources.
+This file defines the Lambda function to be deployed as well as API Gateway for it.
+
+The build of the project is managed by Gradle, and configured in [build.gradle](build.gradle). 
+
+## Deploy the sample application
+To get started, you can use the Gradle wrapper to bootstrap Gradle and run the build:
+
+```bash
+./gradlew build
+```
+
+Once this is done to deploy the example, check out the instructions for getting started with SAM in 
+[the examples directory](../../README.md)
+
+## Additional notes
+
+You can watch the trace information or log information using the SAM CLI:
+```bash
+# Tail the logs
+sam logs --tail $MY_STACK
+
+# Tail the traces
+sam traces --tail
+```
\ No newline at end of file
diff --git a/examples/powertools-examples-core-utilities/gradle/build.gradle b/examples/powertools-examples-core-utilities/gradle/build.gradle
new file mode 100644
index 000000000..e7367c246
--- /dev/null
+++ b/examples/powertools-examples-core-utilities/gradle/build.gradle
@@ -0,0 +1,35 @@
+
+plugins {
+    id 'java'
+    id "io.freefair.aspectj.post-compile-weaving" version "6.6.3"
+}
+
+wrapper {
+    gradleVersion = "7.6.1"
+}
+
+compileJava {
+    sourceCompatibility = "1.8"
+    targetCompatibility = "1.8"
+
+    ajc {
+        enabled = true
+    }
+}
+
+repositories {
+    mavenCentral()
+}
+
+dependencies {
+    implementation 'com.amazonaws:aws-lambda-java-core:1.2.2'
+    implementation 'com.fasterxml.jackson.core:jackson-annotations:2.13.2'
+    implementation 'com.fasterxml.jackson.core:jackson-databind:2.13.2.2'
+    implementation 'com.amazonaws:aws-lambda-java-events:3.11.0'
+    implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.13.2'
+    aspect 'software.amazon.lambda:powertools-tracing:1.17.0'
+    aspect 'software.amazon.lambda:powertools-logging:1.17.0'
+    aspect 'software.amazon.lambda:powertools-metrics:1.17.0'
+    testImplementation 'junit:junit:4.13.2'
+}
+
diff --git a/examples/powertools-examples-core-utilities/gradle/events/event.json b/examples/powertools-examples-core-utilities/gradle/events/event.json
new file mode 100644
index 000000000..070ad8e01
--- /dev/null
+++ b/examples/powertools-examples-core-utilities/gradle/events/event.json
@@ -0,0 +1,62 @@
+{
+  "body": "{\"message\": \"hello world\"}",
+  "resource": "/{proxy+}",
+  "path": "/path/to/resource",
+  "httpMethod": "POST",
+  "isBase64Encoded": false,
+  "queryStringParameters": {
+    "foo": "bar"
+  },
+  "pathParameters": {
+    "proxy": "/path/to/resource"
+  },
+  "stageVariables": {
+    "baz": "qux"
+  },
+  "headers": {
+    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
+    "Accept-Encoding": "gzip, deflate, sdch",
+    "Accept-Language": "en-US,en;q=0.8",
+    "Cache-Control": "max-age=0",
+    "CloudFront-Forwarded-Proto": "https",
+    "CloudFront-Is-Desktop-Viewer": "true",
+    "CloudFront-Is-Mobile-Viewer": "false",
+    "CloudFront-Is-SmartTV-Viewer": "false",
+    "CloudFront-Is-Tablet-Viewer": "false",
+    "CloudFront-Viewer-Country": "US",
+    "Host": "1234567890.execute-api.us-east-1.amazonaws.com",
+    "Upgrade-Insecure-Requests": "1",
+    "User-Agent": "Custom User Agent String",
+    "Via": "1.1 08f323deadbeefa7af34d5feb414ce27.cloudfront.net (CloudFront)",
+    "X-Amz-Cf-Id": "cDehVQoZnx43VYQb9j2-nvCh-9z396Uhbp027Y2JvkCPNLmGJHqlaA==",
+    "X-Forwarded-For": "127.0.0.1, 127.0.0.2",
+    "X-Forwarded-Port": "443",
+    "X-Forwarded-Proto": "https"
+  },
+  "requestContext": {
+    "accountId": "123456789012",
+    "resourceId": "123456",
+    "stage": "prod",
+    "requestId": "c6af9ac6-7b61-11e6-9a41-93e8deadbeef",
+    "requestTime": "09/Apr/2015:12:34:56 +0000",
+    "requestTimeEpoch": 1428582896000,
+    "identity": {
+      "cognitoIdentityPoolId": null,
+      "accountId": null,
+      "cognitoIdentityId": null,
+      "caller": null,
+      "accessKey": null,
+      "sourceIp": "127.0.0.1",
+      "cognitoAuthenticationType": null,
+      "cognitoAuthenticationProvider": null,
+      "userArn": null,
+      "userAgent": "Custom User Agent String",
+      "user": null
+    },
+    "path": "/prod/path/to/resource",
+    "resourcePath": "/{proxy+}",
+    "httpMethod": "POST",
+    "apiId": "1234567890",
+    "protocol": "HTTP/1.1"
+  }
+}
diff --git a/examples/powertools-examples-core-utilities/gradle/gradle/wrapper/.gitignore b/examples/powertools-examples-core-utilities/gradle/gradle/wrapper/.gitignore
new file mode 100644
index 000000000..59c09e205
--- /dev/null
+++ b/examples/powertools-examples-core-utilities/gradle/gradle/wrapper/.gitignore
@@ -0,0 +1,2 @@
+!gradle-wrapper.jar
+
diff --git a/examples/powertools-examples-core-utilities/gradle/gradle/wrapper/gradle-wrapper.jar b/examples/powertools-examples-core-utilities/gradle/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000000000000000000000000000000000000..033e24c4cdf41af1ab109bc7f253b2b887023340
GIT binary patch
diff --git a/examples/powertools-examples-core-utilities/gradle/gradle/wrapper/gradle-wrapper.properties b/examples/powertools-examples-core-utilities/gradle/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 000000000..0d23ac00c
--- /dev/null
+++ b/examples/powertools-examples-core-utilities/gradle/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,7 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip
+networkTimeout=10000
+validateDistributionUrl=true
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/examples/powertools-examples-core-utilities/gradle/gradlew b/examples/powertools-examples-core-utilities/gradle/gradlew
new file mode 100755
index 000000000..fcb6fca14
--- /dev/null
+++ b/examples/powertools-examples-core-utilities/gradle/gradlew
@@ -0,0 +1,248 @@
+#!/bin/sh
+
+#
+# Copyright © 2015-2021 the original authors.
+#
+# 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
+#
+#      https://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.
+#
+
+##############################################################################
+#
+#   Gradle start up script for POSIX generated by Gradle.
+#
+#   Important for running:
+#
+#   (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
+#       noncompliant, but you have some other compliant shell such as ksh or
+#       bash, then to run this script, type that shell name before the whole
+#       command line, like:
+#
+#           ksh Gradle
+#
+#       Busybox and similar reduced shells will NOT work, because this script
+#       requires all of these POSIX shell features:
+#         * functions;
+#         * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
+#           «${var#prefix}», «${var%suffix}», and «$( cmd )»;
+#         * compound commands having a testable exit status, especially «case»;
+#         * various built-in commands including «command», «set», and «ulimit».
+#
+#   Important for patching:
+#
+#   (2) This script targets any POSIX shell, so it avoids extensions provided
+#       by Bash, Ksh, etc; in particular arrays are avoided.
+#
+#       The "traditional" practice of packing multiple parameters into a
+#       space-separated string is a well documented source of bugs and security
+#       problems, so this is (mostly) avoided, by progressively accumulating
+#       options in "$@", and eventually passing that to Java.
+#
+#       Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
+#       and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
+#       see the in-line comments for details.
+#
+#       There are tweaks for specific operating systems such as AIX, CygWin,
+#       Darwin, MinGW, and NonStop.
+#
+#   (3) This script is generated from the Groovy template
+#       https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+#       within the Gradle project.
+#
+#       You can find Gradle at https://github.com/gradle/gradle/.
+#
+##############################################################################
+
+# Attempt to set APP_HOME
+
+# Resolve links: $0 may be a link
+app_path=$0
+
+# Need this for daisy-chained symlinks.
+while
+    APP_HOME=${app_path%"${app_path##*/}"}  # leaves a trailing /; empty if no leading path
+    [ -h "$app_path" ]
+do
+    ls=$( ls -ld "$app_path" )
+    link=${ls#*' -> '}
+    case $link in             #(
+      /*)   app_path=$link ;; #(
+      *)    app_path=$APP_HOME$link ;;
+    esac
+done
+
+# This is normally unused
+# shellcheck disable=SC2034
+APP_BASE_NAME=${0##*/}
+APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD=maximum
+
+warn () {
+    echo "$*"
+} >&2
+
+die () {
+    echo
+    echo "$*"
+    echo
+    exit 1
+} >&2
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "$( uname )" in                #(
+  CYGWIN* )         cygwin=true  ;; #(
+  Darwin* )         darwin=true  ;; #(
+  MSYS* | MINGW* )  msys=true    ;; #(
+  NONSTOP* )        nonstop=true ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+        # IBM's JDK on AIX uses strange locations for the executables
+        JAVACMD=$JAVA_HOME/jre/sh/java
+    else
+        JAVACMD=$JAVA_HOME/bin/java
+    fi
+    if [ ! -x "$JAVACMD" ] ; then
+        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+    fi
+else
+    JAVACMD=java
+    if ! command -v java >/dev/null 2>&1
+    then
+        die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+    fi
+fi
+
+# Increase the maximum file descriptors if we can.
+if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
+    case $MAX_FD in #(
+      max*)
+        # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
+        # shellcheck disable=SC3045
+        MAX_FD=$( ulimit -H -n ) ||
+            warn "Could not query maximum file descriptor limit"
+    esac
+    case $MAX_FD in  #(
+      '' | soft) :;; #(
+      *)
+        # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
+        # shellcheck disable=SC3045
+        ulimit -n "$MAX_FD" ||
+            warn "Could not set maximum file descriptor limit to $MAX_FD"
+    esac
+fi
+
+# Collect all arguments for the java command, stacking in reverse order:
+#   * args from the command line
+#   * the main class name
+#   * -classpath
+#   * -D...appname settings
+#   * --module-path (only if needed)
+#   * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if "$cygwin" || "$msys" ; then
+    APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
+    CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
+
+    JAVACMD=$( cygpath --unix "$JAVACMD" )
+
+    # Now convert the arguments - kludge to limit ourselves to /bin/sh
+    for arg do
+        if
+            case $arg in                                #(
+              -*)   false ;;                            # don't mess with options #(
+              /?*)  t=${arg#/} t=/${t%%/*}              # looks like a POSIX filepath
+                    [ -e "$t" ] ;;                      #(
+              *)    false ;;
+            esac
+        then
+            arg=$( cygpath --path --ignore --mixed "$arg" )
+        fi
+        # Roll the args list around exactly as many times as the number of
+        # args, so each arg winds up back in the position where it started, but
+        # possibly modified.
+        #
+        # NB: a `for` loop captures its iteration list before it begins, so
+        # changing the positional parameters here affects neither the number of
+        # iterations, nor the values presented in `arg`.
+        shift                   # remove old arg
+        set -- "$@" "$arg"      # push replacement arg
+    done
+fi
+
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Collect all arguments for the java command;
+#   * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
+#     shell script including quotes and variable substitutions, so put them in
+#     double quotes to make sure that they get re-expanded; and
+#   * put everything else in single quotes, so that it's not re-expanded.
+
+set -- \
+        "-Dorg.gradle.appname=$APP_BASE_NAME" \
+        -classpath "$CLASSPATH" \
+        org.gradle.wrapper.GradleWrapperMain \
+        "$@"
+
+# Stop when "xargs" is not available.
+if ! command -v xargs >/dev/null 2>&1
+then
+    die "xargs is not available"
+fi
+
+# Use "xargs" to parse quoted args.
+#
+# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
+#
+# In Bash we could simply go:
+#
+#   readarray ARGS < <( xargs -n1 <<<"$var" ) &&
+#   set -- "${ARGS[@]}" "$@"
+#
+# but POSIX shell has neither arrays nor command substitution, so instead we
+# post-process each arg (as a line of input to sed) to backslash-escape any
+# character that might be a shell metacharacter, then use eval to reverse
+# that process (while maintaining the separation between arguments), and wrap
+# the whole thing up as a single "set" statement.
+#
+# This will of course break if any of these variables contains a newline or
+# an unmatched quote.
+#
+
+eval "set -- $(
+        printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
+        xargs -n1 |
+        sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
+        tr '\n' ' '
+    )" '"$@"'
+
+exec "$JAVACMD" "$@"
diff --git a/examples/powertools-examples-core-utilities/gradle/gradlew.bat b/examples/powertools-examples-core-utilities/gradle/gradlew.bat
new file mode 100644
index 000000000..93e3f59f1
--- /dev/null
+++ b/examples/powertools-examples-core-utilities/gradle/gradlew.bat
@@ -0,0 +1,92 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem      https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%"=="" @echo off
+@rem ##########################################################################
+@rem
+@rem  Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%"=="" set DIRNAME=.
+@rem This is normally unused
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if %ERRORLEVEL% equ 0 goto execute
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if %ERRORLEVEL% equ 0 goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+set EXIT_CODE=%ERRORLEVEL%
+if %EXIT_CODE% equ 0 set EXIT_CODE=1
+if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
+exit /b %EXIT_CODE%
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/examples/powertools-examples-core-utilities/gradle/src/main/java/helloworld/App.java b/examples/powertools-examples-core-utilities/gradle/src/main/java/helloworld/App.java
new file mode 100644
index 000000000..fccc63b9a
--- /dev/null
+++ b/examples/powertools-examples-core-utilities/gradle/src/main/java/helloworld/App.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package helloworld;
+
+import static software.amazon.lambda.powertools.metrics.MetricsUtils.metricsLogger;
+import static software.amazon.lambda.powertools.metrics.MetricsUtils.withSingleMetric;
+import static software.amazon.lambda.powertools.tracing.TracingUtils.putMetadata;
+
+import com.amazonaws.services.lambda.runtime.Context;
+import com.amazonaws.services.lambda.runtime.RequestHandler;
+import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent;
+import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.stream.Collectors;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import software.amazon.cloudwatchlogs.emf.model.DimensionSet;
+import software.amazon.cloudwatchlogs.emf.model.Unit;
+import software.amazon.lambda.powertools.logging.Logging;
+import software.amazon.lambda.powertools.logging.LoggingUtils;
+import software.amazon.lambda.powertools.metrics.Metrics;
+import software.amazon.lambda.powertools.tracing.CaptureMode;
+import software.amazon.lambda.powertools.tracing.Tracing;
+import software.amazon.lambda.powertools.tracing.TracingUtils;
+
+/**
+ * Handler for requests to Lambda function.
+ */
+public class App implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {
+    private final static Logger log = LogManager.getLogger(App.class);
+
+    @Logging(logEvent = true, samplingRate = 0.7)
+    @Tracing(captureMode = CaptureMode.RESPONSE_AND_ERROR)
+    @Metrics(namespace = "ServerlessAirline", service = "payment", captureColdStart = true)
+    public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) {
+        Map<String, String> headers = new HashMap<>();
+
+        headers.put("Content-Type", "application/json");
+        headers.put("X-Custom-Header", "application/json");
+
+        metricsLogger().putMetric("CustomMetric1", 1, Unit.COUNT);
+
+        withSingleMetric("CustomMetrics2", 1, Unit.COUNT, "Another", (metric) ->
+        {
+            metric.setDimensions(DimensionSet.of("AnotherService", "CustomService"));
+            metric.setDimensions(DimensionSet.of("AnotherService1", "CustomService1"));
+        });
+
+        LoggingUtils.appendKey("test", "willBeLogged");
+
+        APIGatewayProxyResponseEvent response = new APIGatewayProxyResponseEvent()
+                .withHeaders(headers);
+        try {
+            final String pageContents = this.getPageContents("https://checkip.amazonaws.com");
+            log.info(pageContents);
+            TracingUtils.putAnnotation("Test", "New");
+            String output = String.format("{ \"message\": \"hello world\", \"location\": \"%s\" }", pageContents);
+
+            TracingUtils.withSubsegment("loggingResponse", subsegment ->
+            {
+                String sampled = "log something out";
+                log.info(sampled);
+                log.info(output);
+            });
+
+            log.info("After output");
+            return response
+                    .withStatusCode(200)
+                    .withBody(output);
+        } catch (RuntimeException | IOException e) {
+            return response
+                    .withBody("{}")
+                    .withStatusCode(500);
+        }
+    }
+
+    @Tracing
+    private void log() {
+        log.info("inside threaded logging for function");
+    }
+
+    @Tracing(namespace = "getPageContents", captureMode = CaptureMode.DISABLED)
+    private String getPageContents(String address) throws IOException {
+        URL url = new URL(address);
+        putMetadata("getPageContents", address);
+        try (BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream()))) {
+            return br.lines().collect(Collectors.joining(System.lineSeparator()));
+        }
+    }
+}
diff --git a/examples/powertools-examples-core-utilities/gradle/src/main/java/helloworld/AppStream.java b/examples/powertools-examples-core-utilities/gradle/src/main/java/helloworld/AppStream.java
new file mode 100644
index 000000000..401ef8c48
--- /dev/null
+++ b/examples/powertools-examples-core-utilities/gradle/src/main/java/helloworld/AppStream.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package helloworld;
+
+import com.amazonaws.services.lambda.runtime.Context;
+import com.amazonaws.services.lambda.runtime.RequestStreamHandler;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Map;
+import software.amazon.lambda.powertools.logging.Logging;
+import software.amazon.lambda.powertools.metrics.Metrics;
+
+public class AppStream implements RequestStreamHandler {
+    private static final ObjectMapper mapper = new ObjectMapper();
+
+    @Override
+    @Logging(logEvent = true)
+    @Metrics(namespace = "ServerlessAirline", service = "payment", captureColdStart = true)
+    public void handleRequest(InputStream input, OutputStream output, Context context) throws IOException {
+        Map map = mapper.readValue(input, Map.class);
+
+        System.out.println(map.size());
+    }
+}
diff --git a/examples/powertools-examples-core-utilities/gradle/src/test/java/helloworld/AppTest.java b/examples/powertools-examples-core-utilities/gradle/src/test/java/helloworld/AppTest.java
new file mode 100644
index 000000000..af3ec1275
--- /dev/null
+++ b/examples/powertools-examples-core-utilities/gradle/src/test/java/helloworld/AppTest.java
@@ -0,0 +1,24 @@
+package helloworld;
+
+import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+public class AppTest {
+    @Test
+    public void successfulResponse() {
+        App app = new App();
+        APIGatewayProxyResponseEvent result = app.handleRequest(null, null);
+        assertEquals(200, result.getStatusCode().intValue());
+        assertEquals("application/json", result.getHeaders().get("Content-Type"));
+        String content = result.getBody();
+        assertNotNull(content);
+        assertTrue(content.contains("\"message\""));
+        assertTrue(content.contains("\"hello world\""));
+        assertTrue(content.contains("\"location\""));
+    }
+}
diff --git a/examples/powertools-examples-core-utilities/gradle/template.yaml b/examples/powertools-examples-core-utilities/gradle/template.yaml
new file mode 100644
index 000000000..a717c2998
--- /dev/null
+++ b/examples/powertools-examples-core-utilities/gradle/template.yaml
@@ -0,0 +1,71 @@
+AWSTemplateFormatVersion: '2010-09-09'
+Transform: AWS::Serverless-2016-10-31
+Description: >
+  gradle
+
+  Sample SAM Template for gradle
+
+# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst
+Globals:
+  Function:
+    Timeout: 20
+    Runtime: java11
+    MemorySize: 512
+    Tracing: Active # https://docs.aws.amazon.com/lambda/latest/dg/lambda-x-ray.html
+    Environment:
+      Variables:
+        # Powertools for AWS Lambda (Java) env vars: https://docs.powertools.aws.dev/lambda/java/#environment-variables
+        POWERTOOLS_LOG_LEVEL: INFO
+        POWERTOOLS_LOGGER_SAMPLE_RATE: 0.1
+        POWERTOOLS_LOGGER_LOG_EVENT: true
+        POWERTOOLS_METRICS_NAMESPACE: Coreutilities
+
+Resources:
+  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
+      Runtime: java8
+      MemorySize: 512
+      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
+      Events:
+        HelloWorld:
+          Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api
+          Properties:
+            Path: /hello
+            Method: get
+
+  HelloWorldStreamFunction:
+    Type: AWS::Serverless::Function
+    Properties:
+      CodeUri: .
+      Handler: helloworld.AppStream::handleRequest
+      Runtime: java8
+      MemorySize: 512
+      Tracing: Active
+      Environment:
+        Variables:
+          POWERTOOLS_LOGGER_SAMPLE_RATE: 0.7
+      Events:
+        HelloWorld:
+          Type: Api
+          Properties:
+            Path: /hellostream
+            Method: get
+
+Outputs:
+  # ServerlessRestApi is an implicit API created out of Events key under Serverless::Function
+  # Find out more about other implicit resources you can reference within SAM
+  # https://github.com/awslabs/serverless-application-model/blob/master/docs/internals/generated_resources.rst#api
+  HelloWorldApi:
+    Description: "API Gateway endpoint URL for Prod stage for Hello World function"
+    Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/hello/"
+  HelloWorldFunction:
+    Description: "Hello World Lambda Function ARN"
+    Value: !GetAtt HelloWorldFunction.Arn
+  HelloWorldFunctionIamRole:
+    Description: "Implicit IAM Role created for Hello World function"
+    Value: !GetAtt HelloWorldFunctionRole.Arn
diff --git a/examples/powertools-examples-core/gradle/.gradle/7.3.3/checksums/checksums.lock b/examples/powertools-examples-core/gradle/.gradle/7.3.3/checksums/checksums.lock
new file mode 100644
index 0000000000000000000000000000000000000000..ab02aac0d7cc045b38c939b191240bf8d3f2af7b
GIT binary patch
diff --git a/examples/powertools-examples-core/gradle/.gradle/7.3.3/fileChanges/last-build.bin b/examples/powertools-examples-core/gradle/.gradle/7.3.3/fileChanges/last-build.bin
new file mode 100644
index 0000000000000000000000000000000000000000..f76dd238ade08917e6712764a16a22005a50573d
GIT binary patch
diff --git a/examples/powertools-examples-core/gradle/.gradle/7.3.3/fileHashes/fileHashes.lock b/examples/powertools-examples-core/gradle/.gradle/7.3.3/fileHashes/fileHashes.lock
new file mode 100644
index 0000000000000000000000000000000000000000..d082a98bc5aa56290fd95d661efc99fba8107d56
GIT binary patch
diff --git a/examples/powertools-examples-core/gradle/.gradle/7.3.3/gc.properties b/examples/powertools-examples-core/gradle/.gradle/7.3.3/gc.properties
new file mode 100644
index 000000000..e69de29bb
diff --git a/examples/powertools-examples-core/gradle/.gradle/vcs-1/gc.properties b/examples/powertools-examples-core/gradle/.gradle/vcs-1/gc.properties
new file mode 100644
index 000000000..e69de29bb
diff --git a/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParam.java b/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParam.java
index a13c85496..4475cd439 100644
--- a/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParam.java
+++ b/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParam.java
@@ -16,7 +16,5 @@
 
     String application();
 
-    Class<? extends BaseProvider> provider();
-
     Class<? extends Transformer> transformer() default Transformer.class;
 }
diff --git a/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParametersAspect.java b/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParametersAspect.java
index d9596e64f..66a91b4b7 100644
--- a/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParametersAspect.java
+++ b/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParametersAspect.java
@@ -26,12 +26,15 @@
 @Aspect
 public class AppConfigParametersAspect {
 
+
     @Pointcut("get(* *) && @annotation(appConfigParamAnnotation)")
     public void getParam(AppConfigParam appConfigParamAnnotation) {
     }
 
     @Around("getParam(appConfigParamAnnotation)")
     public Object injectParam(final ProceedingJoinPoint joinPoint, final AppConfigParam appConfigParamAnnotation) {
+        System.out.println("GET IT");
+
         AppConfigProvider provider = AppConfigProvider.builder()
                 .withEnvironment(appConfigParamAnnotation.environment())
                 .withApplication(appConfigParamAnnotation.application())
diff --git a/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProvider.java b/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProvider.java
index cf35f27a9..027f828a3 100644
--- a/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProvider.java
+++ b/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProvider.java
@@ -143,7 +143,7 @@ static class Builder {
          */
         public AppConfigProvider build() {
             if (cacheManager == null) {
-                throw new IllegalStateException("No CacheManager provided; please provide one");
+                cacheManager = new CacheManager();
             }
             if (environment == null) {
                 throw new IllegalStateException("No environment provided; please provide one");
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
new file mode 100644
index 000000000..6953c51ff
--- /dev/null
+++ b/powertools-parameters/powertools-parameters-appconfig/src/test/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParamAspectTest.java
@@ -0,0 +1,20 @@
+package software.amazon.lambda.powertools.parameters.appconfig;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+
+import org.junit.jupiter.api.Test;
+
+// TODO - what can we do with this? We need a way to inject a different
+// AppConfigDataClient in
+//public class AppConfigParamAspectTest {
+//
+//    @AppConfigParam(application = "myApp", environment = "myEnvironment", key = "myKey")
+//    public String myParameter;
+//
+//    @Test
+//    public void parameterInjectedByProvider() {
+//        assertThat(myParameter);
+//    }
+//
+//}
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 780e3cb37..992fc64eb 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
@@ -190,18 +190,6 @@ public void getMultipleValuesThrowsException() {
                 .withMessage("Retrieving multiple parameter values is not supported with the AWS App Config Provider");
     }
 
-    @Test
-    public void testAppConfigProviderBuilderMissingCacheManager_throwsException() {
-
-        // Act & Assert
-        Assertions.assertThatIllegalStateException().isThrownBy(() -> AppConfigProvider.builder()
-                        .withEnvironment(environmentName)
-                        .withApplication(applicationName)
-                        .withClient(client)
-                        .build())
-                .withMessage("No CacheManager provided; please provide one");
-    }
-
     @Test
     public void testAppConfigProviderBuilderMissingEnvironment_throwsException() {
 
diff --git a/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbParam.java b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbParam.java
new file mode 100644
index 000000000..6b62838fb
--- /dev/null
+++ b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbParam.java
@@ -0,0 +1,17 @@
+package software.amazon.lambda.powertools.parameters.dynamodb;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import software.amazon.lambda.powertools.parameters.transform.Transformer;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.FIELD)
+public @interface DynamoDbParam {
+    String key();
+
+    String table();
+
+    Class<? extends Transformer> transformer() default Transformer.class;
+}
diff --git a/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbParamAspect.java b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbParamAspect.java
new file mode 100644
index 000000000..0d5d0d7a7
--- /dev/null
+++ b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbParamAspect.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package software.amazon.lambda.powertools.parameters.dynamodb;
+
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Pointcut;
+import org.aspectj.lang.reflect.FieldSignature;
+
+@Aspect
+public class DynamoDbParamAspect {
+
+
+    @Pointcut("get(* *) && @annotation(ddbConfigParam)")
+    public void getParam(DynamoDbParam ddbConfigParam) {
+    }
+
+    @Around("getParam(ddbConfigParam)")
+    public Object injectParam(final ProceedingJoinPoint joinPoint, final DynamoDbParam ddbConfigParam) {
+        System.out.println("GET IT");
+
+        DynamoDbProvider provider = DynamoDbProvider.builder()
+                .withTable(ddbConfigParam.table())
+                .build();
+
+        if (ddbConfigParam.transformer().isInterface()) {
+            // No transformation
+            return provider.get(ddbConfigParam.key());
+        } else {
+            FieldSignature s = (FieldSignature) joinPoint.getSignature();
+            if (String.class.isAssignableFrom(s.getFieldType())) {
+                // Basic transformation
+                return provider
+                        .withTransformation(ddbConfigParam.transformer())
+                        .get(ddbConfigParam.key());
+            } else {
+                // Complex transformation
+                return provider
+                        .withTransformation(ddbConfigParam.transformer())
+                        .get(ddbConfigParam.key(), s.getFieldType());
+            }
+        }
+    }
+
+}
diff --git a/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProvider.java b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProvider.java
index 27daf780e..d937121a7 100644
--- a/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProvider.java
+++ b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProvider.java
@@ -150,7 +150,7 @@ private static DynamoDbClient createClient() {
          */
         public DynamoDbProvider build() {
             if (cacheManager == null) {
-                throw new IllegalStateException("No CacheManager provided; please provide one");
+                cacheManager = new CacheManager();
             }
             if (table == null) {
                 throw new IllegalStateException("No DynamoDB table name provided; please provide one");
diff --git a/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsParam.java b/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsParam.java
new file mode 100644
index 000000000..5ca05f4de
--- /dev/null
+++ b/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsParam.java
@@ -0,0 +1,15 @@
+package software.amazon.lambda.powertools.parameters.secrets;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import software.amazon.lambda.powertools.parameters.transform.Transformer;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.FIELD)
+public @interface SecretsParam {
+    String key();
+
+    Class<? extends Transformer> transformer() default Transformer.class;
+}
diff --git a/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsParamAspect.java b/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsParamAspect.java
new file mode 100644
index 000000000..b38b8b0cd
--- /dev/null
+++ b/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsParamAspect.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package software.amazon.lambda.powertools.parameters.secrets;
+
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Pointcut;
+import org.aspectj.lang.reflect.FieldSignature;
+
+@Aspect
+public class SecretsParamAspect {
+
+
+    @Pointcut("get(* *) && @annotation(secretsParam)")
+    public void getParam(SecretsParam secretsParam) {
+    }
+
+    @Around("getParam(secretsParam)")
+    public Object injectParam(final ProceedingJoinPoint joinPoint, final SecretsParam secretsParam) {
+        System.out.println("GET IT");
+
+        SecretsProvider provider = SecretsProvider.builder()
+                .build();
+
+        if (secretsParam.transformer().isInterface()) {
+            // No transformation
+            return provider.get(secretsParam.key());
+        } else {
+            FieldSignature s = (FieldSignature) joinPoint.getSignature();
+            if (String.class.isAssignableFrom(s.getFieldType())) {
+                // Basic transformation
+                return provider
+                        .withTransformation(secretsParam.transformer())
+                        .get(secretsParam.key());
+            } else {
+                // Complex transformation
+                return provider
+                        .withTransformation(secretsParam.transformer())
+                        .get(secretsParam.key(), s.getFieldType());
+            }
+        }
+    }
+
+}
diff --git a/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMParam.java b/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMParam.java
new file mode 100644
index 000000000..b8ce2e870
--- /dev/null
+++ b/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMParam.java
@@ -0,0 +1,15 @@
+package software.amazon.lambda.powertools.parameters.ssm;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import software.amazon.lambda.powertools.parameters.transform.Transformer;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.FIELD)
+public @interface SSMParam {
+    String key();
+
+    Class<? extends Transformer> transformer() default Transformer.class;
+}
diff --git a/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMParamAspect.java b/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMParamAspect.java
new file mode 100644
index 000000000..320aff33a
--- /dev/null
+++ b/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMParamAspect.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package software.amazon.lambda.powertools.parameters.ssm;
+
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Pointcut;
+import org.aspectj.lang.reflect.FieldSignature;
+
+@Aspect
+public class SSMParamAspect {
+
+
+    @Pointcut("get(* *) && @annotation(secretsParam)")
+    public void getParam(SSMParam secretsParam) {
+    }
+
+    @Around("getParam(SSMParam)")
+    public Object injectParam(final ProceedingJoinPoint joinPoint, final SSMParam SSMParam) {
+        System.out.println("GET IT");
+
+        SSMProvider provider = SSMProvider.builder()
+                .build();
+
+        if (SSMParam.transformer().isInterface()) {
+            // No transformation
+            return provider.get(SSMParam.key());
+        } else {
+            FieldSignature s = (FieldSignature) joinPoint.getSignature();
+            if (String.class.isAssignableFrom(s.getFieldType())) {
+                // Basic transformation
+                return provider
+                        .withTransformation(SSMParam.transformer())
+                        .get(SSMParam.key());
+            } else {
+                // Complex transformation
+                return provider
+                        .withTransformation(SSMParam.transformer())
+                        .get(SSMParam.key(), s.getFieldType());
+            }
+        }
+    }
+
+}
diff --git a/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerTest.java b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerTest.java
index db64c31fd..5c213a328 100644
--- a/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerTest.java
+++ b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerTest.java
@@ -48,46 +48,46 @@ public void testGetTransformationManager() {
         assertNotNull(transformationManager);
     }
 
-    @Test
-    public void testCreateProvider() {
-
-        // Act
-        CustomProvider customProvider = ParamManager.createProvider(CustomProvider.class);
-
-        // Assert
-        assertNotNull(customProvider);
-    }
-
-    @Test
-    public void testCreateUninstanciableProvider_throwsException() {
-
-        // Act & Assert
-        assertThatRuntimeException().isThrownBy(() -> ParamManager.createProvider(BaseProvider.class));
-    }
-
-    @Test
-    public void testGetProviderWithProviderClass() {
-
+//    @Test
+//    public void testCreateProvider() {
+//
         // Act
-        SecretsProvider secretsProvider = ParamManager.getProvider(SecretsProvider.class);
-
-        // Assert
-        assertNotNull(secretsProvider);
-    }
-
-    @Test
-    public void testGetProviderWithProviderClass_throwsException() {
-
-        // Act & Assert
-        assertThatIllegalStateException().isThrownBy(() -> ParamManager.getProvider(null));
-    }
-
-
-    @Test
-    public void testGetDynamoDBProvider_requireOtherParameters_throwException() {
-
-        // Act & Assert
-        assertThatIllegalArgumentException().isThrownBy(() -> ParamManager.getProvider(DynamoDbProvider.class));
-    }
+//        CustomProvider customProvider = ParamManager.createProvider(CustomProvider.class);
+//
+//        // Assert
+//        assertNotNull(customProvider);
+//    }
+//
+//    @Test
+//    public void testCreateUninstanciableProvider_throwsException() {
+//
+//        // Act & Assert
+//        assertThatRuntimeException().isThrownBy(() -> ParamManager.createProvider(BaseProvider.class));
+//    }
+//
+//    @Test
+//    public void testGetProviderWithProviderClass() {
+//
+//        // Act
+//        SecretsProvider secretsProvider = ParamManager.getProvider(SecretsProvider.class);
+//
+//        // Assert
+//        assertNotNull(secretsProvider);
+//    }
+//
+//    @Test
+//    public void testGetProviderWithProviderClass_throwsException() {
+//
+//        // Act & Assert
+//        assertThatIllegalStateException().isThrownBy(() -> ParamManager.getProvider(null));
+//    }
+//
+//
+//    @Test
+//    public void testGetDynamoDBProvider_requireOtherParameters_throwException() {
+//
+//        // Act & Assert
+//        assertThatIllegalArgumentException().isThrownBy(() -> ParamManager.getProvider(DynamoDbProvider.class));
+//    }
 
 }
diff --git a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/LambdaParametersAspect.java b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/LambdaParametersAspect.java
index 4fad5ff8f..348f9ab82 100644
--- a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/LambdaParametersAspect.java
+++ b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/LambdaParametersAspect.java
@@ -30,27 +30,29 @@ public class LambdaParametersAspect {
     public void getParam(Param paramAnnotation) {
     }
 
-    @Around("getParam(paramAnnotation)")
-    public Object injectParam(final ProceedingJoinPoint joinPoint, final Param paramAnnotation) {
-        BaseProvider provider = ParamManager.getProvider(paramAnnotation.provider());
+    // TODO - get rid of this
 
-        if (paramAnnotation.transformer().isInterface()) {
-            // No transformation
-            return provider.get(paramAnnotation.key());
-        } else {
-            FieldSignature s = (FieldSignature) joinPoint.getSignature();
-            if (String.class.isAssignableFrom(s.getFieldType())) {
-                // Basic transformation
-                return provider
-                        .withTransformation(paramAnnotation.transformer())
-                        .get(paramAnnotation.key());
-            } else {
-                // Complex transformation
-                return provider
-                        .withTransformation(paramAnnotation.transformer())
-                        .get(paramAnnotation.key(), s.getFieldType());
-            }
-        }
-    }
+//    @Around("getParam(paramAnnotation)")
+//    public Object injectParam(final ProceedingJoinPoint joinPoint, final Param paramAnnotation) {
+//        BaseProvider provider = ParamManager.getProvider(paramAnnotation.provider());
+//
+//        if (paramAnnotation.transformer().isInterface()) {
+//            // No transformation
+//            return provider.get(paramAnnotation.key());
+//        } else {
+//            FieldSignature s = (FieldSignature) joinPoint.getSignature();
+//            if (String.class.isAssignableFrom(s.getFieldType())) {
+//                // Basic transformation
+//                return provider
+//                        .withTransformation(paramAnnotation.transformer())
+//                        .get(paramAnnotation.key());
+//            } else {
+//                // Complex transformation
+//                return provider
+//                        .withTransformation(paramAnnotation.transformer())
+//                        .get(paramAnnotation.key(), s.getFieldType());
+//            }
+//        }
+//    }
 
 }

From 357f85968a670c69ca582238513629bf0530bff2 Mon Sep 17 00:00:00 2001
From: Scott Gerring <gerrings@amazon.com>
Date: Fri, 8 Sep 2023 13:23:08 +0200
Subject: [PATCH 07/45] More rejigging

---
 .../appconfig/AppConfigParametersAspect.java  |  3 -
 .../parameters/dynamodb/DynamoDbProvider.java |  2 +-
 .../DynamoDbProviderSchemaException.java      |  2 +-
 .../dynamodb/DynamoDbProviderTest.java        |  2 +-
 .../LambdaParametersAspectTest.java           | 97 -------------------
 .../parameters/LambdaParametersAspect.java    | 58 -----------
 .../lambda/powertools/parameters/Param.java   | 45 ---------
 7 files changed, 3 insertions(+), 206 deletions(-)
 rename powertools-parameters/{src/main/java/software/amazon/lambda/powertools/parameters => powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb}/exception/DynamoDbProviderSchemaException.java (92%)
 delete mode 100644 powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/LambdaParametersAspectTest.java
 delete mode 100644 powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/LambdaParametersAspect.java
 delete mode 100644 powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/Param.java

diff --git a/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParametersAspect.java b/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParametersAspect.java
index 66a91b4b7..636242715 100644
--- a/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParametersAspect.java
+++ b/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParametersAspect.java
@@ -19,9 +19,6 @@
 import org.aspectj.lang.annotation.Aspect;
 import org.aspectj.lang.annotation.Pointcut;
 import org.aspectj.lang.reflect.FieldSignature;
-import software.amazon.lambda.powertools.parameters.BaseProvider;
-import software.amazon.lambda.powertools.parameters.Param;
-import software.amazon.lambda.powertools.parameters.ParamManager;
 
 @Aspect
 public class AppConfigParametersAspect {
diff --git a/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProvider.java b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProvider.java
index d937121a7..b665b1e35 100644
--- a/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProvider.java
+++ b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProvider.java
@@ -32,7 +32,7 @@
 import software.amazon.lambda.powertools.parameters.BaseProvider;
 import software.amazon.lambda.powertools.parameters.ParamProvider;
 import software.amazon.lambda.powertools.parameters.cache.CacheManager;
-import software.amazon.lambda.powertools.parameters.exception.DynamoDbProviderSchemaException;
+import software.amazon.lambda.powertools.parameters.dynamodb.exception.DynamoDbProviderSchemaException;
 import software.amazon.lambda.powertools.parameters.transform.TransformationManager;
 
 /**
diff --git a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/exception/DynamoDbProviderSchemaException.java b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/exception/DynamoDbProviderSchemaException.java
similarity index 92%
rename from powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/exception/DynamoDbProviderSchemaException.java
rename to powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/exception/DynamoDbProviderSchemaException.java
index 77df6e3d3..4a22dbc99 100644
--- a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/exception/DynamoDbProviderSchemaException.java
+++ b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/exception/DynamoDbProviderSchemaException.java
@@ -12,7 +12,7 @@
  *
  */
 
-package software.amazon.lambda.powertools.parameters.exception;
+package software.amazon.lambda.powertools.parameters.dynamodb.exception;
 
 /**
  * Thrown when the DynamoDbProvider comes across parameter data that
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 7e5b5f631..47d04907a 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
@@ -35,7 +35,7 @@
 import software.amazon.awssdk.services.dynamodb.model.QueryRequest;
 import software.amazon.awssdk.services.dynamodb.model.QueryResponse;
 import software.amazon.lambda.powertools.parameters.cache.CacheManager;
-import software.amazon.lambda.powertools.parameters.exception.DynamoDbProviderSchemaException;
+import software.amazon.lambda.powertools.parameters.dynamodb.exception.DynamoDbProviderSchemaException;
 import software.amazon.lambda.powertools.parameters.transform.TransformationManager;
 
 public class DynamoDbProviderTest {
diff --git a/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/LambdaParametersAspectTest.java b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/LambdaParametersAspectTest.java
deleted file mode 100644
index 0fb945554..000000000
--- a/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/LambdaParametersAspectTest.java
+++ /dev/null
@@ -1,97 +0,0 @@
-package software.amazon.lambda.powertools.parameters;/*
- * Copyright 2023 Amazon.com, Inc. or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *     http://www.apache.org/licenses/LICENSE-2.0
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-import org.assertj.core.api.Assertions;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import software.amazon.lambda.powertools.parameters.exception.TransformationException;
-import software.amazon.lambda.powertools.parameters.internal.AnotherObject;
-import software.amazon.lambda.powertools.parameters.internal.CustomProvider;
-import software.amazon.lambda.powertools.parameters.ssm.SSMProvider;
-import software.amazon.lambda.powertools.parameters.transform.Base64Transformer;
-import software.amazon.lambda.powertools.parameters.transform.JsonTransformer;
-import software.amazon.lambda.powertools.parameters.transform.ObjectToDeserialize;
-
-public class LambdaParametersAspectTest {
-
-    @Mock
-    private SSMProvider defaultProvider;
-
-//    @Param(key = "/default", provider = SSMProvider.class)
-//    private String defaultValue;
-
-    @Param(key = "/simple", provider = CustomProvider.class)
-    private String param;
-
-    @Param(key = "/base64", provider = CustomProvider.class, transformer = Base64Transformer.class)
-    private String basicTransform;
-
-    @Param(key = "/json", provider = CustomProvider.class, transformer = JsonTransformer.class)
-    private ObjectToDeserialize complexTransform;
-
-    @Param(key = "/json", provider = CustomProvider.class, transformer = JsonTransformer.class)
-    private AnotherObject wrongTransform;
-
-    @BeforeEach
-    public void init() {
-        MockitoAnnotations.openMocks(this);
-    }
-
-    // @Test
-    // TODO - no more defaults!
-//    public void testDefault_ShouldUseSSMProvider() {
-//        try (MockedStatic<ParamManager> mocked = Mockito.mockStatic(ParamManager.class)) {
-//            mocked.when(() -> ParamManager.getProvider(SSMProvider.class)).thenReturn(defaultProvider);
-//            Mockito.when(defaultProvider.get("/default")).thenReturn("value");
-//
-//            Assertions.assertThat(defaultValue).isEqualTo("value");
-//            mocked.verify(() -> ParamManager.getProvider(SSMProvider.class), Mockito.times(1));
-//            Mockito.verify(defaultProvider, Mockito.times(1)).get("/default");
-//
-//            mocked.reset();
-//        }
-//    }
-
-    @Test
-    public void testSimple() {
-        Assertions.assertThat(param).isEqualTo("value");
-    }
-
-    @Test
-    public void testWithBasicTransform() {
-        Assertions.assertThat(basicTransform).isEqualTo("value");
-    }
-
-    @Test
-    public void testWithComplexTransform() {
-        Assertions.assertThat(complexTransform)
-                .isInstanceOf(ObjectToDeserialize.class)
-                .matches(
-                        o -> o.getFoo().equals("Foo") &&
-                                o.getBar() == 42 &&
-                                o.getBaz() == 123456789);
-    }
-
-    @Test
-    public void testWithComplexTransformWrongTargetClass_ShouldThrowException() {
-        Assertions.assertThatExceptionOfType(TransformationException.class)
-                .isThrownBy(() ->
-                {
-                    AnotherObject obj = wrongTransform;
-                });
-    }
-
-}
diff --git a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/LambdaParametersAspect.java b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/LambdaParametersAspect.java
deleted file mode 100644
index 348f9ab82..000000000
--- a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/LambdaParametersAspect.java
+++ /dev/null
@@ -1,58 +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.parameters;
-
-import org.aspectj.lang.ProceedingJoinPoint;
-import org.aspectj.lang.annotation.Around;
-import org.aspectj.lang.annotation.Aspect;
-import org.aspectj.lang.annotation.Pointcut;
-import org.aspectj.lang.reflect.FieldSignature;
-import software.amazon.lambda.powertools.parameters.BaseProvider;
-import software.amazon.lambda.powertools.parameters.Param;
-import software.amazon.lambda.powertools.parameters.ParamManager;
-
-@Aspect
-public class LambdaParametersAspect {
-
-    @Pointcut("get(* *) && @annotation(paramAnnotation)")
-    public void getParam(Param paramAnnotation) {
-    }
-
-    // TODO - get rid of this
-
-//    @Around("getParam(paramAnnotation)")
-//    public Object injectParam(final ProceedingJoinPoint joinPoint, final Param paramAnnotation) {
-//        BaseProvider provider = ParamManager.getProvider(paramAnnotation.provider());
-//
-//        if (paramAnnotation.transformer().isInterface()) {
-//            // No transformation
-//            return provider.get(paramAnnotation.key());
-//        } else {
-//            FieldSignature s = (FieldSignature) joinPoint.getSignature();
-//            if (String.class.isAssignableFrom(s.getFieldType())) {
-//                // Basic transformation
-//                return provider
-//                        .withTransformation(paramAnnotation.transformer())
-//                        .get(paramAnnotation.key());
-//            } else {
-//                // Complex transformation
-//                return provider
-//                        .withTransformation(paramAnnotation.transformer())
-//                        .get(paramAnnotation.key(), s.getFieldType());
-//            }
-//        }
-//    }
-
-}
diff --git a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/Param.java b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/Param.java
deleted file mode 100644
index d456cbd99..000000000
--- a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/Param.java
+++ /dev/null
@@ -1,45 +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.parameters;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-import software.amazon.lambda.powertools.parameters.transform.Transformer;
-
-/**
- * {@code Param} is used to signal that the annotated field should be
- * populated with a value retrieved from a parameter store through a {@link ParamProvider}.
- *
- * <p>By default {@code Param} use {@link SSMProvider} as parameter provider. This can be overridden specifying
- * the annotation variable {@code Param(provider = <Class-of-the-provider>)}.<br/>
- * The library provide a provider for AWS System Manager Parameters Store ({@link SSMProvider}) and a provider
- * for AWS Secrets Manager ({@link SecretsProvider}).
- * The user can implement a custom provider by extending the abstract class {@link BaseProvider}.</p>
- *
- * <p>If the parameter value requires transformation before being assigned to the annotated field
- * users can specify a {@link Transformer}
- * </p>
- */
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.FIELD)
-public @interface Param {
-    String key();
-
-    Class<? extends BaseProvider> provider();
-
-    Class<? extends Transformer> transformer() default Transformer.class;
-}

From e93b1d0a4d51774fdff292d066cf2a1cf154e0bf Mon Sep 17 00:00:00 2001
From: Scott Gerring <gerrings@amazon.com>
Date: Fri, 8 Sep 2023 14:17:05 +0200
Subject: [PATCH 08/45] Fix build?

---
 .../org/demo/parameters/ParametersFunction.java | 10 ++++++++++
 .../parameters/appconfig/AppConfigParam.java    | 15 ++++++++++++++-
 .../appconfig/AppConfigParamAspectTest.java     |  5 -----
 .../parameters/dynamodb/DynamoDbParam.java      | 14 ++++++++++++++
 .../dynamodb/DynamoDbProviderTest.java          |  9 ---------
 .../parameters/secrets/SecretsParam.java        | 14 ++++++++++++++
 .../powertools/parameters/ssm/SSMParam.java     | 14 ++++++++++++++
 .../powertools/parameters/ssm/SSMProvider.java  |  1 -
 .../parameters/ssm/SSMProviderTest.java         | 17 -----------------
 .../parameters/ParamManagerIntegrationTest.java |  2 +-
 10 files changed, 67 insertions(+), 34 deletions(-)

diff --git a/examples/powertools-examples-parameters/src/main/java/org/demo/parameters/ParametersFunction.java b/examples/powertools-examples-parameters/src/main/java/org/demo/parameters/ParametersFunction.java
index 6eb52a165..7cf4f90e4 100644
--- a/examples/powertools-examples-parameters/src/main/java/org/demo/parameters/ParametersFunction.java
+++ b/examples/powertools-examples-parameters/src/main/java/org/demo/parameters/ParametersFunction.java
@@ -32,12 +32,22 @@
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 import software.amazon.lambda.powertools.parameters.ParamManager;
+import software.amazon.lambda.powertools.parameters.secrets.SecretsParam;
 import software.amazon.lambda.powertools.parameters.secrets.SecretsProvider;
+import software.amazon.lambda.powertools.parameters.ssm.SSMParam;
 import software.amazon.lambda.powertools.parameters.ssm.SSMProvider;
 
 public class ParametersFunction implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {
     private final static Logger log = LogManager.getLogger(ParametersFunction.class);
 
+    // Annotation-style injection from secrets manager
+    @SecretsParam(key = "/powertools-java/userpwd")
+    String secretParamInjected;
+
+    // Annotation-style injection from Systems Manager
+    @SSMParam(key = "/powertools-java/sample/simplekey")
+    String ssmParamInjected;
+
     SSMProvider ssmProvider = SSMProvider
             .builder()
             .build();
diff --git a/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParam.java b/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParam.java
index 4475cd439..d4b024b6a 100644
--- a/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParam.java
+++ b/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParam.java
@@ -1,10 +1,23 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
 package software.amazon.lambda.powertools.parameters.appconfig;
 
 import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;
-import software.amazon.lambda.powertools.parameters.BaseProvider;
 import software.amazon.lambda.powertools.parameters.transform.Transformer;
 
 @Retention(RetentionPolicy.RUNTIME)
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 6953c51ff..2337c4c9d 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
@@ -1,10 +1,5 @@
 package software.amazon.lambda.powertools.parameters.appconfig;
 
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-
-import org.junit.jupiter.api.Test;
-
 // TODO - what can we do with this? We need a way to inject a different
 // AppConfigDataClient in
 //public class AppConfigParamAspectTest {
diff --git a/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbParam.java b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbParam.java
index 6b62838fb..45c3b83aa 100644
--- a/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbParam.java
+++ b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbParam.java
@@ -1,3 +1,17 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
 package software.amazon.lambda.powertools.parameters.dynamodb;
 
 import java.lang.annotation.ElementType;
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 47d04907a..0d0fbd2d9 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
@@ -217,15 +217,6 @@ public void getValuesWithMalformedRowThrows() {
         });
     }
 
-    @Test
-    public void testDynamoDBBuilderMissingCacheManager_throwsException() {
-
-        // Act & Assert
-        assertThatIllegalStateException().isThrownBy(() -> DynamoDbProvider.builder()
-                .withTable("table")
-                .build());
-    }
-
     @Test
     public void testDynamoDBBuilderMissingTable_throwsException() {
 
diff --git a/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsParam.java b/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsParam.java
index 5ca05f4de..a9e7f5646 100644
--- a/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsParam.java
+++ b/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsParam.java
@@ -1,3 +1,17 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
 package software.amazon.lambda.powertools.parameters.secrets;
 
 import java.lang.annotation.ElementType;
diff --git a/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMParam.java b/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMParam.java
index b8ce2e870..ced673829 100644
--- a/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMParam.java
+++ b/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMParam.java
@@ -1,3 +1,17 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
 package software.amazon.lambda.powertools.parameters.ssm;
 
 import java.lang.annotation.ElementType;
diff --git a/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMProvider.java b/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMProvider.java
index 7f308228d..a21821009 100644
--- a/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMProvider.java
+++ b/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMProvider.java
@@ -29,7 +29,6 @@
 import software.amazon.awssdk.utils.StringUtils;
 import software.amazon.lambda.powertools.common.internal.UserAgentConfigurator;
 import software.amazon.lambda.powertools.parameters.BaseProvider;
-import software.amazon.lambda.powertools.parameters.ParamManager;
 import software.amazon.lambda.powertools.parameters.cache.CacheManager;
 import software.amazon.lambda.powertools.parameters.transform.TransformationManager;
 import software.amazon.lambda.powertools.parameters.transform.Transformer;
diff --git a/powertools-parameters/powertools-parameters-ssm/src/test/java/software/amazon/lambda/powertools/parameters/ssm/SSMProviderTest.java b/powertools-parameters/powertools-parameters-ssm/src/test/java/software/amazon/lambda/powertools/parameters/ssm/SSMProviderTest.java
index a85f71727..bdbc97f7c 100644
--- a/powertools-parameters/powertools-parameters-ssm/src/test/java/software/amazon/lambda/powertools/parameters/ssm/SSMProviderTest.java
+++ b/powertools-parameters/powertools-parameters-ssm/src/test/java/software/amazon/lambda/powertools/parameters/ssm/SSMProviderTest.java
@@ -16,12 +16,6 @@
 
 import static java.util.Arrays.asList;
 import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-import static org.mockito.MockitoAnnotations.openMocks;
 
 import java.time.temporal.ChronoUnit;
 import java.util.ArrayList;
@@ -200,17 +194,6 @@ public void getMultipleWithNextToken() {
         Assertions.assertThat(request2.nextToken()).isEqualTo("123abc");
     }
 
-    @Test
-    public void testSecretsProviderBuilderMissingCacheManager_throwsException() {
-
-        // Act & Assert
-        Assertions.assertThatIllegalStateException().isThrownBy(() -> SSMProvider.builder()
-                        .withClient(client)
-                        .withTransformationManager(transformationManager)
-                        .build())
-                .withMessage("No CacheManager provided, please provide one");
-    }
-
     private void initMock(String expectedValue) {
         Parameter parameter = Parameter.builder().value(expectedValue).build();
         GetParameterResponse result = GetParameterResponse.builder().parameter(parameter).build();
diff --git a/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerIntegrationTest.java b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerIntegrationTest.java
index e06dd7e13..dce1bf664 100644
--- a/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerIntegrationTest.java
+++ b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerIntegrationTest.java
@@ -65,7 +65,7 @@ public class ParamManagerIntegrationTest {
     public void setup() throws IllegalAccessException {
         openMocks(this);
 
-        writeStaticField(ParamManager.class, "providers", new ConcurrentHashMap<>(), true);
+        //writeStaticField(ParamManager.class, "providers", new ConcurrentHashMap<>(), true);
     }
 
     @Test

From 69619e8b9dc99a4929204f4494f1d50ce699a1b5 Mon Sep 17 00:00:00 2001
From: Scott Gerring <gerrings@amazon.com>
Date: Fri, 8 Sep 2023 15:12:39 +0200
Subject: [PATCH 09/45] spotbugs exclude path change

---
 pom.xml                                                         | 2 +-
 .../amazon/lambda/powertools/parameters/dynamodb/Builder.java   | 2 ++
 2 files changed, 3 insertions(+), 1 deletion(-)
 create mode 100644 powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/Builder.java

diff --git a/pom.xml b/pom.xml
index 47cc228db..f52c3f409 100644
--- a/pom.xml
+++ b/pom.xml
@@ -511,7 +511,7 @@
                         </executions>
                         <configuration>
                             <xmlOutput>true</xmlOutput>
-                            <excludeFilterFile>../spotbugs-exclude.xml</excludeFilterFile>
+                            <excludeFilterFile>${project.basedir}/spotbugs-exclude.xml</excludeFilterFile>
                         </configuration>
                     </plugin>
                 </plugins>
diff --git a/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/Builder.java b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/Builder.java
new file mode 100644
index 000000000..ad7dbf6db
--- /dev/null
+++ b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/Builder.java
@@ -0,0 +1,2 @@
+package software.amazon.lambda.powertools.parameters.dynamodb;public class Builder {
+}

From 9bfff82635a836e60ba9ea83fd9a94684b0760af Mon Sep 17 00:00:00 2001
From: Scott Gerring <gerrings@amazon.com>
Date: Fri, 8 Sep 2023 15:18:42 +0200
Subject: [PATCH 10/45] More excludes

---
 powertools-parameters/spotbugs-exclude.xml | 37 ++++++++++++++++++++++
 spotbugs-exclude.xml                       | 16 ----------
 2 files changed, 37 insertions(+), 16 deletions(-)
 create mode 100644 powertools-parameters/spotbugs-exclude.xml

diff --git a/powertools-parameters/spotbugs-exclude.xml b/powertools-parameters/spotbugs-exclude.xml
new file mode 100644
index 000000000..98536870b
--- /dev/null
+++ b/powertools-parameters/spotbugs-exclude.xml
@@ -0,0 +1,37 @@
+<!-- This file specifies a spotbugs filter for excluding reports that
+     should not be considered errors.
+     The format of this file is documented at:
+       https://spotbugs.readthedocs.io/en/latest/filter.html
+     When possible, please specify the full names of the bug codes,
+     using the pattern attribute, to make it clearer what reports are
+     being suppressed.  You can find a listing of codes at:
+       https://spotbugs.readthedocs.io/en/latest/bugDescriptions.html
+  -->
+<FindBugsFilter>
+    <Match>
+        <Bug pattern="EI_EXPOSE_REP2"/>
+        <Or>
+            <And>
+                <Class name="software.amazon.lambda.powertools.parameters.BaseProvider"/>
+                <Field name="cacheManager"/>
+            </And>
+            <And>
+                <Class name="software.amazon.lambda.powertools.parameters.transform.TransformationManager"/>
+                <Field name="transformer"/>
+            </And>
+        </Or>
+    </Match>
+    <Match>
+        <Bug pattern="MS_EXPOSE_REP"/>
+        <Or>
+            <And>
+                <Class name="software.amazon.lambda.powertools.parameters.ParamManager"/>
+                <Method name="getCacheManager"/>
+            </And>
+            <And>
+                <Class name="software.amazon.lambda.powertools.parameters.ParamManager"/>
+                <Method name="getTransformationManager"/>
+            </And>
+        </Or>
+    </Match>
+</FindBugsFilter>
\ No newline at end of file
diff --git a/spotbugs-exclude.xml b/spotbugs-exclude.xml
index eca7e266f..fd1ef6f44 100644
--- a/spotbugs-exclude.xml
+++ b/spotbugs-exclude.xml
@@ -65,14 +65,6 @@
                 <Class name="software.amazon.lambda.powertools.sqs.internal.BatchContext"/>
                 <Field name="client"/>
             </And>
-            <And>
-                <Class name="software.amazon.lambda.powertools.parameters.BaseProvider"/>
-                <Field name="cacheManager"/>
-            </And>
-            <And>
-                <Class name="software.amazon.lambda.powertools.parameters.transform.TransformationManager"/>
-                <Field name="transformer"/>
-            </And>
             <And>
                 <Class name="software.amazon.lambda.powertools.idempotency.Idempotency$Config"/>
                 <Field name="store"/>
@@ -140,18 +132,10 @@
                 <Class name="software.amazon.lambda.powertools.sqs.SqsUtils"/>
                 <Method name="objectMapper"/>
             </And>
-            <And>
-                <Class name="software.amazon.lambda.powertools.parameters.ParamManager"/>
-                <Method name="getCacheManager"/>
-            </And>
             <And>
                 <Class name="software.amazon.lambda.powertools.sqs.SqsUtils"/>
                 <Method name="s3Client"/>
             </And>
-            <And>
-                <Class name="software.amazon.lambda.powertools.parameters.ParamManager"/>
-                <Method name="getTransformationManager"/>
-            </And>
         </Or>
     </Match>
     <!--False positive https://github.com/spotbugs/spotbugs/issues/1539-->

From f1106d4639433fe4e0e3c26be2f4fc741241493c Mon Sep 17 00:00:00 2001
From: Scott Gerring <gerrings@amazon.com>
Date: Fri, 8 Sep 2023 15:21:39 +0200
Subject: [PATCH 11/45] Fix pom

---
 pom.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/pom.xml b/pom.xml
index f52c3f409..47cc228db 100644
--- a/pom.xml
+++ b/pom.xml
@@ -511,7 +511,7 @@
                         </executions>
                         <configuration>
                             <xmlOutput>true</xmlOutput>
-                            <excludeFilterFile>${project.basedir}/spotbugs-exclude.xml</excludeFilterFile>
+                            <excludeFilterFile>../spotbugs-exclude.xml</excludeFilterFile>
                         </configuration>
                     </plugin>
                 </plugins>

From 5ce1d868173bc6b82bc18f0cf66cf354a6ed9187 Mon Sep 17 00:00:00 2001
From: Scott Gerring <gerrings@amazon.com>
Date: Mon, 11 Sep 2023 16:39:20 +0200
Subject: [PATCH 12/45] Trying to write an aspect test

---
 .../.gradle/7.3.3/checksums/checksums.lock    | Bin 0 -> 17 bytes
 .../.gradle/7.3.3/fileChanges/last-build.bin  | Bin 0 -> 1 bytes
 .../.gradle/7.3.3/fileHashes/fileHashes.lock  | Bin 0 -> 17 bytes
 .../gradle/.gradle/7.3.3/gc.properties        |   0
 .../gradle/.gradle/vcs-1/gc.properties        |   0
 .../demo/parameters/ParametersFunction.java   |   1 -
 .../internal/LargeMessageProcessor.java       |   1 +
 .../appconfig/AppConfigParametersAspect.java  |  13 +-
 .../appconfig/AppConfigProvider.java          | 115 +-----------------
 .../appconfig/AppConfigProviderBuilder.java   | 106 ++++++++++++++++
 .../appconfig/AppConfigParamAspectTest.java   |  52 ++++++--
 .../parameters/dynamodb/Builder.java          |   2 -
 .../parameters/dynamodb/DynamoDbProvider.java | 105 +---------------
 .../dynamodb/DynamoDbProviderBuilder.java     |  95 +++++++++++++++
 .../dynamodb/DynamoDbProviderE2ETest.java     |   2 +-
 .../dynamodb/DynamoDbProviderTest.java        |   2 +-
 .../parameters/secrets/SecretsProvider.java   | 102 +---------------
 .../secrets/SecretsProviderBuilder.java       |  83 +++++++++++++
 .../secrets/SecretsProviderTest.java          |   2 +-
 .../parameters/ssm/SSMProvider.java           |  91 ++------------
 .../parameters/ssm/SSMProviderBuilder.java    |  82 +++++++++++++
 .../parameters/ssm/SSMProviderTest.java       |   2 +-
 .../parameters/BaseProviderTest.java          |   5 +-
 .../parameters/ParamManagerTest.java          |  93 --------------
 .../parameters/internal/CustomProvider.java   |   2 +-
 .../powertools/parameters/BaseProvider.java   |   9 +-
 .../powertools/parameters/ParamManager.java   |  38 ------
 27 files changed, 448 insertions(+), 555 deletions(-)
 create mode 100644 examples/powertools-examples-core-utilities/gradle/.gradle/7.3.3/checksums/checksums.lock
 create mode 100644 examples/powertools-examples-core-utilities/gradle/.gradle/7.3.3/fileChanges/last-build.bin
 create mode 100644 examples/powertools-examples-core-utilities/gradle/.gradle/7.3.3/fileHashes/fileHashes.lock
 create mode 100644 examples/powertools-examples-core-utilities/gradle/.gradle/7.3.3/gc.properties
 create mode 100644 examples/powertools-examples-core-utilities/gradle/.gradle/vcs-1/gc.properties
 create mode 100644 powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProviderBuilder.java
 delete mode 100644 powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/Builder.java
 create mode 100644 powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderBuilder.java
 create mode 100644 powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProviderBuilder.java
 create mode 100644 powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMProviderBuilder.java
 delete mode 100644 powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerTest.java
 delete mode 100644 powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/ParamManager.java

diff --git a/examples/powertools-examples-core-utilities/gradle/.gradle/7.3.3/checksums/checksums.lock b/examples/powertools-examples-core-utilities/gradle/.gradle/7.3.3/checksums/checksums.lock
new file mode 100644
index 0000000000000000000000000000000000000000..137f02edd07205014ea750fc7f5af43c8b21b0d3
GIT binary patch
diff --git a/examples/powertools-examples-core-utilities/gradle/.gradle/7.3.3/fileChanges/last-build.bin b/examples/powertools-examples-core-utilities/gradle/.gradle/7.3.3/fileChanges/last-build.bin
new file mode 100644
index 0000000000000000000000000000000000000000..f76dd238ade08917e6712764a16a22005a50573d
GIT binary patch
diff --git a/examples/powertools-examples-core-utilities/gradle/.gradle/7.3.3/fileHashes/fileHashes.lock b/examples/powertools-examples-core-utilities/gradle/.gradle/7.3.3/fileHashes/fileHashes.lock
new file mode 100644
index 0000000000000000000000000000000000000000..d2358784bf82bce372f41c1be1b805984af62bf7
GIT binary patch
diff --git a/examples/powertools-examples-core-utilities/gradle/.gradle/7.3.3/gc.properties b/examples/powertools-examples-core-utilities/gradle/.gradle/7.3.3/gc.properties
new file mode 100644
index 000000000..e69de29bb
diff --git a/examples/powertools-examples-core-utilities/gradle/.gradle/vcs-1/gc.properties b/examples/powertools-examples-core-utilities/gradle/.gradle/vcs-1/gc.properties
new file mode 100644
index 000000000..e69de29bb
diff --git a/examples/powertools-examples-parameters/src/main/java/org/demo/parameters/ParametersFunction.java b/examples/powertools-examples-parameters/src/main/java/org/demo/parameters/ParametersFunction.java
index 7cf4f90e4..57f953d43 100644
--- a/examples/powertools-examples-parameters/src/main/java/org/demo/parameters/ParametersFunction.java
+++ b/examples/powertools-examples-parameters/src/main/java/org/demo/parameters/ParametersFunction.java
@@ -31,7 +31,6 @@
 import java.util.stream.Collectors;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
-import software.amazon.lambda.powertools.parameters.ParamManager;
 import software.amazon.lambda.powertools.parameters.secrets.SecretsParam;
 import software.amazon.lambda.powertools.parameters.secrets.SecretsProvider;
 import software.amazon.lambda.powertools.parameters.ssm.SSMParam;
diff --git a/powertools-large-messages/src/main/java/software/amazon/lambda/powertools/largemessages/internal/LargeMessageProcessor.java b/powertools-large-messages/src/main/java/software/amazon/lambda/powertools/largemessages/internal/LargeMessageProcessor.java
index 5478931f1..29508bc2f 100644
--- a/powertools-large-messages/src/main/java/software/amazon/lambda/powertools/largemessages/internal/LargeMessageProcessor.java
+++ b/powertools-large-messages/src/main/java/software/amazon/lambda/powertools/largemessages/internal/LargeMessageProcessor.java
@@ -65,6 +65,7 @@ public Object process(ProceedingJoinPoint pjp, boolean deleteS3Object) throws Th
 
         String s3ObjectContent = getS3ObjectContent(payloadPointer);
 
+
         if (LOG.isDebugEnabled()) {
             LOG.debug("Large message [{}] retrieved in S3 [{}]: {}KB", getMessageId(message), payloadPointer,
                     s3ObjectContent.getBytes(StandardCharsets.UTF_8).length / 1024);
diff --git a/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParametersAspect.java b/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParametersAspect.java
index 636242715..dec439302 100644
--- a/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParametersAspect.java
+++ b/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParametersAspect.java
@@ -14,6 +14,7 @@
 
 package software.amazon.lambda.powertools.parameters.appconfig;
 
+import java.util.function.BiFunction;
 import org.aspectj.lang.ProceedingJoinPoint;
 import org.aspectj.lang.annotation.Around;
 import org.aspectj.lang.annotation.Aspect;
@@ -23,6 +24,12 @@
 @Aspect
 public class AppConfigParametersAspect {
 
+    private static BiFunction<String, String, AppConfigProvider> providerBuilder =
+        (String env, String app) -> AppConfigProvider.builder()
+                .withEnvironment(env)
+                .withApplication(app)
+                .build();
+
 
     @Pointcut("get(* *) && @annotation(appConfigParamAnnotation)")
     public void getParam(AppConfigParam appConfigParamAnnotation) {
@@ -32,10 +39,8 @@ public void getParam(AppConfigParam appConfigParamAnnotation) {
     public Object injectParam(final ProceedingJoinPoint joinPoint, final AppConfigParam appConfigParamAnnotation) {
         System.out.println("GET IT");
 
-        AppConfigProvider provider = AppConfigProvider.builder()
-                .withEnvironment(appConfigParamAnnotation.environment())
-                .withApplication(appConfigParamAnnotation.application())
-                .build();
+        AppConfigProvider provider = providerBuilder.apply
+                (appConfigParamAnnotation.environment(), appConfigParamAnnotation.application());
 
         if (appConfigParamAnnotation.transformer().isInterface()) {
             // No transformation
diff --git a/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProvider.java b/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProvider.java
index 027f828a3..596a2b917 100644
--- a/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProvider.java
+++ b/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProvider.java
@@ -16,17 +16,12 @@
 
 import java.util.HashMap;
 import java.util.Map;
-import software.amazon.awssdk.core.SdkSystemSetting;
-import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration;
-import software.amazon.awssdk.core.client.config.SdkAdvancedClientOption;
-import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient;
-import software.amazon.awssdk.regions.Region;
 import software.amazon.awssdk.services.appconfigdata.AppConfigDataClient;
 import software.amazon.awssdk.services.appconfigdata.model.GetLatestConfigurationRequest;
 import software.amazon.awssdk.services.appconfigdata.model.GetLatestConfigurationResponse;
 import software.amazon.awssdk.services.appconfigdata.model.StartConfigurationSessionRequest;
-import software.amazon.lambda.powertools.common.internal.UserAgentConfigurator;
 import software.amazon.lambda.powertools.parameters.BaseProvider;
+import software.amazon.lambda.powertools.parameters.ParamProvider;
 import software.amazon.lambda.powertools.parameters.cache.CacheManager;
 import software.amazon.lambda.powertools.parameters.transform.TransformationManager;
 
@@ -51,8 +46,8 @@ public class AppConfigProvider extends BaseProvider {
     private final String environment;
     private final HashMap<String, EstablishedSession> establishedSessions = new HashMap<>();
 
-    AppConfigProvider(CacheManager cacheManager, AppConfigDataClient client, String environment, String application) {
-        super(cacheManager);
+    AppConfigProvider(CacheManager cacheManager, TransformationManager transformationManager, AppConfigDataClient client, String environment, String application) {
+        super(cacheManager, transformationManager);
         this.client = client;
         this.application = application;
         this.environment = environment;
@@ -61,10 +56,10 @@ public class AppConfigProvider extends BaseProvider {
     /**
      * Create a builder that can be used to configure and create a {@link AppConfigProvider}.
      *
-     * @return a new instance of {@link AppConfigProvider.Builder}
+     * @return a new instance of {@link AppConfigProviderBuilder}
      */
-    public static AppConfigProvider.Builder builder() {
-        return new AppConfigProvider.Builder();
+    public static AppConfigProviderBuilder builder() {
+        return new AppConfigProviderBuilder();
     }
 
     /**
@@ -129,102 +124,4 @@ private EstablishedSession(String nextSessionToken, String value) {
         }
     }
 
-    static class Builder {
-        private AppConfigDataClient client;
-        private CacheManager cacheManager;
-        private TransformationManager transformationManager;
-        private String environment;
-        private String application;
-
-        /**
-         * Create a {@link AppConfigProvider} instance.
-         *
-         * @return a {@link AppConfigProvider}
-         */
-        public AppConfigProvider build() {
-            if (cacheManager == null) {
-                cacheManager = new CacheManager();
-            }
-            if (environment == null) {
-                throw new IllegalStateException("No environment provided; please provide one");
-            }
-            if (application == null) {
-                throw new IllegalStateException("No application provided; please provide one");
-            }
-
-            // Create a AppConfigDataClient if we haven't been given one
-            if (client == null) {
-                client = AppConfigDataClient.builder()
-                        .httpClientBuilder(UrlConnectionHttpClient.builder())
-                        .region(Region.of(System.getenv(SdkSystemSetting.AWS_REGION.environmentVariable())))
-                        .overrideConfiguration(ClientOverrideConfiguration.builder()
-                                .putAdvancedOption(SdkAdvancedClientOption.USER_AGENT_SUFFIX,
-                                        UserAgentConfigurator.getUserAgent(BaseProvider.PARAMETERS)).build())
-                        .build();
-            }
-
-            AppConfigProvider provider = new AppConfigProvider(cacheManager, client, environment, application);
-
-            if (transformationManager != null) {
-                provider.setTransformationManager(transformationManager);
-            }
-            return provider;
-        }
-
-        /**
-         * Set custom {@link AppConfigProvider} to pass to the {@link AppConfigDataClient}. <br/>
-         * Use it if you want to customize the region or any other part of the client.
-         *
-         * @param client Custom client
-         * @return the builder to chain calls (eg. <pre>builder.withClient().build()</pre>)
-         */
-        public AppConfigProvider.Builder withClient(AppConfigDataClient client) {
-            this.client = client;
-            return this;
-        }
-
-        /**
-         * <b>Mandatory</b>. Provide an environment to the {@link AppConfigProvider}
-         *
-         * @param environment the AppConfig environment
-         * @return the builder to chain calls (eg. <pre>builder.withCacheManager().build()</pre>)
-         */
-        public AppConfigProvider.Builder withEnvironment(String environment) {
-            this.environment = environment;
-            return this;
-        }
-
-        /**
-         * <b>Mandatory</b>. Provide an application to the {@link AppConfigProvider}
-         *
-         * @param application the application to pull configuration from
-         * @return the builder to chain calls (eg. <pre>builder.withCacheManager().build()</pre>)
-         */
-        public AppConfigProvider.Builder withApplication(String application) {
-            this.application = application;
-            return this;
-        }
-
-        /**
-         * <b>Mandatory</b>. Provide a CacheManager to the {@link AppConfigProvider}
-         *
-         * @param cacheManager the manager that will handle the cache of parameters
-         * @return the builder to chain calls (eg. <pre>builder.withCacheManager().build()</pre>)
-         */
-        public AppConfigProvider.Builder withCacheManager(CacheManager cacheManager) {
-            this.cacheManager = cacheManager;
-            return this;
-        }
-
-        /**
-         * Provide a transformationManager to the {@link AppConfigProvider}
-         *
-         * @param transformationManager the manager that will handle transformation of parameters
-         * @return the builder to chain calls (eg. <pre>builder.withTransformationManager().build()</pre>)
-         */
-        public AppConfigProvider.Builder withTransformationManager(TransformationManager transformationManager) {
-            this.transformationManager = transformationManager;
-            return this;
-        }
-    }
 }
diff --git a/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProviderBuilder.java b/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProviderBuilder.java
new file mode 100644
index 000000000..789ef2701
--- /dev/null
+++ b/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProviderBuilder.java
@@ -0,0 +1,106 @@
+package software.amazon.lambda.powertools.parameters.appconfig;
+
+import software.amazon.awssdk.core.SdkSystemSetting;
+import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration;
+import software.amazon.awssdk.core.client.config.SdkAdvancedClientOption;
+import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.services.appconfigdata.AppConfigDataClient;
+import software.amazon.lambda.powertools.common.internal.UserAgentConfigurator;
+import software.amazon.lambda.powertools.parameters.BaseProvider;
+import software.amazon.lambda.powertools.parameters.cache.CacheManager;
+import software.amazon.lambda.powertools.parameters.transform.TransformationManager;
+
+public class AppConfigProviderBuilder {
+    private AppConfigDataClient client;
+    private CacheManager cacheManager;
+    private TransformationManager transformationManager;
+    private String environment;
+    private String application;
+
+    /**
+     * Create a {@link AppConfigProvider} instance.
+     *
+     * @return a {@link AppConfigProvider}
+     */
+    public AppConfigProvider build() {
+        if (cacheManager == null) {
+            cacheManager = new CacheManager();
+        }
+        if (environment == null) {
+            throw new IllegalStateException("No environment provided; please provide one");
+        }
+        if (application == null) {
+            throw new IllegalStateException("No application provided; please provide one");
+        }
+
+        // Create a AppConfigDataClient if we haven't been given one
+        if (client == null) {
+            client = AppConfigDataClient.builder()
+                    .httpClientBuilder(UrlConnectionHttpClient.builder())
+                    .region(Region.of(System.getenv(SdkSystemSetting.AWS_REGION.environmentVariable())))
+                    .overrideConfiguration(ClientOverrideConfiguration.builder()
+                            .putAdvancedOption(SdkAdvancedClientOption.USER_AGENT_SUFFIX,
+                                    UserAgentConfigurator.getUserAgent(BaseProvider.PARAMETERS)).build())
+                    .build();
+        }
+
+        return new AppConfigProvider(cacheManager, transformationManager, client, environment, application);
+    }
+
+    /**
+     * Set custom {@link AppConfigProvider} to pass to the {@link AppConfigDataClient}. <br/>
+     * Use it if you want to customize the region or any other part of the client.
+     *
+     * @param client Custom client
+     * @return the builder to chain calls (eg. <pre>builder.withClient().build()</pre>)
+     */
+    public AppConfigProviderBuilder withClient(AppConfigDataClient client) {
+        this.client = client;
+        return this;
+    }
+
+    /**
+     * <b>Mandatory</b>. Provide an environment to the {@link AppConfigProvider}
+     *
+     * @param environment the AppConfig environment
+     * @return the builder to chain calls (eg. <pre>builder.withCacheManager().build()</pre>)
+     */
+    public AppConfigProviderBuilder withEnvironment(String environment) {
+        this.environment = environment;
+        return this;
+    }
+
+    /**
+     * <b>Mandatory</b>. Provide an application to the {@link AppConfigProvider}
+     *
+     * @param application the application to pull configuration from
+     * @return the builder to chain calls (eg. <pre>builder.withCacheManager().build()</pre>)
+     */
+    public AppConfigProviderBuilder withApplication(String application) {
+        this.application = application;
+        return this;
+    }
+
+    /**
+     * <b>Mandatory</b>. Provide a CacheManager to the {@link AppConfigProvider}
+     *
+     * @param cacheManager the manager that will handle the cache of parameters
+     * @return the builder to chain calls (eg. <pre>builder.withCacheManager().build()</pre>)
+     */
+    public AppConfigProviderBuilder withCacheManager(CacheManager cacheManager) {
+        this.cacheManager = cacheManager;
+        return this;
+    }
+
+    /**
+     * Provide a transformationManager to the {@link AppConfigProvider}
+     *
+     * @param transformationManager the manager that will handle transformation of parameters
+     * @return the builder to chain calls (eg. <pre>builder.withTransformationManager().build()</pre>)
+     */
+    public AppConfigProviderBuilder withTransformationManager(TransformationManager transformationManager) {
+        this.transformationManager = transformationManager;
+        return this;
+    }
+}
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 2337c4c9d..f38e67f0e 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
@@ -1,15 +1,41 @@
 package software.amazon.lambda.powertools.parameters.appconfig;
 
-// TODO - what can we do with this? We need a way to inject a different
-// AppConfigDataClient in
-//public class AppConfigParamAspectTest {
-//
-//    @AppConfigParam(application = "myApp", environment = "myEnvironment", key = "myKey")
-//    public String myParameter;
-//
-//    @Test
-//    public void parameterInjectedByProvider() {
-//        assertThat(myParameter);
-//    }
-//
-//}
+import static org.apache.commons.lang3.reflect.FieldUtils.writeStaticField;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.function.BiFunction;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
+
+public class AppConfigParamAspectTest {
+
+    @Test
+    public void parameterInjectedByProvider() throws Exception {
+        // Setup our aspect to return a mocked AppConfigProvider
+        String environment = "myEnvironment";
+        String appName = "myApp";
+        String key = "myKey";
+        String value = "myValue";
+        AppConfigProvider provider = Mockito.mock(AppConfigProvider.class);
+        BiFunction<String, String, AppConfigProvider> providerBuilder = (String env, String app) -> {
+            if (env.equals(environment) && app.equals(appName)) {
+                return provider;
+            }
+            throw new RuntimeException("Whoops! Asked for an app/env that we weren't configured for");
+        };
+        writeStaticField(AppConfigParametersAspect.class, "providerBuilder", providerBuilder, true);
+
+        // Setup our mocked AppConfigProvider to return a value for our test data
+        Mockito.when(provider.get(key)).thenReturn(value);
+
+        // Create an instance of a class and let the AppConfigParametersAspect inject it
+        MyInjectedClass obj = new MyInjectedClass();
+        assertThat(obj.myParameter).isEqualTo(value);
+    }
+
+    class MyInjectedClass {
+        @AppConfigParam(application = "myApp", environment = "myEnvironment", key = "myKey")
+        public String myParameter;
+    }
+
+}
diff --git a/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/Builder.java b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/Builder.java
deleted file mode 100644
index ad7dbf6db..000000000
--- a/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/Builder.java
+++ /dev/null
@@ -1,2 +0,0 @@
-package software.amazon.lambda.powertools.parameters.dynamodb;public class Builder {
-}
diff --git a/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProvider.java b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProvider.java
index b665b1e35..5df1c7e58 100644
--- a/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProvider.java
+++ b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProvider.java
@@ -17,18 +17,12 @@
 import java.util.Collections;
 import java.util.Map;
 import java.util.stream.Collectors;
-import software.amazon.awssdk.core.SdkSystemSetting;
-import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration;
-import software.amazon.awssdk.core.client.config.SdkAdvancedClientOption;
-import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient;
-import software.amazon.awssdk.regions.Region;
 import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
 import software.amazon.awssdk.services.dynamodb.model.AttributeValue;
 import software.amazon.awssdk.services.dynamodb.model.GetItemRequest;
 import software.amazon.awssdk.services.dynamodb.model.GetItemResponse;
 import software.amazon.awssdk.services.dynamodb.model.QueryRequest;
 import software.amazon.awssdk.services.dynamodb.model.QueryResponse;
-import software.amazon.lambda.powertools.common.internal.UserAgentConfigurator;
 import software.amazon.lambda.powertools.parameters.BaseProvider;
 import software.amazon.lambda.powertools.parameters.ParamProvider;
 import software.amazon.lambda.powertools.parameters.cache.CacheManager;
@@ -46,23 +40,19 @@ public class DynamoDbProvider extends BaseProvider {
     private final DynamoDbClient client;
     private final String tableName;
 
-    DynamoDbProvider(CacheManager cacheManager, DynamoDbClient client, String tableName) {
-        super(cacheManager);
+    DynamoDbProvider(CacheManager cacheManager, TransformationManager transformationManager, DynamoDbClient client, String tableName) {
+        super(cacheManager, transformationManager);
         this.client = client;
         this.tableName = tableName;
     }
 
-    DynamoDbProvider(CacheManager cacheManager, String tableName) {
-        this(cacheManager, Builder.createClient(), tableName);
-    }
-
     /**
      * Create a builder that can be used to configure and create a {@link DynamoDbProvider}.
      *
-     * @return a new instance of {@link DynamoDbProvider.Builder}
+     * @return a new instance of {@link DynamoDbProviderBuilder}
      */
-    public static DynamoDbProvider.Builder builder() {
-        return new DynamoDbProvider.Builder();
+    public static DynamoDbProviderBuilder builder() {
+        return new DynamoDbProviderBuilder();
     }
 
     /**
@@ -127,89 +117,4 @@ protected Map<String, String> getMultipleValues(String path) {
 
     }
 
-    static class Builder {
-        private DynamoDbClient client;
-        private String table;
-        private CacheManager cacheManager;
-        private TransformationManager transformationManager;
-
-        private static DynamoDbClient createClient() {
-            return DynamoDbClient.builder()
-                    .httpClientBuilder(UrlConnectionHttpClient.builder())
-                    .region(Region.of(System.getenv(SdkSystemSetting.AWS_REGION.environmentVariable())))
-                    .overrideConfiguration(ClientOverrideConfiguration.builder()
-                            .putAdvancedOption(SdkAdvancedClientOption.USER_AGENT_SUFFIX,
-                                    UserAgentConfigurator.getUserAgent(PARAMETERS)).build())
-                    .build();
-        }
-
-        /**
-         * Create a {@link DynamoDbProvider} instance.
-         *
-         * @return a {@link DynamoDbProvider}
-         */
-        public DynamoDbProvider build() {
-            if (cacheManager == null) {
-                cacheManager = new CacheManager();
-            }
-            if (table == null) {
-                throw new IllegalStateException("No DynamoDB table name provided; please provide one");
-            }
-            DynamoDbProvider provider;
-            if (client == null) {
-                client = createClient();
-            }
-            provider = new DynamoDbProvider(cacheManager, client, table);
-
-            if (transformationManager != null) {
-                provider.setTransformationManager(transformationManager);
-            }
-            return provider;
-        }
-
-        /**
-         * Set custom {@link DynamoDbClient} to pass to the {@link DynamoDbClient}. <br/>
-         * Use it if you want to customize the region or any other part of the client.
-         *
-         * @param client Custom client
-         * @return the builder to chain calls (eg. <pre>builder.withClient().build()</pre>)
-         */
-        public DynamoDbProvider.Builder withClient(DynamoDbClient client) {
-            this.client = client;
-            return this;
-        }
-
-        /**
-         * <b>Mandatory</b>. Provide a CacheManager to the {@link DynamoDbProvider}
-         *
-         * @param cacheManager the manager that will handle the cache of parameters
-         * @return the builder to chain calls (eg. <pre>builder.withCacheManager().build()</pre>)
-         */
-        public DynamoDbProvider.Builder withCacheManager(CacheManager cacheManager) {
-            this.cacheManager = cacheManager;
-            return this;
-        }
-
-        /**
-         * <b>Mandatory</b>. Provide a DynamoDB table to the {@link DynamoDbProvider}
-         *
-         * @param table the table that parameters will be retrieved from.
-         * @return the builder to chain calls (eg. <pre>builder.withTable().build()</pre>)
-         */
-        public DynamoDbProvider.Builder withTable(String table) {
-            this.table = table;
-            return this;
-        }
-
-        /**
-         * Provide a transformationManager to the {@link DynamoDbProvider}
-         *
-         * @param transformationManager the manager that will handle transformation of parameters
-         * @return the builder to chain calls (eg. <pre>builder.withTransformationManager().build()</pre>)
-         */
-        public DynamoDbProvider.Builder withTransformationManager(TransformationManager transformationManager) {
-            this.transformationManager = transformationManager;
-            return this;
-        }
-    }
 }
diff --git a/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderBuilder.java b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderBuilder.java
new file mode 100644
index 000000000..a3632fac2
--- /dev/null
+++ b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderBuilder.java
@@ -0,0 +1,95 @@
+package software.amazon.lambda.powertools.parameters.dynamodb;
+
+import software.amazon.awssdk.core.SdkSystemSetting;
+import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration;
+import software.amazon.awssdk.core.client.config.SdkAdvancedClientOption;
+import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
+import software.amazon.lambda.powertools.common.internal.UserAgentConfigurator;
+import software.amazon.lambda.powertools.parameters.BaseProvider;
+import software.amazon.lambda.powertools.parameters.cache.CacheManager;
+import software.amazon.lambda.powertools.parameters.transform.TransformationManager;
+
+class DynamoDbProviderBuilder {
+    private DynamoDbClient client;
+    private String table;
+    private CacheManager cacheManager;
+    private TransformationManager transformationManager;
+
+    static DynamoDbClient createClient() {
+        return DynamoDbClient.builder()
+                .httpClientBuilder(UrlConnectionHttpClient.builder())
+                .region(Region.of(System.getenv(SdkSystemSetting.AWS_REGION.environmentVariable())))
+                .overrideConfiguration(ClientOverrideConfiguration.builder()
+                        .putAdvancedOption(SdkAdvancedClientOption.USER_AGENT_SUFFIX,
+                                UserAgentConfigurator.getUserAgent(BaseProvider.PARAMETERS)).build())
+                .build();
+    }
+
+    /**
+     * Create a {@link DynamoDbProvider} instance.
+     *
+     * @return a {@link DynamoDbProvider}
+     */
+    public DynamoDbProvider build() {
+        if (cacheManager == null) {
+            cacheManager = new CacheManager();
+        }
+        if (table == null) {
+            throw new IllegalStateException("No DynamoDB table name provided; please provide one");
+        }
+        DynamoDbProvider provider;
+        if (client == null) {
+            client = createClient();
+        }
+        provider = new DynamoDbProvider(cacheManager, transformationManager, client, table);
+
+        return provider;
+    }
+
+    /**
+     * Set custom {@link DynamoDbClient} to pass to the {@link DynamoDbClient}. <br/>
+     * Use it if you want to customize the region or any other part of the client.
+     *
+     * @param client Custom client
+     * @return the builder to chain calls (eg. <pre>builder.withClient().build()</pre>)
+     */
+    public DynamoDbProviderBuilder withClient(DynamoDbClient client) {
+        this.client = client;
+        return this;
+    }
+
+    /**
+     * <b>Mandatory</b>. Provide a CacheManager to the {@link DynamoDbProvider}
+     *
+     * @param cacheManager the manager that will handle the cache of parameters
+     * @return the builder to chain calls (eg. <pre>builder.withCacheManager().build()</pre>)
+     */
+    public DynamoDbProviderBuilder withCacheManager(CacheManager cacheManager) {
+        this.cacheManager = cacheManager;
+        return this;
+    }
+
+    /**
+     * <b>Mandatory</b>. Provide a DynamoDB table to the {@link DynamoDbProvider}
+     *
+     * @param table the table that parameters will be retrieved from.
+     * @return the builder to chain calls (eg. <pre>builder.withTable().build()</pre>)
+     */
+    public DynamoDbProviderBuilder withTable(String table) {
+        this.table = table;
+        return this;
+    }
+
+    /**
+     * Provide a transformationManager to the {@link DynamoDbProvider}
+     *
+     * @param transformationManager the manager that will handle transformation of parameters
+     * @return the builder to chain calls (eg. <pre>builder.withTransformationManager().build()</pre>)
+     */
+    public DynamoDbProviderBuilder withTransformationManager(TransformationManager transformationManager) {
+        this.transformationManager = transformationManager;
+        return this;
+    }
+}
diff --git a/powertools-parameters/powertools-parameters-dynamodb/src/test/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderE2ETest.java b/powertools-parameters/powertools-parameters-dynamodb/src/test/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderE2ETest.java
index c7530e1b7..2695938d8 100644
--- a/powertools-parameters/powertools-parameters-dynamodb/src/test/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderE2ETest.java
+++ b/powertools-parameters/powertools-parameters-dynamodb/src/test/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderE2ETest.java
@@ -104,7 +104,7 @@ public void TestGetValues() {
     }
 
     private DynamoDbProvider makeProvider(String tableName) {
-        return new DynamoDbProvider(new CacheManager(), DynamoDbClient.builder()
+        return new DynamoDbProvider(new CacheManager(), null, DynamoDbClient.builder()
                 .httpClientBuilder(UrlConnectionHttpClient.builder()).build(),
                 tableName);
     }
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 0d0fbd2d9..68bfd7cdb 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
@@ -55,7 +55,7 @@ public class DynamoDbProviderTest {
     public void init() {
         openMocks(this);
         CacheManager cacheManager = new CacheManager();
-        provider = new DynamoDbProvider(cacheManager, client, tableName);
+        provider = new DynamoDbProvider(cacheManager, transformationManager, client, tableName);
     }
 
 
diff --git a/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProvider.java b/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProvider.java
index 326c5ef36..c7a9f3fac 100644
--- a/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProvider.java
+++ b/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProvider.java
@@ -19,14 +19,8 @@
 import java.time.temporal.ChronoUnit;
 import java.util.Base64;
 import java.util.Map;
-import software.amazon.awssdk.core.SdkSystemSetting;
-import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration;
-import software.amazon.awssdk.core.client.config.SdkAdvancedClientOption;
-import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient;
-import software.amazon.awssdk.regions.Region;
 import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient;
 import software.amazon.awssdk.services.secretsmanager.model.GetSecretValueRequest;
-import software.amazon.lambda.powertools.common.internal.UserAgentConfigurator;
 import software.amazon.lambda.powertools.parameters.BaseProvider;
 import software.amazon.lambda.powertools.parameters.cache.CacheManager;
 import software.amazon.lambda.powertools.parameters.transform.TransformationManager;
@@ -64,33 +58,22 @@ public class SecretsProvider extends BaseProvider {
      * Constructor with custom {@link SecretsManagerClient}. <br/>
      * Use when you need to customize region or any other attribute of the client.<br/><br/>
      * <p>
-     * Use the {@link Builder} to create an instance of it.
+     * Use the {@link SecretsProviderBuilder} to create an instance of it.
      *
      * @param client custom client you would like to use.
      */
-    public SecretsProvider(CacheManager cacheManager, SecretsManagerClient client) {
-        super(cacheManager);
+    public SecretsProvider(CacheManager cacheManager, TransformationManager transformationManager, SecretsManagerClient client) {
+        super(cacheManager, transformationManager);
         this.client = client;
     }
 
-    /**
-     * Constructor with only a CacheManager<br/>
-     * <p>
-     * Used in {@link ParamManager#createProvider(Class)}
-     *
-     * @param cacheManager handles the parameter caching
-     */
-    public SecretsProvider(CacheManager cacheManager) {
-        this(cacheManager, Builder.createClient());
-    }
-
     /**
      * Create a builder that can be used to configure and create a {@link SecretsProvider}.
      *
-     * @return a new instance of {@link SecretsProvider.Builder}
+     * @return a new instance of {@link SecretsProviderBuilder}
      */
-    public static Builder builder() {
-        return new Builder();
+    public static SecretsProviderBuilder builder() {
+        return new SecretsProviderBuilder();
     }
 
     /**
@@ -152,77 +135,4 @@ SecretsManagerClient getClient() {
         return client;
     }
 
-    public static class Builder {
-
-        private SecretsManagerClient client;
-        private CacheManager cacheManager;
-        private TransformationManager transformationManager;
-
-        private static SecretsManagerClient createClient() {
-            return SecretsManagerClient.builder()
-                    .httpClientBuilder(UrlConnectionHttpClient.builder())
-                    .region(Region.of(System.getenv(SdkSystemSetting.AWS_REGION.environmentVariable())))
-                    .overrideConfiguration(ClientOverrideConfiguration.builder()
-                            .putAdvancedOption(SdkAdvancedClientOption.USER_AGENT_SUFFIX,
-                                    UserAgentConfigurator.getUserAgent(BaseProvider.PARAMETERS)).build())
-                    .build();
-        }
-
-        /**
-         * Create a {@link SecretsProvider} instance.
-         *
-         * @return a {@link SecretsProvider}
-         */
-        public SecretsProvider build() {
-            if (cacheManager == null) {
-                // TODO - what should we do with this
-                cacheManager = new CacheManager();
-            }
-            SecretsProvider provider;
-            if (client == null) {
-                client = createClient();
-            }
-
-            provider = new SecretsProvider(cacheManager, client);
-
-            if (transformationManager != null) {
-                provider.setTransformationManager(transformationManager);
-            }
-            return provider;
-        }
-
-        /**
-         * Set custom {@link SecretsManagerClient} to pass to the {@link SecretsProvider}. <br/>
-         * Use it if you want to customize the region or any other part of the client.
-         *
-         * @param client Custom client
-         * @return the builder to chain calls (eg. <pre>builder.withClient().build()</pre>)
-         */
-        public Builder withClient(SecretsManagerClient client) {
-            this.client = client;
-            return this;
-        }
-
-        /**
-         * <b>Mandatory</b>. Provide a CacheManager to the {@link SecretsProvider}
-         *
-         * @param cacheManager the manager that will handle the cache of parameters
-         * @return the builder to chain calls (eg. <pre>builder.withCacheManager().build()</pre>)
-         */
-        public Builder withCacheManager(CacheManager cacheManager) {
-            this.cacheManager = cacheManager;
-            return this;
-        }
-
-        /**
-         * Provide a transformationManager to the {@link SecretsProvider}
-         *
-         * @param transformationManager the manager that will handle transformation of parameters
-         * @return the builder to chain calls (eg. <pre>builder.withTransformationManager().build()</pre>)
-         */
-        public Builder withTransformationManager(TransformationManager transformationManager) {
-            this.transformationManager = transformationManager;
-            return this;
-        }
-    }
 }
diff --git a/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProviderBuilder.java b/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProviderBuilder.java
new file mode 100644
index 000000000..50358a16e
--- /dev/null
+++ b/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProviderBuilder.java
@@ -0,0 +1,83 @@
+package software.amazon.lambda.powertools.parameters.secrets;
+
+import software.amazon.awssdk.core.SdkSystemSetting;
+import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration;
+import software.amazon.awssdk.core.client.config.SdkAdvancedClientOption;
+import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient;
+import software.amazon.lambda.powertools.common.internal.UserAgentConfigurator;
+import software.amazon.lambda.powertools.parameters.BaseProvider;
+import software.amazon.lambda.powertools.parameters.cache.CacheManager;
+import software.amazon.lambda.powertools.parameters.transform.TransformationManager;
+
+public class SecretsProviderBuilder {
+
+    private SecretsManagerClient client;
+    private CacheManager cacheManager;
+    private TransformationManager transformationManager;
+
+    private static SecretsManagerClient createClient() {
+        return SecretsManagerClient.builder()
+                .httpClientBuilder(UrlConnectionHttpClient.builder())
+                .region(Region.of(System.getenv(SdkSystemSetting.AWS_REGION.environmentVariable())))
+                .overrideConfiguration(ClientOverrideConfiguration.builder()
+                        .putAdvancedOption(SdkAdvancedClientOption.USER_AGENT_SUFFIX,
+                                UserAgentConfigurator.getUserAgent(BaseProvider.PARAMETERS)).build())
+                .build();
+    }
+
+    /**
+     * Create a {@link SecretsProvider} instance.
+     *
+     * @return a {@link SecretsProvider}
+     */
+    public SecretsProvider build() {
+        if (cacheManager == null) {
+            // TODO - what should we do with this
+            cacheManager = new CacheManager();
+        }
+        SecretsProvider provider;
+        if (client == null) {
+            client = createClient();
+        }
+
+        provider = new SecretsProvider(cacheManager, transformationManager, client);
+
+        return provider;
+    }
+
+    /**
+     * Set custom {@link SecretsManagerClient} to pass to the {@link SecretsProvider}. <br/>
+     * Use it if you want to customize the region or any other part of the client.
+     *
+     * @param client Custom client
+     * @return the builder to chain calls (eg. <pre>builder.withClient().build()</pre>)
+     */
+    public SecretsProviderBuilder withClient(SecretsManagerClient client) {
+        this.client = client;
+        return this;
+    }
+
+    /**
+     * <b>Mandatory</b>. Provide a CacheManager to the {@link SecretsProvider}
+     *
+     * @param cacheManager the manager that will handle the cache of parameters
+     * @return the builder to chain calls (eg. <pre>builder.withCacheManager().build()</pre>)
+     */
+    public SecretsProviderBuilder withCacheManager(CacheManager cacheManager) {
+        this.cacheManager = cacheManager;
+        return this;
+    }
+
+    /**
+     * Provide a transformationManager to the {@link SecretsProvider}
+     *
+     * @param transformationManager the manager that will handle transformation of parameters
+     * @return the builder to chain calls (eg. <pre>builder.withTransformationManager().build()</pre>)
+     */
+    public SecretsProviderBuilder withTransformationManager(TransformationManager transformationManager) {
+        this.transformationManager = transformationManager;
+        return this;
+    }
+}
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 1b4cc4306..2e0de7cf3 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
@@ -56,7 +56,7 @@ public class SecretsProviderTest {
     public void init() {
         MockitoAnnotations.openMocks(this);
         cacheManager = new CacheManager();
-        provider = new SecretsProvider(cacheManager, client);
+        provider = new SecretsProvider(cacheManager, transformationManager, client);
     }
 
     @Test
diff --git a/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMProvider.java b/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMProvider.java
index a21821009..43cf18653 100644
--- a/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMProvider.java
+++ b/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMProvider.java
@@ -17,17 +17,11 @@
 import java.time.temporal.ChronoUnit;
 import java.util.HashMap;
 import java.util.Map;
-import software.amazon.awssdk.core.SdkSystemSetting;
-import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration;
-import software.amazon.awssdk.core.client.config.SdkAdvancedClientOption;
-import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient;
-import software.amazon.awssdk.regions.Region;
 import software.amazon.awssdk.services.ssm.SsmClient;
 import software.amazon.awssdk.services.ssm.model.GetParameterRequest;
 import software.amazon.awssdk.services.ssm.model.GetParametersByPathRequest;
 import software.amazon.awssdk.services.ssm.model.GetParametersByPathResponse;
 import software.amazon.awssdk.utils.StringUtils;
-import software.amazon.lambda.powertools.common.internal.UserAgentConfigurator;
 import software.amazon.lambda.powertools.parameters.BaseProvider;
 import software.amazon.lambda.powertools.parameters.cache.CacheManager;
 import software.amazon.lambda.powertools.parameters.transform.TransformationManager;
@@ -81,22 +75,23 @@ public class SSMProvider extends BaseProvider {
      * Constructor with custom {@link SsmClient}. <br/>
      * Use when you need to customize region or any other attribute of the client.<br/><br/>
      * <p>
-     * Use the {@link SSMProvider.Builder} to create an instance of it.
+     * Use the {@link SSMProviderBuilder} to create an instance of it.
      *
      * @param client custom client you would like to use.
+     * @param transformationManager Null, or a transformation manager
      */
-    SSMProvider(CacheManager cacheManager, SsmClient client) {
-        super(cacheManager);
+    SSMProvider(CacheManager cacheManager, TransformationManager transformationManager, SsmClient client) {
+        super(cacheManager, transformationManager);
         this.client = client;
     }
 
     /**
      * Create a builder that can be used to configure and create a {@link SSMProvider}.
      *
-     * @return a new instance of {@link SSMProvider.Builder}
+     * @return a new instance of {@link SSMProviderBuilder}
      */
-    public static SSMProvider.Builder builder() {
-        return new SSMProvider.Builder();
+    public static SSMProviderBuilder builder() {
+        return new SSMProviderBuilder();
     }
 
     /**
@@ -232,76 +227,4 @@ SsmClient getClient() {
         return client;
     }
 
-    public static class Builder {
-        private SsmClient client;
-        private CacheManager cacheManager;
-        private TransformationManager transformationManager;
-
-        private static SsmClient createClient() {
-            return SsmClient.builder()
-                    .httpClientBuilder(UrlConnectionHttpClient.builder())
-                    .region(Region.of(System.getenv(SdkSystemSetting.AWS_REGION.environmentVariable())))
-                    .overrideConfiguration(ClientOverrideConfiguration.builder()
-                            .putAdvancedOption(SdkAdvancedClientOption.USER_AGENT_SUFFIX,
-                                    UserAgentConfigurator.getUserAgent(BaseProvider.PARAMETERS)).build())
-                    .build();
-        }
-
-        /**
-         * Create a {@link SSMProvider} instance.
-         *
-         * @return a {@link SSMProvider}
-         */
-        public SSMProvider build() {
-            if (cacheManager == null) {
-                // TODO - do we want to share this somehow?
-                cacheManager = new CacheManager();
-            }
-            SSMProvider provider;
-            if (client == null) {
-                client = createClient();
-            }
-
-            provider = new SSMProvider(cacheManager, client);
-
-            if (transformationManager != null) {
-                provider.setTransformationManager(transformationManager);
-            }
-            return provider;
-        }
-
-        /**
-         * Set custom {@link SsmClient} to pass to the {@link SSMProvider}. <br/>
-         * Use it if you want to customize the region or any other part of the client.
-         *
-         * @param client Custom client
-         * @return the builder to chain calls (eg. <pre>builder.withClient().build()</pre>)
-         */
-        public SSMProvider.Builder withClient(SsmClient client) {
-            this.client = client;
-            return this;
-        }
-
-        /**
-         * <b>Mandatory</b>. Provide a CacheManager to the {@link SSMProvider}
-         *
-         * @param cacheManager the manager that will handle the cache of parameters
-         * @return the builder to chain calls (eg. <pre>builder.withCacheManager().build()</pre>)
-         */
-        public SSMProvider.Builder withCacheManager(CacheManager cacheManager) {
-            this.cacheManager = cacheManager;
-            return this;
-        }
-
-        /**
-         * Provide a transformationManager to the {@link SSMProvider}
-         *
-         * @param transformationManager the manager that will handle transformation of parameters
-         * @return the builder to chain calls (eg. <pre>builder.withTransformationManager().build()</pre>)
-         */
-        public SSMProvider.Builder withTransformationManager(TransformationManager transformationManager) {
-            this.transformationManager = transformationManager;
-            return this;
-        }
-    }
 }
diff --git a/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMProviderBuilder.java b/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMProviderBuilder.java
new file mode 100644
index 000000000..717167bb4
--- /dev/null
+++ b/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMProviderBuilder.java
@@ -0,0 +1,82 @@
+package software.amazon.lambda.powertools.parameters.ssm;
+
+import software.amazon.awssdk.core.SdkSystemSetting;
+import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration;
+import software.amazon.awssdk.core.client.config.SdkAdvancedClientOption;
+import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.services.ssm.SsmClient;
+import software.amazon.lambda.powertools.common.internal.UserAgentConfigurator;
+import software.amazon.lambda.powertools.parameters.BaseProvider;
+import software.amazon.lambda.powertools.parameters.cache.CacheManager;
+import software.amazon.lambda.powertools.parameters.transform.TransformationManager;
+
+public class SSMProviderBuilder {
+    private SsmClient client;
+    private CacheManager cacheManager;
+    private TransformationManager transformationManager;
+
+    private static SsmClient createClient() {
+        return SsmClient.builder()
+                .httpClientBuilder(UrlConnectionHttpClient.builder())
+                .region(Region.of(System.getenv(SdkSystemSetting.AWS_REGION.environmentVariable())))
+                .overrideConfiguration(ClientOverrideConfiguration.builder()
+                        .putAdvancedOption(SdkAdvancedClientOption.USER_AGENT_SUFFIX,
+                                UserAgentConfigurator.getUserAgent(BaseProvider.PARAMETERS)).build())
+                .build();
+    }
+
+    /**
+     * Create a {@link SSMProvider} instance.
+     *
+     * @return a {@link SSMProvider}
+     */
+    public SSMProvider build() {
+        if (cacheManager == null) {
+            // TODO - do we want to share this somehow?
+            cacheManager = new CacheManager();
+        }
+        SSMProvider provider;
+        if (client == null) {
+            client = createClient();
+        }
+
+        provider = new SSMProvider(cacheManager, transformationManager, client);
+
+        return provider;
+    }
+
+    /**
+     * Set custom {@link SsmClient} to pass to the {@link SSMProvider}. <br/>
+     * Use it if you want to customize the region or any other part of the client.
+     *
+     * @param client Custom client
+     * @return the builder to chain calls (eg. <pre>builder.withClient().build()</pre>)
+     */
+    public SSMProviderBuilder withClient(SsmClient client) {
+        this.client = client;
+        return this;
+    }
+
+    /**
+     * <b>Mandatory</b>. Provide a CacheManager to the {@link SSMProvider}
+     *
+     * @param cacheManager the manager that will handle the cache of parameters
+     * @return the builder to chain calls (eg. <pre>builder.withCacheManager().build()</pre>)
+     */
+    public SSMProviderBuilder withCacheManager(CacheManager cacheManager) {
+        this.cacheManager = cacheManager;
+        return this;
+    }
+
+    /**
+     * Provide a transformationManager to the {@link SSMProvider}
+     *
+     * @param transformationManager the manager that will handle transformation of parameters
+     * @return the builder to chain calls (eg. <pre>builder.withTransformationManager().build()</pre>)
+     */
+    public SSMProviderBuilder withTransformationManager(TransformationManager transformationManager) {
+        this.transformationManager = transformationManager;
+        return this;
+    }
+}
diff --git a/powertools-parameters/powertools-parameters-ssm/src/test/java/software/amazon/lambda/powertools/parameters/ssm/SSMProviderTest.java b/powertools-parameters/powertools-parameters-ssm/src/test/java/software/amazon/lambda/powertools/parameters/ssm/SSMProviderTest.java
index bdbc97f7c..4814ebe1f 100644
--- a/powertools-parameters/powertools-parameters-ssm/src/test/java/software/amazon/lambda/powertools/parameters/ssm/SSMProviderTest.java
+++ b/powertools-parameters/powertools-parameters-ssm/src/test/java/software/amazon/lambda/powertools/parameters/ssm/SSMProviderTest.java
@@ -62,7 +62,7 @@ public class SSMProviderTest {
     public void init() {
         MockitoAnnotations.openMocks(this);
         cacheManager = new CacheManager();
-        provider = new SSMProvider(cacheManager, client);
+        provider = new SSMProvider(cacheManager, null, client);
     }
 
     @Test
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 edc671e2c..0d9f71ab5 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
@@ -53,7 +53,6 @@ public void setup() {
         cacheManager = new CacheManager();
         provider = new BasicProvider(cacheManager);
         transformationManager = new TransformationManager();
-        provider.setTransformationManager(transformationManager);
     }
 
     @Test
@@ -335,7 +334,6 @@ public void getObject_customDefaultTTLAndTTL_expired_shouldGetValue() {
 
     @Test
     public void get_noTransformationManager_shouldThrowException() {
-        provider.setTransformationManager(null);
 
         assertThatIllegalStateException()
                 .isThrownBy(() -> provider.withTransformation(base64).get("foo"));
@@ -343,7 +341,6 @@ public void get_noTransformationManager_shouldThrowException() {
 
     @Test
     public void getObject_noTransformationManager_shouldThrowException() {
-        provider.setTransformationManager(null);
 
         assertThatIllegalStateException()
                 .isThrownBy(() -> provider.get("foo", ObjectToDeserialize.class));
@@ -380,7 +377,7 @@ class BasicProvider extends BaseProvider {
         private String value = "valueFromStore";
 
         public BasicProvider(CacheManager cacheManager) {
-            super(cacheManager);
+            super(cacheManager, null);
         }
 
         public void setValue(String value) {
diff --git a/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerTest.java b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerTest.java
deleted file mode 100644
index 5c213a328..000000000
--- a/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerTest.java
+++ /dev/null
@@ -1,93 +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.parameters;
-
-import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
-import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
-import static org.assertj.core.api.Assertions.assertThatRuntimeException;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
-
-import org.junit.jupiter.api.Test;
-import software.amazon.lambda.powertools.parameters.cache.CacheManager;
-import software.amazon.lambda.powertools.parameters.dynamodb.DynamoDbProvider;
-import software.amazon.lambda.powertools.parameters.internal.CustomProvider;
-import software.amazon.lambda.powertools.parameters.secrets.SecretsProvider;
-import software.amazon.lambda.powertools.parameters.transform.TransformationManager;
-
-public class ParamManagerTest {
-
-    @Test
-    public void testGetCacheManager() {
-
-        // Act
-        CacheManager cacheManager = ParamManager.getCacheManager();
-
-        // Assert
-        assertNotNull(cacheManager);
-    }
-
-    @Test
-    public void testGetTransformationManager() {
-
-        // Act
-        TransformationManager transformationManager = ParamManager.getTransformationManager();
-
-        // Assert
-        assertNotNull(transformationManager);
-    }
-
-//    @Test
-//    public void testCreateProvider() {
-//
-        // Act
-//        CustomProvider customProvider = ParamManager.createProvider(CustomProvider.class);
-//
-//        // Assert
-//        assertNotNull(customProvider);
-//    }
-//
-//    @Test
-//    public void testCreateUninstanciableProvider_throwsException() {
-//
-//        // Act & Assert
-//        assertThatRuntimeException().isThrownBy(() -> ParamManager.createProvider(BaseProvider.class));
-//    }
-//
-//    @Test
-//    public void testGetProviderWithProviderClass() {
-//
-//        // Act
-//        SecretsProvider secretsProvider = ParamManager.getProvider(SecretsProvider.class);
-//
-//        // Assert
-//        assertNotNull(secretsProvider);
-//    }
-//
-//    @Test
-//    public void testGetProviderWithProviderClass_throwsException() {
-//
-//        // Act & Assert
-//        assertThatIllegalStateException().isThrownBy(() -> ParamManager.getProvider(null));
-//    }
-//
-//
-//    @Test
-//    public void testGetDynamoDBProvider_requireOtherParameters_throwException() {
-//
-//        // Act & Assert
-//        assertThatIllegalArgumentException().isThrownBy(() -> ParamManager.getProvider(DynamoDbProvider.class));
-//    }
-
-}
diff --git a/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/internal/CustomProvider.java b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/internal/CustomProvider.java
index 2c9db3712..a98d68c22 100644
--- a/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/internal/CustomProvider.java
+++ b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/internal/CustomProvider.java
@@ -25,7 +25,7 @@ public class CustomProvider extends BaseProvider {
     private final Map<String, String> values = new HashMap<>();
 
     public CustomProvider(CacheManager cacheManager) {
-        super(cacheManager);
+        super(cacheManager, null);
         values.put("/simple", "value");
         values.put("/base64", Base64.getEncoder().encodeToString("value".getBytes()));
         values.put("/json", "{\"foo\":\"Foo\", \"bar\":42, \"baz\":123456789}");
diff --git a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/BaseProvider.java b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/BaseProvider.java
index edb82f5ec..0afed3413 100644
--- a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/BaseProvider.java
+++ b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/BaseProvider.java
@@ -34,11 +34,12 @@ public abstract class BaseProvider implements ParamProvider {
     public static final String PARAMETERS = "parameters";
 
     protected final CacheManager cacheManager;
-    private TransformationManager transformationManager;
+    private final TransformationManager transformationManager;
     private Clock clock;
 
-    public BaseProvider(CacheManager cacheManager) {
+    public BaseProvider(CacheManager cacheManager, TransformationManager transformationManager) {
         this.cacheManager = cacheManager;
+        this.transformationManager = transformationManager;
     }
 
     /**
@@ -225,10 +226,6 @@ protected void resetToDefaults() {
         }
     }
 
-    protected void setTransformationManager(TransformationManager transformationManager) {
-        this.transformationManager = transformationManager;
-    }
-
     /**
      * For test purpose
      *
diff --git a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/ParamManager.java b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/ParamManager.java
deleted file mode 100644
index 79eb796e8..000000000
--- a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/ParamManager.java
+++ /dev/null
@@ -1,38 +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.parameters;
-
-import software.amazon.lambda.powertools.parameters.cache.CacheManager;
-import software.amazon.lambda.powertools.parameters.transform.TransformationManager;
-
-/**
- * Utility class to retrieve instances of parameter providers.
- * Each instance is unique (singleton).
- */
-public final class ParamManager {
-
-    private static final CacheManager cacheManager = new CacheManager();
-    private static final TransformationManager transformationManager = new TransformationManager();
-
-    public static CacheManager getCacheManager() {
-        return cacheManager;
-    }
-
-    public static TransformationManager getTransformationManager() {
-        return transformationManager;
-    }
-
-
-}

From aaba843dad3773a18f55dadf8214b71edc2c5580 Mon Sep 17 00:00:00 2001
From: Scott Gerring <gerrings@amazon.com>
Date: Mon, 18 Sep 2023 20:16:23 +0200
Subject: [PATCH 13/45] Build fix?

---
 .../appconfig/AppConfigProviderBuilder.java   | 14 ++++++
 .../dynamodb/DynamoDbProviderBuilder.java     | 14 ++++++
 .../parameters/secrets/SecretsProvider.java   |  7 +--
 .../secrets/SecretsProviderBuilder.java       | 14 ++++++
 .../parameters/ssm/SSMProviderBuilder.java    | 14 ++++++
 powertools-parameters/spotbugs-exclude.xml    | 46 ++++++++++++++++++-
 spotbugs-exclude.xml                          | 34 ++++++++++++++
 7 files changed, 137 insertions(+), 6 deletions(-)

diff --git a/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProviderBuilder.java b/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProviderBuilder.java
index 789ef2701..38df99c4e 100644
--- a/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProviderBuilder.java
+++ b/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProviderBuilder.java
@@ -1,3 +1,17 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
 package software.amazon.lambda.powertools.parameters.appconfig;
 
 import software.amazon.awssdk.core.SdkSystemSetting;
diff --git a/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderBuilder.java b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderBuilder.java
index a3632fac2..dd81b6469 100644
--- a/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderBuilder.java
+++ b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderBuilder.java
@@ -1,3 +1,17 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
 package software.amazon.lambda.powertools.parameters.dynamodb;
 
 import software.amazon.awssdk.core.SdkSystemSetting;
diff --git a/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProvider.java b/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProvider.java
index c7a9f3fac..3e54a82e8 100644
--- a/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProvider.java
+++ b/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProvider.java
@@ -55,14 +55,11 @@ public class SecretsProvider extends BaseProvider {
     private final SecretsManagerClient client;
 
     /**
-     * Constructor with custom {@link SecretsManagerClient}. <br/>
-     * Use when you need to customize region or any other attribute of the client.<br/><br/>
-     * <p>
-     * Use the {@link SecretsProviderBuilder} to create an instance of it.
+     * Use the {@link SecretsProviderBuilder} to create an instance!
      *
      * @param client custom client you would like to use.
      */
-    public SecretsProvider(CacheManager cacheManager, TransformationManager transformationManager, SecretsManagerClient client) {
+    SecretsProvider(CacheManager cacheManager, TransformationManager transformationManager, SecretsManagerClient client) {
         super(cacheManager, transformationManager);
         this.client = client;
     }
diff --git a/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProviderBuilder.java b/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProviderBuilder.java
index 50358a16e..3b13d0c37 100644
--- a/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProviderBuilder.java
+++ b/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProviderBuilder.java
@@ -1,3 +1,17 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
 package software.amazon.lambda.powertools.parameters.secrets;
 
 import software.amazon.awssdk.core.SdkSystemSetting;
diff --git a/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMProviderBuilder.java b/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMProviderBuilder.java
index 717167bb4..59616e385 100644
--- a/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMProviderBuilder.java
+++ b/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMProviderBuilder.java
@@ -1,3 +1,17 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
 package software.amazon.lambda.powertools.parameters.ssm;
 
 import software.amazon.awssdk.core.SdkSystemSetting;
diff --git a/powertools-parameters/spotbugs-exclude.xml b/powertools-parameters/spotbugs-exclude.xml
index 98536870b..a7f4e4d8c 100644
--- a/powertools-parameters/spotbugs-exclude.xml
+++ b/powertools-parameters/spotbugs-exclude.xml
@@ -15,9 +15,53 @@
                 <Class name="software.amazon.lambda.powertools.parameters.BaseProvider"/>
                 <Field name="cacheManager"/>
             </And>
+            <And>
+                <Class name="software.amazon.lambda.powertools.parameters.BaseProvider"/>
+                <Field name="transformationManager"/>
+            </And>
             <And>
                 <Class name="software.amazon.lambda.powertools.parameters.transform.TransformationManager"/>
-                <Field name="transformer"/>
+                <Field name="transformation"/>
+            </And>
+            <And>
+                <Class name="software.amazon.lambda.powertools.parameters.BaseProvider"/>
+                <Field name="transformationManager"/>
+            </And>
+            <And>
+                <Class name="software.amazon.lambda.powertools.parameters.ssm.SSMProviderBuilder"/>
+                <Field name="transformationManager"/>
+            </And>
+            <And>
+                <Class name="software.amazon.lambda.powertools.parameters.ssm.SSMProviderBuilder"/>
+                <Field name="cacheManager"/>
+            </And>
+            <And>
+                <Class name="software.amazon.lambda.powertools.parameters.ssm.SSMProviderBuilder"/>
+                <Field name="transformationManager"/>
+            </And>
+            <And>
+                <Class name="software.amazon.lambda.powertools.parameters.ssm.SSMProviderBuilder"/>
+                <Field name="client"/>
+            </And>
+            <And>
+                <Class name="software.amazon.lambda.powertools.parameters.secrets.SecretsProviderBuilder"/>
+                <Field name="cacheManager"/>
+            </And>
+            <And>
+                <Class name="software.amazon.lambda.powertools.parameters.secrets.SecretsProviderBuilder"/>
+                <Field name="transformationManager"/>
+            </And>
+            <And>
+                <Class name="software.amazon.lambda.powertools.parameters.secrets.SecretsProviderBuilder"/>
+                <Field name="client"/>
+            </And>
+            <And>
+                <Class name="software.amazon.lambda.powertools.parameters.appconfig.AppConfigProviderBuilder"/>
+                <Field name="cacheManager"/>
+            </And>
+            <And>
+                <Class name="software.amazon.lambda.powertools.parameters.appconfig.AppConfigProviderBuilder"/>
+                <Field name="transformationManager"/>
             </And>
         </Or>
     </Match>
diff --git a/spotbugs-exclude.xml b/spotbugs-exclude.xml
index fd1ef6f44..dc22f22b6 100644
--- a/spotbugs-exclude.xml
+++ b/spotbugs-exclude.xml
@@ -8,6 +8,40 @@
        https://spotbugs.readthedocs.io/en/latest/bugDescriptions.html
   -->
 <FindBugsFilter>
+    <Match>
+        <Bug pattern="EI_EXPOSE_REP2"/>
+        <Or>
+            <And>
+                <Class name="software.amazon.lambda.powertools.parameters.BaseProvider"/>
+                <Field name="cacheManager"/>
+            </And>
+            <And>
+                <Class name="software.amazon.lambda.powertools.parameters.BaseProvider"/>
+                <Field name="transformationManager"/>
+            </And>
+            <And>
+                <Class name="software.amazon.lambda.powertools.parameters.transform.TransformationManager"/>
+                <Field name="transformation"/>
+            </And>
+            <And>
+                <Class name="software.amazon.lambda.powertools.parameters.ssm.SSMProviderBuilder"/>
+                <Field name="transformationManager"/>
+            </And>
+            <And>
+                <Class name="software.amazon.lambda.powertools.parameters.secrets.SecretsProviderBuilder"/>
+                <Field name="cacheManager"/>
+            </And>
+            <And>
+                <Class name="software.amazon.lambda.powertools.parameters.secrets.SecretsProviderBuilder"/>
+                <Field name="transformationManager"/>
+            </And>
+            <And>
+                <Class name="software.amazon.lambda.powertools.parameters.secrets.SecretsProviderBuilder"/>
+                <Field name="client"/>
+            </And>
+
+        </Or>
+    </Match>
     <!-- Internals of Log event for apache log4j-->
     <Match>
         <Bug pattern="EI_EXPOSE_REP"/>

From 0cd48da76fea843d147346bf77861c9825ef10fb Mon Sep 17 00:00:00 2001
From: Scott Gerring <gerrings@amazon.com>
Date: Mon, 18 Sep 2023 20:23:35 +0200
Subject: [PATCH 14/45] Fix test

---
 .../lambda/powertools/parameters/BaseProviderTest.java    | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

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 0d9f71ab5..a4cdd85af 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
@@ -51,8 +51,8 @@ public void setup() {
 
         clock = Clock.systemDefaultZone();
         cacheManager = new CacheManager();
-        provider = new BasicProvider(cacheManager);
         transformationManager = new TransformationManager();
+        provider = new BasicProvider(cacheManager, transformationManager);
     }
 
     @Test
@@ -303,7 +303,6 @@ public void getObject_customDefaultTTL_expired_shouldGetValue() {
     @Test
     public void getObject_customDefaultTTLAndTTL_cached_shouldGetFromCache() {
         provider.setValue("{\"foo\":\"Foo\", \"bar\":42, \"baz\":123456789}");
-
         provider.defaultMaxAge(12, ChronoUnit.MINUTES)
                 .withMaxAge(5, SECONDS)
                 .withTransformation(json)
@@ -334,6 +333,7 @@ public void getObject_customDefaultTTLAndTTL_expired_shouldGetValue() {
 
     @Test
     public void get_noTransformationManager_shouldThrowException() {
+        provider = new BasicProvider(new CacheManager(), null);
 
         assertThatIllegalStateException()
                 .isThrownBy(() -> provider.withTransformation(base64).get("foo"));
@@ -376,8 +376,8 @@ class BasicProvider extends BaseProvider {
 
         private String value = "valueFromStore";
 
-        public BasicProvider(CacheManager cacheManager) {
-            super(cacheManager, null);
+        public BasicProvider(CacheManager cacheManager, TransformationManager transformationManager) {
+            super(cacheManager, transformationManager);
         }
 
         public void setValue(String value) {

From 4b898626bf7d64687dce37763928e59ef0521688 Mon Sep 17 00:00:00 2001
From: Scott Gerring <gerrings@amazon.com>
Date: Mon, 18 Sep 2023 20:29:02 +0200
Subject: [PATCH 15/45] Remove gradle noise

---
 .../gradle/.gradle/7.3.3/checksums/checksums.lock  | Bin 17 -> 0 bytes
 .../.gradle/7.3.3/fileChanges/last-build.bin       | Bin 1 -> 0 bytes
 .../.gradle/7.3.3/fileHashes/fileHashes.lock       | Bin 17 -> 0 bytes
 .../gradle/.gradle/7.3.3/gc.properties             |   0
 .../gradle/.gradle/vcs-1/gc.properties             |   0
 .../gradle/.gradle/7.3.3/checksums/checksums.lock  | Bin 17 -> 0 bytes
 .../.gradle/7.3.3/fileChanges/last-build.bin       | Bin 1 -> 0 bytes
 .../.gradle/7.3.3/fileHashes/fileHashes.lock       | Bin 17 -> 0 bytes
 .../gradle/.gradle/7.3.3/gc.properties             |   0
 .../gradle/.gradle/vcs-1/gc.properties             |   0
 10 files changed, 0 insertions(+), 0 deletions(-)
 delete mode 100644 examples/powertools-examples-core-utilities/gradle/.gradle/7.3.3/checksums/checksums.lock
 delete mode 100644 examples/powertools-examples-core-utilities/gradle/.gradle/7.3.3/fileChanges/last-build.bin
 delete mode 100644 examples/powertools-examples-core-utilities/gradle/.gradle/7.3.3/fileHashes/fileHashes.lock
 delete mode 100644 examples/powertools-examples-core-utilities/gradle/.gradle/7.3.3/gc.properties
 delete mode 100644 examples/powertools-examples-core-utilities/gradle/.gradle/vcs-1/gc.properties
 delete mode 100644 examples/powertools-examples-core/gradle/.gradle/7.3.3/checksums/checksums.lock
 delete mode 100644 examples/powertools-examples-core/gradle/.gradle/7.3.3/fileChanges/last-build.bin
 delete mode 100644 examples/powertools-examples-core/gradle/.gradle/7.3.3/fileHashes/fileHashes.lock
 delete mode 100644 examples/powertools-examples-core/gradle/.gradle/7.3.3/gc.properties
 delete mode 100644 examples/powertools-examples-core/gradle/.gradle/vcs-1/gc.properties

diff --git a/examples/powertools-examples-core-utilities/gradle/.gradle/7.3.3/checksums/checksums.lock b/examples/powertools-examples-core-utilities/gradle/.gradle/7.3.3/checksums/checksums.lock
deleted file mode 100644
index 137f02edd07205014ea750fc7f5af43c8b21b0d3..0000000000000000000000000000000000000000
GIT binary patch
diff --git a/examples/powertools-examples-core-utilities/gradle/.gradle/7.3.3/fileChanges/last-build.bin b/examples/powertools-examples-core-utilities/gradle/.gradle/7.3.3/fileChanges/last-build.bin
deleted file mode 100644
index f76dd238ade08917e6712764a16a22005a50573d..0000000000000000000000000000000000000000
GIT binary patch
diff --git a/examples/powertools-examples-core-utilities/gradle/.gradle/7.3.3/fileHashes/fileHashes.lock b/examples/powertools-examples-core-utilities/gradle/.gradle/7.3.3/fileHashes/fileHashes.lock
deleted file mode 100644
index d2358784bf82bce372f41c1be1b805984af62bf7..0000000000000000000000000000000000000000
GIT binary patch
diff --git a/examples/powertools-examples-core-utilities/gradle/.gradle/7.3.3/gc.properties b/examples/powertools-examples-core-utilities/gradle/.gradle/7.3.3/gc.properties
deleted file mode 100644
index e69de29bb..000000000
diff --git a/examples/powertools-examples-core-utilities/gradle/.gradle/vcs-1/gc.properties b/examples/powertools-examples-core-utilities/gradle/.gradle/vcs-1/gc.properties
deleted file mode 100644
index e69de29bb..000000000
diff --git a/examples/powertools-examples-core/gradle/.gradle/7.3.3/checksums/checksums.lock b/examples/powertools-examples-core/gradle/.gradle/7.3.3/checksums/checksums.lock
deleted file mode 100644
index ab02aac0d7cc045b38c939b191240bf8d3f2af7b..0000000000000000000000000000000000000000
GIT binary patch
diff --git a/examples/powertools-examples-core/gradle/.gradle/7.3.3/fileChanges/last-build.bin b/examples/powertools-examples-core/gradle/.gradle/7.3.3/fileChanges/last-build.bin
deleted file mode 100644
index f76dd238ade08917e6712764a16a22005a50573d..0000000000000000000000000000000000000000
GIT binary patch
diff --git a/examples/powertools-examples-core/gradle/.gradle/7.3.3/fileHashes/fileHashes.lock b/examples/powertools-examples-core/gradle/.gradle/7.3.3/fileHashes/fileHashes.lock
deleted file mode 100644
index d082a98bc5aa56290fd95d661efc99fba8107d56..0000000000000000000000000000000000000000
GIT binary patch
diff --git a/examples/powertools-examples-core/gradle/.gradle/7.3.3/gc.properties b/examples/powertools-examples-core/gradle/.gradle/7.3.3/gc.properties
deleted file mode 100644
index e69de29bb..000000000
diff --git a/examples/powertools-examples-core/gradle/.gradle/vcs-1/gc.properties b/examples/powertools-examples-core/gradle/.gradle/vcs-1/gc.properties
deleted file mode 100644
index e69de29bb..000000000

From 28b70ea3c92350c9181aead0e83500a299c517d4 Mon Sep 17 00:00:00 2001
From: Scott Gerring <gerrings@amazon.com>
Date: Fri, 29 Sep 2023 12:43:24 +0200
Subject: [PATCH 16/45] Review feedback

---
 .../internal/LargeMessageProcessor.java       |  1 -
 .../parameters/appconfig/AppConfigParam.java  | 20 +++++++++
 .../appconfig/AppConfigProviderTest.java      | 34 ++++++++-------
 .../secrets/SecretsProviderTest.java          | 13 +++---
 .../parameters/ssm/SSMProviderTest.java       | 43 +++++++++----------
 5 files changed, 64 insertions(+), 47 deletions(-)

diff --git a/powertools-large-messages/src/main/java/software/amazon/lambda/powertools/largemessages/internal/LargeMessageProcessor.java b/powertools-large-messages/src/main/java/software/amazon/lambda/powertools/largemessages/internal/LargeMessageProcessor.java
index 29508bc2f..5478931f1 100644
--- a/powertools-large-messages/src/main/java/software/amazon/lambda/powertools/largemessages/internal/LargeMessageProcessor.java
+++ b/powertools-large-messages/src/main/java/software/amazon/lambda/powertools/largemessages/internal/LargeMessageProcessor.java
@@ -65,7 +65,6 @@ public Object process(ProceedingJoinPoint pjp, boolean deleteS3Object) throws Th
 
         String s3ObjectContent = getS3ObjectContent(payloadPointer);
 
-
         if (LOG.isDebugEnabled()) {
             LOG.debug("Large message [{}] retrieved in S3 [{}]: {}KB", getMessageId(message), payloadPointer,
                     s3ObjectContent.getBytes(StandardCharsets.UTF_8).length / 1024);
diff --git a/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParam.java b/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParam.java
index d4b024b6a..07cacf8ba 100644
--- a/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParam.java
+++ b/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParam.java
@@ -20,14 +20,34 @@
 import java.lang.annotation.Target;
 import software.amazon.lambda.powertools.parameters.transform.Transformer;
 
+/**
+ * Use this annotation to inject AWS AppConfig parameters into fields in your application. You
+ * can also use {@code AppConfigProviderBuilder} to obtain AppConfig values directly, rather than
+ * injecting them implicitly.
+ * Both {@code environment} and {@code application} fields are necessary.
+ *
+ * @see AppConfigProviderBuilder
+ * @see <a href="https://docs.aws.amazon.com/appconfig>AWS AppConfig</a>
+ * @see <a href="https://docs.powertools.aws.dev/lambda/java/utilities/parameters/">Powertools for AWS Lambda (Java) parameters documentation</a>
+ */
 @Retention(RetentionPolicy.RUNTIME)
 @Target(ElementType.FIELD)
 public @interface AppConfigParam {
     String key();
 
+    /**
+     * <b>Mandatory</b>. Provide an environment to the {@link AppConfigProvider}
+     *
+     */
     String environment();
 
+    /**
+     * <b>Mandatory</b>. Provide an application to the {@link AppConfigProvider}
+     */
     String application();
 
+    /**
+     * <b>Optional</b> Provide a Transformer to transform the returned parameter values.
+     */
     Class<? extends Transformer> transformer() default Transformer.class;
 }
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 992fc64eb..a7a46e05e 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
@@ -14,6 +14,8 @@
 
 package software.amazon.lambda.powertools.parameters.appconfig;
 
+import static org.assertj.core.api.Assertions.assertThat;
+
 import org.assertj.core.api.Assertions;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
@@ -98,18 +100,18 @@ public void getValueRetrievesValue() {
         String returnedValue3 = provider.getValue(defaultTestKey);
 
         // Assert
-        Assertions.assertThat(returnedValue1).isEqualTo(firstResponse.configuration().asUtf8String());
-        Assertions.assertThat(returnedValue2).isEqualTo(secondResponse.configuration().asUtf8String());
-        Assertions.assertThat(returnedValue3).isEqualTo(secondResponse.configuration()
+        assertThat(returnedValue1).isEqualTo(firstResponse.configuration().asUtf8String());
+        assertThat(returnedValue2).isEqualTo(secondResponse.configuration().asUtf8String());
+        assertThat(returnedValue3).isEqualTo(secondResponse.configuration()
                 .asUtf8String()); // Third response is mocked to return null and should re-use previous value
-        Assertions.assertThat(startSessionRequestCaptor.getValue().applicationIdentifier()).isEqualTo(applicationName);
-        Assertions.assertThat(startSessionRequestCaptor.getValue().environmentIdentifier()).isEqualTo(environmentName);
-        Assertions.assertThat(startSessionRequestCaptor.getValue().configurationProfileIdentifier()).isEqualTo(defaultTestKey);
-        Assertions.assertThat(getLatestConfigurationRequestCaptor.getAllValues().get(0).configurationToken()).isEqualTo(
+        assertThat(startSessionRequestCaptor.getValue().applicationIdentifier()).isEqualTo(applicationName);
+        assertThat(startSessionRequestCaptor.getValue().environmentIdentifier()).isEqualTo(environmentName);
+        assertThat(startSessionRequestCaptor.getValue().configurationProfileIdentifier()).isEqualTo(defaultTestKey);
+        assertThat(getLatestConfigurationRequestCaptor.getAllValues().get(0).configurationToken()).isEqualTo(
                 firstSession.initialConfigurationToken());
-        Assertions.assertThat(getLatestConfigurationRequestCaptor.getAllValues().get(1).configurationToken()).isEqualTo(
+        assertThat(getLatestConfigurationRequestCaptor.getAllValues().get(1).configurationToken()).isEqualTo(
                 firstResponse.nextPollConfigurationToken());
-        Assertions.assertThat(getLatestConfigurationRequestCaptor.getAllValues().get(2).configurationToken()).isEqualTo(
+        assertThat(getLatestConfigurationRequestCaptor.getAllValues().get(2).configurationToken()).isEqualTo(
                 secondResponse.nextPollConfigurationToken());
     }
 
@@ -133,7 +135,7 @@ public void getValueNoValueExists() {
 
 
         // Assert
-        Assertions.assertThat(returnedValue).isEqualTo(null);
+        assertThat(returnedValue).isEqualTo(null);
     }
 
     /**
@@ -169,15 +171,15 @@ public void multipleKeysRetrievalWorks() {
         String secondKeyValue = provider.getValue(param2Key);
 
         // Assert
-        Assertions.assertThat(firstKeyValue).isEqualTo(param1Response.configuration().asUtf8String());
-        Assertions.assertThat(secondKeyValue).isEqualTo(param2Response.configuration().asUtf8String());
-        Assertions.assertThat(startSessionRequestCaptor.getAllValues().get(0).configurationProfileIdentifier()).isEqualTo(
+        assertThat(firstKeyValue).isEqualTo(param1Response.configuration().asUtf8String());
+        assertThat(secondKeyValue).isEqualTo(param2Response.configuration().asUtf8String());
+        assertThat(startSessionRequestCaptor.getAllValues().get(0).configurationProfileIdentifier()).isEqualTo(
                 param1Key);
-        Assertions.assertThat(startSessionRequestCaptor.getAllValues().get(1).configurationProfileIdentifier()).isEqualTo(
+        assertThat(startSessionRequestCaptor.getAllValues().get(1).configurationProfileIdentifier()).isEqualTo(
                 param2Key);
-        Assertions.assertThat(getLatestConfigurationRequestCaptor.getAllValues().get(0).configurationToken()).isEqualTo(
+        assertThat(getLatestConfigurationRequestCaptor.getAllValues().get(0).configurationToken()).isEqualTo(
                 param1Session.initialConfigurationToken());
-        Assertions.assertThat(getLatestConfigurationRequestCaptor.getAllValues().get(1).configurationToken()).isEqualTo(
+        assertThat(getLatestConfigurationRequestCaptor.getAllValues().get(1).configurationToken()).isEqualTo(
                 param2Session.initialConfigurationToken());
 
     }
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 2e0de7cf3..891639ff7 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
@@ -15,14 +15,11 @@
 package software.amazon.lambda.powertools.parameters.secrets;
 
 import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
 import static org.assertj.core.api.Assertions.assertThatRuntimeException;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static org.mockito.MockitoAnnotations.openMocks;
 
 import java.time.temporal.ChronoUnit;
 import java.util.Base64;
-import org.assertj.core.api.Assertions;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.mockito.ArgumentCaptor;
@@ -70,8 +67,8 @@ public void getValue() {
 
         String value = provider.getValue(key);
 
-        Assertions.assertThat(value).isEqualTo(expectedValue);
-        Assertions.assertThat(paramCaptor.getValue().secretId()).isEqualTo(key);
+        assertThat(value).isEqualTo(expectedValue);
+        assertThat(paramCaptor.getValue().secretId()).isEqualTo(key);
     }
 
     @Test
@@ -85,15 +82,15 @@ public void getValueBase64() {
 
         String value = provider.getValue(key);
 
-        Assertions.assertThat(value).isEqualTo(expectedValue);
-        Assertions.assertThat(paramCaptor.getValue().secretId()).isEqualTo(key);
+        assertThat(value).isEqualTo(expectedValue);
+        assertThat(paramCaptor.getValue().secretId()).isEqualTo(key);
     }
 
     @Test
     public void getMultipleValuesThrowsException() {
 
         // Act & Assert
-        Assertions.assertThatRuntimeException().isThrownBy(() -> provider.getMultipleValues("path"))
+        assertThatRuntimeException().isThrownBy(() -> provider.getMultipleValues("path"))
                 .withMessage("Impossible to get multiple values from AWS Secrets Manager");
 
     }
diff --git a/powertools-parameters/powertools-parameters-ssm/src/test/java/software/amazon/lambda/powertools/parameters/ssm/SSMProviderTest.java b/powertools-parameters/powertools-parameters-ssm/src/test/java/software/amazon/lambda/powertools/parameters/ssm/SSMProviderTest.java
index 4814ebe1f..23ad2cd63 100644
--- a/powertools-parameters/powertools-parameters-ssm/src/test/java/software/amazon/lambda/powertools/parameters/ssm/SSMProviderTest.java
+++ b/powertools-parameters/powertools-parameters-ssm/src/test/java/software/amazon/lambda/powertools/parameters/ssm/SSMProviderTest.java
@@ -21,7 +21,6 @@
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
-import org.assertj.core.api.Assertions;
 import org.assertj.core.data.MapEntry;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
@@ -73,9 +72,9 @@ public void getValue() {
 
         String value = provider.getValue(key);
 
-        Assertions.assertThat(value).isEqualTo(expectedValue);
-        Assertions.assertThat(paramCaptor.getValue().name()).isEqualTo(key);
-        Assertions.assertThat(paramCaptor.getValue().withDecryption()).isFalse();
+        assertThat(value).isEqualTo(expectedValue);
+        assertThat(paramCaptor.getValue().name()).isEqualTo(key);
+        assertThat(paramCaptor.getValue().withDecryption()).isFalse();
     }
 
     @Test
@@ -86,9 +85,9 @@ public void getValueDecrypted() {
 
         String value = provider.withDecryption().getValue(key);
 
-        Assertions.assertThat(value).isEqualTo(expectedValue);
-        Assertions.assertThat(paramCaptor.getValue().name()).isEqualTo(key);
-        Assertions.assertThat(paramCaptor.getValue().withDecryption()).isTrue();
+        assertThat(value).isEqualTo(expectedValue);
+        assertThat(paramCaptor.getValue().name()).isEqualTo(key);
+        assertThat(paramCaptor.getValue().withDecryption()).isTrue();
     }
 
     @Test
@@ -101,7 +100,7 @@ public void getMultiple() {
         Mockito.when(client.getParametersByPath(paramByPathCaptor.capture())).thenReturn(response);
 
         Map<String, String> params = provider.getMultiple("/prod/app1");
-        Assertions.assertThat(params).contains(
+        assertThat(params).contains(
                 MapEntry.entry("key1", "foo1"),
                 MapEntry.entry("key2", "foo2"),
                 MapEntry.entry("key3", "foo3"));
@@ -109,9 +108,9 @@ public void getMultiple() {
         assertThat(provider.get("/prod/app1/key2")).isEqualTo("foo2");
         assertThat(provider.get("/prod/app1/key3")).isEqualTo("foo3");
 
-        Assertions.assertThat(paramByPathCaptor.getValue().path()).isEqualTo("/prod/app1");
-        Assertions.assertThat(paramByPathCaptor.getValue().withDecryption()).isFalse();
-        Assertions.assertThat(paramByPathCaptor.getValue().recursive()).isFalse();
+        assertThat(paramByPathCaptor.getValue().path()).isEqualTo("/prod/app1");
+        assertThat(paramByPathCaptor.getValue().withDecryption()).isFalse();
+        assertThat(paramByPathCaptor.getValue().recursive()).isFalse();
     }
 
     @Test
@@ -124,7 +123,7 @@ public void getMultipleWithTrailingSlash() {
         Mockito.when(client.getParametersByPath(paramByPathCaptor.capture())).thenReturn(response);
 
         Map<String, String> params = provider.getMultiple("/prod/app1/");
-        Assertions.assertThat(params).contains(
+        assertThat(params).contains(
                 MapEntry.entry("key1", "foo1"),
                 MapEntry.entry("key2", "foo2"),
                 MapEntry.entry("key3", "foo3"));
@@ -132,9 +131,9 @@ public void getMultipleWithTrailingSlash() {
         assertThat(provider.get("/prod/app1/key2")).isEqualTo("foo2");
         assertThat(provider.get("/prod/app1/key3")).isEqualTo("foo3");
 
-        Assertions.assertThat(paramByPathCaptor.getValue().path()).isEqualTo("/prod/app1");
-        Assertions.assertThat(paramByPathCaptor.getValue().withDecryption()).isFalse();
-        Assertions.assertThat(paramByPathCaptor.getValue().recursive()).isFalse();
+        assertThat(paramByPathCaptor.getValue().path()).isEqualTo("/prod/app1");
+        assertThat(paramByPathCaptor.getValue().withDecryption()).isFalse();
+        assertThat(paramByPathCaptor.getValue().recursive()).isFalse();
     }
 
     @Test
@@ -174,7 +173,7 @@ public void getMultipleWithNextToken() {
 
         Map<String, String> params = provider.getMultiple("/prod/app1");
 
-        Assertions.assertThat(params).contains(
+        assertThat(params).contains(
                 MapEntry.entry("key1", "foo1"),
                 MapEntry.entry("key2", "foo2"),
                 MapEntry.entry("key3", "foo3"));
@@ -183,15 +182,15 @@ public void getMultipleWithNextToken() {
         GetParametersByPathRequest request1 = requestParams.get(0);
         GetParametersByPathRequest request2 = requestParams.get(1);
 
-        Assertions.assertThat(asList(request1, request2)).allSatisfy(req ->
+        assertThat(asList(request1, request2)).allSatisfy(req ->
         {
-            Assertions.assertThat(req.path()).isEqualTo("/prod/app1");
-            Assertions.assertThat(req.withDecryption()).isFalse();
-            Assertions.assertThat(req.recursive()).isFalse();
+            assertThat(req.path()).isEqualTo("/prod/app1");
+            assertThat(req.withDecryption()).isFalse();
+            assertThat(req.recursive()).isFalse();
         });
 
-        Assertions.assertThat(request1.nextToken()).isNull();
-        Assertions.assertThat(request2.nextToken()).isEqualTo("123abc");
+        assertThat(request1.nextToken()).isNull();
+        assertThat(request2.nextToken()).isEqualTo("123abc");
     }
 
     private void initMock(String expectedValue) {

From ee092905902885af94db672f5588b9471e708bf9 Mon Sep 17 00:00:00 2001
From: Scott Gerring <gerrings@amazon.com>
Date: Thu, 16 Nov 2023 09:02:42 +0100
Subject: [PATCH 17/45] Remove mockito config

---
 .../powertools-parameters-appconfig/pom.xml            | 10 ----------
 .../powertools-parameters-dynamodb/pom.xml             | 10 ----------
 .../powertools-parameters-secrets/pom.xml              | 10 ----------
 .../powertools-parameters-ssm/pom.xml                  | 10 ----------
 .../powertools-parameters-tests/pom.xml                | 10 ----------
 5 files changed, 50 deletions(-)

diff --git a/powertools-parameters/powertools-parameters-appconfig/pom.xml b/powertools-parameters/powertools-parameters-appconfig/pom.xml
index 46c0dcd01..d44308f6b 100644
--- a/powertools-parameters/powertools-parameters-appconfig/pom.xml
+++ b/powertools-parameters/powertools-parameters-appconfig/pom.xml
@@ -70,16 +70,6 @@
             <artifactId>junit-jupiter-engine</artifactId>
             <scope>test</scope>
         </dependency>
-        <dependency>
-            <groupId>org.mockito</groupId>
-            <artifactId>mockito-core</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.mockito</groupId>
-            <artifactId>mockito-inline</artifactId>
-            <scope>test</scope>
-        </dependency>
         <dependency>
             <groupId>org.apache.commons</groupId>
             <artifactId>commons-lang3</artifactId>
diff --git a/powertools-parameters/powertools-parameters-dynamodb/pom.xml b/powertools-parameters/powertools-parameters-dynamodb/pom.xml
index 71126f6b5..64fbea0fd 100644
--- a/powertools-parameters/powertools-parameters-dynamodb/pom.xml
+++ b/powertools-parameters/powertools-parameters-dynamodb/pom.xml
@@ -70,16 +70,6 @@
             <artifactId>junit-jupiter-engine</artifactId>
             <scope>test</scope>
         </dependency>
-        <dependency>
-            <groupId>org.mockito</groupId>
-            <artifactId>mockito-core</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.mockito</groupId>
-            <artifactId>mockito-inline</artifactId>
-            <scope>test</scope>
-        </dependency>
         <dependency>
             <groupId>org.apache.commons</groupId>
             <artifactId>commons-lang3</artifactId>
diff --git a/powertools-parameters/powertools-parameters-secrets/pom.xml b/powertools-parameters/powertools-parameters-secrets/pom.xml
index 5b4dfad34..0896d9646 100644
--- a/powertools-parameters/powertools-parameters-secrets/pom.xml
+++ b/powertools-parameters/powertools-parameters-secrets/pom.xml
@@ -70,16 +70,6 @@
             <artifactId>junit-jupiter-engine</artifactId>
             <scope>test</scope>
         </dependency>
-        <dependency>
-            <groupId>org.mockito</groupId>
-            <artifactId>mockito-core</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.mockito</groupId>
-            <artifactId>mockito-inline</artifactId>
-            <scope>test</scope>
-        </dependency>
         <dependency>
             <groupId>org.apache.commons</groupId>
             <artifactId>commons-lang3</artifactId>
diff --git a/powertools-parameters/powertools-parameters-ssm/pom.xml b/powertools-parameters/powertools-parameters-ssm/pom.xml
index 47acd5906..dce95ae02 100644
--- a/powertools-parameters/powertools-parameters-ssm/pom.xml
+++ b/powertools-parameters/powertools-parameters-ssm/pom.xml
@@ -70,16 +70,6 @@
             <artifactId>junit-jupiter-engine</artifactId>
             <scope>test</scope>
         </dependency>
-        <dependency>
-            <groupId>org.mockito</groupId>
-            <artifactId>mockito-core</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.mockito</groupId>
-            <artifactId>mockito-inline</artifactId>
-            <scope>test</scope>
-        </dependency>
         <dependency>
             <groupId>org.apache.commons</groupId>
             <artifactId>commons-lang3</artifactId>
diff --git a/powertools-parameters/powertools-parameters-tests/pom.xml b/powertools-parameters/powertools-parameters-tests/pom.xml
index b0bbfdf74..a6a177393 100644
--- a/powertools-parameters/powertools-parameters-tests/pom.xml
+++ b/powertools-parameters/powertools-parameters-tests/pom.xml
@@ -45,16 +45,6 @@
             <artifactId>junit-jupiter-engine</artifactId>
             <scope>test</scope>
         </dependency>
-        <dependency>
-            <groupId>org.mockito</groupId>
-            <artifactId>mockito-core</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.mockito</groupId>
-            <artifactId>mockito-inline</artifactId>
-            <scope>test</scope>
-        </dependency>
         <dependency>
             <groupId>org.apache.commons</groupId>
             <artifactId>commons-lang3</artifactId>

From f7cf9085b32299d407ec3229cc350bb3a2a91432 Mon Sep 17 00:00:00 2001
From: Scott Gerring <gerrings@amazon.com>
Date: Thu, 16 Nov 2023 12:57:56 +0100
Subject: [PATCH 18/45] Aspect tests for all the params aspects

---
 .../appconfig/AppConfigParamAspectTest.java   | 14 +++++
 .../dynamodb/DynamoDbParamAspect.java         |  9 ++-
 .../dynamodb/DynamoDbParamAspectTest.java     | 55 +++++++++++++++++++
 .../secrets/SecretsParamAspect.java           |  6 +-
 .../secrets/SecretsParamAspectTest.java       | 49 +++++++++++++++++
 .../parameters/ssm/SSMParamAspect.java        |  7 ++-
 .../parameters/ssm/SSMParamAspectTest.java    | 51 +++++++++++++++++
 7 files changed, 184 insertions(+), 7 deletions(-)
 create mode 100644 powertools-parameters/powertools-parameters-dynamodb/src/test/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbParamAspectTest.java
 create mode 100644 powertools-parameters/powertools-parameters-secrets/src/test/java/software/amazon/lambda/powertools/parameters/secrets/SecretsParamAspectTest.java
 create mode 100644 powertools-parameters/powertools-parameters-ssm/src/test/java/software/amazon/lambda/powertools/parameters/ssm/SSMParamAspectTest.java

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 f38e67f0e..f50e88ec5 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
@@ -1,3 +1,17 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
 package software.amazon.lambda.powertools.parameters.appconfig;
 
 import static org.apache.commons.lang3.reflect.FieldUtils.writeStaticField;
diff --git a/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbParamAspect.java b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbParamAspect.java
index 0d5d0d7a7..8e6f97aad 100644
--- a/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbParamAspect.java
+++ b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbParamAspect.java
@@ -14,6 +14,7 @@
 
 package software.amazon.lambda.powertools.parameters.dynamodb;
 
+import java.util.function.Function;
 import org.aspectj.lang.ProceedingJoinPoint;
 import org.aspectj.lang.annotation.Around;
 import org.aspectj.lang.annotation.Aspect;
@@ -23,6 +24,10 @@
 @Aspect
 public class DynamoDbParamAspect {
 
+    private static Function<String, DynamoDbProvider> providerBuilder =
+            (String table) -> DynamoDbProvider.builder()
+                    .withTable(table)
+                    .build();
 
     @Pointcut("get(* *) && @annotation(ddbConfigParam)")
     public void getParam(DynamoDbParam ddbConfigParam) {
@@ -32,9 +37,7 @@ public void getParam(DynamoDbParam ddbConfigParam) {
     public Object injectParam(final ProceedingJoinPoint joinPoint, final DynamoDbParam ddbConfigParam) {
         System.out.println("GET IT");
 
-        DynamoDbProvider provider = DynamoDbProvider.builder()
-                .withTable(ddbConfigParam.table())
-                .build();
+        DynamoDbProvider provider = providerBuilder.apply(ddbConfigParam.table());
 
         if (ddbConfigParam.transformer().isInterface()) {
             // No transformation
diff --git a/powertools-parameters/powertools-parameters-dynamodb/src/test/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbParamAspectTest.java b/powertools-parameters/powertools-parameters-dynamodb/src/test/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbParamAspectTest.java
new file mode 100644
index 000000000..07e93a7c1
--- /dev/null
+++ b/powertools-parameters/powertools-parameters-dynamodb/src/test/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbParamAspectTest.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.parameters.dynamodb;
+
+import static org.apache.commons.lang3.reflect.FieldUtils.writeStaticField;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.function.Function;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
+
+public class DynamoDbParamAspectTest {
+
+    @Test
+    public void parameterInjectedByProvider() throws Exception {
+        // Setup our aspect to return a mocked DynamoDbProvider
+        String tableName = "my-test-tablename";
+        String key = "myKey";
+        String value = "myValue";
+        DynamoDbProvider provider = Mockito.mock(DynamoDbProvider.class);
+
+        Function<String, DynamoDbProvider> providerBuilder = (String table) -> {
+            if (table.equals(tableName)) {
+                return provider;
+            }
+            throw new RuntimeException("Whoops! Asked for an app/env that we weren't configured for");
+        };
+        writeStaticField(DynamoDbParamAspect.class, "providerBuilder", providerBuilder, true);
+
+        // Setup our mocked DynamoDbProvider to return a value for our test data
+        Mockito.when(provider.get(key)).thenReturn(value);
+
+        // Create an instance of a class and let the AppConfigParametersAspect inject it
+        MyInjectedClass obj = new MyInjectedClass();
+        assertThat(obj.myParameter).isEqualTo(value);
+    }
+
+    class MyInjectedClass {
+        @DynamoDbParam(table = "my-test-tablename", key = "myKey")
+        public String myParameter;
+    }
+
+}
diff --git a/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsParamAspect.java b/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsParamAspect.java
index b38b8b0cd..d8055811d 100644
--- a/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsParamAspect.java
+++ b/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsParamAspect.java
@@ -14,6 +14,7 @@
 
 package software.amazon.lambda.powertools.parameters.secrets;
 
+import java.util.function.Supplier;
 import org.aspectj.lang.ProceedingJoinPoint;
 import org.aspectj.lang.annotation.Around;
 import org.aspectj.lang.annotation.Aspect;
@@ -23,6 +24,8 @@
 @Aspect
 public class SecretsParamAspect {
 
+    private static Supplier<SecretsProvider> providerBuilder = () -> SecretsProvider.builder()
+            .build();
 
     @Pointcut("get(* *) && @annotation(secretsParam)")
     public void getParam(SecretsParam secretsParam) {
@@ -32,8 +35,7 @@ public void getParam(SecretsParam secretsParam) {
     public Object injectParam(final ProceedingJoinPoint joinPoint, final SecretsParam secretsParam) {
         System.out.println("GET IT");
 
-        SecretsProvider provider = SecretsProvider.builder()
-                .build();
+        SecretsProvider provider = providerBuilder.get();
 
         if (secretsParam.transformer().isInterface()) {
             // No transformation
diff --git a/powertools-parameters/powertools-parameters-secrets/src/test/java/software/amazon/lambda/powertools/parameters/secrets/SecretsParamAspectTest.java b/powertools-parameters/powertools-parameters-secrets/src/test/java/software/amazon/lambda/powertools/parameters/secrets/SecretsParamAspectTest.java
new file mode 100644
index 000000000..7aa0f0872
--- /dev/null
+++ b/powertools-parameters/powertools-parameters-secrets/src/test/java/software/amazon/lambda/powertools/parameters/secrets/SecretsParamAspectTest.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package software.amazon.lambda.powertools.parameters.secrets;
+
+import static org.apache.commons.lang3.reflect.FieldUtils.writeStaticField;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.function.Supplier;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
+
+public class SecretsParamAspectTest {
+
+    @Test
+    public void parameterInjectedByProvider() throws Exception {
+        // Setup our aspect to return a mocked SecretsProvider
+        String key = "myKey";
+        String value = "mySecretValue";
+        SecretsProvider provider = Mockito.mock(SecretsProvider.class);
+
+        Supplier<SecretsProvider> providerBuilder = () -> provider;
+        writeStaticField(SecretsParamAspect.class, "providerBuilder", providerBuilder, true);
+
+        // Setup our mocked SecretsProvider to return a value for our test data
+        Mockito.when(provider.get(key)).thenReturn(value);
+
+        // Create an instance of a class and let the SecretsParamAspect inject it
+        MyInjectedClass obj = new MyInjectedClass();
+        assertThat(obj.mySecret).isEqualTo(value);
+    }
+
+    class MyInjectedClass {
+        @SecretsParam(key = "myKey")
+        public String mySecret;
+    }
+
+}
diff --git a/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMParamAspect.java b/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMParamAspect.java
index 320aff33a..5207cb0eb 100644
--- a/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMParamAspect.java
+++ b/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMParamAspect.java
@@ -14,6 +14,7 @@
 
 package software.amazon.lambda.powertools.parameters.ssm;
 
+import java.util.function.Supplier;
 import org.aspectj.lang.ProceedingJoinPoint;
 import org.aspectj.lang.annotation.Around;
 import org.aspectj.lang.annotation.Aspect;
@@ -23,6 +24,9 @@
 @Aspect
 public class SSMParamAspect {
 
+    // This supplier produces a new SSMProvider each time it is called
+    private static Supplier<SSMProvider> providerBuilder = () -> SSMProvider.builder()
+            .build();
 
     @Pointcut("get(* *) && @annotation(secretsParam)")
     public void getParam(SSMParam secretsParam) {
@@ -32,8 +36,7 @@ public void getParam(SSMParam secretsParam) {
     public Object injectParam(final ProceedingJoinPoint joinPoint, final SSMParam SSMParam) {
         System.out.println("GET IT");
 
-        SSMProvider provider = SSMProvider.builder()
-                .build();
+        SSMProvider provider = providerBuilder.get();
 
         if (SSMParam.transformer().isInterface()) {
             // No transformation
diff --git a/powertools-parameters/powertools-parameters-ssm/src/test/java/software/amazon/lambda/powertools/parameters/ssm/SSMParamAspectTest.java b/powertools-parameters/powertools-parameters-ssm/src/test/java/software/amazon/lambda/powertools/parameters/ssm/SSMParamAspectTest.java
new file mode 100644
index 000000000..3826f5af5
--- /dev/null
+++ b/powertools-parameters/powertools-parameters-ssm/src/test/java/software/amazon/lambda/powertools/parameters/ssm/SSMParamAspectTest.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package software.amazon.lambda.powertools.parameters.ssm;
+
+import static org.apache.commons.lang3.reflect.FieldUtils.writeStaticField;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.function.Supplier;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
+public class SSMParamAspectTest {
+
+    // This class tests the SSM Param aspect in the same fashion
+    // as the tests for the aspects for the other providers.
+
+    @Test
+    public void parameterInjectedByProvider() throws Exception {
+
+        String key = "myKey";
+        String value = "mySecretValue";
+        SSMProvider provider = Mockito.mock(SSMProvider.class);
+
+        Supplier<SSMProvider> providerBuilder = () -> provider;
+        writeStaticField(SSMParamAspect.class, "providerBuilder", providerBuilder, true);
+
+        // Setup our mocked SSMProvider to return a value for our test data
+        Mockito.when(provider.get(key)).thenReturn(value);
+
+        // Create an instance of a class and let the SSMParamAspect inject it
+        MyInjectedClass obj = new MyInjectedClass();
+        assertThat(obj.mySecret).isEqualTo(value);
+    }
+
+    class MyInjectedClass {
+        @SSMParam(key = "myKey")
+        public String mySecret;
+    }
+
+}

From bf433f137a4b21fd16580968ff0cdf6df3045b20 Mon Sep 17 00:00:00 2001
From: Scott Gerring <gerrings@amazon.com>
Date: Wed, 22 Nov 2023 15:34:44 +0100
Subject: [PATCH 19/45] Write some docs

---
 docs/utilities/parameters.md                  | 600 ++++++------------
 .../dynamodb/DynamoDbProviderBuilder.java     |   2 +-
 ...ava => ParamProvidersIntegrationTest.java} |   4 +-
 3 files changed, 211 insertions(+), 395 deletions(-)
 rename powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/{ParamManagerIntegrationTest.java => ParamProvidersIntegrationTest.java} (97%)

diff --git a/docs/utilities/parameters.md b/docs/utilities/parameters.md
index 85d30d77e..771ffa047 100644
--- a/docs/utilities/parameters.md
+++ b/docs/utilities/parameters.md
@@ -4,29 +4,40 @@ description: Utility
 ---
 
 
-The parameters utility provides a way to retrieve parameter values from
+The parameters utilities provide a way to retrieve parameter values from
 [AWS Systems Manager Parameter Store](https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-parameter-store.html), 
 [AWS Secrets Manager](https://aws.amazon.com/secrets-manager/), or [Amazon DynamoDB](https://aws.amazon.com/dynamodb/). 
-It also provides a base class to create your parameter provider implementation.
-
+ 
 **Key features**
 
-* Retrieve one or multiple parameters from the underlying provider
+* Retrieve one or multiple parameters from an underlying provider in a standard way
 * Cache parameter values for a given amount of time (defaults to 5 seconds)
 * Transform parameter values from JSON or base 64 encoded strings
 
 ## Install
-Depending on your version of Java (either Java 1.8 or 11+), the configuration slightly changes.
+In order to provide lightweight dependencies, each parameters module is available as its own
+package:
+
+* **Secrets Manager** - `powertools-parameters-secrets` - [A service that centrally manages the lifecycle of secrets](https://aws.amazon.com/secrets-manager/). Start here if you need to manage secrets only. 
+* **SSM Parameter Store** - `powertools-parameters-ssm` - [A secure, hierarchical store for configuration data management](https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-parameter-store.html). Start here if you need to manage various types of configuration data. 
+* **Amazon DynamoDB** -`powertools-parameters-dynamodb` - [A fast, flexible, NoSQL database](https://aws.amazon.com/dynamodb/)
+* **AWS AppConfig** - `powertools-parameters-appconfig` - [An application focussed configuration store](https://aws.amazon.com/systems-manager/features/appconfig) - start here if you are interested in advanced use cases, such as incremental deployment of configuration changes
+
+You can easily mix and match parameter providers within the same project for different needs.  
+
+Depending on which Java version you are using, you configuration will differ. Note that you must also provide
+the concrete parameters module you want to use below - see the TODOs!
 
 === "Maven Java 11+"
 
-    ```xml hl_lines="3-7 16 18 24-27"
+    ```xml hl_lines="4-7 16 18 26-28"
     <dependencies>
         ...
         <dependency>
             <groupId>software.amazon.lambda</groupId>
-            <artifactId>powertools-parameters</artifactId>
-            <version>{{ powertools.version }}</version>
+             <!-- TODO! Provide the parameters module you want to use here -->
+             <artifactId>powertools-parameters-secrets</artifactId>
+             <version>{{ powertools.version }}</version>
         </dependency>
         ...
     </dependencies>
@@ -46,7 +57,8 @@ Depending on your version of Java (either Java 1.8 or 11+), the configuration sl
                      <aspectLibraries>
                          <aspectLibrary>
                              <groupId>software.amazon.lambda</groupId>
-                             <artifactId>powertools-parameters</artifactId>
+                             <!-- TODO! Provide the parameters module you want to use here -->
+                             <artifactId>powertools-parameters-secrets</artifactId>
                          </aspectLibrary>
                      </aspectLibraries>
                  </configuration>
@@ -65,12 +77,13 @@ Depending on your version of Java (either Java 1.8 or 11+), the configuration sl
 
 === "Maven Java 1.8"
 
-    ```xml hl_lines="3-7 16 18 24-27"
+    ```xml hl_lines="4-7 16 18 26-28"
     <dependencies>
         ...
         <dependency>
             <groupId>software.amazon.lambda</groupId>
-            <artifactId>powertools-parameters</artifactId>
+             <!-- TODO! Provide the parameters module you want to use here -->
+             <artifactId>powertools-parameters-secrets</artifactId>
             <version>{{ powertools.version }}</version>
         </dependency>
         ...
@@ -91,6 +104,7 @@ Depending on your version of Java (either Java 1.8 or 11+), the configuration sl
                      <aspectLibraries>
                          <aspectLibrary>
                              <groupId>software.amazon.lambda</groupId>
+                             <!-- TODO! Provide the parameters module you want to use here -->
                              <artifactId>powertools-parameters</artifactId>
                          </aspectLibrary>
                      </aspectLibraries>
@@ -110,7 +124,7 @@ Depending on your version of Java (either Java 1.8 or 11+), the configuration sl
 
 === "Gradle Java 11+"
 
-    ```groovy hl_lines="3 11"
+    ```groovy hl_lines="3 11 12"
         plugins {
             id 'java'
             id 'io.freefair.aspectj.post-compile-weaving' version '8.1.0'
@@ -121,7 +135,8 @@ Depending on your version of Java (either Java 1.8 or 11+), the configuration sl
         }
         
         dependencies {
-            aspect 'software.amazon.lambda:powertools-parameters:{{ powertools.version }}'
+            // TODO! Provide the parameters module you want to use here
+            aspect 'software.amazon.lambda:powertools-parameters-secrets:{{ powertools.version }}'
         }
         
         sourceCompatibility = 11 // or higher
@@ -130,7 +145,7 @@ Depending on your version of Java (either Java 1.8 or 11+), the configuration sl
 
 === "Gradle Java 1.8"
 
-    ```groovy hl_lines="3 11"
+    ```groovy hl_lines="3 11 12"
         plugins {
             id 'java'
             id 'io.freefair.aspectj.post-compile-weaving' version '6.6.3'
@@ -141,7 +156,8 @@ Depending on your version of Java (either Java 1.8 or 11+), the configuration sl
         }
         
         dependencies {
-            aspect 'software.amazon.lambda:powertools-parameters:{{ powertools.version }}'
+            // TODO! Provide the parameters module you want to use here
+            aspect 'software.amazon.lambda:powertools-parameters-secrets:{{ powertools.version }}'
         }
         
         sourceCompatibility = 1.8
@@ -159,260 +175,240 @@ SSM Parameter Store | `SSMProvider.getMultiple(String)`
 Secrets Manager | `SecretsProvider.get(String)` `SecretsProvider.get(String, Class)`   | `secretsmanager:GetSecretValue`
 DynamoDB | `DynamoDBProvider.get(String)` `DynamoDBProvider.getMultiple(string)` | `dynamodb:GetItem` `dynamoDB:Query`
 
-## SSM Parameter Store
+## Retrieving Parameters
+You can retrieve parameters either using annotations or by using the `xParamProvider` class for each parameter
+provider directly. The latter is useful if you need to configure the underlying SDK client, for example to use
+a different region or credentials, the former is simpler to use.
 
-You can retrieve a single parameter using SSMProvider.get() and pass the key of the parameter.
-For multiple parameters, you can use SSMProvider.getMultiple() and pass the path to retrieve them all.
+### Using Annotations
 
-Alternatively, you can retrieve an instance of a provider and configure its underlying SDK client,
-in order to get data from other regions or use specific credentials.
+=== "Secrets Manager: @SecretsParam"
 
-=== "SSMProvider"
-
-    ```java hl_lines="6"
-    import software.amazon.lambda.powertools.parameters.SSMProvider;
-    import software.amazon.lambda.powertools.parameters.ParamManager;
-
-    public class AppWithSSM implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {
-        // Get an instance of the SSM Provider
-        SSMProvider ssmProvider = ParamManager.getSsmProvider();
-    
-        // Retrieve a single parameter
-        String value = ssmProvider.get("/my/parameter");
+    ```java hl_lines="9 10"
+    import com.amazonaws.services.lambda.runtime.RequestHandler;
+    import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent;
+    import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent;
+    import software.amazon.lambda.powertools.parameters.secrets.SecretsParam;
     
-        // Retrieve multiple parameters from a path prefix
-        // This returns a Map with the parameter name as key
-        Map<String, String> values = ssmProvider.getMultiple("/my/path/prefix");
-    
-    }
+    public class ParametersFunction implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {
+
+    // Annotation-style injection from secrets manager
+    @SecretsParam(key = "/powertools-java/userpwd")
+    String secretParam;
     ```
 
-=== "SSMProvider with a custom client"
+=== "Systems Manager: @SSMParam"
 
-    ```java hl_lines="5 7"
-    import software.amazon.lambda.powertools.parameters.SSMProvider;
-    import software.amazon.lambda.powertools.parameters.ParamManager;
+    ```java hl_lines="9 10"
+    import com.amazonaws.services.lambda.runtime.RequestHandler;
+    import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent;
+    import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent;
+    import software.amazon.lambda.powertools.parameters.ssm.SSMParam;
 
-    public class AppWithSSM implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {
-        SsmClient client = SsmClient.builder().region(Region.EU_CENTRAL_1).build();
-        // Get an instance of the SSM Provider
-        SSMProvider ssmProvider = ParamManager.getSsmProvider(client);
-    
-        // Retrieve a single parameter
-        String value = ssmProvider.get("/my/parameter");
-    
-        // Retrieve multiple parameters from a path prefix
-        // This returns a Map with the parameter name as key
-        Map<String, String> values = ssmProvider.getMultiple("/my/path/prefix");
-    
-    }
+    public class ParametersFunction implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {
+
+    // Annotation-style injection from SSM Parameter Store
+    @SSMParam(key = "/powertools-java/param")
+    String ssmParam;
     ```
 
-### Additional arguments
+=== "DynamoDB: @DyanmoDbParam"
 
-The AWS Systems Manager Parameter Store provider supports two additional arguments for the `get()` and `getMultiple()` methods:
+    ```java hl_lines="9 10"
+    import com.amazonaws.services.lambda.runtime.RequestHandler;
+    import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent;
+    import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent;
+    import software.amazon.lambda.powertools.parameters.dynamodb.DynamoDBParam;
 
-| Option     | Default | Description |
-|---------------|---------|-------------|
-| **withDecryption()**   | `False` | Will automatically decrypt the parameter. |
-| **recursive()** | `False`  | For `getMultiple()` only, will fetch all parameter values recursively based on a path prefix. |
+    public class ParametersFunction implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {
 
-**Example:**
+    // Annotation-style injection from DynamoDB
+    @DynamoDbParam(table = "my-test-tablename", key = "myKey")
+    String ddbParam;
+    ```
 
-=== "AppWithSSM.java"
+=== "AppConfig: @AppConfigParam"
 
-    ```java hl_lines="9 12"
-    import software.amazon.lambda.powertools.parameters.SSMProvider;
-    import software.amazon.lambda.powertools.parameters.ParamManager;
+    ```java hl_lines="9 10"
+    import com.amazonaws.services.lambda.runtime.RequestHandler;
+    import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent;
+    import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent;
+    import software.amazon.lambda.powertools.parameters.appconfig.AppConfigParam;
 
-    public class AppWithSSM implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {
-        // Get an instance of the SSM Provider
-        SSMProvider ssmProvider = ParamManager.getSsmProvider();
-    
-        // Retrieve a single parameter and decrypt it
-        String value = ssmProvider.withDecryption().get("/my/parameter");
+    public class ParametersFunction implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {
     
-        // Retrieve multiple parameters recursively from a path prefix
-        Map<String, String> values = ssmProvider.recursive().getMultiple("/my/path/prefix");
-    
-    }
+    // Annotation-style injection from AppConfig
+    @AppConfigParam(application = "my-app", environment = "my-env", key = "myKey")
+    String appConfigParam;
     ```
 
-## Secrets Manager
 
-For secrets stored in Secrets Manager, use `getSecretsProvider`.
+### Using the `ParamProvider` classes
 
-Alternatively, you can retrieve an instance of a provider and configure its underlying SDK client,
-in order to get data from other regions or use specific credentials.
+=== "Secrets Manager"
 
-
-=== "SecretsProvider"
-
-    ```java hl_lines="9"
-    import software.amazon.lambda.powertools.parameters.SecretsProvider;
-    import software.amazon.lambda.powertools.parameters.ParamManager;
+    ```java hl_lines="15-19 23-28"
+    import static software.amazon.lambda.powertools.parameters.transform.Transformer.base64;
+    
+    import com.amazonaws.services.lambda.runtime.Context;
+    import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient;
+    import software.amazon.lambda.powertools.parameters.secrets.SecretsProvider;
+    
+    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.time.temporal.ChronoUnit;
 
     public class AppWithSecrets implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {
-        // Get an instance of the Secrets Provider
-        SecretsProvider secretsProvider = ParamManager.getSecretsProvider();
     
-        // Retrieve a single secret
-        String value = secretsProvider.get("/my/secret");
+        // Get an instance of the SecretsProvider. We can provide a custom client here if we want,
+        // for instance to use a particular region.
+        SecretsProvider secretsProvider = SecretsProvider
+                .builder()
+                .withClient(SecretsManagerClient.builder().build())
+                .build();
     
+        public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent input, Context context) {
+            // Retrieve a single secret
+            String value = secretsProvider
+                    // Transform parameter from base64
+                    .withTransformation(base64)
+                    // By default values are cached for 5 seconds, specify 10 seconds instead.
+                    .withMaxAge(10, ChronoUnit.SECONDS)
+                    .get("/my/secret");
+    
+            // Return the result
+            return new APIGatewayProxyResponseEvent()
+                    .withStatusCode(200)
+                    .withBody(value);
+        }
     }
     ```
 
-=== "SecretsProvider with a custom client"
+=== "Systems Manager"
 
-    ```java hl_lines="5 7"
-    import software.amazon.lambda.powertools.parameters.SecretsProvider;
-    import software.amazon.lambda.powertools.parameters.ParamManager;
+    ```java hl_lines="15-19 23-28"
+    import static software.amazon.lambda.powertools.parameters.transform.Transformer.base64;
+    
+    import com.amazonaws.services.lambda.runtime.Context;
+    import com.amazonaws.services.lambda.runtime.RequestHandler;
+    import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent;
+    import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent;
+    import software.amazon.awssdk.services.ssm.SsmClient;
+    import software.amazon.lambda.powertools.parameters.ssm.SSMProvider;
+    import java.time.temporal.ChronoUnit;
 
     public class AppWithSecrets implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {
-        SecretsManagerClient client = SecretsManagerClient.builder().region(Region.EU_CENTRAL_1).build();
-        // Get an instance of the Secrets Provider
-        SecretsProvider secretsProvider = ParamManager.getSecretsProvider(client);
     
-        // Retrieve a single secret
-        String value = secretsProvider.get("/my/secret");
+        // Get an instance of the SSMProvider. We can provide a custom client here if we want,
+        // for instance to use a particular region.
+        SSMProvider ssmProvider = SSMProvider
+                .builder()
+                .withClient(SsmClient.builder().build())
+                .build();
     
+        public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent input, Context context) {
+            // Retrieve a single secret
+            String value = ssmProvider
+                    // Transform parameter from base64
+                    .withTransformation(base64)
+                    // By default values are cached for 5 seconds, specify 10 seconds instead.
+                    .withMaxAge(10, ChronoUnit.SECONDS)
+                    .get("/my/secret");
+    
+            // Return the result
+            return new APIGatewayProxyResponseEvent()
+                    .withStatusCode(200)
+                    .withBody(value);
+        }
     }
     ```
 
-## DynamoDB 
-To get secrets stored in DynamoDB, use `getDynamoDbProvider`, providing the name of the table that
-contains the secrets. As with the other providers, an overloaded methods allows you to retrieve 
-a `DynamoDbProvider` providing a client if you need to configure it yourself. 
-
-=== "DynamoDbProvider"
-
-    ```java hl_lines="6 9"
-    import software.amazon.lambda.powertools.parameters.DynamoDbProvider;
-    import software.amazon.lambda.powertools.parameters.ParamManager;
+=== "DynamoDB"
 
-    public class AppWithDynamoDbParameters implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {
-        // Get an instance of the DynamoDbProvider
-        DynamoDbProvider ddbProvider = ParamManager.getDynamoDbProvider("my-parameters-table");
+    ```java hl_lines="15-19 23-28"
+    import static software.amazon.lambda.powertools.parameters.transform.Transformer.base64;
     
-        // Retrieve a single parameter
-        String value = ddbProvider.get("my-key"); 
-    } 
-    ```
-
-=== "DynamoDbProvider with a custom client"
-
-    ```java hl_lines="9 10 11 12 15 18"
-    import software.amazon.lambda.powertools.parameters.DynamoDbProvider;
-    import software.amazon.lambda.powertools.parameters.ParamManager;
+    import com.amazonaws.services.lambda.runtime.Context;
+    import com.amazonaws.services.lambda.runtime.RequestHandler;
+    import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent;
+    import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent;
     import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
-    import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient;
-    import software.amazon.awssdk.regions.Region;
-
-    public class AppWithDynamoDbParameters implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {
-        // Get a DynamoDB Client with an explicit region
-        DynamoDbClient ddbClient = DynamoDbClient.builder()
-                .httpClientBuilder(UrlConnectionHttpClient.builder())
-                .region(Region.EU_CENTRAL_2)
-                .build();
-
-        // Get an instance of the DynamoDbProvider
-        DynamoDbProvider provider = ParamManager.getDynamoDbProvider(ddbClient, "test-table");
-    
-        // Retrieve a single parameter
-        String value = ddbProvider.get("my-key"); 
-    } 
-    ```
-
-## AppConfig
-To get parameters stored in AppConfig, use `getAppConfigProvider`, providing the application and environment
-name to retrieve configuration from. As with the other providers, an overloaded method allows you to retrieve
-an `AppConfigProvider` providing a client if you need to configure it yourself.
-
-=== "AppConfigProvider"
-
-    ```java hl_lines="6 9"
-    import software.amazon.lambda.powertools.parameters.AppConfigProvider;
-    import software.amazon.lambda.powertools.parameters.ParamManager;
+    import software.amazon.lambda.powertools.parameters.dynamodb.DynamoDbProvider;
+    import java.time.temporal.ChronoUnit;
 
-    public class AppWitAppConfigParameters implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {
-        // Get an instance of the AppConfigProvider
-        AppConfigProvider appConfigProvider = ParamManager.getAppConfigProvider("my-environment", "my-app");
+    public class AppWithSecrets implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {
     
-        // Retrieve a single parameter
-        String value = appConfigProvider.get("my-key"); 
-    } 
-    ```
-
-=== "AppConfigProvider with a custom client"
-
-    ```java hl_lines="9 10 11 12 15 18"
-    import software.amazon.lambda.powertools.parameters.AppConfigProvider;
-    import software.amazon.lambda.powertools.parameters.ParamManager;
-    import software.amazon.awssdk.services.appconfigdata.AppConfigDataClient;
-    import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient;
-    import software.amazon.awssdk.regions.Region;
-
-    public class AppWithDynamoDbParameters implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {
-        // Get an AppConfig Client with an explicit region
-        AppConfigDataClient appConfigDataClient = AppConfigDataClient.builder()
-                .httpClientBuilder(UrlConnectionHttpClient.builder())
-                .region(Region.EU_CENTRAL_2)
+        // Get an instance of the SecretsProvider. We can provide a custom client here if we want,
+        // for instance to use a particular region.
+        DynamoDbProvider ddbProvider = DynamoDbProvider
+                .builder()
+                .withClient(DynamoDbClient.builder().build())
                 .build();
-
-        // Get an instance of the DynamoDbProvider
-        AppConfigProvider appConfigProvider = ParamManager.getAppConfigProvider(appConfigDataClient, "my-environment", "my-app");
     
-        // Retrieve a single parameter
-        String value = appConfigProvider.get("my-key"); 
-    } 
+        public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent input, Context context) {
+            // Retrieve a single secret
+            String value = ddbProvider
+                    // Transform parameter from base64
+                    .withTransformation(base64)
+                    // By default values are cached for 5 seconds, specify 10 seconds instead.
+                    .withMaxAge(10, ChronoUnit.SECONDS)
+                    .get("/my/secret");
+    
+            // Return the result
+            return new APIGatewayProxyResponseEvent()
+                    .withStatusCode(200)
+                    .withBody(value);
+        }
+    }
     ```
 
+=== "AppConfig"
 
-## Advanced configuration
-
-### Caching
-
-By default, all parameters and their corresponding values are cached for 5 seconds.
-
-You can customize this default value using `defaultMaxAge`. You can also customize this value for each parameter using 
-`withMaxAge`.
-
-=== "Provider with default Max age"
-
-    ```java hl_lines="9"
-    import software.amazon.lambda.powertools.parameters.SecretsProvider;
-    import software.amazon.lambda.powertools.parameters.ParamManager;
+    ```java hl_lines="15-19 23-28"
+    import static software.amazon.lambda.powertools.parameters.transform.Transformer.base64;
+    
+    import com.amazonaws.services.lambda.runtime.Context;
+    import com.amazonaws.services.lambda.runtime.RequestHandler;
+    import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent;
+    import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent;
+    import software.amazon.awssdk.services.appconfigdata.AppConfigDataClient;
+    import software.amazon.lambda.powertools.parameters.appconfig.AppConfigProvider;
+    import java.time.temporal.ChronoUnit;
 
     public class AppWithSecrets implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {
-        // Get an instance of the Secrets Provider
-        SecretsProvider secretsProvider = ParamManager.getSecretsProvider()
-                                                      .defaultMaxAge(10, ChronoUnit.SECONDS);
-
-        String value = secretsProvider.get("/my/secret");
     
-    }
+        // Get an instance of the SecretsProvider. We can provide a custom client here if we want,
+        // for instance to use a particular region.
+        AppConfigProvider appConfigProvider = AppConfigProvider
+                .builder()
+                .withClient(AppConfigDataClient.builder().build())
+                .build();
+    
+        public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent input, Context context) {
+            // Retrieve a single secret
+            String value = appConfigProvider
+                    // Transform parameter from base64
+                    .withTransformation(base64)
+                    // By default values are cached for 5 seconds, specify 10 seconds instead.
+                    .withMaxAge(10, ChronoUnit.SECONDS)
+                    .get("/my/secret");
+    
+            // Return the result
+            return new APIGatewayProxyResponseEvent()
+                    .withStatusCode(200)
+                    .withBody(value);
+        }
+    }    
     ```
 
-=== "Provider with age for each param"
-
-    ```java hl_lines="8"
-    import software.amazon.lambda.powertools.parameters.SecretsProvider;
-    import software.amazon.lambda.powertools.parameters.ParamManager;
+## Advanced configuration
 
-    public class AppWithSecrets implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {
-        SecretsManagerClient client = SecretsManagerClient.builder().region(Region.EU_CENTRAL_1).build();
-        
-        SecretsProvider secretsProvider = ParamManager.getSecretsProvider(client);
-
-        String value = secretsProvider.withMaxAge(10, ChronoUnit.SECONDS).get("/my/secret");
-    
-    }
-    ```
 
 ### Transform values
 
 Parameter values can be transformed using ```withTransformation(transformerClass)```.
-Base64 and JSON transformations are provided. For more complex transformation, you need to specify how to deserialize-
+Base64 and JSON transformations are provided. For more complex transformation, you need to specify how to deserialize.
 
 !!! warning "`SSMProvider.getMultiple()` does not support transformation and will return simple Strings."
 
@@ -431,7 +427,7 @@ Base64 and JSON transformations are provided. For more complex transformation, y
                         .get("/my/parameter/json", MyObj.class);
     ```
 
-## Write your own Transformer
+### Write your own Transformer
 
 You can write your own transformer, by implementing the `Transformer` interface and the `applyTransformation()` method.
 For example, if you wish to deserialize XML into an object.
@@ -461,181 +457,3 @@ For example, if you wish to deserialize XML into an object.
                             .withTransformation(XmlTransformer.class)
                             .get("/my/parameter/xml", MyObj.class);
     ```
-
-### Fluent API
-
-To simplify the use of the library, you can chain all method calls before a get.
-
-=== "Fluent API call"
-
-    ```java
-        ssmProvider
-          .defaultMaxAge(10, SECONDS)     // will set 10 seconds as the default cache TTL
-          .withMaxAge(1, MINUTES)         // will set the cache TTL for this value at 1 minute
-          .withTransformation(json)       // json is a static import from Transformer.json
-          .withDecryption()               // enable decryption of the parameter value
-          .get("/my/param", MyObj.class); // finally get the value
-    ```
-
-## Create your own provider
-
-You can create your own custom parameter store provider by inheriting the ```BaseProvider``` class and implementing the
-```String getValue(String key)``` method to retrieve data from your underlying store. All transformation and caching logic is handled by the get() methods in the base class.
-
-=== "Example implementation using S3 as a custom parameter"
-
-    ```java
-    public class S3Provider extends BaseProvider {
-    
-        private final S3Client client;
-        private String bucket;
-    
-        S3Provider(CacheManager cacheManager) {
-            this(cacheManager, S3Client.create());
-        }
-    
-        S3Provider(CacheManager cacheManager, S3Client client) {
-            super(cacheManager);
-            this.client = client;
-        }
-    
-        public S3Provider withBucket(String bucket) {
-            this.bucket = bucket;
-            return this;
-        }
-    
-        @Override
-        protected String getValue(String key) {
-            if (bucket == null) {
-                throw new IllegalStateException("A bucket must be specified, using withBucket() method");
-            }
-    
-            GetObjectRequest request = GetObjectRequest.builder().bucket(bucket).key(key).build();
-            ResponseBytes<GetObjectResponse> response = client.getObject(request, ResponseTransformer.toBytes());
-            return response.asUtf8String();
-        }
-    
-        @Override
-        protected Map<String, String> getMultipleValues(String path) {
-            if (bucket == null) {
-                throw new IllegalStateException("A bucket must be specified, using withBucket() method");
-            }
-    
-            ListObjectsV2Request listRequest = ListObjectsV2Request.builder().bucket(bucket).prefix(path).build();
-            List<S3Object> s3Objects = client.listObjectsV2(listRequest).contents();
-    
-            Map<String, String> result = new HashMap<>();
-            s3Objects.forEach(s3Object -> {
-                result.put(s3Object.key(), getValue(s3Object.key()));
-            });
-    
-            return result;
-        }
-    
-        @Override
-        protected void resetToDefaults() {
-            super.resetToDefaults();
-            bucket = null;
-        }
-    
-    }
-    ```
-
-=== "Using custom parameter store"
-
-    ```java hl_lines="3"
-        S3Provider provider = new S3Provider(ParamManager.getCacheManager());
-
-        provider.setTransformationManager(ParamManager.getTransformationManager());
-
-        String value = provider.withBucket("myBucket").get("myKey");
-    ```
-
-## Annotation
-
-You can make use of the annotation `@Param` to inject a parameter value in a variable.
-
-By default, it will use `SSMProvider` to retrieve the value from AWS System Manager Parameter Store.
-You could specify a different provider as long as it extends `BaseProvider` and/or a `Transformer`.
-
-=== "Param Annotation"
-
-    ```java hl_lines="3"
-    public class AppWithAnnotation implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {
-    
-        @Param(key = "/my/parameter/json")
-        ObjectToDeserialize value;
-    
-    }
-    ```
-
-=== "Custom Provider Usage"
-    
-    ```java hl_lines="3"
-    public class AppWithAnnotation implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {
-    
-        @Param(key = "/my/parameter/json" provider = SecretsProvider.class, transformer = JsonTransformer.class)
-        ObjectToDeserialize value;
-    
-    }
-    ```
-
-    In this case ```SecretsProvider``` will be used to retrieve a raw value that is then trasformed into the target Object by using ```JsonTransformer```.
-    To show the convenience of the annotation compare the following two code snippets.
-
-
-### Install
-
-If you want to use the ```@Param``` annotation in your project add configuration to compile-time weave (CTW) the powertools-parameters aspects into your project.
-
-=== "Maven"
-
-    ```xml
-    <build>
-        <plugins>
-            ...
-            <plugin>
-                 <groupId>dev.aspectj</groupId>
-                 <artifactId>aspectj-maven-plugin</artifactId>
-                 <version>1.13.1</version>
-                 <configuration>
-                     ...
-                     <aspectLibraries>
-                         ...
-                         <aspectLibrary>
-                             <groupId>software.amazon.lambda</groupId>
-                             <artifactId>powertools-parameters</artifactId>
-                         </aspectLibrary>
-                     </aspectLibraries>
-                 </configuration>
-                 <executions>
-                     <execution>
-                         <goals>
-                             <goal>compile</goal>
-                         </goals>
-                     </execution>
-                 </executions>
-            </plugin>
-            ...
-        </plugins>
-    </build>
-    ```
-    
-=== "Gradle"
-
-    ```groovy
-    plugins{
-        id 'java'
-        id 'io.freefair.aspectj.post-compile-weaving' version '6.3.0'
-    }
-
-    repositories {
-        mavenCentral()
-    }
-
-    dependencies {
-        ...
-        aspect 'software.amazon.lambda:powertools-parameters:{{ powertools.version }}'
-        implementation 'org.aspectj:aspectjrt:1.9.19'
-    }
-    ```
\ No newline at end of file
diff --git a/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderBuilder.java b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderBuilder.java
index dd81b6469..66e33c70d 100644
--- a/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderBuilder.java
+++ b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderBuilder.java
@@ -25,7 +25,7 @@
 import software.amazon.lambda.powertools.parameters.cache.CacheManager;
 import software.amazon.lambda.powertools.parameters.transform.TransformationManager;
 
-class DynamoDbProviderBuilder {
+public class DynamoDbProviderBuilder {
     private DynamoDbClient client;
     private String table;
     private CacheManager cacheManager;
diff --git a/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerIntegrationTest.java b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/ParamProvidersIntegrationTest.java
similarity index 97%
rename from powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerIntegrationTest.java
rename to powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/ParamProvidersIntegrationTest.java
index dce1bf664..fe7b66959 100644
--- a/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerIntegrationTest.java
+++ b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/ParamProvidersIntegrationTest.java
@@ -14,7 +14,6 @@
 
 package software.amazon.lambda.powertools.parameters;
 
-import static org.apache.commons.lang3.reflect.FieldUtils.writeStaticField;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.times;
@@ -25,7 +24,6 @@
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
 import org.assertj.core.data.MapEntry;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
@@ -45,7 +43,7 @@
 import software.amazon.lambda.powertools.parameters.secrets.SecretsProvider;
 import software.amazon.lambda.powertools.parameters.ssm.SSMProvider;
 
-public class ParamManagerIntegrationTest {
+public class ParamProvidersIntegrationTest {
 
     @Mock
     SsmClient ssmClient;

From 2a7f9cb4d7dcc1edbd479aa7b8f688f072c083fd Mon Sep 17 00:00:00 2001
From: Scott Gerring <gerrings@amazon.com>
Date: Wed, 22 Nov 2023 15:40:19 +0100
Subject: [PATCH 20/45] rearrange pom

---
 pom.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/pom.xml b/pom.xml
index 4c022db75..3c2768b98 100644
--- a/pom.xml
+++ b/pom.xml
@@ -57,8 +57,8 @@
         <module>powertools-parameters/powertools-parameters-ssm</module>
         <module>powertools-parameters/powertools-parameters-secrets</module>
         <module>powertools-parameters/powertools-parameters-dynamodb</module>
-        <module>powertools-parameters/powertools-parameters-tests</module>
         <module>powertools-parameters/powertools-parameters-appconfig</module>
+        <module>powertools-parameters/powertools-parameters-tests</module>
     </modules>
 
     <scm>

From 54c16647369d72f3b02e8e90098715f25ebe24a5 Mon Sep 17 00:00:00 2001
From: Scott Gerring <gerrings@amazon.com>
Date: Wed, 22 Nov 2023 15:44:38 +0100
Subject: [PATCH 21/45] More warning ignores

---
 powertools-parameters/spotbugs-exclude.xml | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/powertools-parameters/spotbugs-exclude.xml b/powertools-parameters/spotbugs-exclude.xml
index a7f4e4d8c..5903492f3 100644
--- a/powertools-parameters/spotbugs-exclude.xml
+++ b/powertools-parameters/spotbugs-exclude.xml
@@ -63,6 +63,20 @@
                 <Class name="software.amazon.lambda.powertools.parameters.appconfig.AppConfigProviderBuilder"/>
                 <Field name="transformationManager"/>
             </And>
+
+            <And>
+                <Class name="software.amazon.lambda.powertools.parameters.dynamodb.DynamoDbProviderBuilder"/>
+                <Field name="cacheManager"/>
+            </And>
+            <And>
+                <Class name="software.amazon.lambda.powertools.parameters.dynamodb.DynamoDbProviderBuilder"/>
+                <Field name="transformationManager"/>
+            </And>
+            <And>
+                <Class name="software.amazon.lambda.powertools.parameters.dynamodb.DynamoDbProviderBuilder"/>
+                <Field name="client"/>
+            </And>
+
         </Or>
     </Match>
     <Match>

From 762baf381aaad7628fe612c437bec629c86f0701 Mon Sep 17 00:00:00 2001
From: Scott Gerring <gerrings@amazon.com>
Date: Thu, 23 Nov 2023 08:50:01 +0100
Subject: [PATCH 22/45] Removed some unecessary overrides

---
 .../dynamodb/DynamoDbProviderBuilder.java     |  5 ++++
 .../parameters/secrets/SecretsProvider.java   | 28 ------------------
 .../parameters/ssm/SSMProvider.java           | 29 -------------------
 .../powertools/parameters/BaseProvider.java   |  2 +-
 4 files changed, 6 insertions(+), 58 deletions(-)

diff --git a/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderBuilder.java b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderBuilder.java
index 66e33c70d..6fd525b83 100644
--- a/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderBuilder.java
+++ b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderBuilder.java
@@ -14,6 +14,7 @@
 
 package software.amazon.lambda.powertools.parameters.dynamodb;
 
+import java.time.temporal.ChronoUnit;
 import software.amazon.awssdk.core.SdkSystemSetting;
 import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration;
 import software.amazon.awssdk.core.client.config.SdkAdvancedClientOption;
@@ -31,6 +32,10 @@ public class DynamoDbProviderBuilder {
     private CacheManager cacheManager;
     private TransformationManager transformationManager;
 
+    // Allows the user to override default max age
+    private int maxAge;
+    private ChronoUnit unit;
+
     static DynamoDbClient createClient() {
         return DynamoDbClient.builder()
                 .httpClientBuilder(UrlConnectionHttpClient.builder())
diff --git a/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProvider.java b/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProvider.java
index 3e54a82e8..600db6212 100644
--- a/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProvider.java
+++ b/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProvider.java
@@ -16,7 +16,6 @@
 
 import static java.nio.charset.StandardCharsets.UTF_8;
 
-import java.time.temporal.ChronoUnit;
 import java.util.Base64;
 import java.util.Map;
 import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient;
@@ -24,7 +23,6 @@
 import software.amazon.lambda.powertools.parameters.BaseProvider;
 import software.amazon.lambda.powertools.parameters.cache.CacheManager;
 import software.amazon.lambda.powertools.parameters.transform.TransformationManager;
-import software.amazon.lambda.powertools.parameters.transform.Transformer;
 
 /**
  * AWS Secrets Manager Parameter Provider<br/><br/>
@@ -100,32 +98,6 @@ protected Map<String, String> getMultipleValues(String path) {
         throw new UnsupportedOperationException("Impossible to get multiple values from AWS Secrets Manager");
     }
 
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public SecretsProvider defaultMaxAge(int maxAge, ChronoUnit unit) {
-        super.defaultMaxAge(maxAge, unit);
-        return this;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public SecretsProvider withMaxAge(int maxAge, ChronoUnit unit) {
-        super.withMaxAge(maxAge, unit);
-        return this;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public SecretsProvider withTransformation(Class<? extends Transformer> transformerClass) {
-        super.withTransformation(transformerClass);
-        return this;
-    }
 
     // For test purpose only
     SecretsManagerClient getClient() {
diff --git a/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMProvider.java b/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMProvider.java
index 43cf18653..55e1a67c1 100644
--- a/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMProvider.java
+++ b/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMProvider.java
@@ -14,7 +14,6 @@
 
 package software.amazon.lambda.powertools.parameters.ssm;
 
-import java.time.temporal.ChronoUnit;
 import java.util.HashMap;
 import java.util.Map;
 import software.amazon.awssdk.services.ssm.SsmClient;
@@ -25,7 +24,6 @@
 import software.amazon.lambda.powertools.parameters.BaseProvider;
 import software.amazon.lambda.powertools.parameters.cache.CacheManager;
 import software.amazon.lambda.powertools.parameters.transform.TransformationManager;
-import software.amazon.lambda.powertools.parameters.transform.Transformer;
 
 /**
  * AWS System Manager Parameter Store Provider <br/><br/>
@@ -109,33 +107,6 @@ public String getValue(String key) {
         return client.getParameter(request).parameter().value();
     }
 
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public SSMProvider defaultMaxAge(int maxAge, ChronoUnit unit) {
-        super.defaultMaxAge(maxAge, unit);
-        return this;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public SSMProvider withMaxAge(int maxAge, ChronoUnit unit) {
-        super.withMaxAge(maxAge, unit);
-        return this;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public SSMProvider withTransformation(Class<? extends Transformer> transformerClass) {
-        super.withTransformation(transformerClass);
-        return this;
-    }
-
     /**
      * Tells System Manager Parameter Store to decrypt the parameter value.<br/>
      * By default, parameter values are not decrypted.<br/>
diff --git a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/BaseProvider.java b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/BaseProvider.java
index 0afed3413..1b6f5786a 100644
--- a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/BaseProvider.java
+++ b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/BaseProvider.java
@@ -69,7 +69,7 @@ public BaseProvider(CacheManager cacheManager, TransformationManager transformat
      * @param unit   Unit of time
      * @return the provider itself in order to chain calls (eg. <pre>provider.defaultMaxAge(10, SECONDS).get("key")</pre>).
      */
-    protected BaseProvider defaultMaxAge(int maxAge, ChronoUnit unit) {
+    public BaseProvider defaultMaxAge(int maxAge, ChronoUnit unit) {
         Duration duration = Duration.of(maxAge, unit);
         cacheManager.setDefaultExpirationTime(duration);
         return this;

From b5e0602b73814efb50840a0c7ec5a1653f27df03 Mon Sep 17 00:00:00 2001
From: Scott Gerring <gerrings@amazon.com>
Date: Tue, 28 Nov 2023 08:04:35 +0100
Subject: [PATCH 23/45] Remove defaultMaxAge from BaseProvider intf

---
 .../demo/parameters/ParametersFunction.java   |  2 +-
 .../secrets/SecretsProviderTest.java          |  1 -
 .../parameters/ssm/SSMProviderTest.java       |  1 -
 .../parameters/BaseProviderTest.java          | 30 +++++++++----------
 .../powertools/parameters/BaseProvider.java   | 17 +----------
 5 files changed, 17 insertions(+), 34 deletions(-)

diff --git a/examples/powertools-examples-parameters/src/main/java/org/demo/parameters/ParametersFunction.java b/examples/powertools-examples-parameters/src/main/java/org/demo/parameters/ParametersFunction.java
index 57f953d43..9a1d3636b 100644
--- a/examples/powertools-examples-parameters/src/main/java/org/demo/parameters/ParametersFunction.java
+++ b/examples/powertools-examples-parameters/src/main/java/org/demo/parameters/ParametersFunction.java
@@ -54,7 +54,7 @@ public class ParametersFunction implements RequestHandler<APIGatewayProxyRequest
             .builder()
             .build();
 
-    String simpleValue = ssmProvider.defaultMaxAge(30, SECONDS).get("/powertools-java/sample/simplekey");
+    String simpleValue = ssmProvider.withMaxAge(30, SECONDS).get("/powertools-java/sample/simplekey");
     String listValue = ssmProvider.withMaxAge(60, SECONDS).get("/powertools-java/sample/keylist");
     MyObject jsonObj = ssmProvider.withTransformation(json).get("/powertools-java/sample/keyjson", MyObject.class);
     Map<String, String> allValues = ssmProvider.getMultiple("/powertools-java/sample");
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 891639ff7..21173cad1 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
@@ -62,7 +62,6 @@ public void getValue() {
         String expectedValue = "Value1";
         GetSecretValueResponse response = GetSecretValueResponse.builder().secretString(expectedValue).build();
         Mockito.when(client.getSecretValue(paramCaptor.capture())).thenReturn(response);
-        provider.defaultMaxAge(1, ChronoUnit.DAYS);
         provider.withMaxAge(2, ChronoUnit.DAYS);
 
         String value = provider.getValue(key);
diff --git a/powertools-parameters/powertools-parameters-ssm/src/test/java/software/amazon/lambda/powertools/parameters/ssm/SSMProviderTest.java b/powertools-parameters/powertools-parameters-ssm/src/test/java/software/amazon/lambda/powertools/parameters/ssm/SSMProviderTest.java
index 23ad2cd63..25a06595c 100644
--- a/powertools-parameters/powertools-parameters-ssm/src/test/java/software/amazon/lambda/powertools/parameters/ssm/SSMProviderTest.java
+++ b/powertools-parameters/powertools-parameters-ssm/src/test/java/software/amazon/lambda/powertools/parameters/ssm/SSMProviderTest.java
@@ -197,7 +197,6 @@ private void initMock(String expectedValue) {
         Parameter parameter = Parameter.builder().value(expectedValue).build();
         GetParameterResponse result = GetParameterResponse.builder().parameter(parameter).build();
         Mockito.when(client.getParameter(paramCaptor.capture())).thenReturn(result);
-        provider.defaultMaxAge(1, ChronoUnit.DAYS);
         provider.withMaxAge(2, ChronoUnit.DAYS);
         provider.recursive();
     }
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 a4cdd85af..c4a0ef391 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
@@ -25,6 +25,7 @@
 import static software.amazon.lambda.powertools.parameters.transform.Transformer.json;
 
 import java.time.Clock;
+import java.time.Duration;
 import java.time.temporal.ChronoUnit;
 import java.util.Base64;
 import java.util.HashMap;
@@ -136,8 +137,10 @@ public void get_customTTL_expired_shouldGetValue() {
     }
 
     @Test
+    // TODO Scott - remove this, or change to mutating the CacheManager first?
     public void get_customDefaultTTL_cached_shouldGetFromCache() {
-        provider.defaultMaxAge(12, ChronoUnit.MINUTES).get("foobar");
+        provider.cacheManager.setDefaultExpirationTime(Duration.of(12, MINUTES));
+        provider.get("foobar");
         getFromStore = false;
 
         provider.setClock(offset(clock, of(10, MINUTES)));
@@ -148,7 +151,6 @@ public void get_customDefaultTTL_cached_shouldGetFromCache() {
 
     @Test
     public void get_customDefaultTTL_expired_shouldGetValue() {
-        provider.defaultMaxAge(2, ChronoUnit.MINUTES).get("barbaz");
         getFromStore = false;
 
         provider.setClock(offset(clock, of(3, MINUTES)));
@@ -159,9 +161,7 @@ public void get_customDefaultTTL_expired_shouldGetValue() {
 
     @Test
     public void get_customDefaultTTLAndTTL_cached_shouldGetFromCache() {
-        provider.defaultMaxAge(12, ChronoUnit.MINUTES)
-                .withMaxAge(5, SECONDS)
-                .get("foobaz");
+        provider.get("foobaz");
         getFromStore = false;
 
         provider.setClock(offset(clock, of(4, SECONDS)));
@@ -172,8 +172,7 @@ public void get_customDefaultTTLAndTTL_cached_shouldGetFromCache() {
 
     @Test
     public void get_customDefaultTTLAndTTL_expired_shouldGetValue() {
-        provider.defaultMaxAge(2, ChronoUnit.MINUTES)
-                .withMaxAge(5, SECONDS)
+        provider.withMaxAge(5, SECONDS)
                 .get("bariton");
         getFromStore = false;
 
@@ -274,8 +273,9 @@ public void getObject_customTTL_expired_shouldGetValue() {
     public void getObject_customDefaultTTL_cached_shouldGetFromCache() {
         provider.setValue("{\"foo\":\"Foo\", \"bar\":42, \"baz\":123456789}");
 
-        provider.defaultMaxAge(12, ChronoUnit.MINUTES)
-                .withTransformation(json)
+        provider.cacheManager.setDefaultExpirationTime(Duration.of(12, MINUTES));
+
+        provider.withTransformation(json)
                 .get("foo", ObjectToDeserialize.class);
         getFromStore = false;
 
@@ -286,11 +286,11 @@ public void getObject_customDefaultTTL_cached_shouldGetFromCache() {
     }
 
     @Test
+    // TODO Scott
     public void getObject_customDefaultTTL_expired_shouldGetValue() {
         provider.setValue("{\"foo\":\"Foo\", \"bar\":42, \"baz\":123456789}");
 
-        provider.defaultMaxAge(2, ChronoUnit.MINUTES)
-                .withTransformation(json)
+        provider.withTransformation(json)
                 .get("foo", ObjectToDeserialize.class);
         getFromStore = false;
 
@@ -301,10 +301,10 @@ public void getObject_customDefaultTTL_expired_shouldGetValue() {
     }
 
     @Test
+    // TODO Scott
     public void getObject_customDefaultTTLAndTTL_cached_shouldGetFromCache() {
         provider.setValue("{\"foo\":\"Foo\", \"bar\":42, \"baz\":123456789}");
-        provider.defaultMaxAge(12, ChronoUnit.MINUTES)
-                .withMaxAge(5, SECONDS)
+        provider.withMaxAge(5, SECONDS)
                 .withTransformation(json)
                 .get("foo", ObjectToDeserialize.class);
         getFromStore = false;
@@ -316,11 +316,11 @@ public void getObject_customDefaultTTLAndTTL_cached_shouldGetFromCache() {
     }
 
     @Test
+    // TODO Scott
     public void getObject_customDefaultTTLAndTTL_expired_shouldGetValue() {
         provider.setValue("{\"foo\":\"Foo\", \"bar\":42, \"baz\":123456789}");
 
-        provider.defaultMaxAge(2, ChronoUnit.MINUTES)
-                .withMaxAge(5, SECONDS)
+        provider.withMaxAge(5, SECONDS)
                 .withTransformation(json)
                 .get("foo", ObjectToDeserialize.class);
         getFromStore = false;
diff --git a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/BaseProvider.java b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/BaseProvider.java
index 1b6f5786a..bedace28c 100644
--- a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/BaseProvider.java
+++ b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/BaseProvider.java
@@ -60,25 +60,10 @@ public BaseProvider(CacheManager cacheManager, TransformationManager transformat
      */
     protected abstract Map<String, String> getMultipleValues(String path);
 
-    /**
-     * (Optional) Set the default max age for the cache of all parameters. Override the default 5 seconds.<br/>
-     * If for some parameters, you need to set a different maxAge, use {@link #withMaxAge(int, ChronoUnit)}.<br />
-     * Use {@link #withMaxAge(int, ChronoUnit)} after {#defaultMaxAge(int, ChronoUnit)} in the chain.
-     *
-     * @param maxAge Maximum time to cache the parameter, before calling the underlying parameter store.
-     * @param unit   Unit of time
-     * @return the provider itself in order to chain calls (eg. <pre>provider.defaultMaxAge(10, SECONDS).get("key")</pre>).
-     */
-    public BaseProvider defaultMaxAge(int maxAge, ChronoUnit unit) {
-        Duration duration = Duration.of(maxAge, unit);
-        cacheManager.setDefaultExpirationTime(duration);
-        return this;
-    }
-
     /**
      * (Optional) Builder method to call before {@link #get(String)} or {@link #get(String, Class)}
      * to set cache max age for the parameter to get.<br/><br/>
-     * The max age is reset to default (either 5 or a custom value set with {@link #defaultMaxAge}) after each get,
+     * The max age is reset to default (either 5 or a custom value that may be set on the CacheManager) after each get,
      * so you need to use this method for each parameter to cache with non-default max age.<br/><br/>
      *
      * <b>Not Thread Safe</b>: calling this method simultaneously by several threads

From 8e680f7b8f96752e57044b4acb360e6429e338e4 Mon Sep 17 00:00:00 2001
From: Scott Gerring <gerrings@amazon.com>
Date: Wed, 29 Nov 2023 11:28:43 +0100
Subject: [PATCH 24/45] Refactoring param aspects to pull out shared code

---
 .../appconfig/AppConfigParametersAspect.java  | 23 ++--------
 .../dynamodb/DynamoDbParamAspect.java         | 25 +++--------
 .../secrets/SecretsParamAspect.java           | 22 ++--------
 .../parameters/ssm/SSMParamAspect.java        | 23 ++--------
 .../parameters/BaseParamAspect.java           | 42 +++++++++++++++++++
 .../lambda/powertools/parameters}/pom.xml     |  0
 6 files changed, 58 insertions(+), 77 deletions(-)
 create mode 100644 powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/BaseParamAspect.java
 rename powertools-parameters/{ => src/main/java/software/amazon/lambda/powertools/parameters}/pom.xml (100%)

diff --git a/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParametersAspect.java b/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParametersAspect.java
index dec439302..ac726a031 100644
--- a/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParametersAspect.java
+++ b/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParametersAspect.java
@@ -20,9 +20,10 @@
 import org.aspectj.lang.annotation.Aspect;
 import org.aspectj.lang.annotation.Pointcut;
 import org.aspectj.lang.reflect.FieldSignature;
+import software.amazon.lambda.powertools.parameters.BaseParamAspect;
 
 @Aspect
-public class AppConfigParametersAspect {
+public class AppConfigParametersAspect extends BaseParamAspect {
 
     private static BiFunction<String, String, AppConfigProvider> providerBuilder =
         (String env, String app) -> AppConfigProvider.builder()
@@ -37,28 +38,12 @@ public void getParam(AppConfigParam appConfigParamAnnotation) {
 
     @Around("getParam(appConfigParamAnnotation)")
     public Object injectParam(final ProceedingJoinPoint joinPoint, final AppConfigParam appConfigParamAnnotation) {
-        System.out.println("GET IT");
 
         AppConfigProvider provider = providerBuilder.apply
                 (appConfigParamAnnotation.environment(), appConfigParamAnnotation.application());
 
-        if (appConfigParamAnnotation.transformer().isInterface()) {
-            // No transformation
-            return provider.get(appConfigParamAnnotation.key());
-        } else {
-            FieldSignature s = (FieldSignature) joinPoint.getSignature();
-            if (String.class.isAssignableFrom(s.getFieldType())) {
-                // Basic transformation
-                return provider
-                        .withTransformation(appConfigParamAnnotation.transformer())
-                        .get(appConfigParamAnnotation.key());
-            } else {
-                // Complex transformation
-                return provider
-                        .withTransformation(appConfigParamAnnotation.transformer())
-                        .get(appConfigParamAnnotation.key(), s.getFieldType());
-            }
-        }
+        return getAndTransform(appConfigParamAnnotation.key(), appConfigParamAnnotation.transformer(), provider,
+                (FieldSignature) joinPoint.getSignature());
     }
 
 }
diff --git a/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbParamAspect.java b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbParamAspect.java
index 8e6f97aad..2ac121ed5 100644
--- a/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbParamAspect.java
+++ b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbParamAspect.java
@@ -20,9 +20,11 @@
 import org.aspectj.lang.annotation.Aspect;
 import org.aspectj.lang.annotation.Pointcut;
 import org.aspectj.lang.reflect.FieldSignature;
+import software.amazon.lambda.powertools.parameters.BaseParamAspect;
+import software.amazon.lambda.powertools.parameters.BaseProvider;
 
 @Aspect
-public class DynamoDbParamAspect {
+public class DynamoDbParamAspect extends BaseParamAspect {
 
     private static Function<String, DynamoDbProvider> providerBuilder =
             (String table) -> DynamoDbProvider.builder()
@@ -37,25 +39,8 @@ public void getParam(DynamoDbParam ddbConfigParam) {
     public Object injectParam(final ProceedingJoinPoint joinPoint, final DynamoDbParam ddbConfigParam) {
         System.out.println("GET IT");
 
-        DynamoDbProvider provider = providerBuilder.apply(ddbConfigParam.table());
-
-        if (ddbConfigParam.transformer().isInterface()) {
-            // No transformation
-            return provider.get(ddbConfigParam.key());
-        } else {
-            FieldSignature s = (FieldSignature) joinPoint.getSignature();
-            if (String.class.isAssignableFrom(s.getFieldType())) {
-                // Basic transformation
-                return provider
-                        .withTransformation(ddbConfigParam.transformer())
-                        .get(ddbConfigParam.key());
-            } else {
-                // Complex transformation
-                return provider
-                        .withTransformation(ddbConfigParam.transformer())
-                        .get(ddbConfigParam.key(), s.getFieldType());
-            }
-        }
+        BaseProvider provider = providerBuilder.apply(ddbConfigParam.table());
+        return getAndTransform(ddbConfigParam.key(), ddbConfigParam.transformer(), provider, (FieldSignature)joinPoint.getSignature());
     }
 
 }
diff --git a/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsParamAspect.java b/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsParamAspect.java
index d8055811d..e947a7107 100644
--- a/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsParamAspect.java
+++ b/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsParamAspect.java
@@ -20,9 +20,10 @@
 import org.aspectj.lang.annotation.Aspect;
 import org.aspectj.lang.annotation.Pointcut;
 import org.aspectj.lang.reflect.FieldSignature;
+import software.amazon.lambda.powertools.parameters.BaseParamAspect;
 
 @Aspect
-public class SecretsParamAspect {
+public class SecretsParamAspect extends BaseParamAspect {
 
     private static Supplier<SecretsProvider> providerBuilder = () -> SecretsProvider.builder()
             .build();
@@ -36,24 +37,7 @@ public Object injectParam(final ProceedingJoinPoint joinPoint, final SecretsPara
         System.out.println("GET IT");
 
         SecretsProvider provider = providerBuilder.get();
-
-        if (secretsParam.transformer().isInterface()) {
-            // No transformation
-            return provider.get(secretsParam.key());
-        } else {
-            FieldSignature s = (FieldSignature) joinPoint.getSignature();
-            if (String.class.isAssignableFrom(s.getFieldType())) {
-                // Basic transformation
-                return provider
-                        .withTransformation(secretsParam.transformer())
-                        .get(secretsParam.key());
-            } else {
-                // Complex transformation
-                return provider
-                        .withTransformation(secretsParam.transformer())
-                        .get(secretsParam.key(), s.getFieldType());
-            }
-        }
+        return getAndTransform(secretsParam.key(), secretsParam.transformer(), provider, (FieldSignature)joinPoint.getSignature());
     }
 
 }
diff --git a/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMParamAspect.java b/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMParamAspect.java
index 5207cb0eb..8d684fd78 100644
--- a/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMParamAspect.java
+++ b/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMParamAspect.java
@@ -20,9 +20,11 @@
 import org.aspectj.lang.annotation.Aspect;
 import org.aspectj.lang.annotation.Pointcut;
 import org.aspectj.lang.reflect.FieldSignature;
+import software.amazon.lambda.powertools.parameters.BaseParamAspect;
+import software.amazon.lambda.powertools.parameters.BaseProvider;
 
 @Aspect
-public class SSMParamAspect {
+public class SSMParamAspect extends BaseParamAspect {
 
     // This supplier produces a new SSMProvider each time it is called
     private static Supplier<SSMProvider> providerBuilder = () -> SSMProvider.builder()
@@ -37,24 +39,7 @@ public Object injectParam(final ProceedingJoinPoint joinPoint, final SSMParam SS
         System.out.println("GET IT");
 
         SSMProvider provider = providerBuilder.get();
-
-        if (SSMParam.transformer().isInterface()) {
-            // No transformation
-            return provider.get(SSMParam.key());
-        } else {
-            FieldSignature s = (FieldSignature) joinPoint.getSignature();
-            if (String.class.isAssignableFrom(s.getFieldType())) {
-                // Basic transformation
-                return provider
-                        .withTransformation(SSMParam.transformer())
-                        .get(SSMParam.key());
-            } else {
-                // Complex transformation
-                return provider
-                        .withTransformation(SSMParam.transformer())
-                        .get(SSMParam.key(), s.getFieldType());
-            }
-        }
+        return getAndTransform(SSMParam.key(), SSMParam.transformer(), provider, (FieldSignature)joinPoint.getSignature());
     }
 
 }
diff --git a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/BaseParamAspect.java b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/BaseParamAspect.java
new file mode 100644
index 000000000..acde71cf9
--- /dev/null
+++ b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/BaseParamAspect.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2023 Amazon.com, Inc. or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package software.amazon.lambda.powertools.parameters;
+
+import org.aspectj.lang.reflect.FieldSignature;
+import software.amazon.lambda.powertools.parameters.transform.Transformer;
+
+public class BaseParamAspect {
+
+    protected Object getAndTransform(String key, Class<? extends Transformer> transformer, BaseProvider provider,
+                                     FieldSignature fieldSignature) {
+        if (transformer.isInterface()) {
+            // No transformation
+            return provider.get(key);
+        } else {
+            Class fieldType = fieldSignature.getFieldType();
+            if (String.class.isAssignableFrom(fieldType)) {
+                // Basic transformation
+                return provider
+                        .withTransformation(transformer)
+                        .get(key);
+            } else {
+                // Complex transformation
+                return provider
+                        .withTransformation(transformer)
+                        .get(key, fieldType);
+            }
+        }
+    }
+}
diff --git a/powertools-parameters/pom.xml b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/pom.xml
similarity index 100%
rename from powertools-parameters/pom.xml
rename to powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/pom.xml

From cb87a5c2b185d9d2030c0d1ad13cbc82b66e5f8e Mon Sep 17 00:00:00 2001
From: Scott Gerring <gerrings@amazon.com>
Date: Wed, 29 Nov 2023 11:29:19 +0100
Subject: [PATCH 25/45] Refactoring param aspects to pull out shared code

---
 .../appconfig/AppConfigParametersAspect.java   |  5 +++++
 .../dynamodb/DynamoDbParamAspect.java          |  5 +++++
 .../dynamodb/DynamoDbProviderBuilder.java      |  3 ---
 .../parameters/secrets/SecretsParamAspect.java |  5 +++++
 .../parameters/ssm/SSMParamAspect.java         |  5 +++++
 .../powertools/parameters/BaseParamAspect.java | 18 +++++++++++++++++-
 6 files changed, 37 insertions(+), 4 deletions(-)

diff --git a/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParametersAspect.java b/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParametersAspect.java
index ac726a031..0c7610434 100644
--- a/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParametersAspect.java
+++ b/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParametersAspect.java
@@ -22,6 +22,11 @@
 import org.aspectj.lang.reflect.FieldSignature;
 import software.amazon.lambda.powertools.parameters.BaseParamAspect;
 
+/**
+ * Provides the AppConfig parameter aspect. This aspect is responsible for injecting
+ * parameters from AppConfig into fields annotated with @AppConfigParam. See the
+ * README and Powertools for Lambda (Java) documentation for information on using this feature.
+ */
 @Aspect
 public class AppConfigParametersAspect extends BaseParamAspect {
 
diff --git a/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbParamAspect.java b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbParamAspect.java
index 2ac121ed5..f04b65678 100644
--- a/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbParamAspect.java
+++ b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbParamAspect.java
@@ -23,6 +23,11 @@
 import software.amazon.lambda.powertools.parameters.BaseParamAspect;
 import software.amazon.lambda.powertools.parameters.BaseProvider;
 
+/**
+ * Provides the DynamoDB parameter aspect. This aspect is responsible for injecting
+ * parameters from DynamoDB into fields annotated with @DynamoDbParam. See the
+ * README and Powertools for Lambda (Java) documentation for information on using this feature.
+ */
 @Aspect
 public class DynamoDbParamAspect extends BaseParamAspect {
 
diff --git a/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderBuilder.java b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderBuilder.java
index 6fd525b83..1eab340d6 100644
--- a/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderBuilder.java
+++ b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderBuilder.java
@@ -31,9 +31,6 @@ public class DynamoDbProviderBuilder {
     private String table;
     private CacheManager cacheManager;
     private TransformationManager transformationManager;
-
-    // Allows the user to override default max age
-    private int maxAge;
     private ChronoUnit unit;
 
     static DynamoDbClient createClient() {
diff --git a/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsParamAspect.java b/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsParamAspect.java
index e947a7107..d68ed22d7 100644
--- a/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsParamAspect.java
+++ b/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsParamAspect.java
@@ -22,6 +22,11 @@
 import org.aspectj.lang.reflect.FieldSignature;
 import software.amazon.lambda.powertools.parameters.BaseParamAspect;
 
+/**
+ * Provides the Secrets parameter aspect. This aspect is responsible for injecting
+ * parameters from Secrets Provider into fields annotated with @SecretsParam. See the
+ * README and Powertools for Lambda (Java) documentation for information on using this feature.
+ */
 @Aspect
 public class SecretsParamAspect extends BaseParamAspect {
 
diff --git a/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMParamAspect.java b/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMParamAspect.java
index 8d684fd78..140af0330 100644
--- a/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMParamAspect.java
+++ b/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMParamAspect.java
@@ -23,6 +23,11 @@
 import software.amazon.lambda.powertools.parameters.BaseParamAspect;
 import software.amazon.lambda.powertools.parameters.BaseProvider;
 
+/**
+ * Provides the SSM parameter store parameter aspect. This aspect is responsible for injecting
+ * parameters from SSM Parameter Store into fields annotated with @SSMParam. See the
+ * README and Powertools for Lambda (Java) documentation for information on using this feature.
+ */
 @Aspect
 public class SSMParamAspect extends BaseParamAspect {
 
diff --git a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/BaseParamAspect.java b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/BaseParamAspect.java
index acde71cf9..53ed48733 100644
--- a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/BaseParamAspect.java
+++ b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/BaseParamAspect.java
@@ -17,8 +17,24 @@
 import org.aspectj.lang.reflect.FieldSignature;
 import software.amazon.lambda.powertools.parameters.transform.Transformer;
 
-public class BaseParamAspect {
+/**
+ * Provides a common base for all parameter aspects. This lets us group functionality that
+ * we need to reimplement in each aspect. This class should be extended for each
+ * additional parameter aspect.
+ */
+public abstract class BaseParamAspect {
 
+    /**
+     * Gets the parameter value from the provider and transforms it if necessary. This transformation
+     * is generic across all parameter providers.
+     *
+     * @param key The key of the parameter to get
+     * @param transformer The transformer to use to transform the parameter value
+     * @param provider A concrete instance of the parameter provider to retrieve the value from
+     * @param fieldSignature The signature of the field that the parameter is being injected into
+     *
+     * @return The value of the parameter, transformed if necessary
+     */
     protected Object getAndTransform(String key, Class<? extends Transformer> transformer, BaseProvider provider,
                                      FieldSignature fieldSignature) {
         if (transformer.isInterface()) {

From e283e4ab37f37766e92936b4f5fc4fdbe3a54f26 Mon Sep 17 00:00:00 2001
From: Scott Gerring <gerrings@amazon.com>
Date: Wed, 29 Nov 2023 11:32:14 +0100
Subject: [PATCH 26/45] Undid madness

---
 .../software/amazon/lambda/powertools/parameters => }/pom.xml     | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 rename powertools-parameters/{src/main/java/software/amazon/lambda/powertools/parameters => }/pom.xml (100%)

diff --git a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/pom.xml b/powertools-parameters/pom.xml
similarity index 100%
rename from powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/pom.xml
rename to powertools-parameters/pom.xml

From 9f8486fc0f754d7e010ef0e4419e36874409ec0d Mon Sep 17 00:00:00 2001
From: Scott Gerring <gerrings@amazon.com>
Date: Wed, 29 Nov 2023 11:39:15 +0100
Subject: [PATCH 27/45] Another unused field

---
 .../powertools/parameters/dynamodb/DynamoDbProviderBuilder.java  | 1 -
 1 file changed, 1 deletion(-)

diff --git a/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderBuilder.java b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderBuilder.java
index 1eab340d6..a0dd80186 100644
--- a/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderBuilder.java
+++ b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderBuilder.java
@@ -31,7 +31,6 @@ public class DynamoDbProviderBuilder {
     private String table;
     private CacheManager cacheManager;
     private TransformationManager transformationManager;
-    private ChronoUnit unit;
 
     static DynamoDbClient createClient() {
         return DynamoDbClient.builder()

From a955fac637103bcd8698e2e32e06c1f6b456c681 Mon Sep 17 00:00:00 2001
From: Scott Gerring <gerrings@amazon.com>
Date: Wed, 29 Nov 2023 12:00:55 +0100
Subject: [PATCH 28/45] Checkstyle

---
 .../parameters/appconfig/AppConfigParam.java           |  1 -
 .../appconfig/AppConfigParametersAspect.java           | 10 +++++-----
 .../parameters/appconfig/AppConfigProvider.java        |  3 ++-
 .../parameters/dynamodb/DynamoDbParamAspect.java       |  5 +++--
 .../parameters/dynamodb/DynamoDbProvider.java          |  9 +++++----
 .../parameters/dynamodb/DynamoDbProviderBuilder.java   |  1 -
 .../parameters/secrets/SecretsParamAspect.java         |  5 +++--
 .../powertools/parameters/secrets/SecretsProvider.java |  3 ++-
 .../powertools/parameters/ssm/SSMParamAspect.java      | 10 +++++-----
 .../lambda/powertools/parameters/ssm/SSMProvider.java  |  2 +-
 .../powertools/parameters/ssm/SSMParamAspectTest.java  |  1 +
 .../powertools/parameters/ssm/SSMProviderTest.java     |  3 ++-
 .../lambda/powertools/parameters/BaseParamAspect.java  |  7 +++----
 13 files changed, 32 insertions(+), 28 deletions(-)

diff --git a/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParam.java b/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParam.java
index 07cacf8ba..32ba97a2e 100644
--- a/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParam.java
+++ b/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParam.java
@@ -37,7 +37,6 @@
 
     /**
      * <b>Mandatory</b>. Provide an environment to the {@link AppConfigProvider}
-     *
      */
     String environment();
 
diff --git a/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParametersAspect.java b/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParametersAspect.java
index 0c7610434..5e65dab7b 100644
--- a/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParametersAspect.java
+++ b/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParametersAspect.java
@@ -30,11 +30,11 @@
 @Aspect
 public class AppConfigParametersAspect extends BaseParamAspect {
 
-    private static BiFunction<String, String, AppConfigProvider> providerBuilder =
-        (String env, String app) -> AppConfigProvider.builder()
-                .withEnvironment(env)
-                .withApplication(app)
-                .build();
+    private static final BiFunction<String, String, AppConfigProvider> providerBuilder =
+            (String env, String app) -> AppConfigProvider.builder()
+                    .withEnvironment(env)
+                    .withApplication(app)
+                    .build();
 
 
     @Pointcut("get(* *) && @annotation(appConfigParamAnnotation)")
diff --git a/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProvider.java b/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProvider.java
index 596a2b917..d884e4512 100644
--- a/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProvider.java
+++ b/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProvider.java
@@ -46,7 +46,8 @@ public class AppConfigProvider extends BaseProvider {
     private final String environment;
     private final HashMap<String, EstablishedSession> establishedSessions = new HashMap<>();
 
-    AppConfigProvider(CacheManager cacheManager, TransformationManager transformationManager, AppConfigDataClient client, String environment, String application) {
+    AppConfigProvider(CacheManager cacheManager, TransformationManager transformationManager,
+                      AppConfigDataClient client, String environment, String application) {
         super(cacheManager, transformationManager);
         this.client = client;
         this.application = application;
diff --git a/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbParamAspect.java b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbParamAspect.java
index f04b65678..6f7c8bc0e 100644
--- a/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbParamAspect.java
+++ b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbParamAspect.java
@@ -31,7 +31,7 @@
 @Aspect
 public class DynamoDbParamAspect extends BaseParamAspect {
 
-    private static Function<String, DynamoDbProvider> providerBuilder =
+    private static final Function<String, DynamoDbProvider> providerBuilder =
             (String table) -> DynamoDbProvider.builder()
                     .withTable(table)
                     .build();
@@ -45,7 +45,8 @@ public Object injectParam(final ProceedingJoinPoint joinPoint, final DynamoDbPar
         System.out.println("GET IT");
 
         BaseProvider provider = providerBuilder.apply(ddbConfigParam.table());
-        return getAndTransform(ddbConfigParam.key(), ddbConfigParam.transformer(), provider, (FieldSignature)joinPoint.getSignature());
+        return getAndTransform(ddbConfigParam.key(), ddbConfigParam.transformer(), provider,
+                (FieldSignature) joinPoint.getSignature());
     }
 
 }
diff --git a/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProvider.java b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProvider.java
index 5df1c7e58..adf316fc3 100644
--- a/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProvider.java
+++ b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProvider.java
@@ -40,7 +40,8 @@ public class DynamoDbProvider extends BaseProvider {
     private final DynamoDbClient client;
     private final String tableName;
 
-    DynamoDbProvider(CacheManager cacheManager, TransformationManager transformationManager, DynamoDbClient client, String tableName) {
+    DynamoDbProvider(CacheManager cacheManager, TransformationManager transformationManager, DynamoDbClient client,
+                     String tableName) {
         super(cacheManager, transformationManager);
         this.client = client;
         this.tableName = tableName;
@@ -74,7 +75,7 @@ protected String getValue(String key) {
         // If we don't have an item at the key, we should return null.
         if (resp.hasItem() && !resp.item().values().isEmpty()) {
             if (!resp.item().containsKey("value")) {
-                throw new DynamoDbProviderSchemaException("Missing 'value': " + resp.item().toString());
+                throw new DynamoDbProviderSchemaException("Missing 'value': " + resp.item());
             }
             return resp.item().get("value").s();
         }
@@ -103,10 +104,10 @@ protected Map<String, String> getMultipleValues(String path) {
                 .peek((i) ->
                 {
                     if (!i.containsKey("sk")) {
-                        throw new DynamoDbProviderSchemaException("Missing 'sk': " + i.toString());
+                        throw new DynamoDbProviderSchemaException("Missing 'sk': " + i);
                     }
                     if (!i.containsKey("value")) {
-                        throw new DynamoDbProviderSchemaException("Missing 'value': " + i.toString());
+                        throw new DynamoDbProviderSchemaException("Missing 'value': " + i);
                     }
                 })
                 .collect(
diff --git a/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderBuilder.java b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderBuilder.java
index a0dd80186..66e33c70d 100644
--- a/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderBuilder.java
+++ b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderBuilder.java
@@ -14,7 +14,6 @@
 
 package software.amazon.lambda.powertools.parameters.dynamodb;
 
-import java.time.temporal.ChronoUnit;
 import software.amazon.awssdk.core.SdkSystemSetting;
 import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration;
 import software.amazon.awssdk.core.client.config.SdkAdvancedClientOption;
diff --git a/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsParamAspect.java b/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsParamAspect.java
index d68ed22d7..2d216d94e 100644
--- a/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsParamAspect.java
+++ b/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsParamAspect.java
@@ -30,7 +30,7 @@
 @Aspect
 public class SecretsParamAspect extends BaseParamAspect {
 
-    private static Supplier<SecretsProvider> providerBuilder = () -> SecretsProvider.builder()
+    private static final Supplier<SecretsProvider> providerBuilder = () -> SecretsProvider.builder()
             .build();
 
     @Pointcut("get(* *) && @annotation(secretsParam)")
@@ -42,7 +42,8 @@ public Object injectParam(final ProceedingJoinPoint joinPoint, final SecretsPara
         System.out.println("GET IT");
 
         SecretsProvider provider = providerBuilder.get();
-        return getAndTransform(secretsParam.key(), secretsParam.transformer(), provider, (FieldSignature)joinPoint.getSignature());
+        return getAndTransform(secretsParam.key(), secretsParam.transformer(), provider,
+                (FieldSignature) joinPoint.getSignature());
     }
 
 }
diff --git a/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProvider.java b/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProvider.java
index 600db6212..6fe6194f3 100644
--- a/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProvider.java
+++ b/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProvider.java
@@ -57,7 +57,8 @@ public class SecretsProvider extends BaseProvider {
      *
      * @param client custom client you would like to use.
      */
-    SecretsProvider(CacheManager cacheManager, TransformationManager transformationManager, SecretsManagerClient client) {
+    SecretsProvider(CacheManager cacheManager, TransformationManager transformationManager,
+                    SecretsManagerClient client) {
         super(cacheManager, transformationManager);
         this.client = client;
     }
diff --git a/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMParamAspect.java b/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMParamAspect.java
index 140af0330..2ff73904e 100644
--- a/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMParamAspect.java
+++ b/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMParamAspect.java
@@ -21,7 +21,6 @@
 import org.aspectj.lang.annotation.Pointcut;
 import org.aspectj.lang.reflect.FieldSignature;
 import software.amazon.lambda.powertools.parameters.BaseParamAspect;
-import software.amazon.lambda.powertools.parameters.BaseProvider;
 
 /**
  * Provides the SSM parameter store parameter aspect. This aspect is responsible for injecting
@@ -32,19 +31,20 @@
 public class SSMParamAspect extends BaseParamAspect {
 
     // This supplier produces a new SSMProvider each time it is called
-    private static Supplier<SSMProvider> providerBuilder = () -> SSMProvider.builder()
+    private static final Supplier<SSMProvider> providerBuilder = () -> SSMProvider.builder()
             .build();
 
     @Pointcut("get(* *) && @annotation(secretsParam)")
     public void getParam(SSMParam secretsParam) {
     }
 
-    @Around("getParam(SSMParam)")
-    public Object injectParam(final ProceedingJoinPoint joinPoint, final SSMParam SSMParam) {
+    @Around("getParam(ssmPaam)")
+    public Object injectParam(final ProceedingJoinPoint joinPoint, final SSMParam ssmPaam) {
         System.out.println("GET IT");
 
         SSMProvider provider = providerBuilder.get();
-        return getAndTransform(SSMParam.key(), SSMParam.transformer(), provider, (FieldSignature)joinPoint.getSignature());
+        return getAndTransform(ssmPaam.key(), ssmPaam.transformer(), provider,
+                (FieldSignature) joinPoint.getSignature());
     }
 
 }
diff --git a/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMProvider.java b/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMProvider.java
index 55e1a67c1..3a88c90be 100644
--- a/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMProvider.java
+++ b/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMProvider.java
@@ -75,7 +75,7 @@ public class SSMProvider extends BaseProvider {
      * <p>
      * Use the {@link SSMProviderBuilder} to create an instance of it.
      *
-     * @param client custom client you would like to use.
+     * @param client                custom client you would like to use.
      * @param transformationManager Null, or a transformation manager
      */
     SSMProvider(CacheManager cacheManager, TransformationManager transformationManager, SsmClient client) {
diff --git a/powertools-parameters/powertools-parameters-ssm/src/test/java/software/amazon/lambda/powertools/parameters/ssm/SSMParamAspectTest.java b/powertools-parameters/powertools-parameters-ssm/src/test/java/software/amazon/lambda/powertools/parameters/ssm/SSMParamAspectTest.java
index 3826f5af5..e56d20ffa 100644
--- a/powertools-parameters/powertools-parameters-ssm/src/test/java/software/amazon/lambda/powertools/parameters/ssm/SSMParamAspectTest.java
+++ b/powertools-parameters/powertools-parameters-ssm/src/test/java/software/amazon/lambda/powertools/parameters/ssm/SSMParamAspectTest.java
@@ -20,6 +20,7 @@
 import java.util.function.Supplier;
 import org.junit.jupiter.api.Test;
 import org.mockito.Mockito;
+
 public class SSMParamAspectTest {
 
     // This class tests the SSM Param aspect in the same fashion
diff --git a/powertools-parameters/powertools-parameters-ssm/src/test/java/software/amazon/lambda/powertools/parameters/ssm/SSMProviderTest.java b/powertools-parameters/powertools-parameters-ssm/src/test/java/software/amazon/lambda/powertools/parameters/ssm/SSMProviderTest.java
index 25a06595c..b105da438 100644
--- a/powertools-parameters/powertools-parameters-ssm/src/test/java/software/amazon/lambda/powertools/parameters/ssm/SSMProviderTest.java
+++ b/powertools-parameters/powertools-parameters-ssm/src/test/java/software/amazon/lambda/powertools/parameters/ssm/SSMProviderTest.java
@@ -153,7 +153,8 @@ public void getMultiple_cached_shouldNotCallSSM() {
         provider.get("/prod/app1/key2");
         provider.get("/prod/app1/key3");
 
-        Mockito.verify(client, Mockito.times(1)).getParametersByPath(ArgumentMatchers.any(GetParametersByPathRequest.class));
+        Mockito.verify(client, Mockito.times(1))
+                .getParametersByPath(ArgumentMatchers.any(GetParametersByPathRequest.class));
 
     }
 
diff --git a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/BaseParamAspect.java b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/BaseParamAspect.java
index 53ed48733..f7ebdf97a 100644
--- a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/BaseParamAspect.java
+++ b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/BaseParamAspect.java
@@ -28,11 +28,10 @@ public abstract class BaseParamAspect {
      * Gets the parameter value from the provider and transforms it if necessary. This transformation
      * is generic across all parameter providers.
      *
-     * @param key The key of the parameter to get
-     * @param transformer The transformer to use to transform the parameter value
-     * @param provider A concrete instance of the parameter provider to retrieve the value from
+     * @param key            The key of the parameter to get
+     * @param transformer    The transformer to use to transform the parameter value
+     * @param provider       A concrete instance of the parameter provider to retrieve the value from
      * @param fieldSignature The signature of the field that the parameter is being injected into
-     *
      * @return The value of the parameter, transformed if necessary
      */
     protected Object getAndTransform(String key, Class<? extends Transformer> transformer, BaseProvider provider,

From 9c86b6fa66aba4924e1a3ce09483a6a41b60d965 Mon Sep 17 00:00:00 2001
From: Scott Gerring <gerrings@amazon.com>
Date: Wed, 29 Nov 2023 12:15:10 +0100
Subject: [PATCH 29/45] Drop final modifier for tests

---
 .../parameters/appconfig/AppConfigParametersAspect.java         | 2 +-
 .../powertools/parameters/dynamodb/DynamoDbParamAspect.java     | 2 +-
 .../powertools/parameters/secrets/SecretsParamAspect.java       | 2 +-
 .../amazon/lambda/powertools/parameters/ssm/SSMParamAspect.java | 2 +-
 4 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParametersAspect.java b/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParametersAspect.java
index 5e65dab7b..b151da6e0 100644
--- a/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParametersAspect.java
+++ b/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParametersAspect.java
@@ -30,7 +30,7 @@
 @Aspect
 public class AppConfigParametersAspect extends BaseParamAspect {
 
-    private static final BiFunction<String, String, AppConfigProvider> providerBuilder =
+    private static BiFunction<String, String, AppConfigProvider> providerBuilder =
             (String env, String app) -> AppConfigProvider.builder()
                     .withEnvironment(env)
                     .withApplication(app)
diff --git a/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbParamAspect.java b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbParamAspect.java
index 6f7c8bc0e..d3b49e021 100644
--- a/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbParamAspect.java
+++ b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbParamAspect.java
@@ -31,7 +31,7 @@
 @Aspect
 public class DynamoDbParamAspect extends BaseParamAspect {
 
-    private static final Function<String, DynamoDbProvider> providerBuilder =
+    private static Function<String, DynamoDbProvider> providerBuilder =
             (String table) -> DynamoDbProvider.builder()
                     .withTable(table)
                     .build();
diff --git a/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsParamAspect.java b/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsParamAspect.java
index 2d216d94e..8e897762d 100644
--- a/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsParamAspect.java
+++ b/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsParamAspect.java
@@ -30,7 +30,7 @@
 @Aspect
 public class SecretsParamAspect extends BaseParamAspect {
 
-    private static final Supplier<SecretsProvider> providerBuilder = () -> SecretsProvider.builder()
+    private static Supplier<SecretsProvider> providerBuilder = () -> SecretsProvider.builder()
             .build();
 
     @Pointcut("get(* *) && @annotation(secretsParam)")
diff --git a/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMParamAspect.java b/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMParamAspect.java
index 2ff73904e..3d238149e 100644
--- a/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMParamAspect.java
+++ b/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMParamAspect.java
@@ -31,7 +31,7 @@
 public class SSMParamAspect extends BaseParamAspect {
 
     // This supplier produces a new SSMProvider each time it is called
-    private static final Supplier<SSMProvider> providerBuilder = () -> SSMProvider.builder()
+    private static Supplier<SSMProvider> providerBuilder = () -> SSMProvider.builder()
             .build();
 
     @Pointcut("get(* *) && @annotation(secretsParam)")

From cf170d49dd6c9ee35577fc2f7a5f21941e4c397d Mon Sep 17 00:00:00 2001
From: Scott Gerring <gerrings@amazon.com>
Date: Fri, 8 Dec 2023 09:44:05 +0100
Subject: [PATCH 30/45] Review comments

---
 docs/utilities/parameters.md                  | 340 +++++++++++++-----
 mkdocs.yml                                    |   2 +-
 .../parameters/ssm/SSMProviderBuilder.java    |   5 +-
 .../powertools-parameters-tests/pom.xml       |   5 +-
 .../parameters/BaseProviderTest.java          |  21 +-
 5 files changed, 277 insertions(+), 96 deletions(-)

diff --git a/docs/utilities/parameters.md b/docs/utilities/parameters.md
index 771ffa047..064d6e747 100644
--- a/docs/utilities/parameters.md
+++ b/docs/utilities/parameters.md
@@ -6,9 +6,10 @@ description: Utility
 
 The parameters utilities provide a way to retrieve parameter values from
 [AWS Systems Manager Parameter Store](https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-parameter-store.html), 
-[AWS Secrets Manager](https://aws.amazon.com/secrets-manager/), or [Amazon DynamoDB](https://aws.amazon.com/dynamodb/). 
+[AWS Secrets Manager](https://aws.amazon.com/secrets-manager/), [Amazon DynamoDB](https://aws.amazon.com/dynamodb/), 
+or [AWS AppConfig](https://aws.amazon.com/systems-manager/features/appconfig/). 
  
-**Key features**
+## Key features
 
 * Retrieve one or multiple parameters from an underlying provider in a standard way
 * Cache parameter values for a given amount of time (defaults to 5 seconds)
@@ -18,10 +19,10 @@ The parameters utilities provide a way to retrieve parameter values from
 In order to provide lightweight dependencies, each parameters module is available as its own
 package:
 
-* **Secrets Manager** - `powertools-parameters-secrets` - [A service that centrally manages the lifecycle of secrets](https://aws.amazon.com/secrets-manager/). Start here if you need to manage secrets only. 
-* **SSM Parameter Store** - `powertools-parameters-ssm` - [A secure, hierarchical store for configuration data management](https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-parameter-store.html). Start here if you need to manage various types of configuration data. 
-* **Amazon DynamoDB** -`powertools-parameters-dynamodb` - [A fast, flexible, NoSQL database](https://aws.amazon.com/dynamodb/)
-* **AWS AppConfig** - `powertools-parameters-appconfig` - [An application focussed configuration store](https://aws.amazon.com/systems-manager/features/appconfig) - start here if you are interested in advanced use cases, such as incremental deployment of configuration changes
+* **Secrets Manager** - `powertools-parameters-secrets`  
+* **SSM Parameter Store** - `powertools-parameters-ssm`  
+* **Amazon DynamoDB** -`powertools-parameters-dynamodb` 
+* **AWS AppConfig** - `powertools-parameters-appconfig`
 
 You can easily mix and match parameter providers within the same project for different needs.  
 
@@ -30,13 +31,18 @@ the concrete parameters module you want to use below - see the TODOs!
 
 === "Maven Java 11+"
 
-    ```xml hl_lines="4-7 16 18 26-28"
+    ```xml hl_lines="4-12 17 24 30-34"
     <dependencies>
         ...
         <dependency>
             <groupId>software.amazon.lambda</groupId>
+
              <!-- TODO! Provide the parameters module you want to use here -->
              <artifactId>powertools-parameters-secrets</artifactId>
+             <artifactId>powertools-parameters-ssm</artifactId>
+             <artifactId>powertools-parameters-dynamodb</artifactId>
+             <artifactId>powertools-parameters-appconfig</artifactId>
+
              <version>{{ powertools.version }}</version>
         </dependency>
         ...
@@ -55,9 +61,9 @@ the concrete parameters module you want to use below - see the TODOs!
                      <target>11</target> <!-- or higher -->
                      <complianceLevel>11</complianceLevel> <!-- or higher -->
                      <aspectLibraries>
+                         <!-- TODO! Provide an aspectLibrary for each of the parameters module(s) you want to use here -->
                          <aspectLibrary>
                              <groupId>software.amazon.lambda</groupId>
-                             <!-- TODO! Provide the parameters module you want to use here -->
                              <artifactId>powertools-parameters-secrets</artifactId>
                          </aspectLibrary>
                      </aspectLibraries>
@@ -77,14 +83,19 @@ the concrete parameters module you want to use below - see the TODOs!
 
 === "Maven Java 1.8"
 
-    ```xml hl_lines="4-7 16 18 26-28"
+    ```xml hl_lines="4-12 17 24 30-34"
     <dependencies>
         ...
         <dependency>
             <groupId>software.amazon.lambda</groupId>
+
              <!-- TODO! Provide the parameters module you want to use here -->
              <artifactId>powertools-parameters-secrets</artifactId>
-            <version>{{ powertools.version }}</version>
+             <artifactId>powertools-parameters-ssm</artifactId>
+             <artifactId>powertools-parameters-dynamodb</artifactId>
+             <artifactId>powertools-parameters-appconfig</artifactId>
+
+             <version>{{ powertools.version }}</version>
         </dependency>
         ...
     </dependencies>
@@ -102,10 +113,10 @@ the concrete parameters module you want to use below - see the TODOs!
                      <target>1.8</target>
                      <complianceLevel>1.8</complianceLevel>
                      <aspectLibraries>
+                         <!-- TODO! Provide an aspectLibrary for each of the parameters module(s) you want to use here -->
                          <aspectLibrary>
                              <groupId>software.amazon.lambda</groupId>
-                             <!-- TODO! Provide the parameters module you want to use here -->
-                             <artifactId>powertools-parameters</artifactId>
+                             <artifactId>powertools-parameters-secrets</artifactId>
                          </aspectLibrary>
                      </aspectLibraries>
                  </configuration>
@@ -155,8 +166,8 @@ the concrete parameters module you want to use below - see the TODOs!
             mavenCentral()
         }
         
+         // TODO! Provide an aspectLibrary for each of the parameters module(s) you want to use here
         dependencies {
-            // TODO! Provide the parameters module you want to use here
             aspect 'software.amazon.lambda:powertools-parameters-secrets:{{ powertools.version }}'
         }
         
@@ -168,12 +179,14 @@ the concrete parameters module you want to use below - see the TODOs!
 
 This utility requires additional permissions to work as expected. See the table below:
 
-Provider | Function/Method                                                      | IAM Permission
-------------------------------------------------- |----------------------------------------------------------------------| ---------------------------------------------------------------------------------
-SSM Parameter Store | `SSMProvider.get(String)` `SSMProvider.get(String, Class)`           | `ssm:GetParameter`
-SSM Parameter Store | `SSMProvider.getMultiple(String)`                                    | `ssm:GetParametersByPath`
-Secrets Manager | `SecretsProvider.get(String)` `SecretsProvider.get(String, Class)`   | `secretsmanager:GetSecretValue`
-DynamoDB | `DynamoDBProvider.get(String)` `DynamoDBProvider.getMultiple(string)` | `dynamodb:GetItem` `dynamoDB:Query`
+| Provider  | Function/Method                                                         | IAM Permission                                                            |
+|-----------|-------------------------------------------------------------------------|---------------------------------------------------------------------------|
+| SSM       | `SSMProvider.get(String)` `SSMProvider.get(String, Class)`              | `ssm:GetParameter`                                                        |
+| SSM       | `SSMProvider.getMultiple(String)`                                       | `ssm:GetParametersByPath`                                                 |
+| SSM       | If using `withDecryption(true)`                                         | You must add an additional permission `kms:Decrypt`                       |
+| Secrets   | `SecretsProvider.get(String)` `SecretsProvider.get(String, Class)`      | `secretsmanager:GetSecretValue`                                           |
+| DynamoDB  | `DynamoDBProvider.get(String)` `DynamoDBProvider.getMultiple(string)`   | `dynamodb:GetItem` `dynamoDB:Query`                                       |
+| AppConfig | `AppConfigProvider.get(String)` `AppConfigProvider.getMultiple(string)` | `appconfig:StartConfigurationSession`, `appConfig:GetLatestConfiguration` |
 
 ## Retrieving Parameters
 You can retrieve parameters either using annotations or by using the `xParamProvider` class for each parameter
@@ -184,62 +197,80 @@ a different region or credentials, the former is simpler to use.
 
 === "Secrets Manager: @SecretsParam"
 
-    ```java hl_lines="9 10"
+    ```java hl_lines="8 9"
+    import com.amazonaws.services.lambda.runtime.Context;
     import com.amazonaws.services.lambda.runtime.RequestHandler;
-    import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent;
-    import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent;
     import software.amazon.lambda.powertools.parameters.secrets.SecretsParam;
     
-    public class ParametersFunction implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {
+    public class ParametersFunction implements RequestHandler<String, String> {
+
+        // Annotation-style injection from secrets manager
+        @SecretsParam(key = "/powertools-java/userpwd")
+        String secretParam;
 
-    // Annotation-style injection from secrets manager
-    @SecretsParam(key = "/powertools-java/userpwd")
-    String secretParam;
+        public string handleRequest(String request, Context context) {
+            // Because this is a secret, we probably don't want to return it! Return something indicating
+            // we could access it instead.
+            return "Retrieved a secret, and sensibly refusing to return it!";
+        }
+    }
     ```
 
-=== "Systems Manager: @SSMParam"
+=== "SSM Parameters Store: @SSMParam"
 
-    ```java hl_lines="9 10"
+    ```java hl_lines="8 9"
+    import com.amazonaws.services.lambda.runtime.Context;
     import com.amazonaws.services.lambda.runtime.RequestHandler;
-    import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent;
-    import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent;
     import software.amazon.lambda.powertools.parameters.ssm.SSMParam;
 
-    public class ParametersFunction implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {
+    public class ParametersFunction implements RequestHandler<String, String> {
+
+        // Annotation-style injection from SSM Parameter Store
+        @SSMParam(key = "/powertools-java/param")
+        String ssmParam;
 
-    // Annotation-style injection from SSM Parameter Store
-    @SSMParam(key = "/powertools-java/param")
-    String ssmParam;
+        public string handleRequest(String request, Context context) {
+            return ssmParam; // Request handler simply returns our configuration value
+        }
+    }
     ```
 
 === "DynamoDB: @DyanmoDbParam"
 
-    ```java hl_lines="9 10"
+    ```java hl_lines="8 9"
+    import com.amazonaws.services.lambda.runtime.Context;
     import com.amazonaws.services.lambda.runtime.RequestHandler;
-    import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent;
-    import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent;
     import software.amazon.lambda.powertools.parameters.dynamodb.DynamoDBParam;
 
-    public class ParametersFunction implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {
+    public class ParametersFunction implements RequestHandler<String, String> {
 
-    // Annotation-style injection from DynamoDB
-    @DynamoDbParam(table = "my-test-tablename", key = "myKey")
-    String ddbParam;
+        // Annotation-style injection from DynamoDB
+        @DynamoDbParam(table = "my-test-tablename", key = "myKey")
+        String ddbParam;
+
+        public string handleRequest(String request, Context context) {
+            return ddbParam;  // Request handler simply returns our configuration value
+        }
+    }
     ```
 
 === "AppConfig: @AppConfigParam"
 
-    ```java hl_lines="9 10"
+    ```java hl_lines="8 9"
+    import com.amazonaws.services.lambda.runtime.Context;
     import com.amazonaws.services.lambda.runtime.RequestHandler;
-    import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent;
-    import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent;
     import software.amazon.lambda.powertools.parameters.appconfig.AppConfigParam;
 
-    public class ParametersFunction implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {
+    public class ParametersFunction implements RequestHandler<String, String> {
     
-    // Annotation-style injection from AppConfig
-    @AppConfigParam(application = "my-app", environment = "my-env", key = "myKey")
-    String appConfigParam;
+        // Annotation-style injection from AppConfig
+        @AppConfigParam(application = "my-app", environment = "my-env", key = "myKey")
+        String appConfigParam;
+
+        public string handleRequest(String request, Context context) {
+            return appConfigParam; // Request handler simply returns our configuration value
+        }
+    }
     ```
 
 
@@ -247,19 +278,16 @@ a different region or credentials, the former is simpler to use.
 
 === "Secrets Manager"
 
-    ```java hl_lines="15-19 23-28"
+    ```java hl_lines="13-16 20-25"
     import static software.amazon.lambda.powertools.parameters.transform.Transformer.base64;
     
     import com.amazonaws.services.lambda.runtime.Context;
     import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient;
     import software.amazon.lambda.powertools.parameters.secrets.SecretsProvider;
-    
     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.time.temporal.ChronoUnit;
 
-    public class AppWithSecrets implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {
+    public class RequestHandlerWithParams implements RequestHandler<String, String> {
     
         // Get an instance of the SecretsProvider. We can provide a custom client here if we want,
         // for instance to use a particular region.
@@ -268,7 +296,7 @@ a different region or credentials, the former is simpler to use.
                 .withClient(SecretsManagerClient.builder().build())
                 .build();
     
-        public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent input, Context context) {
+        public String handleRequest(String input, Context context) {
             // Retrieve a single secret
             String value = secretsProvider
                     // Transform parameter from base64
@@ -277,28 +305,25 @@ a different region or credentials, the former is simpler to use.
                     .withMaxAge(10, ChronoUnit.SECONDS)
                     .get("/my/secret");
     
-            // Return the result
-            return new APIGatewayProxyResponseEvent()
-                    .withStatusCode(200)
-                    .withBody(value);
+            // Because this is a secret, we probably don't want to return it! Return something indicating
+            // we could access it instead.
+            return "Retrieved a secret, and sensibly refusing to return it!";
         }
     }
     ```
 
 === "Systems Manager"
 
-    ```java hl_lines="15-19 23-28"
+    ```java hl_lines="13-16 20-27"
     import static software.amazon.lambda.powertools.parameters.transform.Transformer.base64;
     
     import com.amazonaws.services.lambda.runtime.Context;
     import com.amazonaws.services.lambda.runtime.RequestHandler;
-    import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent;
-    import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent;
     import software.amazon.awssdk.services.ssm.SsmClient;
     import software.amazon.lambda.powertools.parameters.ssm.SSMProvider;
     import java.time.temporal.ChronoUnit;
 
-    public class AppWithSecrets implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {
+    public class RequestHandlerWithParams implements RequestHandler<String, String> {
     
         // Get an instance of the SSMProvider. We can provide a custom client here if we want,
         // for instance to use a particular region.
@@ -307,7 +332,7 @@ a different region or credentials, the former is simpler to use.
                 .withClient(SsmClient.builder().build())
                 .build();
     
-        public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent input, Context context) {
+        public String handleRequest(String input, Context context) {
             // Retrieve a single secret
             String value = ssmProvider
                     // Transform parameter from base64
@@ -315,29 +340,27 @@ a different region or credentials, the former is simpler to use.
                     // By default values are cached for 5 seconds, specify 10 seconds instead.
                     .withMaxAge(10, ChronoUnit.SECONDS)
                     .get("/my/secret");
-    
+                    // We might instead want to retrieve multiple secrets at once, returning a Map of key/value pairs
+                    // .getMultiple("/my/secret/path");
+
             // Return the result
-            return new APIGatewayProxyResponseEvent()
-                    .withStatusCode(200)
-                    .withBody(value);
+            return value;
         }
     }
     ```
 
 === "DynamoDB"
 
-    ```java hl_lines="15-19 23-28"
+    ```java hl_lines="13-16 20-27"
     import static software.amazon.lambda.powertools.parameters.transform.Transformer.base64;
     
     import com.amazonaws.services.lambda.runtime.Context;
     import com.amazonaws.services.lambda.runtime.RequestHandler;
-    import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent;
-    import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent;
     import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
     import software.amazon.lambda.powertools.parameters.dynamodb.DynamoDbProvider;
     import java.time.temporal.ChronoUnit;
 
-    public class AppWithSecrets implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {
+    public class RequestHandlerWithParams implements RequestHandler<String, String> {
     
         // Get an instance of the SecretsProvider. We can provide a custom client here if we want,
         // for instance to use a particular region.
@@ -346,7 +369,7 @@ a different region or credentials, the former is simpler to use.
                 .withClient(DynamoDbClient.builder().build())
                 .build();
     
-        public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent input, Context context) {
+        public String handleRequest(String input, Context context) {
             // Retrieve a single secret
             String value = ddbProvider
                     // Transform parameter from base64
@@ -354,29 +377,27 @@ a different region or credentials, the former is simpler to use.
                     // By default values are cached for 5 seconds, specify 10 seconds instead.
                     .withMaxAge(10, ChronoUnit.SECONDS)
                     .get("/my/secret");
+                    // We might instead want to retrieve multiple values at once, returning a Map of key/value pairs
+                    // .getMultiple("my-partition-key-value");
     
             // Return the result
-            return new APIGatewayProxyResponseEvent()
-                    .withStatusCode(200)
-                    .withBody(value);
+            return value;
         }
     }
     ```
 
 === "AppConfig"
 
-    ```java hl_lines="15-19 23-28"
+    ```java hl_lines="13-16 20-25"
     import static software.amazon.lambda.powertools.parameters.transform.Transformer.base64;
     
     import com.amazonaws.services.lambda.runtime.Context;
     import com.amazonaws.services.lambda.runtime.RequestHandler;
-    import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent;
-    import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent;
     import software.amazon.awssdk.services.appconfigdata.AppConfigDataClient;
     import software.amazon.lambda.powertools.parameters.appconfig.AppConfigProvider;
     import java.time.temporal.ChronoUnit;
 
-    public class AppWithSecrets implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {
+    public class RequestHandlerWithParams implements RequestHandler<String, String> {
     
         // Get an instance of the SecretsProvider. We can provide a custom client here if we want,
         // for instance to use a particular region.
@@ -385,7 +406,7 @@ a different region or credentials, the former is simpler to use.
                 .withClient(AppConfigDataClient.builder().build())
                 .build();
     
-        public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent input, Context context) {
+        public String handleRequest(String input, Context context) {
             // Retrieve a single secret
             String value = appConfigProvider
                     // Transform parameter from base64
@@ -395,22 +416,52 @@ a different region or credentials, the former is simpler to use.
                     .get("/my/secret");
     
             // Return the result
-            return new APIGatewayProxyResponseEvent()
-                    .withStatusCode(200)
-                    .withBody(value);
+            return value;
         }
     }    
     ```
 
 ## Advanced configuration
 
+### Default cache timeout
+Each provider uses the CacheManager to cache parameter values. By default, values are cached for 5 seconds. If you
+wish to customize this, you can provide a custom `CacheManager` to your provider with an appropriate timeout configured.
+`CacheManager` instances can also be shared between providers.
+
+=== "Customize Cache"
+
+    ```java hl_lines="9 10 14 19"
+    import java.time.Duration;
+    import software.amazon.lambda.powertools.parameters.appconfig.AppConfigProvider;
+    import software.amazon.lambda.powertools.parameters.cache.CacheManager;
+    
+    public class CustomizeCache {
+        
+        public void CustomizeCache() {
+    
+            CacheManager cacheManager = new CacheManager();
+            cacheManager.setDefaultExpirationTime(Duration.ofSeconds(10));
+    
+            AppConfigProvider paramProvider = AppConfigProvider
+                    .builder()
+                    .withCacheManager(cacheManager)
+                    .withClient(AppConfigDataClient.builder().build())
+                    .build();
+    
+            // We can override the default per `get` 
+            paramProvider.withMaxAge(20, ChronoUnit.SECONDS)
+                    .get("my-param");
+        }
+    }
+    ```
+
 
 ### Transform values
 
 Parameter values can be transformed using ```withTransformation(transformerClass)```.
 Base64 and JSON transformations are provided. For more complex transformation, you need to specify how to deserialize.
 
-!!! warning "`SSMProvider.getMultiple()` does not support transformation and will return simple Strings."
+!!! warning "`getMultiple()` does not support transformation and will return simple Strings."
 
 === "Base64 Transformation"
     ```java
@@ -427,7 +478,7 @@ Base64 and JSON transformations are provided. For more complex transformation, y
                         .get("/my/parameter/json", MyObj.class);
     ```
 
-### Write your own Transformer
+### Create your own Transformer
 
 You can write your own transformer, by implementing the `Transformer` interface and the `applyTransformation()` method.
 For example, if you wish to deserialize XML into an object.
@@ -457,3 +508,122 @@ For example, if you wish to deserialize XML into an object.
                             .withTransformation(XmlTransformer.class)
                             .get("/my/parameter/xml", MyObj.class);
     ```
+
+### Create your own Provider
+You can create your own custom parameter store provider by implementing a handful of classes: 
+
+=== "CustomProvider.java"
+
+    ```java
+    import java.util.Map;
+    import software.amazon.lambda.powertools.parameters.BaseProvider;
+    import software.amazon.lambda.powertools.parameters.cache.CacheManager;
+    import software.amazon.lambda.powertools.parameters.transform.TransformationManager;
+    
+    public class CustomProvider extends BaseProvider {
+    
+        public CustomProvider(CacheManager cacheManager, TransformationManager transformationManager) {
+            super(cacheManager, transformationManager);
+        }
+
+        public CustomProviderBuilder builder() {
+            return new CustomProviderBuilder();
+        }
+    
+        @Override
+        protected String getValue(String key) {
+            throw new RuntimeException("TODO - return a single value");
+        }
+    
+        @Override
+        protected Map<String, String> getMultipleValues(String path) {
+            throw new RuntimeException("TODO - Optional - return multiple values");
+        }
+    }
+    ```
+
+=== "CustomProviderBuilder.java"
+
+    ```java
+    public class CustomProviderBuilder {
+        private CacheManager cacheManager;
+        private TransformationManager transformationManager;
+
+        /**
+         * Create a {@link DynamoDbProvider} instance.
+         *
+         * @return a {@link DynamoDbProvider}
+         */
+        public CustomProvider build() {
+            if (cacheManager == null) {
+                cacheManager = new CacheManager();
+            }
+            return new CustomProvider(cacheManager, transformationManager);
+        }
+
+        /**
+         * Provide a CacheManager to the {@link CustomProvider}
+         *
+         * @param cacheManager the manager that will handle the cache of parameters
+         * @return the builder to chain calls (eg. <pre>builder.withCacheManager().build()</pre>)
+         */
+        public CustomProviderBuilder withCacheManager(CacheManager cacheManager) {
+            this.cacheManager = cacheManager;
+            return this;
+        }
+
+        /**
+         * Provide a transformationManager to the {@link DynamoDbProvider}
+         *
+         * @param transformationManager the manager that will handle transformation of parameters
+         * @return the builder to chain calls (eg. <pre>builder.withTransformationManager().build()</pre>)
+         */
+        public CustomProviderBuilder withTransformationManager(TransformationManager transformationManager) {
+            this.transformationManager = transformationManager;
+            return this;
+        }
+    }
+    ```
+
+=== "CustomProviderParam.java"
+    
+    ```java 
+    import java.lang.annotation.ElementType;
+    import java.lang.annotation.Retention;
+    import java.lang.annotation.RetentionPolicy;
+    import java.lang.annotation.Target;
+    import software.amazon.lambda.powertools.parameters.transform.Transformer;
+    
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target(ElementType.FIELD)
+    public @interface CustomProviderParam {
+        // The parameter key  
+        String key();
+
+        // The transformer to use
+        Class<? extends Transformer> transformer() default Transformer.class;
+    }
+    ```
+
+=== "CustomProviderAspect.java"
+
+    ```java
+    @Aspect
+    public class CustomProviderAspect extends BaseParamAspect {
+    
+        @Pointcut("get(* *) && @annotation(ddbConfigParam)")
+        public void getParam(CustomProviderParam customConfigParam) {
+        }
+    
+        @Around("getParam(customConfigParam)")
+        public Object injectParam(final ProceedingJoinPoint joinPoint, final CustomProviderParam customConfigParam) {
+            System.out.println("GET IT");
+    
+            BaseProvider provider = CustomProvider.builder().build();
+
+            return getAndTransform(customConfigParam.key(), ddbConfigParam.transformer(), provider,
+                    (FieldSignature) joinPoint.getSignature());
+        }
+    
+    }
+    ```
\ No newline at end of file
diff --git a/mkdocs.yml b/mkdocs.yml
index a8569f664..eb28caa7a 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -85,7 +85,7 @@ extra_javascript:
 
 extra:
   powertools:
-    version: 1.18.0 # to update after each release (we do not want snapshot version here)
+    version: 2.0.0-SNAPSHOT # to update after each release (we do not want snapshot version here)
 
 repo_url: https://github.com/aws-powertools/powertools-lambda-java
 edit_uri: edit/main/docs
diff --git a/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMProviderBuilder.java b/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMProviderBuilder.java
index 59616e385..e38fddc84 100644
--- a/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMProviderBuilder.java
+++ b/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMProviderBuilder.java
@@ -25,6 +25,9 @@
 import software.amazon.lambda.powertools.parameters.cache.CacheManager;
 import software.amazon.lambda.powertools.parameters.transform.TransformationManager;
 
+/**
+ * Builder for the {@link SSMProvider}
+ */
 public class SSMProviderBuilder {
     private SsmClient client;
     private CacheManager cacheManager;
@@ -73,7 +76,7 @@ public SSMProviderBuilder withClient(SsmClient client) {
     }
 
     /**
-     * <b>Mandatory</b>. Provide a CacheManager to the {@link SSMProvider}
+     * Provide a CacheManager to the {@link SSMProvider}
      *
      * @param cacheManager the manager that will handle the cache of parameters
      * @return the builder to chain calls (eg. <pre>builder.withCacheManager().build()</pre>)
diff --git a/powertools-parameters/powertools-parameters-tests/pom.xml b/powertools-parameters/powertools-parameters-tests/pom.xml
index a6a177393..d8e9b2a02 100644
--- a/powertools-parameters/powertools-parameters-tests/pom.xml
+++ b/powertools-parameters/powertools-parameters-tests/pom.xml
@@ -13,7 +13,7 @@
     <artifactId>powertools-parameters-tests</artifactId>
     <description>Powertools parameters tests that cut across all the parameters providers</description>
     <properties>
-        <!-- Don't deploy the examples -->
+        <!-- Don't deploy the tests -->
         <maven.deploy.skip>true</maven.deploy.skip>
     </properties>
 
@@ -21,16 +21,19 @@
         <dependency>
             <groupId>software.amazon.lambda</groupId>
             <artifactId>powertools-parameters-ssm</artifactId>
+            <scope>test</scope>
             <version>${project.version}</version>
         </dependency>
         <dependency>
             <groupId>software.amazon.lambda</groupId>
             <artifactId>powertools-parameters-secrets</artifactId>
+            <scope>test</scope>
             <version>${project.version}</version>
         </dependency>
         <dependency>
             <groupId>software.amazon.lambda</groupId>
             <artifactId>powertools-parameters-dynamodb</artifactId>
+            <scope>test</scope>
             <version>${project.version}</version>
         </dependency>
 
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 c4a0ef391..e2b46599e 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
@@ -137,7 +137,6 @@ public void get_customTTL_expired_shouldGetValue() {
     }
 
     @Test
-    // TODO Scott - remove this, or change to mutating the CacheManager first?
     public void get_customDefaultTTL_cached_shouldGetFromCache() {
         provider.cacheManager.setDefaultExpirationTime(Duration.of(12, MINUTES));
         provider.get("foobar");
@@ -151,6 +150,7 @@ public void get_customDefaultTTL_cached_shouldGetFromCache() {
 
     @Test
     public void get_customDefaultTTL_expired_shouldGetValue() {
+        provider.cacheManager.setDefaultExpirationTime(Duration.of(2, MINUTES));
         getFromStore = false;
 
         provider.setClock(offset(clock, of(3, MINUTES)));
@@ -172,8 +172,10 @@ public void get_customDefaultTTLAndTTL_cached_shouldGetFromCache() {
 
     @Test
     public void get_customDefaultTTLAndTTL_expired_shouldGetValue() {
-        provider.withMaxAge(5, SECONDS)
-                .get("bariton");
+
+        provider.cacheManager.setDefaultExpirationTime(Duration.ofSeconds(5));
+
+        provider.get("bariton");
         getFromStore = false;
 
         provider.setClock(offset(clock, of(6, SECONDS)));
@@ -286,10 +288,11 @@ public void getObject_customDefaultTTL_cached_shouldGetFromCache() {
     }
 
     @Test
-    // TODO Scott
     public void getObject_customDefaultTTL_expired_shouldGetValue() {
         provider.setValue("{\"foo\":\"Foo\", \"bar\":42, \"baz\":123456789}");
 
+        provider.cacheManager.setDefaultExpirationTime(Duration.of(2, MINUTES));
+
         provider.withTransformation(json)
                 .get("foo", ObjectToDeserialize.class);
         getFromStore = false;
@@ -301,11 +304,12 @@ public void getObject_customDefaultTTL_expired_shouldGetValue() {
     }
 
     @Test
-    // TODO Scott
     public void getObject_customDefaultTTLAndTTL_cached_shouldGetFromCache() {
         provider.setValue("{\"foo\":\"Foo\", \"bar\":42, \"baz\":123456789}");
-        provider.withMaxAge(5, SECONDS)
-                .withTransformation(json)
+
+        provider.cacheManager.setDefaultExpirationTime(Duration.ofSeconds(5));
+
+        provider.withTransformation(json)
                 .get("foo", ObjectToDeserialize.class);
         getFromStore = false;
 
@@ -316,10 +320,11 @@ public void getObject_customDefaultTTLAndTTL_cached_shouldGetFromCache() {
     }
 
     @Test
-    // TODO Scott
     public void getObject_customDefaultTTLAndTTL_expired_shouldGetValue() {
         provider.setValue("{\"foo\":\"Foo\", \"bar\":42, \"baz\":123456789}");
 
+        provider.cacheManager.setDefaultExpirationTime(Duration.ofMinutes(2));
+
         provider.withMaxAge(5, SECONDS)
                 .withTransformation(json)
                 .get("foo", ObjectToDeserialize.class);

From 23c7e1c367043c513e8337a896635f3e7fe70729 Mon Sep 17 00:00:00 2001
From: Scott Gerring <gerrings@amazon.com>
Date: Fri, 8 Dec 2023 12:48:36 +0100
Subject: [PATCH 31/45] Incremental doc changes

---
 docs/utilities/parameters.md | 108 ++++++++++++++++++++++-------------
 1 file changed, 69 insertions(+), 39 deletions(-)

diff --git a/docs/utilities/parameters.md b/docs/utilities/parameters.md
index 064d6e747..971b2c509 100644
--- a/docs/utilities/parameters.md
+++ b/docs/utilities/parameters.md
@@ -278,14 +278,13 @@ a different region or credentials, the former is simpler to use.
 
 === "Secrets Manager"
 
-    ```java hl_lines="13-16 20-25"
+    ```java hl_lines="12-15 19"
     import static software.amazon.lambda.powertools.parameters.transform.Transformer.base64;
     
     import com.amazonaws.services.lambda.runtime.Context;
     import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient;
     import software.amazon.lambda.powertools.parameters.secrets.SecretsProvider;
     import com.amazonaws.services.lambda.runtime.RequestHandler;
-    import java.time.temporal.ChronoUnit;
 
     public class RequestHandlerWithParams implements RequestHandler<String, String> {
     
@@ -298,12 +297,7 @@ a different region or credentials, the former is simpler to use.
     
         public String handleRequest(String input, Context context) {
             // Retrieve a single secret
-            String value = secretsProvider
-                    // Transform parameter from base64
-                    .withTransformation(base64)
-                    // By default values are cached for 5 seconds, specify 10 seconds instead.
-                    .withMaxAge(10, ChronoUnit.SECONDS)
-                    .get("/my/secret");
+            String value = secretsProvider.get("/my/secret");
     
             // Because this is a secret, we probably don't want to return it! Return something indicating
             // we could access it instead.
@@ -314,14 +308,13 @@ a different region or credentials, the former is simpler to use.
 
 === "Systems Manager"
 
-    ```java hl_lines="13-16 20-27"
+    ```java hl_lines="12-15 19-20 22"
     import static software.amazon.lambda.powertools.parameters.transform.Transformer.base64;
     
     import com.amazonaws.services.lambda.runtime.Context;
     import com.amazonaws.services.lambda.runtime.RequestHandler;
     import software.amazon.awssdk.services.ssm.SsmClient;
     import software.amazon.lambda.powertools.parameters.ssm.SSMProvider;
-    import java.time.temporal.ChronoUnit;
 
     public class RequestHandlerWithParams implements RequestHandler<String, String> {
     
@@ -335,10 +328,6 @@ a different region or credentials, the former is simpler to use.
         public String handleRequest(String input, Context context) {
             // Retrieve a single secret
             String value = ssmProvider
-                    // Transform parameter from base64
-                    .withTransformation(base64)
-                    // By default values are cached for 5 seconds, specify 10 seconds instead.
-                    .withMaxAge(10, ChronoUnit.SECONDS)
                     .get("/my/secret");
                     // We might instead want to retrieve multiple secrets at once, returning a Map of key/value pairs
                     // .getMultiple("/my/secret/path");
@@ -351,14 +340,13 @@ a different region or credentials, the former is simpler to use.
 
 === "DynamoDB"
 
-    ```java hl_lines="13-16 20-27"
+    ```java hl_lines="12-15 19-20 22"
     import static software.amazon.lambda.powertools.parameters.transform.Transformer.base64;
     
     import com.amazonaws.services.lambda.runtime.Context;
     import com.amazonaws.services.lambda.runtime.RequestHandler;
     import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
     import software.amazon.lambda.powertools.parameters.dynamodb.DynamoDbProvider;
-    import java.time.temporal.ChronoUnit;
 
     public class RequestHandlerWithParams implements RequestHandler<String, String> {
     
@@ -372,10 +360,6 @@ a different region or credentials, the former is simpler to use.
         public String handleRequest(String input, Context context) {
             // Retrieve a single secret
             String value = ddbProvider
-                    // Transform parameter from base64
-                    .withTransformation(base64)
-                    // By default values are cached for 5 seconds, specify 10 seconds instead.
-                    .withMaxAge(10, ChronoUnit.SECONDS)
                     .get("/my/secret");
                     // We might instead want to retrieve multiple values at once, returning a Map of key/value pairs
                     // .getMultiple("my-partition-key-value");
@@ -388,14 +372,13 @@ a different region or credentials, the former is simpler to use.
 
 === "AppConfig"
 
-    ```java hl_lines="13-16 20-25"
+    ```java hl_lines="12-15 19-20"
     import static software.amazon.lambda.powertools.parameters.transform.Transformer.base64;
     
     import com.amazonaws.services.lambda.runtime.Context;
     import com.amazonaws.services.lambda.runtime.RequestHandler;
     import software.amazon.awssdk.services.appconfigdata.AppConfigDataClient;
     import software.amazon.lambda.powertools.parameters.appconfig.AppConfigProvider;
-    import java.time.temporal.ChronoUnit;
 
     public class RequestHandlerWithParams implements RequestHandler<String, String> {
     
@@ -409,10 +392,6 @@ a different region or credentials, the former is simpler to use.
         public String handleRequest(String input, Context context) {
             // Retrieve a single secret
             String value = appConfigProvider
-                    // Transform parameter from base64
-                    .withTransformation(base64)
-                    // By default values are cached for 5 seconds, specify 10 seconds instead.
-                    .withMaxAge(10, ChronoUnit.SECONDS)
                     .get("/my/secret");
     
             // Return the result
@@ -423,14 +402,38 @@ a different region or credentials, the former is simpler to use.
 
 ## Advanced configuration
 
-### Default cache timeout
-Each provider uses the CacheManager to cache parameter values. By default, values are cached for 5 seconds. If you
-wish to customize this, you can provide a custom `CacheManager` to your provider with an appropriate timeout configured.
-`CacheManager` instances can also be shared between providers.
+### Caching
+Each provider uses the CacheManager to cache parameter values. When a value is retrieved using from the provider, a 
+custom cache duration can be provided using `withMaxAge(duration, unit)`. 
+
+If this is not specified, the default value set on the CacheManager itself will be used. This default can be customized
+by calling `setDefaultExpirationTime(duration, unit)` on the CacheManager.
 
-=== "Customize Cache"
+=== "Customize Cache - Per Item"
 
-    ```java hl_lines="9 10 14 19"
+    ```java hl_lines="14 15"
+    import java.time.Duration;
+    import software.amazon.lambda.powertools.parameters.appconfig.AppConfigProvider;
+    import software.amazon.lambda.powertools.parameters.cache.CacheManager;
+    
+    public class CustomizeCacheTimeout {
+        
+        public void CustomizeCache() {
+    
+            AppConfigProvider paramProvider = AppConfigProvider
+                    .builder()
+                    .build();
+    
+            // Cache for 20 seconds, rather than the default 5.
+            return paramProvider.withMaxAge(20, ChronoUnit.SECONDS)
+                    .get("my-param");
+        }
+    }
+    ```
+
+=== "Customize Cache - Change Default"
+
+    ```java hl_lines="9 10 14 19 22-25"
     import java.time.Duration;
     import software.amazon.lambda.powertools.parameters.appconfig.AppConfigProvider;
     import software.amazon.lambda.powertools.parameters.cache.CacheManager;
@@ -448,9 +451,15 @@ wish to customize this, you can provide a custom `CacheManager` to your provider
                     .withClient(AppConfigDataClient.builder().build())
                     .build();
     
-            // We can override the default per `get` 
-            paramProvider.withMaxAge(20, ChronoUnit.SECONDS)
-                    .get("my-param");
+            // Will use the default specified above - 10 seconds 
+            String myParam1 = paramProvider.get("myParam1");
+
+            // Will override the default above 
+            String myParam2 = paramProvider
+                .withMaxAge(20, ChronoUnit.SECONDS)
+                .get("myParam2"); 
+
+            return myParam2;
         }
     }
     ```
@@ -478,6 +487,10 @@ Base64 and JSON transformations are provided. For more complex transformation, y
                         .get("/my/parameter/json", MyObj.class);
     ```
 
+### Decrypt Values
+
+
+
 ### Create your own Transformer
 
 You can write your own transformer, by implementing the `Transformer` interface and the `applyTransformation()` method.
@@ -485,7 +498,7 @@ For example, if you wish to deserialize XML into an object.
 
 === "XmlTransformer.java"
 
-    ```java hl_lines="1"
+    ```java
     public class XmlTransformer<T> implements Transformer<T> {
     
         private final XmlMapper mapper = new XmlMapper();
@@ -520,6 +533,10 @@ You can create your own custom parameter store provider by implementing a handfu
     import software.amazon.lambda.powertools.parameters.cache.CacheManager;
     import software.amazon.lambda.powertools.parameters.transform.TransformationManager;
     
+    /**
+    Our custom parameter provider itself. This does the heavy lifting of retrieving
+    parameters from whatever our underlying parameter store might be.
+    */
     public class CustomProvider extends BaseProvider {
     
         public CustomProvider(CacheManager cacheManager, TransformationManager transformationManager) {
@@ -545,14 +562,17 @@ You can create your own custom parameter store provider by implementing a handfu
 === "CustomProviderBuilder.java"
 
     ```java
+    /**
+    Provides a builder-style interface to configure our @{link CustomProvider}.
+    */
     public class CustomProviderBuilder {
         private CacheManager cacheManager;
         private TransformationManager transformationManager;
 
         /**
-         * Create a {@link DynamoDbProvider} instance.
+         * Create a {@link CustomProvider} instance.
          *
-         * @return a {@link DynamoDbProvider}
+         * @return a {@link CustomProvider}
          */
         public CustomProvider build() {
             if (cacheManager == null) {
@@ -573,7 +593,7 @@ You can create your own custom parameter store provider by implementing a handfu
         }
 
         /**
-         * Provide a transformationManager to the {@link DynamoDbProvider}
+         * Provide a transformationManager to the {@link CustomProvider}
          *
          * @param transformationManager the manager that will handle transformation of parameters
          * @return the builder to chain calls (eg. <pre>builder.withTransformationManager().build()</pre>)
@@ -594,6 +614,11 @@ You can create your own custom parameter store provider by implementing a handfu
     import java.lang.annotation.Target;
     import software.amazon.lambda.powertools.parameters.transform.Transformer;
     
+    /**
+    Aspect to inject a parameter from our custom provider. Note that if you
+    want to implement a provider _without_ an Aspect and field injection, you can
+    skip implementing both this and the {@link CustomProviderAspect} class.
+    */
     @Retention(RetentionPolicy.RUNTIME)
     @Target(ElementType.FIELD)
     public @interface CustomProviderParam {
@@ -608,6 +633,11 @@ You can create your own custom parameter store provider by implementing a handfu
 === "CustomProviderAspect.java"
 
     ```java
+
+    /**
+    Aspect to inject a parameter from our custom provider where the {@link CustomProviderParam}
+    annotation is used.
+    */
     @Aspect
     public class CustomProviderAspect extends BaseParamAspect {
     

From 646bd54942dd28c48b068f6312feeac8932555a7 Mon Sep 17 00:00:00 2001
From: Scott Gerring <gerrings@amazon.com>
Date: Fri, 8 Dec 2023 13:08:53 +0100
Subject: [PATCH 32/45] Cleanup

---
 docs/utilities/parameters.md | 174 ++++++++++++++++++++++-------------
 1 file changed, 112 insertions(+), 62 deletions(-)

diff --git a/docs/utilities/parameters.md b/docs/utilities/parameters.md
index 971b2c509..23ccd5368 100644
--- a/docs/utilities/parameters.md
+++ b/docs/utilities/parameters.md
@@ -193,7 +193,13 @@ You can retrieve parameters either using annotations or by using the `xParamProv
 provider directly. The latter is useful if you need to configure the underlying SDK client, for example to use
 a different region or credentials, the former is simpler to use.
 
-### Using Annotations
+## Built-in provider classes
+
+This section describes the built-in provider classes for each parameter store, providing
+examples showing how to inject parameters using annotations, and how to use the provider
+interface. In cases where a provider supports extra features, these will also be described.
+
+### Secrets Manager
 
 === "Secrets Manager: @SecretsParam"
 
@@ -216,66 +222,6 @@ a different region or credentials, the former is simpler to use.
     }
     ```
 
-=== "SSM Parameters Store: @SSMParam"
-
-    ```java hl_lines="8 9"
-    import com.amazonaws.services.lambda.runtime.Context;
-    import com.amazonaws.services.lambda.runtime.RequestHandler;
-    import software.amazon.lambda.powertools.parameters.ssm.SSMParam;
-
-    public class ParametersFunction implements RequestHandler<String, String> {
-
-        // Annotation-style injection from SSM Parameter Store
-        @SSMParam(key = "/powertools-java/param")
-        String ssmParam;
-
-        public string handleRequest(String request, Context context) {
-            return ssmParam; // Request handler simply returns our configuration value
-        }
-    }
-    ```
-
-=== "DynamoDB: @DyanmoDbParam"
-
-    ```java hl_lines="8 9"
-    import com.amazonaws.services.lambda.runtime.Context;
-    import com.amazonaws.services.lambda.runtime.RequestHandler;
-    import software.amazon.lambda.powertools.parameters.dynamodb.DynamoDBParam;
-
-    public class ParametersFunction implements RequestHandler<String, String> {
-
-        // Annotation-style injection from DynamoDB
-        @DynamoDbParam(table = "my-test-tablename", key = "myKey")
-        String ddbParam;
-
-        public string handleRequest(String request, Context context) {
-            return ddbParam;  // Request handler simply returns our configuration value
-        }
-    }
-    ```
-
-=== "AppConfig: @AppConfigParam"
-
-    ```java hl_lines="8 9"
-    import com.amazonaws.services.lambda.runtime.Context;
-    import com.amazonaws.services.lambda.runtime.RequestHandler;
-    import software.amazon.lambda.powertools.parameters.appconfig.AppConfigParam;
-
-    public class ParametersFunction implements RequestHandler<String, String> {
-    
-        // Annotation-style injection from AppConfig
-        @AppConfigParam(application = "my-app", environment = "my-env", key = "myKey")
-        String appConfigParam;
-
-        public string handleRequest(String request, Context context) {
-            return appConfigParam; // Request handler simply returns our configuration value
-        }
-    }
-    ```
-
-
-### Using the `ParamProvider` classes
-
 === "Secrets Manager"
 
     ```java hl_lines="12-15 19"
@@ -306,7 +252,36 @@ a different region or credentials, the former is simpler to use.
     }
     ```
 
-=== "Systems Manager"
+### SSM Parameter Store
+
+The AWS Systems Manager Parameter Store provider supports two additional arguments for the `get()` and `getMultiple()` methods:
+
+| Option     | Default | Description |
+|---------------|---------|-------------|
+| **withDecryption()**   | `False` | Will automatically decrypt the parameter. |
+| **recursive()** | `False`  | For `getMultiple()` only, will fetch all parameter values recursively based on a path prefix. |
+
+
+=== "SSM Parameter Store: @SSMParam"
+
+    ```java hl_lines="8 9"
+    import com.amazonaws.services.lambda.runtime.Context;
+    import com.amazonaws.services.lambda.runtime.RequestHandler;
+    import software.amazon.lambda.powertools.parameters.ssm.SSMParam;
+
+    public class ParametersFunction implements RequestHandler<String, String> {
+
+        // Annotation-style injection from SSM Parameter Store
+        @SSMParam(key = "/powertools-java/param")
+        String ssmParam;
+
+        public string handleRequest(String request, Context context) {
+            return ssmParam; // Request handler simply returns our configuration value
+        }
+    }
+    ```
+
+=== "SSM"
 
     ```java hl_lines="12-15 19-20 22"
     import static software.amazon.lambda.powertools.parameters.transform.Transformer.base64;
@@ -338,6 +313,46 @@ a different region or credentials, the former is simpler to use.
     }
     ```
 
+=== "SSM: Additional Options"
+
+    ```java hl_lines="9 12"
+    import software.amazon.lambda.powertools.parameters.SSMProvider;
+    import software.amazon.lambda.powertools.parameters.ParamManager;
+
+    public class AppWithSSM implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {
+        // Get an instance of the SSM Provider
+        SSMProvider ssmProvider = ParamManager.getSsmProvider();
+    
+        // Retrieve a single parameter and decrypt it
+        String value = ssmProvider.withDecryption().get("/my/parameter");
+    
+        // Retrieve multiple parameters recursively from a path prefix
+        Map<String, String> values = ssmProvider.recursive().getMultiple("/my/path/prefix");
+    
+    }
+    ```
+
+### DynamoDB
+
+=== "DynamoDB: @DyanmoDbParam"
+
+    ```java hl_lines="8 9"
+    import com.amazonaws.services.lambda.runtime.Context;
+    import com.amazonaws.services.lambda.runtime.RequestHandler;
+    import software.amazon.lambda.powertools.parameters.dynamodb.DynamoDBParam;
+
+    public class ParametersFunction implements RequestHandler<String, String> {
+
+        // Annotation-style injection from DynamoDB
+        @DynamoDbParam(table = "my-test-tablename", key = "myKey")
+        String ddbParam;
+
+        public string handleRequest(String request, Context context) {
+            return ddbParam;  // Request handler simply returns our configuration value
+        }
+    }
+    ```
+
 === "DynamoDB"
 
     ```java hl_lines="12-15 19-20 22"
@@ -370,6 +385,27 @@ a different region or credentials, the former is simpler to use.
     }
     ```
 
+### AppConfig
+
+=== "AppConfig: @AppConfigParam"
+
+    ```java hl_lines="8 9"
+    import com.amazonaws.services.lambda.runtime.Context;
+    import com.amazonaws.services.lambda.runtime.RequestHandler;
+    import software.amazon.lambda.powertools.parameters.appconfig.AppConfigParam;
+
+    public class ParametersFunction implements RequestHandler<String, String> {
+    
+        // Annotation-style injection from AppConfig
+        @AppConfigParam(application = "my-app", environment = "my-env", key = "myKey")
+        String appConfigParam;
+
+        public string handleRequest(String request, Context context) {
+            return appConfigParam; // Request handler simply returns our configuration value
+        }
+    }
+    ```
+
 === "AppConfig"
 
     ```java hl_lines="12-15 19-20"
@@ -522,6 +558,20 @@ For example, if you wish to deserialize XML into an object.
                             .get("/my/parameter/xml", MyObj.class);
     ```
 
+### Fluent API
+
+To simplify the use of the library, you can chain all method calls before a get.
+
+=== "Fluent API call"
+
+    ```java
+        ssmProvider
+          .defaultMaxAge(10, SECONDS)     // will set 10 seconds as the default cache TTL
+          .withMaxAge(1, MINUTES)         // will set the cache TTL for this value at 1 minute
+          .withTransformation(json)       // json is a static import from Transformer.json
+          .withDecryption()               // enable decryption of the parameter value
+          .get("/my/param", MyObj.class); // finally get the value
+
 ### Create your own Provider
 You can create your own custom parameter store provider by implementing a handful of classes: 
 

From e994192135d23475f050975590829bf9dea88256 Mon Sep 17 00:00:00 2001
From: Scott Gerring <scottgerring@users.noreply.github.com>
Date: Fri, 8 Dec 2023 14:12:52 +0100
Subject: [PATCH 33/45] Apply suggestions from code review
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Co-authored-by: Jérôme Van Der Linden <117538+jeromevdl@users.noreply.github.com>
---
 docs/utilities/parameters.md | 44 +++++++++++++++++-------------------
 1 file changed, 21 insertions(+), 23 deletions(-)

diff --git a/docs/utilities/parameters.md b/docs/utilities/parameters.md
index 23ccd5368..38de7b5d3 100644
--- a/docs/utilities/parameters.md
+++ b/docs/utilities/parameters.md
@@ -222,7 +222,7 @@ interface. In cases where a provider supports extra features, these will also be
     }
     ```
 
-=== "Secrets Manager"
+=== "Secrets Manager: SecretsProvider"
 
     ```java hl_lines="12-15 19"
     import static software.amazon.lambda.powertools.parameters.transform.Transformer.base64;
@@ -281,7 +281,7 @@ The AWS Systems Manager Parameter Store provider supports two additional argumen
     }
     ```
 
-=== "SSM"
+=== "SSM Parameter Store: SSMProvider"
 
     ```java hl_lines="12-15 19-20 22"
     import static software.amazon.lambda.powertools.parameters.transform.Transformer.base64;
@@ -313,7 +313,7 @@ The AWS Systems Manager Parameter Store provider supports two additional argumen
     }
     ```
 
-=== "SSM: Additional Options"
+=== "SSM Parameter Store: Additional Options"
 
     ```java hl_lines="9 12"
     import software.amazon.lambda.powertools.parameters.SSMProvider;
@@ -353,7 +353,7 @@ The AWS Systems Manager Parameter Store provider supports two additional argumen
     }
     ```
 
-=== "DynamoDB"
+=== "DynamoDB: DynamoDbProvider"
 
     ```java hl_lines="12-15 19-20 22"
     import static software.amazon.lambda.powertools.parameters.transform.Transformer.base64;
@@ -406,7 +406,7 @@ The AWS Systems Manager Parameter Store provider supports two additional argumen
     }
     ```
 
-=== "AppConfig"
+=== "AppConfig: AppConfigProvider"
 
     ```java hl_lines="12-15 19-20"
     import static software.amazon.lambda.powertools.parameters.transform.Transformer.base64;
@@ -439,11 +439,11 @@ The AWS Systems Manager Parameter Store provider supports two additional argumen
 ## Advanced configuration
 
 ### Caching
-Each provider uses the CacheManager to cache parameter values. When a value is retrieved using from the provider, a 
+Each provider uses the `CacheManager` to cache parameter values. When a value is retrieved using from the provider, a 
 custom cache duration can be provided using `withMaxAge(duration, unit)`. 
 
-If this is not specified, the default value set on the CacheManager itself will be used. This default can be customized
-by calling `setDefaultExpirationTime(duration, unit)` on the CacheManager.
+If this is not specified, the default value set on the `CacheManager` itself will be used. This default can be customized
+by calling `setDefaultExpirationTime(duration, unit)` on the `CacheManager`.
 
 === "Customize Cache - Per Item"
 
@@ -523,11 +523,9 @@ Base64 and JSON transformations are provided. For more complex transformation, y
                         .get("/my/parameter/json", MyObj.class);
     ```
 
-### Decrypt Values
 
 
-
-### Create your own Transformer
+#### Create your own Transformer
 
 You can write your own transformer, by implementing the `Transformer` interface and the `applyTransformation()` method.
 For example, if you wish to deserialize XML into an object.
@@ -584,9 +582,9 @@ You can create your own custom parameter store provider by implementing a handfu
     import software.amazon.lambda.powertools.parameters.transform.TransformationManager;
     
     /**
-    Our custom parameter provider itself. This does the heavy lifting of retrieving
-    parameters from whatever our underlying parameter store might be.
-    */
+     * Our custom parameter provider itself. This does the heavy lifting of retrieving
+     * parameters from whatever our underlying parameter store might be.
+    **/
     public class CustomProvider extends BaseProvider {
     
         public CustomProvider(CacheManager cacheManager, TransformationManager transformationManager) {
@@ -613,8 +611,8 @@ You can create your own custom parameter store provider by implementing a handfu
 
     ```java
     /**
-    Provides a builder-style interface to configure our @{link CustomProvider}.
-    */
+     * Provides a builder-style interface to configure our @{link CustomProvider}.
+    **/
     public class CustomProviderBuilder {
         private CacheManager cacheManager;
         private TransformationManager transformationManager;
@@ -665,10 +663,10 @@ You can create your own custom parameter store provider by implementing a handfu
     import software.amazon.lambda.powertools.parameters.transform.Transformer;
     
     /**
-    Aspect to inject a parameter from our custom provider. Note that if you
-    want to implement a provider _without_ an Aspect and field injection, you can
-    skip implementing both this and the {@link CustomProviderAspect} class.
-    */
+     * Aspect to inject a parameter from our custom provider. Note that if you
+     * want to implement a provider _without_ an Aspect and field injection, you can
+     * skip implementing both this and the {@link CustomProviderAspect} class.
+    **/
     @Retention(RetentionPolicy.RUNTIME)
     @Target(ElementType.FIELD)
     public @interface CustomProviderParam {
@@ -685,9 +683,9 @@ You can create your own custom parameter store provider by implementing a handfu
     ```java
 
     /**
-    Aspect to inject a parameter from our custom provider where the {@link CustomProviderParam}
-    annotation is used.
-    */
+     * Aspect to inject a parameter from our custom provider where the {@link CustomProviderParam}
+     * annotation is used.
+    **/
     @Aspect
     public class CustomProviderAspect extends BaseParamAspect {
     

From 19fc9880c39f3c67571e0edc62e53f40ac81989b Mon Sep 17 00:00:00 2001
From: Scott Gerring <scottgerring@users.noreply.github.com>
Date: Fri, 8 Dec 2023 14:27:43 +0100
Subject: [PATCH 34/45] Apply suggestions from code review
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Co-authored-by: Jérôme Van Der Linden <117538+jeromevdl@users.noreply.github.com>
---
 .../parameters/appconfig/AppConfigProviderBuilder.java         | 2 +-
 .../powertools/parameters/dynamodb/DynamoDbParamAspect.java    | 3 +--
 .../powertools/parameters/dynamodb/DynamoDbProvider.java       | 2 +-
 .../powertools/parameters/secrets/SecretsParamAspect.java      | 3 +--
 .../lambda/powertools/parameters/ssm/SSMParamAspect.java       | 1 -
 5 files changed, 4 insertions(+), 7 deletions(-)

diff --git a/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProviderBuilder.java b/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProviderBuilder.java
index 38df99c4e..ef93dfa81 100644
--- a/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProviderBuilder.java
+++ b/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProviderBuilder.java
@@ -63,7 +63,7 @@ public AppConfigProvider build() {
     }
 
     /**
-     * Set custom {@link AppConfigProvider} to pass to the {@link AppConfigDataClient}. <br/>
+     * Set custom {@link AppConfigDataClient} to pass to the {@link AppConfigProvider}. <br/>
      * Use it if you want to customize the region or any other part of the client.
      *
      * @param client Custom client
diff --git a/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbParamAspect.java b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbParamAspect.java
index d3b49e021..1aa022cbd 100644
--- a/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbParamAspect.java
+++ b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbParamAspect.java
@@ -24,7 +24,7 @@
 import software.amazon.lambda.powertools.parameters.BaseProvider;
 
 /**
- * Provides the DynamoDB parameter aspect. This aspect is responsible for injecting
+ * Provides the Amazon DynamoDB parameter aspect. This aspect is responsible for injecting
  * parameters from DynamoDB into fields annotated with @DynamoDbParam. See the
  * README and Powertools for Lambda (Java) documentation for information on using this feature.
  */
@@ -42,7 +42,6 @@ public void getParam(DynamoDbParam ddbConfigParam) {
 
     @Around("getParam(ddbConfigParam)")
     public Object injectParam(final ProceedingJoinPoint joinPoint, final DynamoDbParam ddbConfigParam) {
-        System.out.println("GET IT");
 
         BaseProvider provider = providerBuilder.apply(ddbConfigParam.table());
         return getAndTransform(ddbConfigParam.key(), ddbConfigParam.transformer(), provider,
diff --git a/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProvider.java b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProvider.java
index adf316fc3..4a1476e38 100644
--- a/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProvider.java
+++ b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProvider.java
@@ -30,7 +30,7 @@
 import software.amazon.lambda.powertools.parameters.transform.TransformationManager;
 
 /**
- * Implements a {@link ParamProvider} on top of DynamoDB. The schema of the table
+ * Implements a {@link ParamProvider} on top of Amazon DynamoDB. The schema of the table
  * is described in the Powertools for AWS Lambda (Java) documentation.
  *
  * @see <a href="https://docs.powertools.aws.dev/lambda-java/utilities/parameters">Parameters provider documentation</a>
diff --git a/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsParamAspect.java b/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsParamAspect.java
index 8e897762d..748c88cc9 100644
--- a/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsParamAspect.java
+++ b/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsParamAspect.java
@@ -24,7 +24,7 @@
 
 /**
  * Provides the Secrets parameter aspect. This aspect is responsible for injecting
- * parameters from Secrets Provider into fields annotated with @SecretsParam. See the
+ * parameters from AWS Secrets Manager into fields annotated with @SecretsParam. See the
  * README and Powertools for Lambda (Java) documentation for information on using this feature.
  */
 @Aspect
@@ -39,7 +39,6 @@ public void getParam(SecretsParam secretsParam) {
 
     @Around("getParam(secretsParam)")
     public Object injectParam(final ProceedingJoinPoint joinPoint, final SecretsParam secretsParam) {
-        System.out.println("GET IT");
 
         SecretsProvider provider = providerBuilder.get();
         return getAndTransform(secretsParam.key(), secretsParam.transformer(), provider,
diff --git a/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMParamAspect.java b/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMParamAspect.java
index 3d238149e..b4d370506 100644
--- a/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMParamAspect.java
+++ b/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMParamAspect.java
@@ -40,7 +40,6 @@ public void getParam(SSMParam secretsParam) {
 
     @Around("getParam(ssmPaam)")
     public Object injectParam(final ProceedingJoinPoint joinPoint, final SSMParam ssmPaam) {
-        System.out.println("GET IT");
 
         SSMProvider provider = providerBuilder.get();
         return getAndTransform(ssmPaam.key(), ssmPaam.transformer(), provider,

From 8fee25b4337c63f491301a0e43bd0dc4675e470e Mon Sep 17 00:00:00 2001
From: Scott Gerring <gerrings@amazon.com>
Date: Fri, 8 Dec 2023 14:27:55 +0100
Subject: [PATCH 35/45] Review feedback

---
 docs/utilities/parameters.md                  |  5 +---
 mkdocs.yml                                    |  2 +-
 powertools-parameters/pom.xml                 | 23 -------------------
 .../powertools-parameters-appconfig/pom.xml   | 22 ------------------
 .../appconfig/AppConfigProviderBuilder.java   |  6 ++++-
 .../appconfig/AppConfigProviderTest.java      | 10 ++++----
 .../powertools-parameters-dynamodb/pom.xml    | 22 ------------------
 .../dynamodb/DynamoDbProviderBuilder.java     |  6 ++++-
 .../powertools-parameters-secrets/pom.xml     | 22 ------------------
 .../parameters/secrets/SecretsProvider.java   |  2 +-
 .../secrets/SecretsProviderBuilder.java       |  6 ++++-
 .../powertools-parameters-ssm/pom.xml         | 22 ------------------
 .../parameters/ssm/SSMProvider.java           |  4 ++--
 .../parameters/ssm/SSMProviderBuilder.java    |  1 -
 .../parameters/BaseProviderTest.java          |  5 ++--
 .../ParamProvidersIntegrationTest.java        |  2 --
 powertools-parameters/spotbugs-exclude.xml    | 13 -----------
 17 files changed, 29 insertions(+), 144 deletions(-)

diff --git a/docs/utilities/parameters.md b/docs/utilities/parameters.md
index 38de7b5d3..3084dd58d 100644
--- a/docs/utilities/parameters.md
+++ b/docs/utilities/parameters.md
@@ -564,7 +564,6 @@ To simplify the use of the library, you can chain all method calls before a get.
 
     ```java
         ssmProvider
-          .defaultMaxAge(10, SECONDS)     // will set 10 seconds as the default cache TTL
           .withMaxAge(1, MINUTES)         // will set the cache TTL for this value at 1 minute
           .withTransformation(json)       // json is a static import from Transformer.json
           .withDecryption()               // enable decryption of the parameter value
@@ -694,9 +693,7 @@ You can create your own custom parameter store provider by implementing a handfu
         }
     
         @Around("getParam(customConfigParam)")
-        public Object injectParam(final ProceedingJoinPoint joinPoint, final CustomProviderParam customConfigParam) {
-            System.out.println("GET IT");
-    
+        public Object injectParam(final ProceedingJoinPoint joinPoint, final CustomProviderParam customConfigParam) { 
             BaseProvider provider = CustomProvider.builder().build();
 
             return getAndTransform(customConfigParam.key(), ddbConfigParam.transformer(), provider,
diff --git a/mkdocs.yml b/mkdocs.yml
index eb28caa7a..b7f793e18 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -85,7 +85,7 @@ extra_javascript:
 
 extra:
   powertools:
-    version: 2.0.0-SNAPSHOT # to update after each release (we do not want snapshot version here)
+    version: 2.0.0 # to update after each release (we do not want snapshot version here)
 
 repo_url: https://github.com/aws-powertools/powertools-lambda-java
 edit_uri: edit/main/docs
diff --git a/powertools-parameters/pom.xml b/powertools-parameters/pom.xml
index 64952408b..1bc662457 100644
--- a/powertools-parameters/pom.xml
+++ b/powertools-parameters/pom.xml
@@ -30,29 +30,6 @@
 
     <description>Set of utilities to retrieve parameters - common interface</description>
 
-    <url>https://aws.amazon.com/lambda/</url>
-    <issueManagement>
-        <system>GitHub Issues</system>
-        <url>https://github.com/aws-powertools/powertools-lambda-java/issues</url>
-    </issueManagement>
-    <scm>
-        <url>https://github.com/aws-powertools/powertools-lambda-java.git</url>
-    </scm>
-    <developers>
-        <developer>
-            <name>Powertools for AWS Lambda team</name>
-            <organization>Amazon Web Services</organization>
-            <organizationUrl>https://aws.amazon.com/</organizationUrl>
-        </developer>
-    </developers>
-
-    <distributionManagement>
-        <snapshotRepository>
-            <id>ossrh</id>
-            <url>https://aws.oss.sonatype.org/content/repositories/snapshots</url>
-        </snapshotRepository>
-    </distributionManagement>
-
     <dependencies>
         <dependency>
             <groupId>software.amazon.lambda</groupId>
diff --git a/powertools-parameters/powertools-parameters-appconfig/pom.xml b/powertools-parameters/powertools-parameters-appconfig/pom.xml
index d44308f6b..3a3018c7c 100644
--- a/powertools-parameters/powertools-parameters-appconfig/pom.xml
+++ b/powertools-parameters/powertools-parameters-appconfig/pom.xml
@@ -15,28 +15,6 @@
     <name>Powertools for AWS Lambda (Java) library Parameters - AppConfig</name>
     <description>AppConfig implementation for the Parameters module</description>
 
-    <issueManagement>
-        <system>GitHub Issues</system>
-        <url>https://github.com/aws-powertools/powertools-lambda-java/issues</url>
-    </issueManagement>
-    <scm>
-        <url>https://github.com/aws-powertools/powertools-lambda-java.git</url>
-    </scm>
-    <developers>
-        <developer>
-            <name>Powertools for AWS Lambda team</name>
-            <organization>Amazon Web Services</organization>
-            <organizationUrl>https://aws.amazon.com/</organizationUrl>
-        </developer>
-    </developers>
-
-    <distributionManagement>
-        <snapshotRepository>
-            <id>ossrh</id>
-            <url>https://aws.oss.sonatype.org/content/repositories/snapshots</url>
-        </snapshotRepository>
-    </distributionManagement>
-
     <dependencies>
         <dependency>
             <groupId>software.amazon.lambda</groupId>
diff --git a/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProviderBuilder.java b/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProviderBuilder.java
index 38df99c4e..691df7ca9 100644
--- a/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProviderBuilder.java
+++ b/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProviderBuilder.java
@@ -22,9 +22,13 @@
 import software.amazon.awssdk.services.appconfigdata.AppConfigDataClient;
 import software.amazon.lambda.powertools.common.internal.UserAgentConfigurator;
 import software.amazon.lambda.powertools.parameters.BaseProvider;
+import software.amazon.lambda.powertools.parameters.ParamProvider;
 import software.amazon.lambda.powertools.parameters.cache.CacheManager;
 import software.amazon.lambda.powertools.parameters.transform.TransformationManager;
 
+/**
+ * Implements a {@link ParamProvider} on top of the AppConfig service. AppConfig provides
+ */
 public class AppConfigProviderBuilder {
     private AppConfigDataClient client;
     private CacheManager cacheManager;
@@ -97,7 +101,7 @@ public AppConfigProviderBuilder withApplication(String application) {
     }
 
     /**
-     * <b>Mandatory</b>. Provide a CacheManager to the {@link AppConfigProvider}
+     * Provide a CacheManager to the {@link AppConfigProvider}
      *
      * @param cacheManager the manager that will handle the cache of parameters
      * @return the builder to chain calls (eg. <pre>builder.withCacheManager().build()</pre>)
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 a7a46e05e..7cbf7256b 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
@@ -14,7 +14,9 @@
 
 package software.amazon.lambda.powertools.parameters.appconfig;
 
-import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
+import static org.assertj.core.api.Assertions.assertThatRuntimeException;
+import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
 
 import org.assertj.core.api.Assertions;
 import org.junit.jupiter.api.BeforeEach;
@@ -188,7 +190,7 @@ public void multipleKeysRetrievalWorks() {
     public void getMultipleValuesThrowsException() {
 
         // Act & Assert
-        Assertions.assertThatRuntimeException().isThrownBy(() -> provider.getMultipleValues("path"))
+        assertThatRuntimeException().isThrownBy(() -> provider.getMultipleValues("path"))
                 .withMessage("Retrieving multiple parameter values is not supported with the AWS App Config Provider");
     }
 
@@ -196,7 +198,7 @@ public void getMultipleValuesThrowsException() {
     public void testAppConfigProviderBuilderMissingEnvironment_throwsException() {
 
         // Act & Assert
-        Assertions.assertThatIllegalStateException().isThrownBy(() -> AppConfigProvider.builder()
+        assertThatIllegalStateException().isThrownBy(() -> AppConfigProvider.builder()
                         .withCacheManager(new CacheManager())
                         .withApplication(applicationName)
                         .withClient(client)
@@ -208,7 +210,7 @@ public void testAppConfigProviderBuilderMissingEnvironment_throwsException() {
     public void testAppConfigProviderBuilderMissingApplication_throwsException() {
 
         // Act & Assert
-        Assertions.assertThatIllegalStateException().isThrownBy(() -> AppConfigProvider.builder()
+        assertThatIllegalStateException().isThrownBy(() -> AppConfigProvider.builder()
                         .withCacheManager(new CacheManager())
                         .withEnvironment(environmentName)
                         .withClient(client)
diff --git a/powertools-parameters/powertools-parameters-dynamodb/pom.xml b/powertools-parameters/powertools-parameters-dynamodb/pom.xml
index 64fbea0fd..ad32bdff8 100644
--- a/powertools-parameters/powertools-parameters-dynamodb/pom.xml
+++ b/powertools-parameters/powertools-parameters-dynamodb/pom.xml
@@ -15,28 +15,6 @@
     <name>Powertools for AWS Lambda (Java) library Parameters - DynamoDB</name>
     <description>DynamoDB implementation for the Parameters module</description>
 
-    <issueManagement>
-        <system>GitHub Issues</system>
-        <url>https://github.com/aws-powertools/powertools-lambda-java/issues</url>
-    </issueManagement>
-    <scm>
-        <url>https://github.com/aws-powertools/powertools-lambda-java.git</url>
-    </scm>
-    <developers>
-        <developer>
-            <name>Powertools for AWS Lambda team</name>
-            <organization>Amazon Web Services</organization>
-            <organizationUrl>https://aws.amazon.com/</organizationUrl>
-        </developer>
-    </developers>
-
-    <distributionManagement>
-        <snapshotRepository>
-            <id>ossrh</id>
-            <url>https://aws.oss.sonatype.org/content/repositories/snapshots</url>
-        </snapshotRepository>
-    </distributionManagement>
-
     <dependencies>
         <dependency>
             <groupId>software.amazon.lambda</groupId>
diff --git a/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderBuilder.java b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderBuilder.java
index 66e33c70d..6b6610ba1 100644
--- a/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderBuilder.java
+++ b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderBuilder.java
@@ -22,9 +22,13 @@
 import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
 import software.amazon.lambda.powertools.common.internal.UserAgentConfigurator;
 import software.amazon.lambda.powertools.parameters.BaseProvider;
+import software.amazon.lambda.powertools.parameters.ParamProvider;
 import software.amazon.lambda.powertools.parameters.cache.CacheManager;
 import software.amazon.lambda.powertools.parameters.transform.TransformationManager;
 
+/**
+ * Implements a {@link ParamProvider} on top of the DynamoDB service. DynamoDB provides
+ */
 public class DynamoDbProviderBuilder {
     private DynamoDbClient client;
     private String table;
@@ -75,7 +79,7 @@ public DynamoDbProviderBuilder withClient(DynamoDbClient client) {
     }
 
     /**
-     * <b>Mandatory</b>. Provide a CacheManager to the {@link DynamoDbProvider}
+     * Provide a CacheManager to the {@link DynamoDbProvider}
      *
      * @param cacheManager the manager that will handle the cache of parameters
      * @return the builder to chain calls (eg. <pre>builder.withCacheManager().build()</pre>)
diff --git a/powertools-parameters/powertools-parameters-secrets/pom.xml b/powertools-parameters/powertools-parameters-secrets/pom.xml
index 0896d9646..6c4501ca3 100644
--- a/powertools-parameters/powertools-parameters-secrets/pom.xml
+++ b/powertools-parameters/powertools-parameters-secrets/pom.xml
@@ -15,28 +15,6 @@
     <name>Powertools for AWS Lambda (Java) library Parameters - Secrets Manager</name>
     <description>Secrets Manager implementation for the Parameters module</description>
 
-    <issueManagement>
-        <system>GitHub Issues</system>
-        <url>https://github.com/aws-powertools/powertools-lambda-java/issues</url>
-    </issueManagement>
-    <scm>
-        <url>https://github.com/aws-powertools/powertools-lambda-java.git</url>
-    </scm>
-    <developers>
-        <developer>
-            <name>Powertools for AWS Lambda team</name>
-            <organization>Amazon Web Services</organization>
-            <organizationUrl>https://aws.amazon.com/</organizationUrl>
-        </developer>
-    </developers>
-
-    <distributionManagement>
-        <snapshotRepository>
-            <id>ossrh</id>
-            <url>https://aws.oss.sonatype.org/content/repositories/snapshots</url>
-        </snapshotRepository>
-    </distributionManagement>
-
     <dependencies>
         <dependency>
             <groupId>software.amazon.lambda</groupId>
diff --git a/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProvider.java b/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProvider.java
index 6fe6194f3..b17fd91c7 100644
--- a/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProvider.java
+++ b/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProvider.java
@@ -29,7 +29,7 @@
  *
  * <u>Samples:</u>
  * <pre>
- *     SecretsProvider provider = ParamManager.getSecretsProvider();
+ *     SecretsProvider provider = SecretsProvider.builder().build();
  *
  *     String value = provider.get("key");
  *     System.out.println(value);
diff --git a/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProviderBuilder.java b/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProviderBuilder.java
index 3b13d0c37..125425200 100644
--- a/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProviderBuilder.java
+++ b/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProviderBuilder.java
@@ -22,9 +22,13 @@
 import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient;
 import software.amazon.lambda.powertools.common.internal.UserAgentConfigurator;
 import software.amazon.lambda.powertools.parameters.BaseProvider;
+import software.amazon.lambda.powertools.parameters.ParamProvider;
 import software.amazon.lambda.powertools.parameters.cache.CacheManager;
 import software.amazon.lambda.powertools.parameters.transform.TransformationManager;
 
+/**
+ * Implements a {@link ParamProvider} on top of the SecretsManager service. SecretsManager provides
+ */
 public class SecretsProviderBuilder {
 
     private SecretsManagerClient client;
@@ -74,7 +78,7 @@ public SecretsProviderBuilder withClient(SecretsManagerClient client) {
     }
 
     /**
-     * <b>Mandatory</b>. Provide a CacheManager to the {@link SecretsProvider}
+     * Provide a CacheManager to the {@link SecretsProvider}
      *
      * @param cacheManager the manager that will handle the cache of parameters
      * @return the builder to chain calls (eg. <pre>builder.withCacheManager().build()</pre>)
diff --git a/powertools-parameters/powertools-parameters-ssm/pom.xml b/powertools-parameters/powertools-parameters-ssm/pom.xml
index dce95ae02..80276189d 100644
--- a/powertools-parameters/powertools-parameters-ssm/pom.xml
+++ b/powertools-parameters/powertools-parameters-ssm/pom.xml
@@ -15,28 +15,6 @@
     <name>Powertools for AWS Lambda (Java) library Parameters - SSM</name>
     <description>SSM Parameter Store implementation for the Parameters module</description>
 
-    <issueManagement>
-        <system>GitHub Issues</system>
-        <url>https://github.com/aws-powertools/powertools-lambda-java/issues</url>
-    </issueManagement>
-    <scm>
-        <url>https://github.com/aws-powertools/powertools-lambda-java.git</url>
-    </scm>
-    <developers>
-        <developer>
-            <name>Powertools for AWS Lambda team</name>
-            <organization>Amazon Web Services</organization>
-            <organizationUrl>https://aws.amazon.com/</organizationUrl>
-        </developer>
-    </developers>
-
-    <distributionManagement>
-        <snapshotRepository>
-            <id>ossrh</id>
-            <url>https://aws.oss.sonatype.org/content/repositories/snapshots</url>
-        </snapshotRepository>
-    </distributionManagement>
-
     <dependencies>
         <dependency>
             <groupId>software.amazon.lambda</groupId>
diff --git a/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMProvider.java b/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMProvider.java
index 3a88c90be..d60cd8aee 100644
--- a/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMProvider.java
+++ b/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMProvider.java
@@ -30,7 +30,7 @@
  *
  * <u>Samples:</u>
  * <pre>
- *     SSMProvider provider = ParamManager.getSsmProvider();
+ *     SSMProvider provider = SSMProvider.builder().build();
  *
  *     String value = provider.get("key");
  *     System.out.println(value);
@@ -166,7 +166,7 @@ private Map<String, String> getMultipleBis(String path, String nextToken) {
             res.parameters().forEach(parameter ->
             {
                 /* Standardize the parameter name
-                   The parameter name returned by SSM will contained the full path.
+                   The parameter name returned by SSM will contain the full path.
                    However, for readability, we should return only the part after
                    the path.
                  */
diff --git a/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMProviderBuilder.java b/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMProviderBuilder.java
index e38fddc84..3b4fff1b3 100644
--- a/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMProviderBuilder.java
+++ b/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMProviderBuilder.java
@@ -50,7 +50,6 @@ private static SsmClient createClient() {
      */
     public SSMProvider build() {
         if (cacheManager == null) {
-            // TODO - do we want to share this somehow?
             cacheManager = new CacheManager();
         }
         SSMProvider provider;
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 e2b46599e..5fa740253 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
@@ -173,9 +173,9 @@ public void get_customDefaultTTLAndTTL_cached_shouldGetFromCache() {
     @Test
     public void get_customDefaultTTLAndTTL_expired_shouldGetValue() {
 
-        provider.cacheManager.setDefaultExpirationTime(Duration.ofSeconds(5));
+        provider.cacheManager.setDefaultExpirationTime(Duration.ofMinutes(2));
 
-        provider.get("bariton");
+        provider.withMaxAge(5, SECONDS).get("bariton");
         getFromStore = false;
 
         provider.setClock(offset(clock, of(6, SECONDS)));
@@ -310,6 +310,7 @@ public void getObject_customDefaultTTLAndTTL_cached_shouldGetFromCache() {
         provider.cacheManager.setDefaultExpirationTime(Duration.ofSeconds(5));
 
         provider.withTransformation(json)
+                .withMaxAge(5, SECONDS)
                 .get("foo", ObjectToDeserialize.class);
         getFromStore = false;
 
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 fe7b66959..7d790d140 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
@@ -62,8 +62,6 @@ public class ParamProvidersIntegrationTest {
     @BeforeEach
     public void setup() throws IllegalAccessException {
         openMocks(this);
-
-        //writeStaticField(ParamManager.class, "providers", new ConcurrentHashMap<>(), true);
     }
 
     @Test
diff --git a/powertools-parameters/spotbugs-exclude.xml b/powertools-parameters/spotbugs-exclude.xml
index 5903492f3..d48e9bee1 100644
--- a/powertools-parameters/spotbugs-exclude.xml
+++ b/powertools-parameters/spotbugs-exclude.xml
@@ -79,17 +79,4 @@
 
         </Or>
     </Match>
-    <Match>
-        <Bug pattern="MS_EXPOSE_REP"/>
-        <Or>
-            <And>
-                <Class name="software.amazon.lambda.powertools.parameters.ParamManager"/>
-                <Method name="getCacheManager"/>
-            </And>
-            <And>
-                <Class name="software.amazon.lambda.powertools.parameters.ParamManager"/>
-                <Method name="getTransformationManager"/>
-            </And>
-        </Or>
-    </Match>
 </FindBugsFilter>
\ No newline at end of file

From f356ab47358824bfd928f9a297f2367fece5c3f4 Mon Sep 17 00:00:00 2001
From: Scott Gerring <gerrings@amazon.com>
Date: Fri, 8 Dec 2023 15:00:42 +0100
Subject: [PATCH 36/45] More review changes

---
 docs/utilities/parameters.md                  |  4 +---
 .../parameters/appconfig/AppConfigParam.java  |  5 +++++
 .../appconfig/AppConfigProvider.java          |  7 +++++++
 .../parameters/dynamodb/DynamoDbParam.java    | 20 +++++++++++++++++++
 .../parameters/dynamodb/DynamoDbProvider.java |  7 +++++++
 .../parameters/secrets/SecretsParam.java      | 17 ++++++++++++++++
 .../parameters/secrets/SecretsProvider.java   |  7 +++++++
 .../powertools/parameters/ssm/SSMParam.java   | 18 +++++++++++++++++
 .../parameters/ssm/SSMProvider.java           |  7 +++++++
 9 files changed, 89 insertions(+), 3 deletions(-)

diff --git a/docs/utilities/parameters.md b/docs/utilities/parameters.md
index 3084dd58d..7771a7942 100644
--- a/docs/utilities/parameters.md
+++ b/docs/utilities/parameters.md
@@ -456,9 +456,7 @@ by calling `setDefaultExpirationTime(duration, unit)` on the `CacheManager`.
         
         public void CustomizeCache() {
     
-            AppConfigProvider paramProvider = AppConfigProvider
-                    .builder()
-                    .build();
+            AppConfigProvider paramProvider = AppConfigProvider.create();
     
             // Cache for 20 seconds, rather than the default 5.
             return paramProvider.withMaxAge(20, ChronoUnit.SECONDS)
diff --git a/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParam.java b/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParam.java
index 32ba97a2e..eb959be76 100644
--- a/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParam.java
+++ b/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParam.java
@@ -29,6 +29,11 @@
  * @see AppConfigProviderBuilder
  * @see <a href="https://docs.aws.amazon.com/appconfig>AWS AppConfig</a>
  * @see <a href="https://docs.powertools.aws.dev/lambda/java/utilities/parameters/">Powertools for AWS Lambda (Java) parameters documentation</a>
+ *
+ * <pre>
+ * @AppConfigParam(key = "my-param", environment = "my-env", application = "my-app")
+ * String appConfigParam;
+ * </pre>
  */
 @Retention(RetentionPolicy.RUNTIME)
 @Target(ElementType.FIELD)
diff --git a/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProvider.java b/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProvider.java
index d884e4512..e157aafeb 100644
--- a/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProvider.java
+++ b/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProvider.java
@@ -63,6 +63,13 @@ public static AppConfigProviderBuilder builder() {
         return new AppConfigProviderBuilder();
     }
 
+    /**
+     * Create a AppConfigProvider with all default settings.
+     */
+    public static AppConfigProvider create() {
+        return new AppConfigProviderBuilder().build();
+    }
+
     /**
      * Retrieve the parameter value from the AppConfig parameter store.<br />
      *
diff --git a/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbParam.java b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbParam.java
index 45c3b83aa..f1ba4fe8a 100644
--- a/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbParam.java
+++ b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbParam.java
@@ -20,12 +20,32 @@
 import java.lang.annotation.Target;
 import software.amazon.lambda.powertools.parameters.transform.Transformer;
 
+/**
+ * Inject a parameter from the DynamoDB Parameter Store into a field. You can also use
+ * {@code DynamoDbProviderBuilder} to obtain DynamoDB values directly, rather than injecting them implicitly.
+ *
+ * Usage:
+ * <pre>
+ * @SSMParam(key = "my-param", table = "my-table")
+ * String myParameter;
+ * </pre>
+ */
 @Retention(RetentionPolicy.RUNTIME)
 @Target(ElementType.FIELD)
 public @interface DynamoDbParam {
+    /**
+     * <b>Mandatory</b>. Partition key from the DynamoDB table
+     */
     String key();
 
+    /**
+     * <b>Mandatory</b>. Table name for the DynamoDB table
+     * @return
+     */
     String table();
 
+    /**
+     * <b>Optional</b> Provide a Transformer to transform the returned parameter values.
+     */
     Class<? extends Transformer> transformer() default Transformer.class;
 }
diff --git a/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProvider.java b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProvider.java
index 4a1476e38..add68e317 100644
--- a/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProvider.java
+++ b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProvider.java
@@ -56,6 +56,13 @@ public static DynamoDbProviderBuilder builder() {
         return new DynamoDbProviderBuilder();
     }
 
+    /**
+     * Create a DynamoDbProvider with all default settings.
+     */
+    public static DynamoDbProvider create() {
+        return new DynamoDbProviderBuilder().build();
+    }
+
     /**
      * Return a single value from the DynamoDB parameter provider.
      *
diff --git a/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsParam.java b/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsParam.java
index a9e7f5646..f9c110c49 100644
--- a/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsParam.java
+++ b/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsParam.java
@@ -20,10 +20,27 @@
 import java.lang.annotation.Target;
 import software.amazon.lambda.powertools.parameters.transform.Transformer;
 
+/**
+ * Inject a parameter from the Secrets Manager into a field. You can also use
+ * {@code SecretsProviderBuilder} to obtain Secrets Manager values directly, rather than
+ * injecting them implicitly.
+ *
+ * <pre>
+ * @SecretsParam(key = "my-secret")
+ * String mySecret;
+ * </pre>
+ */
 @Retention(RetentionPolicy.RUNTIME)
 @Target(ElementType.FIELD)
 public @interface SecretsParam {
+    /**
+     * <b>Mandatory</b>. key from the secrets manager store.
+     * @return
+     */
     String key();
 
+    /**
+     * <b>Optional</b>. a transfer to apply to the value
+     */
     Class<? extends Transformer> transformer() default Transformer.class;
 }
diff --git a/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProvider.java b/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProvider.java
index b17fd91c7..9087c1ad6 100644
--- a/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProvider.java
+++ b/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProvider.java
@@ -72,6 +72,13 @@ public static SecretsProviderBuilder builder() {
         return new SecretsProviderBuilder();
     }
 
+    /**
+     * Create a SecretsProvider with all default settings.
+     */
+    public static SecretsProvider create() {
+        return new SecretsProviderBuilder().build();
+    }
+
     /**
      * Retrieve the parameter value from the AWS Secrets Manager.
      *
diff --git a/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMParam.java b/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMParam.java
index ced673829..9b1587bb4 100644
--- a/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMParam.java
+++ b/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMParam.java
@@ -20,10 +20,28 @@
 import java.lang.annotation.Target;
 import software.amazon.lambda.powertools.parameters.transform.Transformer;
 
+/**
+ * Inject a parameter from the SSM Parameter Store into a field. You can also use
+ * {@code SSMProviderBuilder} to obtain SSM values directly, rather than injecting them implicitly.
+ *
+ * Usage:
+ * <pre>
+ * @SSMParam(key = "/my/parameter")
+ * String myParameter;
+ * </pre>
+ */
 @Retention(RetentionPolicy.RUNTIME)
 @Target(ElementType.FIELD)
 public @interface SSMParam {
+    /**
+     * <b>Mandatory</b>. Key from the SSM parameter store
+     * @return
+     */
     String key();
 
+
+    /**
+     * <b>Optional</b>. a transfer to apply to the value
+     */
     Class<? extends Transformer> transformer() default Transformer.class;
 }
diff --git a/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMProvider.java b/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMProvider.java
index d60cd8aee..c24b08b84 100644
--- a/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMProvider.java
+++ b/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMProvider.java
@@ -92,6 +92,13 @@ public static SSMProviderBuilder builder() {
         return new SSMProviderBuilder();
     }
 
+    /**
+     * Create a SSMProvider with all default settings.
+     */
+    public static SSMProvider create() {
+        return new SSMProviderBuilder().build();
+    }
+
     /**
      * Retrieve the parameter value from the AWS System Manager Parameter Store.
      *

From 4a5cecf733b147e3e962a8198dc3c3d59dbda700 Mon Sep 17 00:00:00 2001
From: Scott Gerring <scottgerring@users.noreply.github.com>
Date: Fri, 8 Dec 2023 15:01:41 +0100
Subject: [PATCH 37/45] Update
 powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParametersAspect.java
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Co-authored-by: Jérôme Van Der Linden <117538+jeromevdl@users.noreply.github.com>
---
 .../parameters/appconfig/AppConfigParametersAspect.java         | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParametersAspect.java b/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParametersAspect.java
index b151da6e0..7ab4cf23e 100644
--- a/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParametersAspect.java
+++ b/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParametersAspect.java
@@ -24,7 +24,7 @@
 
 /**
  * Provides the AppConfig parameter aspect. This aspect is responsible for injecting
- * parameters from AppConfig into fields annotated with @AppConfigParam. See the
+ * parameters from AWS AppConfig into fields annotated with @AppConfigParam. See the
  * README and Powertools for Lambda (Java) documentation for information on using this feature.
  */
 @Aspect

From f27b69f72fc9d87b0020262cb137ece179ca5ab7 Mon Sep 17 00:00:00 2001
From: Scott Gerring <gerrings@amazon.com>
Date: Fri, 8 Dec 2023 15:09:01 +0100
Subject: [PATCH 38/45] E2E tests fix

---
 powertools-e2e-tests/handlers/batch/pom.xml                | 2 +-
 powertools-e2e-tests/handlers/idempotency/pom.xml          | 2 +-
 powertools-e2e-tests/handlers/largemessage/pom.xml         | 2 +-
 .../handlers/largemessage_idempotent/pom.xml               | 2 +-
 powertools-e2e-tests/handlers/logging/pom.xml              | 2 +-
 powertools-e2e-tests/handlers/metrics/pom.xml              | 2 +-
 powertools-e2e-tests/handlers/parameters/pom.xml           | 2 +-
 .../software/amazon/lambda/powertools/e2e/Function.java    | 7 ++++++-
 powertools-e2e-tests/handlers/pom.xml                      | 2 +-
 powertools-e2e-tests/handlers/tracing/pom.xml              | 2 +-
 powertools-e2e-tests/handlers/validation-alb-event/pom.xml | 2 +-
 .../handlers/validation-apigw-event/pom.xml                | 2 +-
 .../powertools/parameters/appconfig/AppConfigProvider.java | 6 ------
 13 files changed, 17 insertions(+), 18 deletions(-)

diff --git a/powertools-e2e-tests/handlers/batch/pom.xml b/powertools-e2e-tests/handlers/batch/pom.xml
index aee9bf3dd..ccb9926f1 100644
--- a/powertools-e2e-tests/handlers/batch/pom.xml
+++ b/powertools-e2e-tests/handlers/batch/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <groupId>software.amazon.lambda</groupId>
         <artifactId>e2e-test-handlers-parent</artifactId>
-        <version>1.0.0</version>
+        <version>2.0.0</version>
     </parent>
 
     <artifactId>e2e-test-handler-batch</artifactId>
diff --git a/powertools-e2e-tests/handlers/idempotency/pom.xml b/powertools-e2e-tests/handlers/idempotency/pom.xml
index 22b6a1c53..f033fce24 100644
--- a/powertools-e2e-tests/handlers/idempotency/pom.xml
+++ b/powertools-e2e-tests/handlers/idempotency/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <groupId>software.amazon.lambda</groupId>
         <artifactId>e2e-test-handlers-parent</artifactId>
-        <version>1.0.0</version>
+        <version>2.0.0</version>
     </parent>
 
     <artifactId>e2e-test-handler-idempotency</artifactId>
diff --git a/powertools-e2e-tests/handlers/largemessage/pom.xml b/powertools-e2e-tests/handlers/largemessage/pom.xml
index 8302624ef..e6539f4fe 100644
--- a/powertools-e2e-tests/handlers/largemessage/pom.xml
+++ b/powertools-e2e-tests/handlers/largemessage/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <groupId>software.amazon.lambda</groupId>
         <artifactId>e2e-test-handlers-parent</artifactId>
-        <version>1.0.0</version>
+        <version>2.0.0</version>
     </parent>
 
     <artifactId>e2e-test-handler-largemessage</artifactId>
diff --git a/powertools-e2e-tests/handlers/largemessage_idempotent/pom.xml b/powertools-e2e-tests/handlers/largemessage_idempotent/pom.xml
index 1fe9092ef..5e7f026bf 100644
--- a/powertools-e2e-tests/handlers/largemessage_idempotent/pom.xml
+++ b/powertools-e2e-tests/handlers/largemessage_idempotent/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <groupId>software.amazon.lambda</groupId>
         <artifactId>e2e-test-handlers-parent</artifactId>
-        <version>1.0.0</version>
+        <version>2.0.0</version>
     </parent>
 
     <artifactId>e2e-test-handler-large-msg-idempotent</artifactId>
diff --git a/powertools-e2e-tests/handlers/logging/pom.xml b/powertools-e2e-tests/handlers/logging/pom.xml
index 05e91d8e3..86c149f45 100644
--- a/powertools-e2e-tests/handlers/logging/pom.xml
+++ b/powertools-e2e-tests/handlers/logging/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <groupId>software.amazon.lambda</groupId>
         <artifactId>e2e-test-handlers-parent</artifactId>
-        <version>1.0.0</version>
+        <version>2.0.0</version>
     </parent>
 
     <artifactId>e2e-test-handler-logging</artifactId>
diff --git a/powertools-e2e-tests/handlers/metrics/pom.xml b/powertools-e2e-tests/handlers/metrics/pom.xml
index 2f3cabd16..ce5e934d8 100644
--- a/powertools-e2e-tests/handlers/metrics/pom.xml
+++ b/powertools-e2e-tests/handlers/metrics/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <groupId>software.amazon.lambda</groupId>
         <artifactId>e2e-test-handlers-parent</artifactId>
-        <version>1.0.0</version>
+        <version>2.0.0</version>
     </parent>
 
     <artifactId>e2e-test-handler-metrics</artifactId>
diff --git a/powertools-e2e-tests/handlers/parameters/pom.xml b/powertools-e2e-tests/handlers/parameters/pom.xml
index 4d5330da0..0b8c5d118 100644
--- a/powertools-e2e-tests/handlers/parameters/pom.xml
+++ b/powertools-e2e-tests/handlers/parameters/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <groupId>software.amazon.lambda</groupId>
         <artifactId>e2e-test-handlers-parent</artifactId>
-        <version>1.0.0</version>
+        <version>2.0.0</version>
     </parent>
 
     <artifactId>e2e-test-handler-parameters</artifactId>
diff --git a/powertools-e2e-tests/handlers/parameters/src/main/java/software/amazon/lambda/powertools/e2e/Function.java b/powertools-e2e-tests/handlers/parameters/src/main/java/software/amazon/lambda/powertools/e2e/Function.java
index 3a83a1b05..016844117 100644
--- a/powertools-e2e-tests/handlers/parameters/src/main/java/software/amazon/lambda/powertools/e2e/Function.java
+++ b/powertools-e2e-tests/handlers/parameters/src/main/java/software/amazon/lambda/powertools/e2e/Function.java
@@ -24,7 +24,12 @@ public class Function implements RequestHandler<Input, String> {
 
     @Logging
     public String handleRequest(Input input, Context context) {
-        AppConfigProvider provider = ParamManager.getAppConfigProvider(input.getEnvironment(), input.getApp());
+        AppConfigProvider provider = AppConfigProvider.builder()
+                .withApplication(input.getApp())
+                .withEnvironment(input.getEnvironment())
+                .build();
+
+        //(input.getEnvironment(), input.getApp());
         return provider.get(input.getKey());
 
     }
diff --git a/powertools-e2e-tests/handlers/pom.xml b/powertools-e2e-tests/handlers/pom.xml
index 7c1208470..f27634feb 100644
--- a/powertools-e2e-tests/handlers/pom.xml
+++ b/powertools-e2e-tests/handlers/pom.xml
@@ -4,7 +4,7 @@
 
     <groupId>software.amazon.lambda</groupId>
     <artifactId>e2e-test-handlers-parent</artifactId>
-    <version>1.0.0</version>
+    <version>2.0.0</version>
     <packaging>pom</packaging>
     <name>Handlers for End-to-End tests</name>
     <description>Fake handlers that use Powertools for AWS Lambda (Java).</description>
diff --git a/powertools-e2e-tests/handlers/tracing/pom.xml b/powertools-e2e-tests/handlers/tracing/pom.xml
index b9240c356..b1bc14c05 100644
--- a/powertools-e2e-tests/handlers/tracing/pom.xml
+++ b/powertools-e2e-tests/handlers/tracing/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <groupId>software.amazon.lambda</groupId>
         <artifactId>e2e-test-handlers-parent</artifactId>
-        <version>1.0.0</version>
+        <version>2.0.0</version>
     </parent>
 
     <artifactId>e2e-test-handler-tracing</artifactId>
diff --git a/powertools-e2e-tests/handlers/validation-alb-event/pom.xml b/powertools-e2e-tests/handlers/validation-alb-event/pom.xml
index 31570fe4e..36695b9a4 100644
--- a/powertools-e2e-tests/handlers/validation-alb-event/pom.xml
+++ b/powertools-e2e-tests/handlers/validation-alb-event/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <groupId>software.amazon.lambda</groupId>
         <artifactId>e2e-test-handlers-parent</artifactId>
-        <version>1.0.0</version>
+        <version>2.0.0</version>
     </parent>
 
     <artifactId>e2e-test-handler-validation-alb-event</artifactId>
diff --git a/powertools-e2e-tests/handlers/validation-apigw-event/pom.xml b/powertools-e2e-tests/handlers/validation-apigw-event/pom.xml
index 9129abc7d..8bb927778 100644
--- a/powertools-e2e-tests/handlers/validation-apigw-event/pom.xml
+++ b/powertools-e2e-tests/handlers/validation-apigw-event/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <groupId>software.amazon.lambda</groupId>
         <artifactId>e2e-test-handlers-parent</artifactId>
-        <version>1.0.0</version>
+        <version>2.0.0</version>
     </parent>
 
     <artifactId>e2e-test-handler-validation-apigw-event</artifactId>
diff --git a/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProvider.java b/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProvider.java
index e157aafeb..5fd272c9b 100644
--- a/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProvider.java
+++ b/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProvider.java
@@ -63,12 +63,6 @@ public static AppConfigProviderBuilder builder() {
         return new AppConfigProviderBuilder();
     }
 
-    /**
-     * Create a AppConfigProvider with all default settings.
-     */
-    public static AppConfigProvider create() {
-        return new AppConfigProviderBuilder().build();
-    }
 
     /**
      * Retrieve the parameter value from the AppConfig parameter store.<br />

From dccd961729facc15de710d3488fad0b8ce463194 Mon Sep 17 00:00:00 2001
From: Scott Gerring <gerrings@amazon.com>
Date: Fri, 8 Dec 2023 15:14:56 +0100
Subject: [PATCH 39/45] A final change?

---
 docs/utilities/parameters.md | 22 +---------------------
 1 file changed, 1 insertion(+), 21 deletions(-)

diff --git a/docs/utilities/parameters.md b/docs/utilities/parameters.md
index 7771a7942..607791a82 100644
--- a/docs/utilities/parameters.md
+++ b/docs/utilities/parameters.md
@@ -445,27 +445,7 @@ custom cache duration can be provided using `withMaxAge(duration, unit)`.
 If this is not specified, the default value set on the `CacheManager` itself will be used. This default can be customized
 by calling `setDefaultExpirationTime(duration, unit)` on the `CacheManager`.
 
-=== "Customize Cache - Per Item"
-
-    ```java hl_lines="14 15"
-    import java.time.Duration;
-    import software.amazon.lambda.powertools.parameters.appconfig.AppConfigProvider;
-    import software.amazon.lambda.powertools.parameters.cache.CacheManager;
-    
-    public class CustomizeCacheTimeout {
-        
-        public void CustomizeCache() {
-    
-            AppConfigProvider paramProvider = AppConfigProvider.create();
-    
-            // Cache for 20 seconds, rather than the default 5.
-            return paramProvider.withMaxAge(20, ChronoUnit.SECONDS)
-                    .get("my-param");
-        }
-    }
-    ```
-
-=== "Customize Cache - Change Default"
+=== "Customize Cache"
 
     ```java hl_lines="9 10 14 19 22-25"
     import java.time.Duration;

From fab773e04c308ca1e8406f00e196c989f7e6d36a Mon Sep 17 00:00:00 2001
From: Scott Gerring <gerrings@amazon.com>
Date: Fri, 8 Dec 2023 15:25:02 +0100
Subject: [PATCH 40/45] Removed useless create

---
 .../powertools/parameters/dynamodb/DynamoDbProvider.java   | 7 -------
 1 file changed, 7 deletions(-)

diff --git a/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProvider.java b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProvider.java
index add68e317..4a1476e38 100644
--- a/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProvider.java
+++ b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProvider.java
@@ -56,13 +56,6 @@ public static DynamoDbProviderBuilder builder() {
         return new DynamoDbProviderBuilder();
     }
 
-    /**
-     * Create a DynamoDbProvider with all default settings.
-     */
-    public static DynamoDbProvider create() {
-        return new DynamoDbProviderBuilder().build();
-    }
-
     /**
      * Return a single value from the DynamoDB parameter provider.
      *

From f7e1a24a35348cc3223579080c64a3c92d9f5c98 Mon Sep 17 00:00:00 2001
From: Scott Gerring <gerrings@amazon.com>
Date: Fri, 8 Dec 2023 15:51:02 +0100
Subject: [PATCH 41/45] Will this do it?

---
 powertools-e2e-tests/handlers/parameters/pom.xml | 2 +-
 powertools-e2e-tests/handlers/pom.xml            | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/powertools-e2e-tests/handlers/parameters/pom.xml b/powertools-e2e-tests/handlers/parameters/pom.xml
index 0b8c5d118..60cf8d868 100644
--- a/powertools-e2e-tests/handlers/parameters/pom.xml
+++ b/powertools-e2e-tests/handlers/parameters/pom.xml
@@ -19,7 +19,7 @@
         </dependency>
         <dependency>
             <groupId>software.amazon.lambda</groupId>
-            <artifactId>powertools-parameters</artifactId>
+            <artifactId>powertools-parameters-appconfig</artifactId>
         </dependency>
         <dependency>
             <groupId>com.amazonaws</groupId>
diff --git a/powertools-e2e-tests/handlers/pom.xml b/powertools-e2e-tests/handlers/pom.xml
index f27634feb..9476d24b6 100644
--- a/powertools-e2e-tests/handlers/pom.xml
+++ b/powertools-e2e-tests/handlers/pom.xml
@@ -71,7 +71,7 @@
             </dependency>
             <dependency>
                 <groupId>software.amazon.lambda</groupId>
-                <artifactId>powertools-parameters</artifactId>
+                <artifactId>powertools-parameters-appconfig</artifactId>
                 <version>${lambda.powertools.version}</version>
             </dependency>
             <dependency>

From 487bd77bf5efa75af271c0611903f0af55d3e11c Mon Sep 17 00:00:00 2001
From: Scott Gerring <gerrings@amazon.com>
Date: Fri, 8 Dec 2023 16:03:01 +0100
Subject: [PATCH 42/45] Clean up E2E test tree

---
 pom.xml                                       | 29 -------------------
 powertools-e2e-tests/handlers/batch/pom.xml   |  2 +-
 .../handlers/idempotency/pom.xml              |  2 +-
 .../handlers/largemessage/pom.xml             |  2 +-
 .../handlers/largemessage_idempotent/pom.xml  |  2 +-
 powertools-e2e-tests/handlers/logging/pom.xml |  2 +-
 powertools-e2e-tests/handlers/metrics/pom.xml |  4 +--
 .../handlers/parameters/pom.xml               |  4 +--
 .../lambda/powertools/e2e/Function.java       |  3 +-
 powertools-e2e-tests/handlers/pom.xml         |  8 +++--
 powertools-e2e-tests/handlers/tracing/pom.xml |  2 +-
 .../handlers/validation-alb-event/pom.xml     |  2 +-
 .../handlers/validation-apigw-event/pom.xml   |  2 +-
 13 files changed, 19 insertions(+), 45 deletions(-)

diff --git a/pom.xml b/pom.xml
index 3c2768b98..1d35a990f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -605,35 +605,6 @@
             </activation>
             <build>
                 <plugins>
-                    <plugin>
-                        <!-- we run checkstyle only on Java 11, no need to run it for all JDK, it's just code style -->
-                        <groupId>org.apache.maven.plugins</groupId>
-                        <artifactId>maven-checkstyle-plugin</artifactId>
-                        <version>3.3.0</version>
-                        <configuration>
-                            <configLocation>checkstyle.xml</configLocation>
-                            <encoding>UTF-8</encoding>
-                            <consoleOutput>true</consoleOutput>
-                            <failsOnError>true</failsOnError>
-                            <linkXRef>false</linkXRef>
-                        </configuration>
-                        <!-- does not work without this dependency -->
-                        <!-- does not work with this dependency on Java 8 -->
-                        <dependencies>
-                            <dependency>
-                                <groupId>com.puppycrawl.tools</groupId>
-                                <artifactId>checkstyle</artifactId>
-                                <version>10.12.3</version>
-                            </dependency>
-                        </dependencies>
-                        <executions>
-                            <execution>
-                                <goals>
-                                    <goal>check</goal>
-                                </goals>
-                            </execution>
-                        </executions>
-                    </plugin>
                 </plugins>
             </build>
         </profile>
diff --git a/powertools-e2e-tests/handlers/batch/pom.xml b/powertools-e2e-tests/handlers/batch/pom.xml
index ccb9926f1..8740dcb0b 100644
--- a/powertools-e2e-tests/handlers/batch/pom.xml
+++ b/powertools-e2e-tests/handlers/batch/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <groupId>software.amazon.lambda</groupId>
         <artifactId>e2e-test-handlers-parent</artifactId>
-        <version>2.0.0</version>
+        <version>2.0.0-SNAPSHOT</version>
     </parent>
 
     <artifactId>e2e-test-handler-batch</artifactId>
diff --git a/powertools-e2e-tests/handlers/idempotency/pom.xml b/powertools-e2e-tests/handlers/idempotency/pom.xml
index f033fce24..a0e6bd4fc 100644
--- a/powertools-e2e-tests/handlers/idempotency/pom.xml
+++ b/powertools-e2e-tests/handlers/idempotency/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <groupId>software.amazon.lambda</groupId>
         <artifactId>e2e-test-handlers-parent</artifactId>
-        <version>2.0.0</version>
+        <version>2.0.0-SNAPSHOT</version>
     </parent>
 
     <artifactId>e2e-test-handler-idempotency</artifactId>
diff --git a/powertools-e2e-tests/handlers/largemessage/pom.xml b/powertools-e2e-tests/handlers/largemessage/pom.xml
index e6539f4fe..277e76fc1 100644
--- a/powertools-e2e-tests/handlers/largemessage/pom.xml
+++ b/powertools-e2e-tests/handlers/largemessage/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <groupId>software.amazon.lambda</groupId>
         <artifactId>e2e-test-handlers-parent</artifactId>
-        <version>2.0.0</version>
+        <version>2.0.0-SNAPSHOT</version>
     </parent>
 
     <artifactId>e2e-test-handler-largemessage</artifactId>
diff --git a/powertools-e2e-tests/handlers/largemessage_idempotent/pom.xml b/powertools-e2e-tests/handlers/largemessage_idempotent/pom.xml
index 5e7f026bf..d887341c5 100644
--- a/powertools-e2e-tests/handlers/largemessage_idempotent/pom.xml
+++ b/powertools-e2e-tests/handlers/largemessage_idempotent/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <groupId>software.amazon.lambda</groupId>
         <artifactId>e2e-test-handlers-parent</artifactId>
-        <version>2.0.0</version>
+        <version>2.0.0-SNAPSHOT</version>
     </parent>
 
     <artifactId>e2e-test-handler-large-msg-idempotent</artifactId>
diff --git a/powertools-e2e-tests/handlers/logging/pom.xml b/powertools-e2e-tests/handlers/logging/pom.xml
index 86c149f45..222c5ab2e 100644
--- a/powertools-e2e-tests/handlers/logging/pom.xml
+++ b/powertools-e2e-tests/handlers/logging/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <groupId>software.amazon.lambda</groupId>
         <artifactId>e2e-test-handlers-parent</artifactId>
-        <version>2.0.0</version>
+        <version>2.0.0-SNAPSHOT</version>
     </parent>
 
     <artifactId>e2e-test-handler-logging</artifactId>
diff --git a/powertools-e2e-tests/handlers/metrics/pom.xml b/powertools-e2e-tests/handlers/metrics/pom.xml
index ce5e934d8..68059e67e 100644
--- a/powertools-e2e-tests/handlers/metrics/pom.xml
+++ b/powertools-e2e-tests/handlers/metrics/pom.xml
@@ -5,12 +5,12 @@
     <parent>
         <groupId>software.amazon.lambda</groupId>
         <artifactId>e2e-test-handlers-parent</artifactId>
-        <version>2.0.0</version>
+        <version>2.0.0-SNAPSHOT</version>
     </parent>
 
     <artifactId>e2e-test-handler-metrics</artifactId>
     <packaging>jar</packaging>
-    <name>A Lambda function using Powertools for AWS Lambda (Java) Parameters</name>
+    <name>A Lambda function using Powertools for AWS Lambda (Java) Metrics</name>
 
     <dependencies>
         <dependency>
diff --git a/powertools-e2e-tests/handlers/parameters/pom.xml b/powertools-e2e-tests/handlers/parameters/pom.xml
index 60cf8d868..328d30485 100644
--- a/powertools-e2e-tests/handlers/parameters/pom.xml
+++ b/powertools-e2e-tests/handlers/parameters/pom.xml
@@ -5,12 +5,12 @@
     <parent>
         <groupId>software.amazon.lambda</groupId>
         <artifactId>e2e-test-handlers-parent</artifactId>
-        <version>2.0.0</version>
+        <version>2.0.0-SNAPSHOT</version>
     </parent>
 
     <artifactId>e2e-test-handler-parameters</artifactId>
     <packaging>jar</packaging>
-    <name>A Lambda function using powertools logging</name>
+    <name>A Lambda function using powertools parameters</name>
 
     <dependencies>
         <dependency>
diff --git a/powertools-e2e-tests/handlers/parameters/src/main/java/software/amazon/lambda/powertools/e2e/Function.java b/powertools-e2e-tests/handlers/parameters/src/main/java/software/amazon/lambda/powertools/e2e/Function.java
index 016844117..1e151825e 100644
--- a/powertools-e2e-tests/handlers/parameters/src/main/java/software/amazon/lambda/powertools/e2e/Function.java
+++ b/powertools-e2e-tests/handlers/parameters/src/main/java/software/amazon/lambda/powertools/e2e/Function.java
@@ -17,8 +17,7 @@
 import com.amazonaws.services.lambda.runtime.Context;
 import com.amazonaws.services.lambda.runtime.RequestHandler;
 import software.amazon.lambda.powertools.logging.Logging;
-import software.amazon.lambda.powertools.parameters.AppConfigProvider;
-import software.amazon.lambda.powertools.parameters.ParamManager;
+import software.amazon.lambda.powertools.parameters.appconfig.AppConfigProvider;
 
 public class Function implements RequestHandler<Input, String> {
 
diff --git a/powertools-e2e-tests/handlers/pom.xml b/powertools-e2e-tests/handlers/pom.xml
index 9476d24b6..2c73de977 100644
--- a/powertools-e2e-tests/handlers/pom.xml
+++ b/powertools-e2e-tests/handlers/pom.xml
@@ -4,7 +4,7 @@
 
     <groupId>software.amazon.lambda</groupId>
     <artifactId>e2e-test-handlers-parent</artifactId>
-    <version>2.0.0</version>
+    <version>2.0.0-SNAPSHOT</version>
     <packaging>pom</packaging>
     <name>Handlers for End-to-End tests</name>
     <description>Fake handlers that use Powertools for AWS Lambda (Java).</description>
@@ -27,12 +27,16 @@
     </properties>
 
     <modules>
+        <module>batch</module>
+        <module>largemessage</module>
+        <module>largemessage_idempotent</module>
         <module>logging</module>
         <module>tracing</module>
         <module>metrics</module>
         <module>idempotency</module>
         <module>parameters</module>
-        <module>validation</module>
+        <module>validation-alb-event</module>
+        <module>validation-apigw-event</module>
     </modules>
 
     <dependencyManagement>
diff --git a/powertools-e2e-tests/handlers/tracing/pom.xml b/powertools-e2e-tests/handlers/tracing/pom.xml
index b1bc14c05..b96fcef0a 100644
--- a/powertools-e2e-tests/handlers/tracing/pom.xml
+++ b/powertools-e2e-tests/handlers/tracing/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <groupId>software.amazon.lambda</groupId>
         <artifactId>e2e-test-handlers-parent</artifactId>
-        <version>2.0.0</version>
+        <version>2.0.0-SNAPSHOT</version>
     </parent>
 
     <artifactId>e2e-test-handler-tracing</artifactId>
diff --git a/powertools-e2e-tests/handlers/validation-alb-event/pom.xml b/powertools-e2e-tests/handlers/validation-alb-event/pom.xml
index 36695b9a4..be50094c1 100644
--- a/powertools-e2e-tests/handlers/validation-alb-event/pom.xml
+++ b/powertools-e2e-tests/handlers/validation-alb-event/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <groupId>software.amazon.lambda</groupId>
         <artifactId>e2e-test-handlers-parent</artifactId>
-        <version>2.0.0</version>
+        <version>2.0.0-SNAPSHOT</version>
     </parent>
 
     <artifactId>e2e-test-handler-validation-alb-event</artifactId>
diff --git a/powertools-e2e-tests/handlers/validation-apigw-event/pom.xml b/powertools-e2e-tests/handlers/validation-apigw-event/pom.xml
index 8bb927778..f204a8a9f 100644
--- a/powertools-e2e-tests/handlers/validation-apigw-event/pom.xml
+++ b/powertools-e2e-tests/handlers/validation-apigw-event/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <groupId>software.amazon.lambda</groupId>
         <artifactId>e2e-test-handlers-parent</artifactId>
-        <version>2.0.0</version>
+        <version>2.0.0-SNAPSHOT</version>
     </parent>
 
     <artifactId>e2e-test-handler-validation-apigw-event</artifactId>

From d36f36dae3d9e6a8d6d1a5092579072a7928e567 Mon Sep 17 00:00:00 2001
From: Scott Gerring <scottgerring@users.noreply.github.com>
Date: Mon, 11 Dec 2023 12:43:01 +0100
Subject: [PATCH 43/45] Apply suggestions from code review
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Co-authored-by: Jérôme Van Der Linden <117538+jeromevdl@users.noreply.github.com>
---
 .../parameters/appconfig/AppConfigProviderTest.java        | 7 +++----
 .../powertools/parameters/dynamodb/DynamoDbParam.java      | 2 +-
 2 files changed, 4 insertions(+), 5 deletions(-)

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 7cbf7256b..bfa60618a 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
@@ -16,16 +16,15 @@
 
 import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
 import static org.assertj.core.api.Assertions.assertThatRuntimeException;
-import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.MockitoAnnotations.openMocks;
 
-import org.assertj.core.api.Assertions;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Captor;
 import org.mockito.Mock;
 import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
 import software.amazon.awssdk.core.SdkBytes;
 import software.amazon.awssdk.services.appconfigdata.AppConfigDataClient;
 import software.amazon.awssdk.services.appconfigdata.model.GetLatestConfigurationRequest;
@@ -53,7 +52,7 @@ public class AppConfigProviderTest {
 
     @BeforeEach
     public void init() {
-        MockitoAnnotations.openMocks(this);
+       openMocks(this);
 
         provider = AppConfigProvider.builder()
                 .withClient(client)
diff --git a/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbParam.java b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbParam.java
index f1ba4fe8a..946786cb4 100644
--- a/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbParam.java
+++ b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbParam.java
@@ -26,7 +26,7 @@
  *
  * Usage:
  * <pre>
- * @SSMParam(key = "my-param", table = "my-table")
+ * @DynamoDbParam(key = "my-param", table = "my-table")
  * String myParameter;
  * </pre>
  */

From c7422f205a94c124988cd9346982a646fbe46d9b Mon Sep 17 00:00:00 2001
From: Scott Gerring <scottgerring@users.noreply.github.com>
Date: Mon, 11 Dec 2023 12:46:47 +0100
Subject: [PATCH 44/45] Apply suggestions from code review
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Co-authored-by: Jérôme Van Der Linden <117538+jeromevdl@users.noreply.github.com>
---
 docs/utilities/parameters.md | 22 ++++++++++------------
 1 file changed, 10 insertions(+), 12 deletions(-)

diff --git a/docs/utilities/parameters.md b/docs/utilities/parameters.md
index 607791a82..f72c7704e 100644
--- a/docs/utilities/parameters.md
+++ b/docs/utilities/parameters.md
@@ -215,9 +215,8 @@ interface. In cases where a provider supports extra features, these will also be
         String secretParam;
 
         public string handleRequest(String request, Context context) {
-            // Because this is a secret, we probably don't want to return it! Return something indicating
-            // we could access it instead.
-            return "Retrieved a secret, and sensibly refusing to return it!";
+            // ... do something with the secretParam here
+            return "something";
         }
     }
     ```
@@ -245,9 +244,8 @@ interface. In cases where a provider supports extra features, these will also be
             // Retrieve a single secret
             String value = secretsProvider.get("/my/secret");
     
-            // Because this is a secret, we probably don't want to return it! Return something indicating
-            // we could access it instead.
-            return "Retrieved a secret, and sensibly refusing to return it!";
+            // ... do something with the secretParam here
+            return "something";
         }
     }
     ```
@@ -301,10 +299,10 @@ The AWS Systems Manager Parameter Store provider supports two additional argumen
                 .build();
     
         public String handleRequest(String input, Context context) {
-            // Retrieve a single secret
+            // Retrieve a single param
             String value = ssmProvider
                     .get("/my/secret");
-                    // We might instead want to retrieve multiple secrets at once, returning a Map of key/value pairs
+                    // We might instead want to retrieve multiple parameters at once, returning a Map of key/value pairs
                     // .getMultiple("/my/secret/path");
 
             // Return the result
@@ -365,7 +363,7 @@ The AWS Systems Manager Parameter Store provider supports two additional argumen
 
     public class RequestHandlerWithParams implements RequestHandler<String, String> {
     
-        // Get an instance of the SecretsProvider. We can provide a custom client here if we want,
+        // Get an instance of the DynamoDbProvider. We can provide a custom client here if we want,
         // for instance to use a particular region.
         DynamoDbProvider ddbProvider = DynamoDbProvider
                 .builder()
@@ -373,7 +371,7 @@ The AWS Systems Manager Parameter Store provider supports two additional argumen
                 .build();
     
         public String handleRequest(String input, Context context) {
-            // Retrieve a single secret
+            // Retrieve a single param
             String value = ddbProvider
                     .get("/my/secret");
                     // We might instead want to retrieve multiple values at once, returning a Map of key/value pairs
@@ -418,7 +416,7 @@ The AWS Systems Manager Parameter Store provider supports two additional argumen
 
     public class RequestHandlerWithParams implements RequestHandler<String, String> {
     
-        // Get an instance of the SecretsProvider. We can provide a custom client here if we want,
+        // Get an instance of the AppConfigProvider. We can provide a custom client here if we want,
         // for instance to use a particular region.
         AppConfigProvider appConfigProvider = AppConfigProvider
                 .builder()
@@ -426,7 +424,7 @@ The AWS Systems Manager Parameter Store provider supports two additional argumen
                 .build();
     
         public String handleRequest(String input, Context context) {
-            // Retrieve a single secret
+            // Retrieve a single param
             String value = appConfigProvider
                     .get("/my/secret");
     

From 75abe1e3e00f7fe9b0744a8c82fb9c79a60d7999 Mon Sep 17 00:00:00 2001
From: Scott Gerring <scottgerring@users.noreply.github.com>
Date: Mon, 11 Dec 2023 13:10:05 +0100
Subject: [PATCH 45/45] Update
 powertools-parameters/powertools-parameters-appconfig/src/test/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProviderTest.java
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Co-authored-by: Jérôme Van Der Linden <117538+jeromevdl@users.noreply.github.com>
---
 .../powertools/parameters/appconfig/AppConfigProviderTest.java  | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

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 bfa60618a..ded568e8d 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
@@ -52,7 +52,7 @@ public class AppConfigProviderTest {
 
     @BeforeEach
     public void init() {
-       openMocks(this);
+        openMocks(this);
 
         provider = AppConfigProvider.builder()
                 .withClient(client)
