Skip to content

Add ServiceClientConfiguration to SdkClient #3830

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 20 commits into from
Mar 24, 2023
Merged
6 changes: 6 additions & 0 deletions .changes/next-release/feature-AWSSDKforJavav2-18cd42a.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"category": "AWS SDK for Java v2",
"contributor": "",
"type": "feature",
"description": "Adds ServiceClientConfiguration to SdkClient which exposes client settings to the user"
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import software.amazon.awssdk.codegen.emitters.GeneratorTaskParams;
import software.amazon.awssdk.codegen.poet.builder.BaseClientBuilderClass;
import software.amazon.awssdk.codegen.poet.builder.BaseClientBuilderInterface;
import software.amazon.awssdk.codegen.poet.model.ServiceClientConfigurationClass;

/**
* Task for classes shared by {@link AsyncClientGeneratorTasks} and {@link SyncClientGeneratorTasks}.
Expand All @@ -34,7 +35,8 @@ public CommonClientGeneratorTasks(GeneratorTaskParams dependencies) {
@Override
protected List<GeneratorTask> createTasks() throws Exception {
return Arrays.asList(createBaseBuilderTask(),
createBaseBuilderInterfaceTask());
createBaseBuilderInterfaceTask(),
createServiceClientConfigurationTask());
}

private GeneratorTask createBaseBuilderTask() throws IOException {
Expand All @@ -44,4 +46,8 @@ private GeneratorTask createBaseBuilderTask() throws IOException {
private GeneratorTask createBaseBuilderInterfaceTask() throws IOException {
return createPoetGeneratorTask(new BaseClientBuilderInterface(model));
}

private GeneratorTask createServiceClientConfigurationTask() throws IOException {
return createPoetGeneratorTask(new ServiceClientConfigurationClass(model));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,14 @@ public ClassName getClientClass(String className) {
return ClassName.get(model.getMetadata().getFullClientPackageName(), className);
}

/**
* @return A Poet {@link ClassName} for the generated service client configuration.
*/
public ClassName getServiceConfigClass() {
return PoetUtils.classNameFromFqcn(model.getMetadata().getFullClientPackageName() + "."
+ model.getMetadata().getServiceName() + "ServiceClientConfiguration");
}

