Skip to content

Commit 1dfdfdd

Browse files
authored
Add ServiceClientConfiguration to SdkClient (#3830)
* Add ServiceClientConfiguration to SdkClient * Remove test * Implement method in test clients * Add tests * Add tests * Refactor test clients * Refactoring * Add AwsServiceClientConfiguration and refactor * Fix build issues * Refactoring * Refactoring * Refactoring * Refactoring * Refactoring * Refactoring * Add codegen test * Fix build failure - change return type * Remove unused import * Refactoring * Fix import
1 parent 0875b58 commit 1dfdfdd

File tree

40 files changed

+916
-48
lines changed

40 files changed

+916
-48
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"category": "AWS SDK for Java v2",
3+
"contributor": "",
4+
"type": "feature",
5+
"description": "Adds ServiceClientConfiguration to SdkClient which exposes client settings to the user"
6+
}

codegen/src/main/java/software/amazon/awssdk/codegen/emitters/tasks/CommonClientGeneratorTasks.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import software.amazon.awssdk.codegen.emitters.GeneratorTaskParams;
2323
import software.amazon.awssdk.codegen.poet.builder.BaseClientBuilderClass;
2424
import software.amazon.awssdk.codegen.poet.builder.BaseClientBuilderInterface;
25+
import software.amazon.awssdk.codegen.poet.model.ServiceClientConfigurationClass;
2526

