Skip to content

Commit d2cd231

Browse files
authored
Address remaining SRA TODOs and add more documentations (#6617)
* Address remaining SRA TODOs and add more documentations * Address feedback
1 parent 942a40e commit d2cd231

File tree

9 files changed

+166
-48
lines changed

9 files changed

+166
-48
lines changed

core/aws-core/src/main/java/software/amazon/awssdk/awscore/internal/AwsExecutionContextBuilder.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -263,14 +263,14 @@ private static void putAuthSchemeResolutionAttributes(ExecutionAttributes execut
263263
SdkClientConfiguration clientConfig,
264264
SdkRequest originalRequest) {
265265

266-
// TODO(sra-identity-and-auth): When request-level auth scheme provider is added, use the request-level auth scheme
267-
// provider if the customer specified an override, otherwise fall back to the one on the client.
266+
// TODO(request-override auth scheme feature): When request-level auth scheme provider is added, use the request-level
267+
// auth scheme provider if the customer specified an override, otherwise fall back to the one on the client.
268268
AuthSchemeProvider authSchemeProvider = clientConfig.option(SdkClientOption.AUTH_SCHEME_PROVIDER);
269269

270270
// Use auth schemes that the user specified at the request level with
271271
// preference over those on the client.
272-
// TODO(sra-identity-and-auth): The request level schemes should be "merged" with client level, with request preferred
273-
// over client.
272+
// TODO(request-override auth scheme feature): The request level schemes should be "merged" with client level, with
273+
// request preferred over client.
274274
Map<String, AuthScheme<?>> authSchemes = clientConfig.option(SdkClientOption.AUTH_SCHEMES);
275275

276276
IdentityProviders identityProviders = resolveIdentityProviders(originalRequest, clientConfig);

core/identity-spi/src/main/java/software/amazon/awssdk/identity/spi/internal/DefaultIdentityProviders.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,9 @@
3636
@SdkInternalApi
3737
public final class DefaultIdentityProviders implements IdentityProviders {
3838
/**
39-
* TODO(sra-identity-auth): Currently, some customers assume we won't interact with the identity providers when we create
40-
* the client. This isn't true - we need to call identityType. To TEMPORARILY work around those customer's tests failing,
41-
* this is marked lazy. Once we fully migrate over to the SRA as the default code path, we should remove this lazy and
42-
* ticket everyone in live who is making those bad assumptions.
39+
* Currently, some customers assume we won't interact with the identity providers when we create
40+
* the client. This isn't true - we need to call identityType. To work around those customer's tests failing,
41+
* this is marked lazy. See JAVA-8670 for more details.
4342
*/
4443
private final Lazy<Map<Class<?>, IdentityProvider<?>>> identityProviders;
4544
private final List<IdentityProvider<?>> identityProvidersList;

core/identity-spi/src/test/java/software/amazon/awssdk/identity/spi/IdentityProvidersTest.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,6 @@ public void copyBuilder_addIdentityProvider_works() {
9999

100100
@Test
101101
public void identityProviders_notTouched_untilNeeded() {
102-
// TODO(sra-identity-auth): This should be removed once everything is on useSraAuth = true
103102
IdentityProvider<AwsCredentialsIdentity> awsCredentialsProvider = Mockito.mock(IdentityProvider.class);
104103
IdentityProviders providers =
105104
IdentityProviders.builder()

core/sdk-core/src/main/java/software/amazon/awssdk/core/RequestOverrideConfiguration.java

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -489,21 +489,43 @@ default B putRawQueryParameter(String name, String value) {
489489
* @param plugins The list of plugins for this request.
490490
* @return This object for method chaining.
491491
*/
492-
@SdkPreviewApi
493492
B plugins(List<SdkPlugin> plugins);
494493

495494
/**
496-
* Add a plugin used to update the configuration used by this request.
497-
*
498-
* @param plugin The plugin to add.
495+
* Adds a plugin that will modify the configuration used by this specific request.
496+
*
497+
* <p>Request-level plugins are applied at request execution time. Multiple plugins can be added and
498+
* are executed in the order they were added.
499+
*
500+
* <p><b>Note:</b> Request-level override configuration (e.g., {@link #apiCallTimeout(Duration)}) takes
501+
* precedence over request-level plugin settings. This means if you set a value directly on the request
502+
* override configuration and also set it via a plugin, the direct configuration value will be used.
503+
*
504+
* <p>Example:
505+
* {@snippet :
506+
* SdkPlugin highTimeoutPlugin = config -> {
507+
* config.overrideConfiguration(c -> c.apiCallTimeout(Duration.ofMinutes(5)));
508+
* };
509+
*
510+
* GetObjectResponse response = s3Client.getObject(
511+
* GetObjectRequest.builder()
512+
* .bucket("my-bucket")
513+
* .key("large-file")
514+
* .overrideConfiguration(c -> c.addPlugin(highTimeoutPlugin))
515+
* .build(),
516+
* ResponseTransformer.toBytes()
517+
* );
518+
* }
519+
*
520+
* @param plugin the plugin to add
521+
* @return this builder for method chaining
522+
* @see SdkPlugin
499523
*/
500-
@SdkPreviewApi
501524
B addPlugin(SdkPlugin plugin);
502525

503526
/**
504527
* Returns the list of registered plugins
505528
*/
506-
@SdkPreviewApi
507529
List<SdkPlugin> plugins();
508530

509531
/**

core/sdk-core/src/main/java/software/amazon/awssdk/core/SdkPlugin.java

Lines changed: 97 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,23 +15,115 @@
1515

1616
package software.amazon.awssdk.core;
1717

18-
import software.amazon.awssdk.annotations.SdkPreviewApi;
1918
import software.amazon.awssdk.annotations.SdkPublicApi;
2019
import software.amazon.awssdk.annotations.ThreadSafe;
2120
import software.amazon.awssdk.utils.SdkAutoCloseable;
2221

2322
/**
24-
* A plugin modifies a client's configuration when the client is created or at request execution
25-
* time.
23+
* A plugin that modifies SDK client configuration at client creation time or per-request execution time.
24+
*
25+
* <p>Plugins provide an extensibility mechanism for customizing SDK client behavior without modifying core SDK code.
26+
* They can modify configuration such as retry policies, timeouts, execution interceptors, endpoints, and authentication
27+
* schemes.
28+
*
29+
* <p>Plugins can be applied at two levels:
30+
* <ul>
31+
* <li><b>Client-level:</b> Applied once during client creation and affects all requests made by that client</li>
32+
* <li><b>Request-level:</b> Applied per-request and can override client-level configuration for specific requests</li>
33+
* </ul>
34+
*
35+
* <p><b>When to use plugins vs direct configuration:</b>
36+
* <ul>
37+
* <li>Use <b>direct configuration</b> for simple, one-time client setup specific to your application</li>
38+
* <li>Use <b>plugins</b> when you need to:
39+
* <ul>
40+
* <li>Reuse the same configuration across multiple SDK clients</li>
41+
* <li>Package configuration as a library or module for distribution</li>
42+
* <li>Apply conditional or dynamic configuration logic</li>
43+
* <li>Compose multiple configuration strategies together</li>
44+
* </ul>
45+
* </li>
46+
* </ul>
47+
*
48+
* <p><b>Client-level plugin example:</b>
49+
* {@snippet :
50+
* // Create a reusable plugin with multiple configuration settings
51+
* SdkPlugin standardPlugin = config -> {
52+
* config.endpointOverride(URI.create("https://127.0.0.1"))
53+
* .overrideConfiguration(c -> c
54+
* .apiCallTimeout(Duration.ofSeconds(30))
55+
* .addExecutionInterceptor(new LoggingInterceptor()));
56+
* };
57+
*
58+
* // Apply to multiple clients
59+
* S3Client s3Client = S3Client.builder()
60+
* .addPlugin(standardPlugin)
61+
* .build();
62+
*
63+
* DynamoDbClient dynamoClient = DynamoDbClient.builder()
64+
* .addPlugin(standardPlugin)
65+
* .build();
66+
* }
67+
*
68+
* <p><b>Composing multiple plugins:</b>
69+
* {@snippet :
70+
* // Core plugin always applied
71+
* SdkPlugin corePlugin = config -> {
72+
* config.overrideConfiguration(c -> c.apiCallTimeout(Duration.ofSeconds(30)));
73+
* };
74+
*
75+
* // Optional feature plugins
76+
* SdkPlugin compressionPlugin = config -> {
77+
* config.overrideConfiguration(c -> c.compressionConfiguration(
78+
* CompressionConfiguration.builder().requestCompressionEnabled(true).build()));
79+
* };
80+
*
81+
* SdkPlugin tracingPlugin = config -> {
82+
* config.overrideConfiguration(c -> c.addExecutionInterceptor(new TracingInterceptor()));
83+
* };
84+
*
85+
* // Conditionally compose plugins based on feature flags
86+
* S3Client.Builder builder = S3Client.builder().addPlugin(corePlugin);
87+
* if (compressionEnabled) {
88+
* builder.addPlugin(compressionPlugin);
89+
* }
90+
* if (tracingEnabled) {
91+
* builder.addPlugin(tracingPlugin);
92+
* }
93+
* S3Client client = builder.build();
94+
* }
95+
*
96+
* <p>Plugins are invoked after default configuration is applied, allowing them to override SDK defaults.
97+
* Multiple plugins can be registered and are executed in the order they were added.
98+
*
99+
* <p><b>Configuration precedence (highest to lowest):</b>
100+
* <ol>
101+
* <li>Plugin settings (applied last, highest precedence)</li>
102+
* <li>Direct client builder settings (e.g., {@code .overrideConfiguration()})</li>
103+
* <li>Service-specific defaults</li>
104+
* <li>Global SDK defaults</li>
105+
* </ol>
106+
*
107+
* <p><b>Note:</b> Request-level plugins have different precedence behavior. Request-level override configuration
108+
* takes precedence over request-level plugin settings, meaning direct request configuration will override plugin
109+
* settings for that request.
110+
*
111+
* @see software.amazon.awssdk.core.client.builder.SdkClientBuilder#addPlugin(SdkPlugin)
112+
* @see software.amazon.awssdk.core.RequestOverrideConfiguration.Builder#addPlugin(SdkPlugin)
26113
*/
27-
@SdkPreviewApi
28114
@SdkPublicApi
29115
@ThreadSafe
30116
@FunctionalInterface
31117
public interface SdkPlugin extends SdkAutoCloseable {
32118

33119
/**
34-
* Modify the provided client configuration.
120+
* Modifies the provided client configuration.
121+
*
122+
* <p>This method is invoked by the SDK to allow the plugin to customize the client configuration.
123+
* Implementations can modify any aspect of the configuration exposed through the builder, including
124+
* override configuration, endpoints, and authentication schemes.
125+
*
126+
* @param config the configuration builder to modify
35127
*/
36128
void configureClient(SdkServiceClientConfiguration.Builder config);
37129

core/sdk-core/src/main/java/software/amazon/awssdk/core/client/builder/SdkClientBuilder.java

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
import java.net.URI;
1919
import java.util.List;
2020
import java.util.function.Consumer;
21-
import software.amazon.awssdk.annotations.SdkPreviewApi;
2221
import software.amazon.awssdk.annotations.SdkPublicApi;
2322
import software.amazon.awssdk.core.SdkPlugin;
2423
import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration;
@@ -80,18 +79,38 @@ default B putAuthScheme(AuthScheme<?> authScheme) {
8079
}
8180

8281
/**
83-
* Adds a plugin to the client builder. The plugins will be invoked when building the client to allow them to change the
84-
* configuration of the built client.
82+
* Adds a plugin to the client builder that will modify the client configuration when the client is built.
83+
*
84+
* <p>Plugins are invoked after all default configuration is applied, allowing them to override SDK defaults.
85+
* Multiple plugins can be added and are executed in the order they were added. The configuration changes made
86+
* by plugins apply to all requests made by the built client.
87+
*
88+
* <p><b>Important:</b> Plugin settings have the highest precedence and will override any configuration set directly
89+
* on the client builder (e.g., via {@code overrideConfiguration()}).
90+
*
91+
* <p>Example:
92+
* {@snippet :
93+
* SdkPlugin customPlugin = config -> {
94+
* config.endpointOverride(URI.create("https://localhost:8080"))
95+
* .overrideConfiguration(c -> c.apiCallTimeout(Duration.ofSeconds(30)));
96+
* };
97+
*
98+
* S3Client client = S3Client.builder()
99+
* .addPlugin(customPlugin)
100+
* .build();
101+
* }
102+
*
103+
* @param plugin the plugin to add
104+
* @return this builder for method chaining
105+
* @see SdkPlugin
85106
*/
86-
@SdkPreviewApi
87107
default B addPlugin(SdkPlugin plugin) {
88108
throw new UnsupportedOperationException();
89109
}
90110

91111
/**
92112
* Returns the list of plugins configured on the client builder.
93113
*/
94-
@SdkPreviewApi
95114
default List<SdkPlugin> plugins() {
96115
throw new UnsupportedOperationException();
97116
}

services/ec2/src/main/java/software/amazon/awssdk/services/ec2/transform/internal/GeneratePreSignUrlInterceptor.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,6 @@ private Aws4PresignerParams getPresignerParams(ExecutionAttributes attributes, S
146146
.build();
147147
}
148148

149-
// TODO(sra-identity-and-auth): add test case for SELECTED_AUTH_SCHEME case
150149
private AwsCredentials resolveCredentials(ExecutionAttributes attributes) {
151150
return attributes.getOptionalAttribute(SELECTED_AUTH_SCHEME)
152151
.map(selectedAuthScheme -> selectedAuthScheme.identity())

test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/AsyncRequestBodyFlexibleChecksumInTrailerTest.java

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,6 @@
2626
import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
2727
import static com.github.tomakehurst.wiremock.client.WireMock.verify;
2828
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
29-
import static software.amazon.awssdk.auth.signer.S3SignerExecutionAttribute.ENABLE_CHUNKED_ENCODING;
30-
import static software.amazon.awssdk.auth.signer.S3SignerExecutionAttribute.ENABLE_PAYLOAD_SIGNING;
3129
import static software.amazon.awssdk.http.Header.CONTENT_LENGTH;
3230
import static software.amazon.awssdk.http.Header.CONTENT_TYPE;
3331

@@ -85,24 +83,12 @@ public void setupClient() {
8583
.credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create("akid", "skid")))
8684
.region(Region.US_EAST_1)
8785
.endpointOverride(URI.create("http://localhost:" + wireMock.port()))
88-
.overrideConfiguration(
89-
// TODO(sra-identity-and-auth): we should remove these
90-
// overrides once we set up codegen to set chunk-encoding to true
91-
// for requests that are streaming and checksum-enabled
92-
o -> o.putExecutionAttribute(ENABLE_CHUNKED_ENCODING, true)
93-
.putExecutionAttribute(ENABLE_PAYLOAD_SIGNING, false))
9486
.build();
9587

9688
asyncClient = ProtocolRestJsonAsyncClient.builder()
9789
.credentialsProvider(AnonymousCredentialsProvider.create())
9890
.region(Region.US_EAST_1)
9991
.endpointOverride(URI.create("http://localhost:" + wireMock.port()))
100-
.overrideConfiguration(
101-
// TODO(sra-identity-and-auth): we should remove these
102-
// overrides once we set up codegen to set chunk-encoding to true
103-
// for requests that are streaming and checksum-enabled
104-
o -> o.putExecutionAttribute(ENABLE_CHUNKED_ENCODING, true)
105-
.putExecutionAttribute(ENABLE_PAYLOAD_SIGNING, false))
10692
.build();
10793
}
10894

test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/SdkPluginTest.java

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@
3838
import java.util.function.BiConsumer;
3939
import java.util.function.Supplier;
4040
import java.util.stream.Stream;
41-
import org.junit.jupiter.api.Disabled;
4241
import org.junit.jupiter.params.ParameterizedTest;
4342
import org.junit.jupiter.params.provider.MethodSource;
4443
import org.mockito.Mockito;
@@ -61,8 +60,6 @@
6160
import software.amazon.awssdk.core.interceptor.ExecutionInterceptor;
6261
import software.amazon.awssdk.core.interceptor.SdkInternalExecutionAttribute;
6362
import software.amazon.awssdk.core.internal.retry.SdkDefaultRetryStrategy;
64-
import software.amazon.awssdk.core.retry.RetryMode;
65-
import software.amazon.awssdk.core.retry.RetryPolicy;
6663
import software.amazon.awssdk.endpoints.Endpoint;
6764
import software.amazon.awssdk.http.SdkHttpClient;
6865
import software.amazon.awssdk.http.auth.aws.scheme.AwsV4AuthScheme;
@@ -77,7 +74,6 @@
7774
import software.amazon.awssdk.profiles.ProfileFile;
7875
import software.amazon.awssdk.profiles.ProfileProperty;
7976
import software.amazon.awssdk.regions.Region;
80-
import software.amazon.awssdk.retries.DefaultRetryStrategy;
8177
import software.amazon.awssdk.retries.api.RetryStrategy;
8278
import software.amazon.awssdk.services.protocolrestjson.ProtocolRestJsonClient;
8379
import software.amazon.awssdk.services.protocolrestjson.ProtocolRestJsonClientBuilder;
@@ -467,7 +463,6 @@ public <T> void requestPluginSeesCustomerClientConfiguredValue(TestCase<T> testC
467463

468464
@ParameterizedTest
469465
@MethodSource("testCases")
470-
@Disabled("Request-level values are currently higher-priority than plugin settings.") // TODO(sra-identity-auth)
471466
public <T> void requestPluginSeesCustomerRequestConfiguredValue(TestCase<T> testCase) {
472467
if (testCase.requestSetter == null) {
473468
System.out.println("No request setting available.");
@@ -480,7 +475,11 @@ public <T> void requestPluginSeesCustomerRequestConfiguredValue(TestCase<T> test
480475
SdkPlugin plugin = config -> {
481476
ProtocolRestJsonServiceClientConfiguration.Builder conf =
482477
(ProtocolRestJsonServiceClientConfiguration.Builder) config;
483-
testCase.pluginValidator.accept(conf, testCase.nonDefaultValue);
478+
// Request-level values are currently higher-priority than plugin settings.
479+
// This is not the intended behavior and is inconsistent with client-level plugin.
480+
// However, we can't fix it directly due to backwards compatibility. See
481+
// JAVA-8671 for more details.
482+
testCase.pluginValidator.accept(conf, testCase.defaultValue);
484483
timesCalled.incrementAndGet();
485484
};
486485

@@ -570,8 +569,11 @@ public void beforeTransmission(Context.BeforeTransmission context, ExecutionAttr
570569
AwsRequestOverrideConfiguration.builder()
571570
.addPlugin(plugin)
572571
.applyMutation(c -> {
573-
// TODO(sra-identity-auth): request-level plugins should override request-level
574-
// configuration
572+
// testCase.requestSetter is not applied here because request-level values are
573+
// currently higher-priority than plugin settings.
574+
// This is not the intended behavior and is inconsistent with client-level plugin.
575+
// However, we can't fix it directly due to backwards compatibility. See
576+
// JAVA-8671 for more details.
575577
// if (testCase.requestSetter != null) {
576578
// testCase.requestSetter.accept(c, testCase.defaultValue);
577579
// }

0 commit comments

Comments
 (0)