From 444d09e284bff53fe4ea32c5de09e2f2686d6d66 Mon Sep 17 00:00:00 2001 From: John Viegas Date: Wed, 23 Jul 2025 14:34:59 -0700 Subject: [PATCH 1/6] Update the default retry strategy to standard from legacy --- .changes/next-release/feature-AWSSDKforJavav2-8c493dd.json | 6 ++++++ .../java/software/amazon/awssdk/core/retry/RetryMode.java | 2 +- .../awssdk/services/BusinessMetricsUserAgentTest.java | 3 ++- .../services/retry/ExceptionAttemptMessageBehaviorTest.java | 4 ++-- .../services/retry/RetryStrategySetupUsingRetryMode.java | 4 ++-- .../ServiceClientConfigurationTest.java | 4 ++-- .../ServiceClientConfigurationUsingPluginsTest.java | 4 ++-- 7 files changed, 17 insertions(+), 10 deletions(-) create mode 100644 .changes/next-release/feature-AWSSDKforJavav2-8c493dd.json diff --git a/.changes/next-release/feature-AWSSDKforJavav2-8c493dd.json b/.changes/next-release/feature-AWSSDKforJavav2-8c493dd.json new file mode 100644 index 000000000000..e626d024ecf9 --- /dev/null +++ b/.changes/next-release/feature-AWSSDKforJavav2-8c493dd.json @@ -0,0 +1,6 @@ +{ + "type": "feature", + "category": "AWS SDK for Java v2", + "contributor": "", + "description": "Update the default retry strategy to standard based on [Modernizing the default retry strategy](https://aws.amazon.com/blogs/developer/updating-aws-sdk-defaults-aws-sts-service-endpoint-and-retry-strategy/)" +} diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/retry/RetryMode.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/retry/RetryMode.java index fdfe4fa68a82..872fa9952e85 100644 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/retry/RetryMode.java +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/retry/RetryMode.java @@ -130,7 +130,7 @@ public static Resolver resolver() { * Allows customizing the variables used during determination of a {@link RetryMode}. Created via {@link #resolver()}. */ public static class Resolver { - private static final RetryMode SDK_DEFAULT_RETRY_MODE = LEGACY; + private static final RetryMode SDK_DEFAULT_RETRY_MODE = STANDARD; private Supplier profileFile; private String profileName; diff --git a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/BusinessMetricsUserAgentTest.java b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/BusinessMetricsUserAgentTest.java index 9bbb0f2eb602..9bebd6214abb 100644 --- a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/BusinessMetricsUserAgentTest.java +++ b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/BusinessMetricsUserAgentTest.java @@ -76,7 +76,7 @@ public void cleanup() { private static Stream inputValues() { return Stream.of( - Arguments.of("Default values", null, Arrays.asList("D", "N", "P", "T")), + Arguments.of("Default values", null, Arrays.asList("E", "N", "P", "T")), Arguments.of("Account ID preferred mode ", AccountIdEndpointMode.PREFERRED, Arrays.asList("P", "T")), Arguments.of("Account ID disabled mode ", AccountIdEndpointMode.DISABLED, Arrays.asList("Q", "T")), Arguments.of("Account ID required mode ", AccountIdEndpointMode.REQUIRED, Arrays.asList("R", "T")) @@ -98,6 +98,7 @@ void validate_metricsString_forDifferentConfigValues(String description, assertThatThrownBy(() -> clientBuilder.build().operationWithNoInputOrOutput(r -> {}).join()).hasMessageContaining("stop"); String userAgent = assertAndGetUserAgentString(); + System.out.println("userAgent "+userAgent); expectedMetrics.forEach(expectedMetric -> assertThat(userAgent).matches(METRIC_SEARCH_PATTERN.apply(expectedMetric))); } diff --git a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/retry/ExceptionAttemptMessageBehaviorTest.java b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/retry/ExceptionAttemptMessageBehaviorTest.java index 68195ad3b1a9..0ea62a59b6c0 100644 --- a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/retry/ExceptionAttemptMessageBehaviorTest.java +++ b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/retry/ExceptionAttemptMessageBehaviorTest.java @@ -88,8 +88,8 @@ public void exceptionMessage_ioException_includesMultipleAttempts() { SdkClientException exception = assertThrows(SdkClientException.class, () -> callAllTypes(client)); - assertThat(exception.getMessage()).contains("SDK Attempt Count: 4"); - wireMock.verify(4, postRequestedFor(anyUrl())); + assertThat(exception.getMessage()).contains("SDK Attempt Count: 3"); + wireMock.verify(3, postRequestedFor(anyUrl())); } @Test diff --git a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/retry/RetryStrategySetupUsingRetryMode.java b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/retry/RetryStrategySetupUsingRetryMode.java index 0bb96a751531..8971776f761c 100644 --- a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/retry/RetryStrategySetupUsingRetryMode.java +++ b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/retry/RetryStrategySetupUsingRetryMode.java @@ -90,8 +90,8 @@ public void request_settingRetryModeInOverrideConfigurationConsumerRunTwice() { // Configuring the client using an unrelated plugin should not remember the previous settings. assertThrows(ProtocolRestJsonException.class, () -> callAllTypes(client, Collections.singletonList(unrelatedPlugin))); - // Four retries, the LEGACY retry strategy is back in. - verifyRequestCount(3 + 4); + // 3 retries, the STANDARD retry strategy is back in. + verifyRequestCount(3 + 3); } @Test diff --git a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/serviceclientconfiguration/ServiceClientConfigurationTest.java b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/serviceclientconfiguration/ServiceClientConfigurationTest.java index 9c589ea1a1ae..daacea390097 100644 --- a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/serviceclientconfiguration/ServiceClientConfigurationTest.java +++ b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/serviceclientconfiguration/ServiceClientConfigurationTest.java @@ -111,7 +111,7 @@ public void syncClient_serviceClientConfiguration_withoutOverrideConfiguration_s assertThat(overrideConfig.apiCallAttemptTimeout()).isNotPresent(); assertThat(overrideConfig.apiCallTimeout()).isNotPresent(); assertThat(overrideConfig.retryPolicy()).isNotPresent(); - assertThat(overrideConfig.retryStrategy().get().maxAttempts()).isEqualTo(4); + assertThat(overrideConfig.retryStrategy().get().maxAttempts()).isEqualTo(3); assertThat(overrideConfig.defaultProfileFile()).hasValue(ProfileFile.defaultProfileFile()); assertThat(overrideConfig.metricPublishers()).isEmpty(); } @@ -196,7 +196,7 @@ public void asyncClient_serviceClientConfiguration_withoutOverrideConfiguration_ assertThat(overrideConfig.apiCallAttemptTimeout()).isNotPresent(); assertThat(overrideConfig.apiCallTimeout()).isNotPresent(); assertThat(overrideConfig.retryPolicy()).isNotPresent(); - assertThat(overrideConfig.retryStrategy().get().maxAttempts()).isEqualTo(4); + assertThat(overrideConfig.retryStrategy().get().maxAttempts()).isEqualTo(3); assertThat(overrideConfig.defaultProfileFile()).hasValue(ProfileFile.defaultProfileFile()); assertThat(overrideConfig.metricPublishers()).isEmpty(); } diff --git a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/serviceclientconfiguration/ServiceClientConfigurationUsingPluginsTest.java b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/serviceclientconfiguration/ServiceClientConfigurationUsingPluginsTest.java index 49d8e915c38b..f301cc4ee1fc 100644 --- a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/serviceclientconfiguration/ServiceClientConfigurationUsingPluginsTest.java +++ b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/serviceclientconfiguration/ServiceClientConfigurationUsingPluginsTest.java @@ -102,7 +102,7 @@ void syncClient_serviceClientConfiguration_withoutOverrideConfiguration_shouldRe assertThat(overrideConfiguration.apiCallAttemptTimeout()).isNotPresent(); assertThat(overrideConfiguration.apiCallTimeout()).isNotPresent(); assertThat(overrideConfiguration.retryPolicy()).isNotPresent(); - assertThat(overrideConfiguration.retryStrategy().get().maxAttempts()).isEqualTo(4); + assertThat(overrideConfiguration.retryStrategy().get().maxAttempts()).isEqualTo(3); assertThat(overrideConfiguration.defaultProfileFile()).hasValue(ProfileFile.defaultProfileFile()); assertThat(overrideConfiguration.metricPublishers()).isEmpty(); } @@ -196,7 +196,7 @@ void asyncClient_serviceClientConfiguration_withoutOverrideConfiguration_shouldR assertThat(result.apiCallAttemptTimeout()).isNotPresent(); assertThat(result.apiCallTimeout()).isNotPresent(); assertThat(result.retryPolicy()).isNotPresent(); - assertThat(result.retryStrategy().get().maxAttempts()).isEqualTo(4); + assertThat(result.retryStrategy().get().maxAttempts()).isEqualTo(3); assertThat(result.defaultProfileFile()).hasValue(ProfileFile.defaultProfileFile()); assertThat(result.metricPublishers()).isEmpty(); } From cab48fa0f1cb30522604278d5f77b6c95f851194 Mon Sep 17 00:00:00 2001 From: John Viegas Date: Wed, 23 Jul 2025 16:10:03 -0700 Subject: [PATCH 2/6] Junits updated after build checks failed --- .../amazon/awssdk/core/http/AmazonHttpClientTest.java | 8 ++++---- .../core/http/ContentStreamProviderWireMockTest.java | 4 ++-- .../software/amazon/awssdk/core/retry/RetryModeTest.java | 4 ++-- .../awssdk/core/retry/RetryPolicyMaxRetriesTest.java | 4 ++-- .../amazon/awssdk/core/retry/RetryPolicyTest.java | 2 +- .../awssdk/core/retry/RetryStrategyMaxRetriesTest.java | 4 ++-- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/http/AmazonHttpClientTest.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/http/AmazonHttpClientTest.java index ecd553b4d267..95f19a45564c 100644 --- a/core/sdk-core/src/test/java/software/amazon/awssdk/core/http/AmazonHttpClientTest.java +++ b/core/sdk-core/src/test/java/software/amazon/awssdk/core/http/AmazonHttpClientTest.java @@ -96,8 +96,8 @@ public void testRetryIoExceptionFromExecute() throws Exception { Assert.assertSame(ioException, e.getCause()); } - // Verify that we called execute 4 times. - verify(sdkHttpClient, times(4)).prepareRequest(any()); + // Verify that we called execute 3 times. + verify(sdkHttpClient, times(3)).prepareRequest(any()); } @Test @@ -119,8 +119,8 @@ public void testRetryIoExceptionFromHandler() throws Exception { Assert.assertSame(exception, e.getCause()); } - // Verify that we called execute 4 times. - verify(mockHandler, times(4)).handle(any(), any()); + // Verify that we called execute 3 times. + verify(mockHandler, times(3)).handle(any(), any()); } diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/http/ContentStreamProviderWireMockTest.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/http/ContentStreamProviderWireMockTest.java index c544254dfb38..a0d4aed24cc2 100644 --- a/core/sdk-core/src/test/java/software/amazon/awssdk/core/http/ContentStreamProviderWireMockTest.java +++ b/core/sdk-core/src/test/java/software/amazon/awssdk/core/http/ContentStreamProviderWireMockTest.java @@ -65,9 +65,9 @@ public void closesAllCreatedInputStreamsFromProvider() { } catch (SdkServiceException ignored) { } - // The test client uses the default retry policy so there should be 4 + // The test client uses the default retry policy so there should be 3 // total attempts and an equal number created streams - assertThat(provider.getCreatedStreams().size()).isEqualTo(4); + assertThat(provider.getCreatedStreams().size()).isEqualTo(3); for (CloseTrackingInputStream is : provider.getCreatedStreams()) { assertThat(is.isClosed()).isTrue(); } diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/retry/RetryModeTest.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/retry/RetryModeTest.java index b5fb23c37ed4..a76b20cb2068 100644 --- a/core/sdk-core/src/test/java/software/amazon/awssdk/core/retry/RetryModeTest.java +++ b/core/sdk-core/src/test/java/software/amazon/awssdk/core/retry/RetryModeTest.java @@ -44,8 +44,8 @@ public class RetryModeTest { public static Collection data() { return Arrays.asList(new Object[] { // Test defaults - new TestData(null, null, null, null, RetryMode.LEGACY), - new TestData(null, null, "PropertyNotSet", null, RetryMode.LEGACY), + new TestData(null, null, null, null, RetryMode.STANDARD), + new TestData(null, null, "PropertyNotSet", null, RetryMode.STANDARD), // Test resolution new TestData("legacy", null, null, null, RetryMode.LEGACY), diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/retry/RetryPolicyMaxRetriesTest.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/retry/RetryPolicyMaxRetriesTest.java index 84e3d5ac51d7..d99049476e11 100644 --- a/core/sdk-core/src/test/java/software/amazon/awssdk/core/retry/RetryPolicyMaxRetriesTest.java +++ b/core/sdk-core/src/test/java/software/amazon/awssdk/core/retry/RetryPolicyMaxRetriesTest.java @@ -44,8 +44,8 @@ public class RetryPolicyMaxRetriesTest { public static Collection data() { return Arrays.asList(new Object[] { // Test defaults - new TestData(null, null, null, null, null, 3), - new TestData(null, null, null, null, "PropertyNotSet", 3), + new TestData(null, null, null, null, null, 2), + new TestData(null, null, null, null, "PropertyNotSet", 2), // Test precedence new TestData("9", "2", "standard", "standard", "PropertySetToStandard", 8), diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/retry/RetryPolicyTest.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/retry/RetryPolicyTest.java index 2d332337fc10..21b6fbd7d66b 100644 --- a/core/sdk-core/src/test/java/software/amazon/awssdk/core/retry/RetryPolicyTest.java +++ b/core/sdk-core/src/test/java/software/amazon/awssdk/core/retry/RetryPolicyTest.java @@ -89,7 +89,7 @@ public void nonRetryPolicy_shouldUseNullCondition() { @Test public void nonRetryMode_shouldUseDefaultRetryMode() { RetryPolicy policy = RetryPolicy.builder().build(); - assertThat(policy.retryMode().toString()).isEqualTo("LEGACY"); + assertThat(policy.retryMode().toString()).isEqualTo("STANDARD"); } @Test diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/retry/RetryStrategyMaxRetriesTest.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/retry/RetryStrategyMaxRetriesTest.java index b712a9ce4c4c..1df8134d0881 100644 --- a/core/sdk-core/src/test/java/software/amazon/awssdk/core/retry/RetryStrategyMaxRetriesTest.java +++ b/core/sdk-core/src/test/java/software/amazon/awssdk/core/retry/RetryStrategyMaxRetriesTest.java @@ -46,8 +46,8 @@ public class RetryStrategyMaxRetriesTest { public static Collection data() { return Arrays.asList(new Object[] { // Test defaults - new TestData(null, null, null, null, null, 4), - new TestData(null, null, null, null, "PropertyNotSet", 4), + new TestData(null, null, null, null, null, 3), + new TestData(null, null, null, null, "PropertyNotSet", 3), // Test precedence new TestData("9", "2", "standard", "standard", From 9ce3003283dbc5e334b44e1c4617811bbddae1b7 Mon Sep 17 00:00:00 2001 From: John Viegas Date: Thu, 24 Jul 2025 06:50:39 -0700 Subject: [PATCH 3/6] Junits updated for DDB --- .../awssdk/services/dynamodb/DynamoDbRetryPolicyTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/dynamodb/src/test/java/software/amazon/awssdk/services/dynamodb/DynamoDbRetryPolicyTest.java b/services/dynamodb/src/test/java/software/amazon/awssdk/services/dynamodb/DynamoDbRetryPolicyTest.java index bcb25c2504d6..75bea3c04eb1 100644 --- a/services/dynamodb/src/test/java/software/amazon/awssdk/services/dynamodb/DynamoDbRetryPolicyTest.java +++ b/services/dynamodb/src/test/java/software/amazon/awssdk/services/dynamodb/DynamoDbRetryPolicyTest.java @@ -123,7 +123,7 @@ void resolve_retryModeNotSetWithEnvNorSupplier_resolvesFromSdkDefault() { RetryStrategy retryStrategy = DynamoDbRetryPolicy.resolveRetryStrategy(sdkClientConfiguration); RetryMode retryMode = SdkDefaultRetryStrategy.retryMode(retryStrategy); - assertThat(retryMode).isEqualTo(RetryMode.LEGACY); + assertThat(retryMode).isEqualTo(RetryMode.STANDARD); } } From 25002ccf73375059399613c44dedd683d142fda4 Mon Sep 17 00:00:00 2001 From: John Viegas Date: Thu, 24 Jul 2025 09:28:46 -0700 Subject: [PATCH 4/6] updated s3 integ test --- .../awssdk/services/s3/GetObjectFaultIntegrationTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/s3/src/it/java/software/amazon/awssdk/services/s3/GetObjectFaultIntegrationTest.java b/services/s3/src/it/java/software/amazon/awssdk/services/s3/GetObjectFaultIntegrationTest.java index 414e8edb4727..6eb0a6c19bfb 100644 --- a/services/s3/src/it/java/software/amazon/awssdk/services/s3/GetObjectFaultIntegrationTest.java +++ b/services/s3/src/it/java/software/amazon/awssdk/services/s3/GetObjectFaultIntegrationTest.java @@ -72,7 +72,7 @@ public void handlerThrowsRetryableException_RetriedUpToLimit() throws Exception }); assertThatThrownBy(() -> s3.getObject(getObjectRequest(), handler)) .isInstanceOf(SdkClientException.class); - assertThat(handler.currentCallCount()).isEqualTo(4); + assertThat(handler.currentCallCount()).isEqualTo(3); } @Test From ecea40da0aaa8fc9492e85cbc11b172b42c6785f Mon Sep 17 00:00:00 2001 From: John Viegas Date: Wed, 30 Jul 2025 11:44:30 -0700 Subject: [PATCH 5/6] add functional test cases with wiremock and explicilty state that total attempts is 9 --- .../DynamoDbDefaultRetryFunctionalTest.java | 110 ++++++++++++++++++ .../dynamodb/DynamoDbRetryPolicyTest.java | 6 + 2 files changed, 116 insertions(+) create mode 100644 services/dynamodb/src/test/java/software/amazon/awssdk/services/dynamodb/DynamoDbDefaultRetryFunctionalTest.java diff --git a/services/dynamodb/src/test/java/software/amazon/awssdk/services/dynamodb/DynamoDbDefaultRetryFunctionalTest.java b/services/dynamodb/src/test/java/software/amazon/awssdk/services/dynamodb/DynamoDbDefaultRetryFunctionalTest.java new file mode 100644 index 000000000000..3bc912209d3f --- /dev/null +++ b/services/dynamodb/src/test/java/software/amazon/awssdk/services/dynamodb/DynamoDbDefaultRetryFunctionalTest.java @@ -0,0 +1,110 @@ +/* + * 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.services.dynamodb; + +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.anyUrl; +import static com.github.tomakehurst.wiremock.client.WireMock.post; +import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; + +import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo; +import com.github.tomakehurst.wiremock.junit5.WireMockTest; +import java.net.URI; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; +import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; +import software.amazon.awssdk.core.SdkSystemSetting; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.dynamodb.model.DynamoDbException; +import software.amazon.awssdk.testutils.EnvironmentVariableHelper; + +/** + * Functional tests to verify DynamoDB client retry behavior with different retry modes. + */ +@WireMockTest +class DynamoDbDefaultRetryFunctionalTest { + + private EnvironmentVariableHelper environmentVariableHelper; + private DynamoDbClient dynamoDbClient; + + @BeforeEach + void setup(WireMockRuntimeInfo wm) { + environmentVariableHelper = new EnvironmentVariableHelper(); + + dynamoDbClient = DynamoDbClient.builder() + .endpointOverride(URI.create(wm.getHttpBaseUrl())) + .credentialsProvider(StaticCredentialsProvider.create( + AwsBasicCredentials.create("test", "test"))) + .region(Region.US_EAST_1) + .build(); + } + + @AfterEach + void tearDown() { + environmentVariableHelper.reset(); + if (dynamoDbClient != null) { + dynamoDbClient.close(); + } + } + + @Test + void listTables_whenNoRetryPolicySet_shouldAttempt9Times(WireMockRuntimeInfo wm) { + stubFor(post(anyUrl()) + .willReturn(aResponse().withStatus(503))); + assertThatExceptionOfType(DynamoDbException.class) + .isThrownBy(() -> dynamoDbClient.listTables()); + int actualAttempts = wm.getWireMock().getAllServeEvents().size(); + assertThat(actualAttempts) + .as("Default retry mode should result in 9 total attempts (1 initial + 8 retries)") + .isEqualTo(9); + } + + @Test + void listTables_whenRetryModeSetToStandard_shouldAttempt10Times(WireMockRuntimeInfo wm) { + environmentVariableHelper.set(SdkSystemSetting.AWS_RETRY_MODE.environmentVariable(), "standard"); + dynamoDbClient.close(); + dynamoDbClient = DynamoDbClient.builder() + .endpointOverride(URI.create(wm.getHttpBaseUrl())) + .credentialsProvider(StaticCredentialsProvider.create( + AwsBasicCredentials.create("test", "test"))) + .region(Region.US_EAST_1) + .build(); + stubFor(post(anyUrl()) + .willReturn(aResponse().withStatus(503))); + assertThatExceptionOfType(DynamoDbException.class) + .isThrownBy(() -> dynamoDbClient.listTables()); + int actualAttempts = wm.getWireMock().getAllServeEvents().size(); + assertThat(actualAttempts) + .as("Standard retry mode should result in 9 total attempts (1 initial + 8 retries)") + .isEqualTo(9); + } + + @Test + void listTables_whenUsingDefaultRetryMode_shouldAttempt9Times(WireMockRuntimeInfo wm) { + stubFor(post(anyUrl()) + .willReturn(aResponse().withStatus(503))); + assertThatExceptionOfType(DynamoDbException.class) + .isThrownBy(() -> dynamoDbClient.listTables()); + int actualAttempts = wm.getWireMock().getAllServeEvents().size(); + assertThat(actualAttempts) + .as("Default retry mode should result in 9 total attempts (1 initial + 8 retries)") + .isEqualTo(9); + } +} diff --git a/services/dynamodb/src/test/java/software/amazon/awssdk/services/dynamodb/DynamoDbRetryPolicyTest.java b/services/dynamodb/src/test/java/software/amazon/awssdk/services/dynamodb/DynamoDbRetryPolicyTest.java index 75bea3c04eb1..d1c488068011 100644 --- a/services/dynamodb/src/test/java/software/amazon/awssdk/services/dynamodb/DynamoDbRetryPolicyTest.java +++ b/services/dynamodb/src/test/java/software/amazon/awssdk/services/dynamodb/DynamoDbRetryPolicyTest.java @@ -126,4 +126,10 @@ void resolve_retryModeNotSetWithEnvNorSupplier_resolvesFromSdkDefault() { assertThat(retryMode).isEqualTo(RetryMode.STANDARD); } + @Test + void test_numRetries_with_defaultSettings() { + SdkClientConfiguration sdkClientConfiguration = SdkClientConfiguration.builder().build(); + RetryStrategy retryStrategy = DynamoDbRetryPolicy.resolveRetryStrategy(sdkClientConfiguration); + assertThat(retryStrategy.maxAttempts()).isEqualTo(9); + } } From ccc2455a001a9c6f83d48ee603166ecd2f3a2e0c Mon Sep 17 00:00:00 2001 From: John Viegas Date: Wed, 30 Jul 2025 13:48:13 -0700 Subject: [PATCH 6/6] Refactored test --- .../DynamoDbDefaultRetryFunctionalTest.java | 53 ++++++++----------- 1 file changed, 22 insertions(+), 31 deletions(-) diff --git a/services/dynamodb/src/test/java/software/amazon/awssdk/services/dynamodb/DynamoDbDefaultRetryFunctionalTest.java b/services/dynamodb/src/test/java/software/amazon/awssdk/services/dynamodb/DynamoDbDefaultRetryFunctionalTest.java index 3bc912209d3f..4c3436c0ac13 100644 --- a/services/dynamodb/src/test/java/software/amazon/awssdk/services/dynamodb/DynamoDbDefaultRetryFunctionalTest.java +++ b/services/dynamodb/src/test/java/software/amazon/awssdk/services/dynamodb/DynamoDbDefaultRetryFunctionalTest.java @@ -26,8 +26,9 @@ import com.github.tomakehurst.wiremock.junit5.WireMockTest; import java.net.URI; import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; import software.amazon.awssdk.core.SdkSystemSetting; @@ -41,21 +42,9 @@ @WireMockTest class DynamoDbDefaultRetryFunctionalTest { - private EnvironmentVariableHelper environmentVariableHelper; + private final EnvironmentVariableHelper environmentVariableHelper = new EnvironmentVariableHelper(); private DynamoDbClient dynamoDbClient; - @BeforeEach - void setup(WireMockRuntimeInfo wm) { - environmentVariableHelper = new EnvironmentVariableHelper(); - - dynamoDbClient = DynamoDbClient.builder() - .endpointOverride(URI.create(wm.getHttpBaseUrl())) - .credentialsProvider(StaticCredentialsProvider.create( - AwsBasicCredentials.create("test", "test"))) - .region(Region.US_EAST_1) - .build(); - } - @AfterEach void tearDown() { environmentVariableHelper.reset(); @@ -64,47 +53,49 @@ void tearDown() { } } - @Test - void listTables_whenNoRetryPolicySet_shouldAttempt9Times(WireMockRuntimeInfo wm) { - stubFor(post(anyUrl()) - .willReturn(aResponse().withStatus(503))); - assertThatExceptionOfType(DynamoDbException.class) - .isThrownBy(() -> dynamoDbClient.listTables()); - int actualAttempts = wm.getWireMock().getAllServeEvents().size(); - assertThat(actualAttempts) - .as("Default retry mode should result in 9 total attempts (1 initial + 8 retries)") - .isEqualTo(9); - } + @ParameterizedTest + @ValueSource(strings = {"adaptive", "legacy", "standard"}) + void listTables_whenRetryModeSet_shouldAttempt9Times(String retryMode, WireMockRuntimeInfo wm) { + // Set the retry mode environment variable + environmentVariableHelper.set(SdkSystemSetting.AWS_RETRY_MODE.environmentVariable(), retryMode); - @Test - void listTables_whenRetryModeSetToStandard_shouldAttempt10Times(WireMockRuntimeInfo wm) { - environmentVariableHelper.set(SdkSystemSetting.AWS_RETRY_MODE.environmentVariable(), "standard"); - dynamoDbClient.close(); + // Build the DynamoDB client here instead of setup so that environment variable options gets picked for each tests dynamoDbClient = DynamoDbClient.builder() .endpointOverride(URI.create(wm.getHttpBaseUrl())) .credentialsProvider(StaticCredentialsProvider.create( - AwsBasicCredentials.create("test", "test"))) + AwsBasicCredentials.create("akid", "skid"))) .region(Region.US_EAST_1) .build(); + stubFor(post(anyUrl()) .willReturn(aResponse().withStatus(503))); + assertThatExceptionOfType(DynamoDbException.class) .isThrownBy(() -> dynamoDbClient.listTables()); + int actualAttempts = wm.getWireMock().getAllServeEvents().size(); assertThat(actualAttempts) - .as("Standard retry mode should result in 9 total attempts (1 initial + 8 retries)") + .as("Retry mode '%s' should result in 9 total attempts (1 initial + 8 retries)", retryMode) .isEqualTo(9); } @Test void listTables_whenUsingDefaultRetryMode_shouldAttempt9Times(WireMockRuntimeInfo wm) { + dynamoDbClient = DynamoDbClient.builder() + .endpointOverride(URI.create(wm.getHttpBaseUrl())) + .credentialsProvider(StaticCredentialsProvider.create( + AwsBasicCredentials.create("akid", "skid"))) + .region(Region.US_EAST_1) + .build(); stubFor(post(anyUrl()) .willReturn(aResponse().withStatus(503))); assertThatExceptionOfType(DynamoDbException.class) .isThrownBy(() -> dynamoDbClient.listTables()); + int actualAttempts = wm.getWireMock().getAllServeEvents().size(); assertThat(actualAttempts) .as("Default retry mode should result in 9 total attempts (1 initial + 8 retries)") .isEqualTo(9); } + }