2627
/**
2728
* Task for classes shared by {@link AsyncClientGeneratorTasks} and {@link SyncClientGeneratorTasks}.
@@ -34,7 +35,8 @@ public CommonClientGeneratorTasks(GeneratorTaskParams dependencies) {
3435
@Override
3536
protected List<GeneratorTask> createTasks() throws Exception {
3637
return Arrays.asList(createBaseBuilderTask(),
37-
createBaseBuilderInterfaceTask());
38+
createBaseBuilderInterfaceTask(),
39+
createServiceClientConfigurationTask());
3840
}
3941

4042
private GeneratorTask createBaseBuilderTask() throws IOException {
@@ -44,4 +46,8 @@ private GeneratorTask createBaseBuilderTask() throws IOException {
4446
private GeneratorTask createBaseBuilderInterfaceTask() throws IOException {
4547
return createPoetGeneratorTask(new BaseClientBuilderInterface(model));
4648
}
49+
50+
private GeneratorTask createServiceClientConfigurationTask() throws IOException {
51+
return createPoetGeneratorTask(new ServiceClientConfigurationClass(model));
52+
}
4753
}

codegen/src/main/java/software/amazon/awssdk/codegen/poet/PoetExtension.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,14 @@ public ClassName getClientClass(String className) {
6565
return ClassName.get(model.getMetadata().getFullClientPackageName(), className);
6666
}
6767

68+
/**
69+
* @return A Poet {@link ClassName} for the generated service client configuration.
70+
*/
71+
public ClassName getServiceConfigClass() {
72+
return PoetUtils.classNameFromFqcn(model.getMetadata().getFullClientPackageName() + "."
73+
+ model.getMetadata().getServiceName() + "ServiceClientConfiguration");
74+
}
75+
6876
/**
6977
* @param operationName Name of the operation
7078
* @return A Poet {@link ClassName} for the response type of a paginated operation in the base service package.

codegen/src/main/java/software/amazon/awssdk/codegen/poet/builder/AsyncClientBuilderClass.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import software.amazon.awssdk.awscore.client.config.AwsClientOption;
2626
import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel;
2727
import software.amazon.awssdk.codegen.poet.ClassSpec;
28+
import software.amazon.awssdk.codegen.poet.PoetExtension;
2829
import software.amazon.awssdk.codegen.poet.PoetUtils;
2930
import software.amazon.awssdk.codegen.poet.rules.EndpointRulesSpecUtils;
3031
import software.amazon.awssdk.codegen.utils.AuthUtils;
@@ -38,6 +39,7 @@ public class AsyncClientBuilderClass implements ClassSpec {
3839
private final ClassName builderInterfaceName;
3940
private final ClassName builderClassName;
4041
private final ClassName builderBaseClassName;
42+
private final ClassName serviceConfigClassName;
4143
private final EndpointRulesSpecUtils endpointRulesSpecUtils;
4244

4345
public AsyncClientBuilderClass(IntermediateModel model) {
@@ -49,6 +51,7 @@ public AsyncClientBuilderClass(IntermediateModel model) {
4951
this.builderClassName = ClassName.get(basePackage, model.getMetadata().getAsyncBuilder());
5052
this.builderBaseClassName = ClassName.get(basePackage, model.getMetadata().getBaseBuilder());
5153
this.endpointRulesSpecUtils = new EndpointRulesSpecUtils(model);
54+
this.serviceConfigClassName = new PoetExtension(model).getServiceConfigClass();
5255
}
5356

5457
@Override
@@ -121,7 +124,11 @@ private MethodSpec buildClientMethod() {
121124
.returns(clientInterfaceName)
122125
.addStatement("$T clientConfiguration = super.asyncClientConfiguration()", SdkClientConfiguration.class)
123126
.addStatement("this.validateClientOptions(clientConfiguration)")
124-
.addCode("return new $T(clientConfiguration);", clientClassName)
127+
.addStatement("$T serviceClientConfiguration = $T.builder()"
128+
+ ".overrideConfiguration(overrideConfiguration())"
129+
+ ".region(clientConfiguration.option($T.AWS_REGION)).build()",
130+
serviceConfigClassName, serviceConfigClassName, AwsClientOption.class)
131+
.addStatement("return new $T(serviceClientConfiguration, clientConfiguration)", clientClassName)
125132
.build();
126133
}
127134

codegen/src/main/java/software/amazon/awssdk/codegen/poet/builder/SyncClientBuilderClass.java

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import software.amazon.awssdk.awscore.client.config.AwsClientOption;
2626
import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel;
2727
import software.amazon.awssdk.codegen.poet.ClassSpec;
28+
import software.amazon.awssdk.codegen.poet.PoetExtension;
2829
import software.amazon.awssdk.codegen.poet.PoetUtils;
2930
import software.amazon.awssdk.codegen.poet.rules.EndpointRulesSpecUtils;
3031
import software.amazon.awssdk.codegen.utils.AuthUtils;
@@ -38,6 +39,7 @@ public class SyncClientBuilderClass implements ClassSpec {
3839
private final ClassName builderInterfaceName;
3940
private final ClassName builderClassName;
4041
private final ClassName builderBaseClassName;
42+
private final ClassName serviceConfigClassName;
4143
private final EndpointRulesSpecUtils endpointRulesSpecUtils;
4244

4345
public SyncClientBuilderClass(IntermediateModel model) {
@@ -49,6 +51,7 @@ public SyncClientBuilderClass(IntermediateModel model) {
4951
this.builderClassName = ClassName.get(basePackage, model.getMetadata().getSyncBuilder());
5052
this.builderBaseClassName = ClassName.get(basePackage, model.getMetadata().getBaseBuilder());
5153
this.endpointRulesSpecUtils = new EndpointRulesSpecUtils(model);
54+
this.serviceConfigClassName = new PoetExtension(model).getServiceConfigClass();
5255
}
5356

5457
@Override
@@ -116,14 +119,17 @@ private MethodSpec endpointProviderMethod() {
116119

117120
private MethodSpec buildClientMethod() {
118121
return MethodSpec.methodBuilder("buildClient")
119-
.addAnnotation(Override.class)
120-
.addModifiers(Modifier.PROTECTED, Modifier.FINAL)
121-
.returns(clientInterfaceName)
122-
.addStatement("$T clientConfiguration = super.syncClientConfiguration()",
123-
SdkClientConfiguration.class)
124-
.addStatement("this.validateClientOptions(clientConfiguration)")
125-
.addCode("return new $T(clientConfiguration);", clientClassName)
126-
.build();
122+
.addAnnotation(Override.class)
123+
.addModifiers(Modifier.PROTECTED, Modifier.FINAL)
124+
.returns(clientInterfaceName)
125+
.addStatement("$T clientConfiguration = super.syncClientConfiguration()", SdkClientConfiguration.class)
126+
.addStatement("this.validateClientOptions(clientConfiguration)")
127+
.addStatement("$T serviceClientConfiguration = $T.builder()"
128+
+ ".overrideConfiguration(overrideConfiguration())"
129+
+ ".region(clientConfiguration.option($T.AWS_REGION)).build()",
130+
serviceConfigClassName, serviceConfigClassName, AwsClientOption.class)
131+
.addStatement("return new $T(serviceClientConfiguration, clientConfiguration)", clientClassName)
132+
.build();
127133
}
128134

129135
private MethodSpec tokenProviderMethodImpl() {

codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/AsyncClientClass.java

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -93,13 +93,15 @@ public final class AsyncClientClass extends AsyncClientInterface {
9393
private final PoetExtension poetExtensions;
9494
private final ClassName className;
9595
private final ProtocolSpec protocolSpec;
96+
private final ClassName serviceClientConfigurationClassName;
9697

9798
public AsyncClientClass(GeneratorTaskParams dependencies) {
9899
super(dependencies.getModel());
99100
this.model = dependencies.getModel();
100101
this.poetExtensions = dependencies.getPoetExtensions();
101102
this.className = poetExtensions.getClientClass(model.getMetadata().getAsyncClient());
102103
this.protocolSpec = getProtocolSpecs(poetExtensions, model);
104+
this.serviceClientConfigurationClassName = new PoetExtension(model).getServiceConfigClass();
103105
}
104106

105107
@Override
@@ -133,7 +135,8 @@ protected void addFields(TypeSpec.Builder type) {
133135
.build())
134136
.addField(AsyncClientHandler.class, "clientHandler", PRIVATE, FINAL)
135137
.addField(protocolSpec.protocolFactory(model))
136-
.addField(SdkClientConfiguration.class, "clientConfiguration", PRIVATE, FINAL);
138+
.addField(SdkClientConfiguration.class, "clientConfiguration", PRIVATE, FINAL)
139+
.addField(serviceClientConfigurationClassName, "serviceClientConfiguration", PRIVATE, FINAL);
137140

138141
// Kinesis doesn't support CBOR for STS yet so need another protocol factory for JSON
139142
if (model.getMetadata().isCborProtocol()) {
@@ -200,12 +203,14 @@ private Stream<MethodSpec> operations(OperationModel opModel) {
200203
}
201204

202205
private MethodSpec constructor(TypeSpec.Builder classBuilder) {
203-
MethodSpec.Builder builder = MethodSpec.constructorBuilder()
204-
.addModifiers(PROTECTED)
205-
.addParameter(SdkClientConfiguration.class, "clientConfiguration")
206-
.addStatement("this.clientHandler = new $T(clientConfiguration)",
207-
AwsAsyncClientHandler.class)
208-
.addStatement("this.clientConfiguration = clientConfiguration");
206+
MethodSpec.Builder builder
207+
= MethodSpec.constructorBuilder()
208+
.addModifiers(PROTECTED)
209+
.addParameter(serviceClientConfigurationClassName, "serviceClientConfiguration")
210+
.addParameter(SdkClientConfiguration.class, "clientConfiguration")
211+
.addStatement("this.clientHandler = new $T(clientConfiguration)", AwsAsyncClientHandler.class)
212+
.addStatement("this.clientConfiguration = clientConfiguration")
213+
.addStatement("this.serviceClientConfiguration = serviceClientConfiguration");
209214
FieldSpec protocolFactoryField = protocolSpec.protocolFactory(model);
210215
if (model.getMetadata().isJsonProtocol()) {
211216
builder.addStatement("this.$N = init($T.builder()).build()", protocolFactoryField.name,
@@ -264,6 +269,16 @@ private MethodSpec nameMethod() {
264269
.build();
265270
}
266271

272+
@Override
273+
protected MethodSpec serviceClientConfigMethod() {
274+
return MethodSpec.methodBuilder("serviceClientConfiguration")
275+
.addAnnotation(Override.class)
276+
.addModifiers(PUBLIC, FINAL)
277+
.returns(serviceClientConfigurationClassName)
278+
.addStatement("return this.serviceClientConfiguration")
279+
.build();
280+
}
281+
267282
@Override
268283
protected void addCloseMethod(TypeSpec.Builder type) {
269284
MethodSpec method = MethodSpec.methodBuilder("close")

codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/AsyncClientInterface.java

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package software.amazon.awssdk.codegen.poet.client;
1717

1818
import static java.util.stream.Collectors.toList;
19+
import static javax.lang.model.element.Modifier.ABSTRACT;
1920
import static javax.lang.model.element.Modifier.DEFAULT;
2021
import static javax.lang.model.element.Modifier.FINAL;
2122
import static javax.lang.model.element.Modifier.PUBLIC;
@@ -41,6 +42,7 @@
4142
import software.amazon.awssdk.annotations.SdkPublicApi;
4243
import software.amazon.awssdk.annotations.ThreadSafe;
4344
import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider;
45+
import software.amazon.awssdk.awscore.AwsClient;
4446
import software.amazon.awssdk.codegen.docs.ClientType;
4547
import software.amazon.awssdk.codegen.docs.DocConfiguration;
4648
import software.amazon.awssdk.codegen.docs.SimpleMethodOverload;
@@ -55,7 +57,6 @@
5557
import software.amazon.awssdk.codegen.poet.eventstream.EventStreamUtils;
5658
import software.amazon.awssdk.codegen.poet.model.DeprecationUtils;
5759
import software.amazon.awssdk.codegen.utils.PaginatorUtils;
58-
import software.amazon.awssdk.core.SdkClient;
5960
import software.amazon.awssdk.core.async.AsyncRequestBody;
6061
import software.amazon.awssdk.core.async.AsyncResponseTransformer;
6162
import software.amazon.awssdk.regions.ServiceMetadataProvider;
@@ -96,6 +97,7 @@ public TypeSpec poetSpec() {
9697
if (model.hasWaiters()) {
9798
addWaiterMethod(result);
9899
}
100+
result.addMethod(serviceClientConfigMethod());
99101
addAdditionalMethods(result);
100102
addCloseMethod(result);
101103
return result.build();
@@ -106,7 +108,7 @@ protected TypeSpec.Builder createTypeSpec() {
106108
}
107109

108110
protected void addInterfaceClass(TypeSpec.Builder type) {
109-
type.addSuperinterface(SdkClient.class);
111+
type.addSuperinterface(AwsClient.class);
110112
}
111113

112114
protected void addAnnotations(TypeSpec.Builder type) {
@@ -490,6 +492,14 @@ protected MethodSpec utilitiesMethod() {
490492
return utilitiesOperationBody(builder).build();
491493
}
492494

495+
protected MethodSpec serviceClientConfigMethod() {
496+
return MethodSpec.methodBuilder("serviceClientConfiguration")
497+
.addAnnotation(Override.class)
498+
.addModifiers(PUBLIC, ABSTRACT)
499+
.returns(new PoetExtension(model).getServiceConfigClass())
500+
.build();
501+
}
502+
493503
private MethodSpec additionalBuilders(AdditionalBuilderMethod additionalMethod) {
494504

495505
String methodName = Validate.paramNotNull(additionalMethod.getMethodName(), "methodName");

codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/DelegatingAsyncClientClass.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,16 @@ private MethodSpec nameMethod() {
107107
.build();
108108
}
109109

110+
@Override
111+
protected MethodSpec serviceClientConfigMethod() {
112+
return MethodSpec.methodBuilder("serviceClientConfiguration")
113+
.addAnnotation(Override.class)
114+
.addModifiers(PUBLIC, FINAL)
115+
.returns(new PoetExtension(model).getServiceConfigClass())
116+
.addStatement("return delegate.serviceClientConfiguration()")
117+
.build();
118+
}
119+
110120
@Override
111121
protected void addCloseMethod(TypeSpec.Builder type) {
112122
MethodSpec method = MethodSpec.methodBuilder("close")

codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/DelegatingSyncClientClass.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,4 +166,14 @@ private MethodSpec nameMethod() {
166166
.addStatement("return delegate.serviceName()")
167167
.build();
168168
}
169+
170+
@Override
171+
protected MethodSpec serviceClientConfigMethod() {
172+
return MethodSpec.methodBuilder("serviceClientConfiguration")
173+
.addAnnotation(Override.class)
174+
.addModifiers(PUBLIC, FINAL)
175+
.returns(new PoetExtension(model).getServiceConfigClass())
176+
.addStatement("return delegate.serviceClientConfiguration()")
177+
.build();
178+
}
169179
}

codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/SyncClientClass.java

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -69,13 +69,15 @@ public class SyncClientClass extends SyncClientInterface {
6969
private final PoetExtension poetExtensions;
7070
private final ClassName className;
7171
private final ProtocolSpec protocolSpec;
72+
private final ClassName serviceClientConfigurationClassName;
7273

7374
public SyncClientClass(GeneratorTaskParams taskParams) {
7475
super(taskParams.getModel());
7576
this.model = taskParams.getModel();
7677
this.poetExtensions = taskParams.getPoetExtensions();
7778
this.className = poetExtensions.getClientClass(model.getMetadata().getSyncClient());
7879
this.protocolSpec = getProtocolSpecs(poetExtensions, model);
80+
this.serviceClientConfigurationClassName = new PoetExtension(model).getServiceConfigClass();
7981
}
8082

8183
@Override
@@ -105,7 +107,8 @@ protected void addFields(TypeSpec.Builder type) {
105107
type.addField(logger())
106108
.addField(SyncClientHandler.class, "clientHandler", PRIVATE, FINAL)
107109
.addField(protocolSpec.protocolFactory(model))
108-
.addField(SdkClientConfiguration.class, "clientConfiguration", PRIVATE, FINAL);
110+
.addField(SdkClientConfiguration.class, "clientConfiguration", PRIVATE, FINAL)
111+
.addField(serviceClientConfigurationClassName, "serviceClientConfiguration", PRIVATE, FINAL);
109112
}
110113

111114
@Override
@@ -147,18 +150,30 @@ private MethodSpec nameMethod() {
147150
.build();
148151
}
149152

153+
@Override
154+
protected MethodSpec serviceClientConfigMethod() {
155+
return MethodSpec.methodBuilder("serviceClientConfiguration")
156+
.addAnnotation(Override.class)
157+
.addModifiers(PUBLIC, FINAL)
158+
.returns(serviceClientConfigurationClassName)
159+
.addStatement("return this.serviceClientConfiguration")
160+
.build();
161+
}
162+
150163
@Override
151164
public ClassName className() {
152165
return className;
153166
}
154167

155168
private MethodSpec constructor() {
156-
MethodSpec.Builder builder = MethodSpec.constructorBuilder()
157-
.addModifiers(PROTECTED)
158-
.addParameter(SdkClientConfiguration.class, "clientConfiguration")
159-
.addStatement("this.clientHandler = new $T(clientConfiguration)",
160-
protocolSpec.getClientHandlerClass())
161-
.addStatement("this.clientConfiguration = clientConfiguration");
169+
MethodSpec.Builder builder
170+
= MethodSpec.constructorBuilder()
171+
.addModifiers(PROTECTED)
172+
.addParameter(serviceClientConfigurationClassName, "serviceClientConfiguration")
173+
.addParameter(SdkClientConfiguration.class, "clientConfiguration")
174+
.addStatement("this.clientHandler = new $T(clientConfiguration)", protocolSpec.getClientHandlerClass())
175+
.addStatement("this.clientConfiguration = clientConfiguration")
176+
.addStatement("this.serviceClientConfiguration = serviceClientConfiguration");
162177
FieldSpec protocolFactoryField = protocolSpec.protocolFactory(model);
163178
if (model.getMetadata().isJsonProtocol()) {
164179
builder.addStatement("this.$N = init($T.builder()).build()", protocolFactoryField.name,

0 commit comments

Comments
 (0)