From 13adc2269d4a0110a0d1145951b9f7ef16eda3d7 Mon Sep 17 00:00:00 2001 From: RanVaknin <50976344+RanVaknin@users.noreply.github.com> Date: Tue, 2 Sep 2025 14:03:04 -0700 Subject: [PATCH 01/11] Adding thread context package --- bom/pom.xml | 5 +++ pom.xml | 1 + thread-context/pom.xml | 33 ++++++++++++++ .../awssdk/threadcontext/ThreadStorage.java | 45 +++++++++++++++++++ 4 files changed, 84 insertions(+) create mode 100644 thread-context/pom.xml create mode 100644 thread-context/src/main/java/software/amazon/awssdk/threadcontext/ThreadStorage.java diff --git a/bom/pom.xml b/bom/pom.xml index ede5b925100..51494631af0 100644 --- a/bom/pom.xml +++ b/bom/pom.xml @@ -252,6 +252,11 @@ endpoints-spi ${awsjavasdk.version} + + software.amazon.awssdk + thread-context + ${awsjavasdk.version} + software.amazon.awssdk diff --git a/pom.xml b/pom.xml index 42dbdbfc01b..fd1409a27f3 100644 --- a/pom.xml +++ b/pom.xml @@ -95,6 +95,7 @@ test/crt-unavailable-tests test/architecture-tests test/s3-tests + thread-context ${scm.github.url} diff --git a/thread-context/pom.xml b/thread-context/pom.xml new file mode 100644 index 00000000000..e942f7e0a33 --- /dev/null +++ b/thread-context/pom.xml @@ -0,0 +1,33 @@ + + + + + 4.0.0 + + software.amazon.awssdk + aws-sdk-java-pom + 2.33.2-SNAPSHOT + + thread-context + AWS Java SDK :: Thread Context + + Provides thread-local context storage utilities for sharing data across components. + + https://aws.amazon.com/sdkforjava + + \ No newline at end of file diff --git a/thread-context/src/main/java/software/amazon/awssdk/threadcontext/ThreadStorage.java b/thread-context/src/main/java/software/amazon/awssdk/threadcontext/ThreadStorage.java new file mode 100644 index 00000000000..f7223a74f70 --- /dev/null +++ b/thread-context/src/main/java/software/amazon/awssdk/threadcontext/ThreadStorage.java @@ -0,0 +1,45 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package software.amazon.awssdk.threadcontext; + +import java.util.HashMap; +import java.util.Map; + +public final class ThreadStorage { + private static final ThreadLocal> storage = ThreadLocal.withInitial(HashMap::new); + + private ThreadStorage() {} + + public static void put(String key, String value) { + storage.get().put(key, value); + } + + public static String get(String key) { + return storage.get().get(key); + } + + public static String remove(String key) { + return storage.get().remove(key); + } + + public static void clear() { + storage.get().clear(); + } + + public static boolean containsKey(String key) { + return storage.get().containsKey(key); + } +} From 828dc504b6c255e9e09d3ea62496b926af382b9a Mon Sep 17 00:00:00 2001 From: RanVaknin <50976344+RanVaknin@users.noreply.github.com> Date: Tue, 2 Sep 2025 14:04:23 -0700 Subject: [PATCH 02/11] Fix ordering in pom --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index fd1409a27f3..f5577c128f9 100644 --- a/pom.xml +++ b/pom.xml @@ -72,6 +72,7 @@ archetypes third-party v2-migration + thread-context test/http-client-tests test/protocol-tests test/protocol-tests-core @@ -95,7 +96,6 @@ test/crt-unavailable-tests test/architecture-tests test/s3-tests - thread-context ${scm.github.url} From a6d60ec2c25eef7132100495651c0115e3130936 Mon Sep 17 00:00:00 2001 From: RanVaknin <50976344+RanVaknin@users.noreply.github.com> Date: Tue, 2 Sep 2025 14:17:23 -0700 Subject: [PATCH 03/11] Add changelog --- .changes/next-release/feature-AWSSDKforJavav2-2e7c0a3.json | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changes/next-release/feature-AWSSDKforJavav2-2e7c0a3.json diff --git a/.changes/next-release/feature-AWSSDKforJavav2-2e7c0a3.json b/.changes/next-release/feature-AWSSDKforJavav2-2e7c0a3.json new file mode 100644 index 00000000000..4b0c2020e6f --- /dev/null +++ b/.changes/next-release/feature-AWSSDKforJavav2-2e7c0a3.json @@ -0,0 +1,6 @@ +{ + "type": "feature", + "category": "AWS SDK for Java v2", + "contributor": "", + "description": "Adding a small utility class to store data on thread local that can be used across components." +} From b5bcbc50954a6373e25979a152fb433a81e67523 Mon Sep 17 00:00:00 2001 From: RanVaknin <50976344+RanVaknin@users.noreply.github.com> Date: Tue, 2 Sep 2025 14:53:12 -0700 Subject: [PATCH 04/11] Add requirements for publishing new package --- .brazil.json | 1 + aws-sdk-java/pom.xml | 5 ++ pom.xml | 1 + test/architecture-tests/pom.xml | 5 ++ test/tests-coverage-reporting/pom.xml | 5 ++ thread-context/pom.xml | 41 +++++++++++ .../threadcontext/ThreadStorageTest.java | 70 +++++++++++++++++++ 7 files changed, 128 insertions(+) create mode 100644 thread-context/src/test/java/software/amazon/awssdk/threadcontext/ThreadStorageTest.java diff --git a/.brazil.json b/.brazil.json index 7d240cb9bf5..6acd1ba723b 100644 --- a/.brazil.json +++ b/.brazil.json @@ -32,6 +32,7 @@ "s3-transfer-manager": { "packageName": "AwsJavaSdk-S3-TransferManager" }, "s3-event-notifications": { "packageName": "AwsJavaSdk-S3-EventNotifications" }, "sdk-core": { "packageName": "AwsJavaSdk-Core" }, + "thread-context": { "packageName": "AwsJavaSdk-ThreadContext" }, "url-connection-client": { "packageName": "AwsJavaSdk-HttpClient-UrlConnectionClient" }, "utils": { "packageName": "AwsJavaSdk-Core-Utils" }, "imds": { "packageName": "AwsJavaSdk-Imds" }, diff --git a/aws-sdk-java/pom.xml b/aws-sdk-java/pom.xml index 81f8e827a9f..ac745e71fea 100644 --- a/aws-sdk-java/pom.xml +++ b/aws-sdk-java/pom.xml @@ -813,6 +813,11 @@ Amazon AutoScaling, etc). swf ${awsjavasdk.version} + + software.amazon.awssdk + thread-context + ${awsjavasdk.version} + software.amazon.awssdk textract diff --git a/pom.xml b/pom.xml index f5577c128f9..2e942d5f56e 100644 --- a/pom.xml +++ b/pom.xml @@ -659,6 +659,7 @@ protocols regions sdk-core + thread-context http-client-spi apache-client netty-nio-client diff --git a/test/architecture-tests/pom.xml b/test/architecture-tests/pom.xml index 7b255deff4d..ac97eb8cbc3 100644 --- a/test/architecture-tests/pom.xml +++ b/test/architecture-tests/pom.xml @@ -61,6 +61,11 @@ software.amazon.awssdk ${awsjavasdk.version} + + thread-context + software.amazon.awssdk + ${awsjavasdk.version} + s3 software.amazon.awssdk diff --git a/test/tests-coverage-reporting/pom.xml b/test/tests-coverage-reporting/pom.xml index 39e84897ced..d730618895a 100644 --- a/test/tests-coverage-reporting/pom.xml +++ b/test/tests-coverage-reporting/pom.xml @@ -242,6 +242,11 @@ software.amazon.awssdk ${awsjavasdk.version} + + thread-context + software.amazon.awssdk + ${awsjavasdk.version} + diff --git a/core/aws-core/pom.xml b/core/aws-core/pom.xml index 4005eceaddc..82514e2c01c 100644 --- a/core/aws-core/pom.xml +++ b/core/aws-core/pom.xml @@ -115,7 +115,7 @@ software.amazon.awssdk - thread-context + utils-lite ${awsjavasdk.version} diff --git a/core/aws-core/src/main/java/software/amazon/awssdk/awscore/interceptor/TraceIdExecutionInterceptor.java b/core/aws-core/src/main/java/software/amazon/awssdk/awscore/interceptor/TraceIdExecutionInterceptor.java index 08df1c5bfae..e5c866ec72f 100644 --- a/core/aws-core/src/main/java/software/amazon/awssdk/awscore/interceptor/TraceIdExecutionInterceptor.java +++ b/core/aws-core/src/main/java/software/amazon/awssdk/awscore/interceptor/TraceIdExecutionInterceptor.java @@ -23,8 +23,8 @@ import software.amazon.awssdk.core.interceptor.ExecutionAttributes; import software.amazon.awssdk.core.interceptor.ExecutionInterceptor; import software.amazon.awssdk.http.SdkHttpRequest; -import software.amazon.awssdk.threadcontext.ThreadStorage; import software.amazon.awssdk.utils.SystemSetting; +import software.amazon.awssdk.utilslite.internal.SdkInternalThreadLocal; /** * The {@code TraceIdExecutionInterceptor} copies the trace details to the {@link #TRACE_ID_HEADER} header, assuming we seem to @@ -39,7 +39,7 @@ public class TraceIdExecutionInterceptor implements ExecutionInterceptor { @Override public void beforeExecution(Context.BeforeExecution context, ExecutionAttributes executionAttributes) { - String traceId = ThreadStorage.get(CONCURRENT_TRACE_ID_KEY); + String traceId = software.amazon.awssdk.utilslite.internal.SdkInternalThreadLocal.get(CONCURRENT_TRACE_ID_KEY); if (traceId != null) { executionAttributes.putAttribute(TRACE_ID, traceId); } @@ -72,7 +72,7 @@ public void onExecutionFailure(Context.FailedExecution context, ExecutionAttribu private static void saveTraceId(ExecutionAttributes executionAttributes) { String traceId = executionAttributes.getAttribute(TRACE_ID); if (traceId != null) { - ThreadStorage.put(CONCURRENT_TRACE_ID_KEY, executionAttributes.getAttribute(TRACE_ID)); + SdkInternalThreadLocal.put(CONCURRENT_TRACE_ID_KEY, executionAttributes.getAttribute(TRACE_ID)); } } diff --git a/core/aws-core/src/test/java/software/amazon/awssdk/awscore/interceptor/TraceIdExecutionInterceptorTest.java b/core/aws-core/src/test/java/software/amazon/awssdk/awscore/interceptor/TraceIdExecutionInterceptorTest.java index d1b4688d440..8cddcd8f2c7 100644 --- a/core/aws-core/src/test/java/software/amazon/awssdk/awscore/interceptor/TraceIdExecutionInterceptorTest.java +++ b/core/aws-core/src/test/java/software/amazon/awssdk/awscore/interceptor/TraceIdExecutionInterceptorTest.java @@ -28,7 +28,7 @@ import software.amazon.awssdk.http.SdkHttpMethod; import software.amazon.awssdk.http.SdkHttpRequest; import software.amazon.awssdk.testutils.EnvironmentVariableHelper; -import software.amazon.awssdk.threadcontext.ThreadStorage; +import software.amazon.awssdk.utilslite.internal.SdkInternalThreadLocal; public class TraceIdExecutionInterceptorTest { @Test @@ -113,11 +113,11 @@ public void headerNotAddedIfNoTraceIdEnvVar() { } @Test - public void modifyHttpRequest_whenMultiConcurrencyModeWithThreadStorage_shouldAddTraceIdHeader() { + public void modifyHttpRequest_whenMultiConcurrencyModeWithInternalThreadLocal_shouldAddTraceIdHeader() { EnvironmentVariableHelper.run(env -> { resetRelevantEnvVars(env); env.set("AWS_LAMBDA_FUNCTION_NAME", "foo"); - ThreadStorage.put("AWS_LAMBDA_X_TRACE_ID", "ThreadStorage-trace-123"); + software.amazon.awssdk.utilslite.internal.SdkInternalThreadLocal.put("AWS_LAMBDA_X_TRACE_ID", "SdkInternalThreadLocal-trace-123"); try { TraceIdExecutionInterceptor interceptor = new TraceIdExecutionInterceptor(); @@ -127,20 +127,20 @@ public void modifyHttpRequest_whenMultiConcurrencyModeWithThreadStorage_shouldAd Context.ModifyHttpRequest context = context(); SdkHttpRequest request = interceptor.modifyHttpRequest(context, executionAttributes); - assertThat(request.firstMatchingHeader("X-Amzn-Trace-Id")).hasValue("ThreadStorage-trace-123"); + assertThat(request.firstMatchingHeader("X-Amzn-Trace-Id")).hasValue("SdkInternalThreadLocal-trace-123"); } finally { - ThreadStorage.remove("AWS_LAMBDA_X_TRACE_ID"); + software.amazon.awssdk.utilslite.internal.SdkInternalThreadLocal.remove("AWS_LAMBDA_X_TRACE_ID"); } }); } @Test - public void modifyHttpRequest_whenMultiConcurrencyModeWithBothThreadStorageAndSystemProperty_shouldUseThreadStorageValue() { + public void modifyHttpRequest_whenMultiConcurrencyModeWithBothInternalThreadLocalAndSystemProperty_shouldUseInternalThreadLocalValue() { EnvironmentVariableHelper.run(env -> { resetRelevantEnvVars(env); env.set("AWS_LAMBDA_FUNCTION_NAME", "foo"); - ThreadStorage.put("AWS_LAMBDA_X_TRACE_ID", "ThreadStorage-trace-123"); + SdkInternalThreadLocal.put("AWS_LAMBDA_X_TRACE_ID", "SdkInternalThreadLocal-trace-123"); Properties props = System.getProperties(); props.setProperty("com.amazonaws.xray.traceHeader", "sys-prop-345"); @@ -153,20 +153,20 @@ public void modifyHttpRequest_whenMultiConcurrencyModeWithBothThreadStorageAndSy Context.ModifyHttpRequest context = context(); SdkHttpRequest request = interceptor.modifyHttpRequest(context, executionAttributes); - assertThat(request.firstMatchingHeader("X-Amzn-Trace-Id")).hasValue("ThreadStorage-trace-123"); + assertThat(request.firstMatchingHeader("X-Amzn-Trace-Id")).hasValue("SdkInternalThreadLocal-trace-123"); } finally { - ThreadStorage.remove("AWS_LAMBDA_X_TRACE_ID"); + software.amazon.awssdk.utilslite.internal.SdkInternalThreadLocal.remove("AWS_LAMBDA_X_TRACE_ID"); props.remove("com.amazonaws.xray.traceHeader"); } }); } @Test - public void modifyHttpRequest_whenNotInLambdaEnvironmentWithThreadStorage_shouldNotAddHeader() { + public void modifyHttpRequest_whenNotInLambdaEnvironmentWithInternalThreadLocal_shouldNotAddHeader() { EnvironmentVariableHelper.run(env -> { resetRelevantEnvVars(env); - ThreadStorage.put("AWS_LAMBDA_X_TRACE_ID", "should-be-ignored"); + software.amazon.awssdk.utilslite.internal.SdkInternalThreadLocal.put("AWS_LAMBDA_X_TRACE_ID", "should-be-ignored"); try { TraceIdExecutionInterceptor interceptor = new TraceIdExecutionInterceptor(); @@ -179,7 +179,7 @@ public void modifyHttpRequest_whenNotInLambdaEnvironmentWithThreadStorage_should assertThat(request.firstMatchingHeader("X-Amzn-Trace-Id")).isEmpty(); } finally { - ThreadStorage.remove("AWS_LAMBDA_X_TRACE_ID"); + software.amazon.awssdk.utilslite.internal.SdkInternalThreadLocal.remove("AWS_LAMBDA_X_TRACE_ID"); } }); } diff --git a/pom.xml b/pom.xml index 2e942d5f56e..4ac0d06763e 100644 --- a/pom.xml +++ b/pom.xml @@ -72,7 +72,7 @@ archetypes third-party v2-migration - thread-context + utils-lite test/http-client-tests test/protocol-tests test/protocol-tests-core @@ -659,7 +659,7 @@ protocols regions sdk-core - thread-context + utils-lite http-client-spi apache-client netty-nio-client diff --git a/test/architecture-tests/pom.xml b/test/architecture-tests/pom.xml index ac97eb8cbc3..429b732c0f1 100644 --- a/test/architecture-tests/pom.xml +++ b/test/architecture-tests/pom.xml @@ -62,7 +62,7 @@ ${awsjavasdk.version} - thread-context + utils-lite software.amazon.awssdk ${awsjavasdk.version} diff --git a/test/architecture-tests/src/test/java/software/amazon/awssdk/archtests/UtilsLitePackageTest.java b/test/architecture-tests/src/test/java/software/amazon/awssdk/archtests/UtilsLitePackageTest.java new file mode 100644 index 00000000000..b0f8dc5ad1e --- /dev/null +++ b/test/architecture-tests/src/test/java/software/amazon/awssdk/archtests/UtilsLitePackageTest.java @@ -0,0 +1,43 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package software.amazon.awssdk.archtests; + +import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.classes; + +import com.tngtech.archunit.core.domain.JavaClasses; +import com.tngtech.archunit.core.importer.ClassFileImporter; +import com.tngtech.archunit.lang.ArchRule; +import org.junit.jupiter.api.Test; + +/** + * Architecture tests for the utils-lite package to ensure it only contains allowed classes. + */ +public class UtilsLitePackageTest { + + private static final JavaClasses CLASSES = new ClassFileImporter() + .importPackages("software.amazon.awssdk.utilslite"); + + @Test + public void utilsLitePackage_shouldOnlyContainAllowedClasses() { + ArchRule rule = classes() + .that().resideInAPackage("software.amazon.awssdk.utilslite") + .should().haveNameMatching(".*\\.(SdkInternalThreadLocal|SdkInternalThreadLocalTest)") + .allowEmptyShould(true) + .because("utils-lite package should only contain SdkInternalThreadLocal and its test"); + + rule.check(CLASSES); + } +} diff --git a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/TraceIdTest.java b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/TraceIdTest.java index 43c0dad6161..3940643de70 100644 --- a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/TraceIdTest.java +++ b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/TraceIdTest.java @@ -35,7 +35,7 @@ import software.amazon.awssdk.testutils.service.http.MockAsyncHttpClient; import software.amazon.awssdk.testutils.service.http.MockSyncHttpClient; import software.amazon.awssdk.utils.StringInputStream; -import software.amazon.awssdk.threadcontext.ThreadStorage; +import software.amazon.awssdk.utilslite.internal.SdkInternalThreadLocal; /** * Verifies that the {@link TraceIdExecutionInterceptor} is actually wired up for AWS services. @@ -69,7 +69,7 @@ public void traceIdInterceptorIsEnabled() { public void traceIdInterceptorPreservesTraceIdAcrossRetries() { EnvironmentVariableHelper.run(env -> { env.set("AWS_LAMBDA_FUNCTION_NAME", "foo"); - ThreadStorage.put("AWS_LAMBDA_X_TRACE_ID", "ThreadStorage-trace-123"); + software.amazon.awssdk.utilslite.internal.SdkInternalThreadLocal.put("AWS_LAMBDA_X_TRACE_ID", "SdkInternalThreadLocal-trace-123"); try (MockAsyncHttpClient mockHttpClient = new MockAsyncHttpClient(); ProtocolRestJsonAsyncClient client = ProtocolRestJsonAsyncClient.builder() @@ -96,12 +96,12 @@ public void traceIdInterceptorPreservesTraceIdAcrossRetries() { List requests = mockHttpClient.getRequests(); assertThat(requests).hasSize(3); - assertThat(requests.get(0).firstMatchingHeader("X-Amzn-Trace-Id")).hasValue("ThreadStorage-trace-123"); - assertThat(requests.get(1).firstMatchingHeader("X-Amzn-Trace-Id")).hasValue("ThreadStorage-trace-123"); - assertThat(requests.get(2).firstMatchingHeader("X-Amzn-Trace-Id")).hasValue("ThreadStorage-trace-123"); + assertThat(requests.get(0).firstMatchingHeader("X-Amzn-Trace-Id")).hasValue("SdkInternalThreadLocal-trace-123"); + assertThat(requests.get(1).firstMatchingHeader("X-Amzn-Trace-Id")).hasValue("SdkInternalThreadLocal-trace-123"); + assertThat(requests.get(2).firstMatchingHeader("X-Amzn-Trace-Id")).hasValue("SdkInternalThreadLocal-trace-123"); } finally { - ThreadStorage.clear(); + SdkInternalThreadLocal.clear(); } }); } @@ -110,7 +110,7 @@ public void traceIdInterceptorPreservesTraceIdAcrossRetries() { public void traceIdInterceptorPreservesTraceIdAcrossChainedFutures() { EnvironmentVariableHelper.run(env -> { env.set("AWS_LAMBDA_FUNCTION_NAME", "foo"); - ThreadStorage.put("AWS_LAMBDA_X_TRACE_ID", "ThreadStorage-trace-123"); + software.amazon.awssdk.utilslite.internal.SdkInternalThreadLocal.put("AWS_LAMBDA_X_TRACE_ID", "SdkInternalThreadLocal-trace-123"); try (MockAsyncHttpClient mockHttpClient = new MockAsyncHttpClient(); ProtocolRestJsonAsyncClient client = ProtocolRestJsonAsyncClient.builder() @@ -140,11 +140,11 @@ public void traceIdInterceptorPreservesTraceIdAcrossChainedFutures() { assertThat(requests).hasSize(2); - assertThat(requests.get(0).firstMatchingHeader("X-Amzn-Trace-Id")).hasValue("ThreadStorage-trace-123"); - assertThat(requests.get(1).firstMatchingHeader("X-Amzn-Trace-Id")).hasValue("ThreadStorage-trace-123"); + assertThat(requests.get(0).firstMatchingHeader("X-Amzn-Trace-Id")).hasValue("SdkInternalThreadLocal-trace-123"); + assertThat(requests.get(1).firstMatchingHeader("X-Amzn-Trace-Id")).hasValue("SdkInternalThreadLocal-trace-123"); } finally { - ThreadStorage.clear(); + software.amazon.awssdk.utilslite.internal.SdkInternalThreadLocal.clear(); } }); } @@ -153,7 +153,7 @@ public void traceIdInterceptorPreservesTraceIdAcrossChainedFutures() { public void traceIdInterceptorPreservesTraceIdAcrossExceptionallyCompletedFutures() { EnvironmentVariableHelper.run(env -> { env.set("AWS_LAMBDA_FUNCTION_NAME", "foo"); - ThreadStorage.put("AWS_LAMBDA_X_TRACE_ID", "ThreadStorage-trace-123"); + software.amazon.awssdk.utilslite.internal.SdkInternalThreadLocal.put("AWS_LAMBDA_X_TRACE_ID", "SdkInternalThreadLocal-trace-123"); try (MockAsyncHttpClient mockHttpClient = new MockAsyncHttpClient(); ProtocolRestJsonAsyncClient client = ProtocolRestJsonAsyncClient.builder() @@ -183,11 +183,11 @@ public void traceIdInterceptorPreservesTraceIdAcrossExceptionallyCompletedFuture assertThat(requests).hasSize(2); - assertThat(requests.get(0).firstMatchingHeader("X-Amzn-Trace-Id")).hasValue("ThreadStorage-trace-123"); - assertThat(requests.get(1).firstMatchingHeader("X-Amzn-Trace-Id")).hasValue("ThreadStorage-trace-123"); + assertThat(requests.get(0).firstMatchingHeader("X-Amzn-Trace-Id")).hasValue("SdkInternalThreadLocal-trace-123"); + assertThat(requests.get(1).firstMatchingHeader("X-Amzn-Trace-Id")).hasValue("SdkInternalThreadLocal-trace-123"); } finally { - ThreadStorage.clear(); + software.amazon.awssdk.utilslite.internal.SdkInternalThreadLocal.clear(); } }); } @@ -196,7 +196,7 @@ public void traceIdInterceptorPreservesTraceIdAcrossExceptionallyCompletedFuture public void traceIdInterceptorPreservesTraceIdAcrossExceptionallyCompletedFuturesThrownInPreExecution() { EnvironmentVariableHelper.run(env -> { env.set("AWS_LAMBDA_FUNCTION_NAME", "foo"); - ThreadStorage.put("AWS_LAMBDA_X_TRACE_ID", "ThreadStorage-trace-123"); + software.amazon.awssdk.utilslite.internal.SdkInternalThreadLocal.put("AWS_LAMBDA_X_TRACE_ID", "SdkInternalThreadLocal-trace-123"); ExecutionInterceptor throwingInterceptor = new ExecutionInterceptor() { private boolean hasThrown = false; @@ -234,10 +234,10 @@ public void beforeMarshalling(Context.BeforeMarshalling context, ExecutionAttrib List requests = mockHttpClient.getRequests(); assertThat(requests).hasSize(1); - assertThat(requests.get(0).firstMatchingHeader("X-Amzn-Trace-Id")).hasValue("ThreadStorage-trace-123"); + assertThat(requests.get(0).firstMatchingHeader("X-Amzn-Trace-Id")).hasValue("SdkInternalThreadLocal-trace-123"); } finally { - ThreadStorage.clear(); + software.amazon.awssdk.utilslite.internal.SdkInternalThreadLocal.clear(); } }); } diff --git a/test/tests-coverage-reporting/pom.xml b/test/tests-coverage-reporting/pom.xml index d730618895a..c38237517cd 100644 --- a/test/tests-coverage-reporting/pom.xml +++ b/test/tests-coverage-reporting/pom.xml @@ -243,7 +243,7 @@ ${awsjavasdk.version} - thread-context + utils-lite software.amazon.awssdk ${awsjavasdk.version} diff --git a/thread-context/pom.xml b/utils-lite/pom.xml similarity index 91% rename from thread-context/pom.xml rename to utils-lite/pom.xml index 56a1c81bded..02de38eac13 100644 --- a/thread-context/pom.xml +++ b/utils-lite/pom.xml @@ -23,10 +23,10 @@ aws-sdk-java-pom 2.33.2-SNAPSHOT - thread-context - AWS Java SDK :: Thread Context + utils-lite + AWS Java SDK :: Utils Lite - Provides thread-local context storage utilities for sharing data across components. + A package providing minimal external utils. https://aws.amazon.com/sdkforjava @@ -68,7 +68,7 @@ - software.amazon.awssdk.threadcontext + software.amazon.awssdk.utilslite diff --git a/thread-context/src/main/java/software/amazon/awssdk/threadcontext/ThreadStorage.java b/utils-lite/src/main/java/software/amazon/awssdk/utilslite/internal/SdkInternalThreadLocal.java similarity index 77% rename from thread-context/src/main/java/software/amazon/awssdk/threadcontext/ThreadStorage.java rename to utils-lite/src/main/java/software/amazon/awssdk/utilslite/internal/SdkInternalThreadLocal.java index 187551292b9..6cff2983f3c 100644 --- a/thread-context/src/main/java/software/amazon/awssdk/threadcontext/ThreadStorage.java +++ b/utils-lite/src/main/java/software/amazon/awssdk/utilslite/internal/SdkInternalThreadLocal.java @@ -13,24 +13,28 @@ * permissions and limitations under the License. */ -package software.amazon.awssdk.threadcontext; +package software.amazon.awssdk.utilslite.internal; import java.util.HashMap; import java.util.Map; -import software.amazon.awssdk.annotations.SdkProtectedApi; +import software.amazon.awssdk.annotations.SdkInternalApi; /** * Utility for thread-local context storage. */ -@SdkProtectedApi -public final class ThreadStorage { +@SdkInternalApi +public final class SdkInternalThreadLocal { private static final ThreadLocal> STORAGE = ThreadLocal.withInitial(HashMap::new); - private ThreadStorage() { + private SdkInternalThreadLocal() { } public static void put(String key, String value) { - STORAGE.get().put(key, value); + if (value == null) { + STORAGE.get().remove(key); + } else { + STORAGE.get().put(key, value); + } } public static String get(String key) { diff --git a/thread-context/src/test/java/software/amazon/awssdk/threadcontext/ThreadStorageTest.java b/utils-lite/src/test/java/software/amazon/awssdk/utilslite/ThreadStorageTest.java similarity index 53% rename from thread-context/src/test/java/software/amazon/awssdk/threadcontext/ThreadStorageTest.java rename to utils-lite/src/test/java/software/amazon/awssdk/utilslite/ThreadStorageTest.java index 01e4f046408..eb473861478 100644 --- a/thread-context/src/test/java/software/amazon/awssdk/threadcontext/ThreadStorageTest.java +++ b/utils-lite/src/test/java/software/amazon/awssdk/utilslite/ThreadStorageTest.java @@ -13,58 +13,59 @@ * permissions and limitations under the License. */ -package software.amazon.awssdk.threadcontext; +package software.amazon.awssdk.utilslite; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; +import software.amazon.awssdk.utilslite.internal.SdkInternalThreadLocal; import static org.assertj.core.api.Assertions.assertThat; -class ThreadStorageTest { +class SdkInternalThreadLocalTest { @AfterEach void cleanup() { - ThreadStorage.clear(); + SdkInternalThreadLocal.clear(); } @Test void putAndGet_shouldStoreAndRetrieveValue() { - ThreadStorage.put("test-key", "test-value"); + SdkInternalThreadLocal.put("test-key", "test-value"); - assertThat(ThreadStorage.get("test-key")).isEqualTo("test-value"); + assertThat(SdkInternalThreadLocal.get("test-key")).isEqualTo("test-value"); } @Test void get_withNonExistentKey_shouldReturnNull() { - assertThat(ThreadStorage.get("non-existent")).isNull(); + assertThat(SdkInternalThreadLocal.get("non-existent")).isNull(); } @Test void put_withValidKeyValue_shouldStoreValue() { - ThreadStorage.put("test-key", "test-value"); + SdkInternalThreadLocal.put("test-key", "test-value"); - String removed = ThreadStorage.remove("test-key"); + String removed = SdkInternalThreadLocal.remove("test-key"); assertThat(removed).isEqualTo("test-value"); - assertThat(ThreadStorage.get("test-key")).isNull(); + assertThat(SdkInternalThreadLocal.get("test-key")).isNull(); } @Test void remove_withExistingKey_shouldRemoveAndReturnValue() { - ThreadStorage.put("test-key", "test-value"); - ThreadStorage.put("test-key", null); + SdkInternalThreadLocal.put("test-key", "test-value"); + SdkInternalThreadLocal.put("test-key", null); - assertThat(ThreadStorage.get("test-key")).isNull(); + assertThat(SdkInternalThreadLocal.get("test-key")).isNull(); } @Test void clear_withMultipleValues_shouldRemoveAllValues() { - ThreadStorage.put("key1", "value1"); - ThreadStorage.put("key2", "value2"); + SdkInternalThreadLocal.put("key1", "value1"); + SdkInternalThreadLocal.put("key2", "value2"); - ThreadStorage.clear(); + SdkInternalThreadLocal.clear(); - assertThat(ThreadStorage.get("key1")).isNull(); - assertThat(ThreadStorage.get("key2")).isNull(); + assertThat(SdkInternalThreadLocal.get("key1")).isNull(); + assertThat(SdkInternalThreadLocal.get("key2")).isNull(); } } \ No newline at end of file From 3ab733810c3a85ae781a9004a5c693efd80cc8b0 Mon Sep 17 00:00:00 2001 From: RanVaknin <50976344+RanVaknin@users.noreply.github.com> Date: Wed, 3 Sep 2025 15:25:39 -0700 Subject: [PATCH 08/11] remove dependency to see if build successful --- pom.xml | 4 ++-- test/tests-coverage-reporting/pom.xml | 5 ----- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/pom.xml b/pom.xml index 4ac0d06763e..f2a7f99dd05 100644 --- a/pom.xml +++ b/pom.xml @@ -67,12 +67,12 @@ metric-publishers release-scripts utils + utils-lite codegen-lite codegen-lite-maven-plugin archetypes third-party v2-migration - utils-lite test/http-client-tests test/protocol-tests test/protocol-tests-core @@ -659,7 +659,6 @@ protocols regions sdk-core - utils-lite http-client-spi apache-client netty-nio-client @@ -667,6 +666,7 @@ cloudwatch-metric-publisher emf-metric-logging-publisher utils + utils-lite imds retries retries-spi diff --git a/test/tests-coverage-reporting/pom.xml b/test/tests-coverage-reporting/pom.xml index c38237517cd..39e84897ced 100644 --- a/test/tests-coverage-reporting/pom.xml +++ b/test/tests-coverage-reporting/pom.xml @@ -242,11 +242,6 @@ software.amazon.awssdk ${awsjavasdk.version} - - utils-lite - software.amazon.awssdk - ${awsjavasdk.version} -