/**
* @param operationName Name of the operation
* @return A Poet {@link ClassName} for the response type of a paginated operation in the base service package.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import software.amazon.awssdk.awscore.client.config.AwsClientOption;
import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel;
import software.amazon.awssdk.codegen.poet.ClassSpec;
import software.amazon.awssdk.codegen.poet.PoetExtension;
import software.amazon.awssdk.codegen.poet.PoetUtils;
import software.amazon.awssdk.codegen.poet.rules.EndpointRulesSpecUtils;
import software.amazon.awssdk.codegen.utils.AuthUtils;
Expand All @@ -38,6 +39,7 @@ public class AsyncClientBuilderClass implements ClassSpec {
private final ClassName builderInterfaceName;
private final ClassName builderClassName;
private final ClassName builderBaseClassName;
private final ClassName serviceConfigClassName;
private final EndpointRulesSpecUtils endpointRulesSpecUtils;

public AsyncClientBuilderClass(IntermediateModel model) {
Expand All @@ -49,6 +51,7 @@ public AsyncClientBuilderClass(IntermediateModel model) {
this.builderClassName = ClassName.get(basePackage, model.getMetadata().getAsyncBuilder());
this.builderBaseClassName = ClassName.get(basePackage, model.getMetadata().getBaseBuilder());
this.endpointRulesSpecUtils = new EndpointRulesSpecUtils(model);
this.serviceConfigClassName = new PoetExtension(model).getServiceConfigClass();
}

@Override
Expand Down Expand Up @@ -121,7 +124,11 @@ private MethodSpec buildClientMethod() {
.returns(clientInterfaceName)
.addStatement("$T clientConfiguration = super.asyncClientConfiguration()", SdkClientConfiguration.class)
.addStatement("this.validateClientOptions(clientConfiguration)")
.addCode("return new $T(clientConfiguration);", clientClassName)
.addStatement("$T serviceClientConfiguration = $T.builder()"
+ ".overrideConfiguration(overrideConfiguration())"
+ ".region(clientConfiguration.option($T.AWS_REGION)).build()",
serviceConfigClassName, serviceConfigClassName, AwsClientOption.class)
.addStatement("return new $T(serviceClientConfiguration, clientConfiguration)", clientClassName)
.build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import software.amazon.awssdk.awscore.client.config.AwsClientOption;
import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel;
import software.amazon.awssdk.codegen.poet.ClassSpec;
import software.amazon.awssdk.codegen.poet.PoetExtension;
import software.amazon.awssdk.codegen.poet.PoetUtils;
import software.amazon.awssdk.codegen.poet.rules.EndpointRulesSpecUtils;
import software.amazon.awssdk.codegen.utils.AuthUtils;
Expand All @@ -38,6 +39,7 @@ public class SyncClientBuilderClass implements ClassSpec {
private final ClassName builderInterfaceName;
private final ClassName builderClassName;
private final ClassName builderBaseClassName;
private final ClassName serviceConfigClassName;
private final EndpointRulesSpecUtils endpointRulesSpecUtils;

public SyncClientBuilderClass(IntermediateModel model) {
Expand All @@ -49,6 +51,7 @@ public SyncClientBuilderClass(IntermediateModel model) {
this.builderClassName = ClassName.get(basePackage, model.getMetadata().getSyncBuilder());
this.builderBaseClassName = ClassName.get(basePackage, model.getMetadata().getBaseBuilder());
this.endpointRulesSpecUtils = new EndpointRulesSpecUtils(model);
this.serviceConfigClassName = new PoetExtension(model).getServiceConfigClass();
}

@Override
Expand Down Expand Up @@ -116,14 +119,17 @@ private MethodSpec endpointProviderMethod() {

private MethodSpec buildClientMethod() {
return MethodSpec.methodBuilder("buildClient")
.addAnnotation(Override.class)
.addModifiers(Modifier.PROTECTED, Modifier.FINAL)
.returns(clientInterfaceName)
.addStatement("$T clientConfiguration = super.syncClientConfiguration()",
SdkClientConfiguration.class)
.addStatement("this.validateClientOptions(clientConfiguration)")
.addCode("return new $T(clientConfiguration);", clientClassName)
.build();
.addAnnotation(Override.class)
.addModifiers(Modifier.PROTECTED, Modifier.FINAL)
.returns(clientInterfaceName)
.addStatement("$T clientConfiguration = super.syncClientConfiguration()", SdkClientConfiguration.class)
.addStatement("this.validateClientOptions(clientConfiguration)")
.addStatement("$T serviceClientConfiguration = $T.builder()"
+ ".overrideConfiguration(overrideConfiguration())"
+ ".region(clientConfiguration.option($T.AWS_REGION)).build()",
serviceConfigClassName, serviceConfigClassName, AwsClientOption.class)
.addStatement("return new $T(serviceClientConfiguration, clientConfiguration)", clientClassName)
.build();
}

private MethodSpec tokenProviderMethodImpl() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,13 +93,15 @@ public final class AsyncClientClass extends AsyncClientInterface {
private final PoetExtension poetExtensions;
private final ClassName className;
private final ProtocolSpec protocolSpec;
private final ClassName serviceClientConfigurationClassName;

public AsyncClientClass(GeneratorTaskParams dependencies) {
super(dependencies.getModel());
this.model = dependencies.getModel();
this.poetExtensions = dependencies.getPoetExtensions();
this.className = poetExtensions.getClientClass(model.getMetadata().getAsyncClient());
this.protocolSpec = getProtocolSpecs(poetExtensions, model);
this.serviceClientConfigurationClassName = new PoetExtension(model).getServiceConfigClass();
}

@Override
Expand Down Expand Up @@ -133,7 +135,8 @@ protected void addFields(TypeSpec.Builder type) {
.build())
.addField(AsyncClientHandler.class, "clientHandler", PRIVATE, FINAL)
.addField(protocolSpec.protocolFactory(model))
.addField(SdkClientConfiguration.class, "clientConfiguration", PRIVATE, FINAL);
.addField(SdkClientConfiguration.class, "clientConfiguration", PRIVATE, FINAL)
.addField(serviceClientConfigurationClassName, "serviceClientConfiguration", PRIVATE, FINAL);

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

private MethodSpec constructor(TypeSpec.Builder classBuilder) {
MethodSpec.Builder builder = MethodSpec.constructorBuilder()
.addModifiers(PROTECTED)
.addParameter(SdkClientConfiguration.class, "clientConfiguration")
.addStatement("this.clientHandler = new $T(clientConfiguration)",
AwsAsyncClientHandler.class)
.addStatement("this.clientConfiguration = clientConfiguration");
MethodSpec.Builder builder
= MethodSpec.constructorBuilder()
.addModifiers(PROTECTED)
.addParameter(serviceClientConfigurationClassName, "serviceClientConfiguration")
.addParameter(SdkClientConfiguration.class, "clientConfiguration")
.addStatement("this.clientHandler = new $T(clientConfiguration)", AwsAsyncClientHandler.class)
.addStatement("this.clientConfiguration = clientConfiguration")
.addStatement("this.serviceClientConfiguration = serviceClientConfiguration");
FieldSpec protocolFactoryField = protocolSpec.protocolFactory(model);
if (model.getMetadata().isJsonProtocol()) {
builder.addStatement("this.$N = init($T.builder()).build()", protocolFactoryField.name,
Expand Down Expand Up @@ -264,6 +269,16 @@ private MethodSpec nameMethod() {
.build();
}

@Override
protected MethodSpec serviceClientConfigMethod() {
return MethodSpec.methodBuilder("serviceClientConfiguration")
.addAnnotation(Override.class)
.addModifiers(PUBLIC, FINAL)
.returns(serviceClientConfigurationClassName)
.addStatement("return this.serviceClientConfiguration")
.build();
}

@Override
protected void addCloseMethod(TypeSpec.Builder type) {
MethodSpec method = MethodSpec.methodBuilder("close")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
package software.amazon.awssdk.codegen.poet.client;

import static java.util.stream.Collectors.toList;
import static javax.lang.model.element.Modifier.ABSTRACT;
import static javax.lang.model.element.Modifier.DEFAULT;
import static javax.lang.model.element.Modifier.FINAL;
import static javax.lang.model.element.Modifier.PUBLIC;
Expand All @@ -41,6 +42,7 @@
import software.amazon.awssdk.annotations.SdkPublicApi;
import software.amazon.awssdk.annotations.ThreadSafe;
import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider;
import software.amazon.awssdk.awscore.AwsClient;
import software.amazon.awssdk.codegen.docs.ClientType;
import software.amazon.awssdk.codegen.docs.DocConfiguration;
import software.amazon.awssdk.codegen.docs.SimpleMethodOverload;
Expand All @@ -55,7 +57,6 @@
import software.amazon.awssdk.codegen.poet.eventstream.EventStreamUtils;
import software.amazon.awssdk.codegen.poet.model.DeprecationUtils;
import software.amazon.awssdk.codegen.utils.PaginatorUtils;
import software.amazon.awssdk.core.SdkClient;
import software.amazon.awssdk.core.async.AsyncRequestBody;
import software.amazon.awssdk.core.async.AsyncResponseTransformer;
import software.amazon.awssdk.regions.ServiceMetadataProvider;
Expand Down Expand Up @@ -96,6 +97,7 @@ public TypeSpec poetSpec() {
if (model.hasWaiters()) {
addWaiterMethod(result);
}
result.addMethod(serviceClientConfigMethod());
addAdditionalMethods(result);
addCloseMethod(result);
return result.build();
Expand All @@ -106,7 +108,7 @@ protected TypeSpec.Builder createTypeSpec() {
}

protected void addInterfaceClass(TypeSpec.Builder type) {
type.addSuperinterface(SdkClient.class);
type.addSuperinterface(AwsClient.class);
}

protected void addAnnotations(TypeSpec.Builder type) {
Expand Down Expand Up @@ -490,6 +492,14 @@ protected MethodSpec utilitiesMethod() {
return utilitiesOperationBody(builder).build();
}

protected MethodSpec serviceClientConfigMethod() {
return MethodSpec.methodBuilder("serviceClientConfiguration")
.addAnnotation(Override.class)
.addModifiers(PUBLIC, ABSTRACT)
.returns(new PoetExtension(model).getServiceConfigClass())
.build();
}

private MethodSpec additionalBuilders(AdditionalBuilderMethod additionalMethod) {

String methodName = Validate.paramNotNull(additionalMethod.getMethodName(), "methodName");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,16 @@ private MethodSpec nameMethod() {
.build();
}

@Override
protected MethodSpec serviceClientConfigMethod() {
return MethodSpec.methodBuilder("serviceClientConfiguration")
.addAnnotation(Override.class)
.addModifiers(PUBLIC, FINAL)
.returns(new PoetExtension(model).getServiceConfigClass())
.addStatement("return delegate.serviceClientConfiguration()")
.build();
}

@Override
protected void addCloseMethod(TypeSpec.Builder type) {
MethodSpec method = MethodSpec.methodBuilder("close")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,4 +166,14 @@ private MethodSpec nameMethod() {
.addStatement("return delegate.serviceName()")
.build();
}

@Override
protected MethodSpec serviceClientConfigMethod() {
return MethodSpec.methodBuilder("serviceClientConfiguration")
.addAnnotation(Override.class)
.addModifiers(PUBLIC, FINAL)
.returns(new PoetExtension(model).getServiceConfigClass())
.addStatement("return delegate.serviceClientConfiguration()")
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -69,13 +69,15 @@ public class SyncClientClass extends SyncClientInterface {
private final PoetExtension poetExtensions;
private final ClassName className;
private final ProtocolSpec protocolSpec;
private final ClassName serviceClientConfigurationClassName;

public SyncClientClass(GeneratorTaskParams taskParams) {
super(taskParams.getModel());
this.model = taskParams.getModel();
this.poetExtensions = taskParams.getPoetExtensions();
this.className = poetExtensions.getClientClass(model.getMetadata().getSyncClient());
this.protocolSpec = getProtocolSpecs(poetExtensions, model);
this.serviceClientConfigurationClassName = new PoetExtension(model).getServiceConfigClass();
}

@Override
Expand Down Expand Up @@ -105,7 +107,8 @@ protected void addFields(TypeSpec.Builder type) {
type.addField(logger())
.addField(SyncClientHandler.class, "clientHandler", PRIVATE, FINAL)
.addField(protocolSpec.protocolFactory(model))
.addField(SdkClientConfiguration.class, "clientConfiguration", PRIVATE, FINAL);
.addField(SdkClientConfiguration.class, "clientConfiguration", PRIVATE, FINAL)
.addField(serviceClientConfigurationClassName, "serviceClientConfiguration", PRIVATE, FINAL);
}

@Override
Expand Down Expand Up @@ -147,18 +150,30 @@ private MethodSpec nameMethod() {
.build();
}

@Override
protected MethodSpec serviceClientConfigMethod() {
return MethodSpec.methodBuilder("serviceClientConfiguration")
.addAnnotation(Override.class)
.addModifiers(PUBLIC, FINAL)
.returns(serviceClientConfigurationClassName)
.addStatement("return this.serviceClientConfiguration")
.build();
}

@Override
public ClassName className() {
return className;
}

private MethodSpec constructor() {
MethodSpec.Builder builder = MethodSpec.constructorBuilder()
.addModifiers(PROTECTED)
.addParameter(SdkClientConfiguration.class, "clientConfiguration")
.addStatement("this.clientHandler = new $T(clientConfiguration)",
protocolSpec.getClientHandlerClass())
.addStatement("this.clientConfiguration = clientConfiguration");
MethodSpec.Builder builder
= MethodSpec.constructorBuilder()
.addModifiers(PROTECTED)
.addParameter(serviceClientConfigurationClassName, "serviceClientConfiguration")
.addParameter(SdkClientConfiguration.class, "clientConfiguration")
.addStatement("this.clientHandler = new $T(clientConfiguration)", protocolSpec.getClientHandlerClass())
.addStatement("this.clientConfiguration = clientConfiguration")
.addStatement("this.serviceClientConfiguration = serviceClientConfiguration");
FieldSpec protocolFactoryField = protocolSpec.protocolFactory(model);
if (model.getMetadata().isJsonProtocol()) {
builder.addStatement("this.$N = init($T.builder()).build()", protocolFactoryField.name,
Expand Down
Loading