Skip to content

Commit 339daa8

Browse files
committed
Cleaning up protocol factory and introducing builder
1 parent 1a271f9 commit 339daa8

File tree

7 files changed

+150
-171
lines changed

7 files changed

+150
-171
lines changed

codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/JsonProtocolSpec.java

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@
3535
import software.amazon.awssdk.awscore.exception.AwsServiceException;
3636
import software.amazon.awssdk.awscore.protocol.json.AwsJsonProtocol;
3737
import software.amazon.awssdk.awscore.protocol.json.AwsJsonProtocolFactory;
38-
import software.amazon.awssdk.awscore.protocol.json.AwsJsonProtocolMetadata;
3938
import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel;
4039
import software.amazon.awssdk.codegen.model.intermediate.Metadata;
4140
import software.amazon.awssdk.codegen.model.intermediate.OperationModel;
@@ -50,7 +49,6 @@
5049
import software.amazon.awssdk.core.client.handler.ClientExecutionParams;
5150
import software.amazon.awssdk.core.http.HttpResponseHandler;
5251
import software.amazon.awssdk.core.protocol.VoidSdkResponse;
53-
import software.amazon.awssdk.core.protocol.json.JsonClientMetadata;
5452
import software.amazon.awssdk.core.protocol.json.JsonErrorResponseMetadata;
5553
import software.amazon.awssdk.core.protocol.json.JsonErrorShapeMetadata;
5654
import software.amazon.awssdk.core.protocol.json.JsonOperationMetadata;
@@ -82,26 +80,23 @@ public MethodSpec initProtocolFactory(IntermediateModel model) {
8280
.returns(protocolFactory)
8381
.addModifiers(Modifier.PRIVATE)
8482
.addCode(
85-
"return new $T(new $T()\n" +
86-
".withSupportsCbor(supportsCbor)\n" +
87-
".withSupportsIon($L)" +
88-
".withBaseServiceExceptionClass($L.class)",
89-
AwsJsonProtocolFactory.class,
90-
JsonClientMetadata.class,
91-
metadata.isIonProtocol(), baseException);
83+
"return $T.builder()\n" +
84+
".supportsCbor(supportsCbor)\n" +
85+
".supportsIon($L)\n" +
86+
".baseServiceExceptionClass($T.class)\n" +
87+
".protocol($T.$L)\n" +
88+
".protocolVersion($S)\n",
89+
AwsJsonProtocolFactory.class, metadata.isIonProtocol(), baseException,
90+
AwsJsonProtocol.class, protocolEnumName(metadata.getProtocol()),
91+
metadata.getJsonVersion());
9292

9393
if (metadata.getContentType() != null) {
9494
methodSpec.addCode(".withContentTypeOverride($S)", metadata.getContentType());
9595
}
9696

9797
errorUnmarshallers(model).forEach(methodSpec::addCode);
9898

99-
methodSpec.addCode(",\n");
100-
methodSpec.addCode("$T.builder().protocolVersion($S)\n" +
101-
".protocol($T.$L).build()", AwsJsonProtocolMetadata.class,
102-
metadata.getJsonVersion(), AwsJsonProtocol.class, protocolEnumName(metadata.getProtocol()));
103-
104-
methodSpec.addCode(");");
99+
methodSpec.addCode(".build();");
105100

106101
return methodSpec.build();
107102
}

codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-async-client-class.java

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
import software.amazon.awssdk.awscore.internal.client.handler.AwsClientHandlerUtils;
2323
import software.amazon.awssdk.awscore.protocol.json.AwsJsonProtocol;
2424
import software.amazon.awssdk.awscore.protocol.json.AwsJsonProtocolFactory;
25-
import software.amazon.awssdk.awscore.protocol.json.AwsJsonProtocolMetadata;
2625
import software.amazon.awssdk.core.ApiName;
2726
import software.amazon.awssdk.core.SdkResponse;
2827
import software.amazon.awssdk.core.async.AsyncRequestBody;
@@ -35,7 +34,6 @@
3534
import software.amazon.awssdk.core.client.handler.ClientExecutionParams;
3635
import software.amazon.awssdk.core.http.HttpResponseHandler;
3736
import software.amazon.awssdk.core.protocol.VoidSdkResponse;
38-
import software.amazon.awssdk.core.protocol.json.JsonClientMetadata;
3937
import software.amazon.awssdk.core.protocol.json.JsonErrorResponseMetadata;
4038
import software.amazon.awssdk.core.protocol.json.JsonErrorShapeMetadata;
4139
import software.amazon.awssdk.core.protocol.json.JsonOperationMetadata;
@@ -61,6 +59,7 @@
6159
import software.amazon.awssdk.services.json.model.InputEventStreamTwo;
6260
import software.amazon.awssdk.services.json.model.InputEventTwo;
6361
import software.amazon.awssdk.services.json.model.InvalidInputException;
62+
import software.amazon.awssdk.services.json.model.JsonException;
6463
import software.amazon.awssdk.services.json.model.JsonRequest;
6564
import software.amazon.awssdk.services.json.model.PaginatedOperationWithResultKeyRequest;
6665
import software.amazon.awssdk.services.json.model.PaginatedOperationWithResultKeyResponse;
@@ -766,15 +765,16 @@ public void close() {
766765
}
767766

768767
private software.amazon.awssdk.awscore.protocol.json.AwsJsonProtocolFactory init(boolean supportsCbor) {
769-
return new AwsJsonProtocolFactory(
770-
new JsonClientMetadata()
771-
.withSupportsCbor(supportsCbor)
772-
.withSupportsIon(false)
773-
.withBaseServiceExceptionClass(software.amazon.awssdk.services.json.model.JsonException.class)
774-
.addErrorMetadata(
775-
new JsonErrorShapeMetadata().withErrorCode("InvalidInput").withModeledClass(
776-
InvalidInputException.class)), AwsJsonProtocolMetadata.builder().protocolVersion("1.1")
777-
.protocol(AwsJsonProtocol.REST_JSON).build());
768+
return AwsJsonProtocolFactory
769+
.builder()
770+
.supportsCbor(supportsCbor)
771+
.supportsIon(false)
772+
.baseServiceExceptionClass(JsonException.class)
773+
.protocol(AwsJsonProtocol.REST_JSON)
774+
.protocolVersion("1.1")
775+
.addErrorMetadata(
776+
new JsonErrorShapeMetadata().withErrorCode("InvalidInput").withModeledClass(InvalidInputException.class))
777+
.build();
778778
}
779779

780780
private <T extends JsonRequest> T applyPaginatorUserAgent(T request) {

codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-json-client-class.java

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,12 @@
99
import software.amazon.awssdk.awscore.exception.AwsServiceException;
1010
import software.amazon.awssdk.awscore.protocol.json.AwsJsonProtocol;
1111
import software.amazon.awssdk.awscore.protocol.json.AwsJsonProtocolFactory;
12-
import software.amazon.awssdk.awscore.protocol.json.AwsJsonProtocolMetadata;
1312
import software.amazon.awssdk.core.ApiName;
1413
import software.amazon.awssdk.core.client.config.SdkClientConfiguration;
1514
import software.amazon.awssdk.core.client.handler.ClientExecutionParams;
1615
import software.amazon.awssdk.core.client.handler.SyncClientHandler;
1716
import software.amazon.awssdk.core.exception.SdkClientException;
1817
import software.amazon.awssdk.core.http.HttpResponseHandler;
19-
import software.amazon.awssdk.core.protocol.json.JsonClientMetadata;
2018
import software.amazon.awssdk.core.protocol.json.JsonErrorResponseMetadata;
2119
import software.amazon.awssdk.core.protocol.json.JsonErrorShapeMetadata;
2220
import software.amazon.awssdk.core.protocol.json.JsonOperationMetadata;
@@ -559,15 +557,16 @@ private HttpResponseHandler<AwsServiceException> createErrorResponseHandler(AwsJ
559557
}
560558

561559
private software.amazon.awssdk.awscore.protocol.json.AwsJsonProtocolFactory init(boolean supportsCbor) {
562-
return new AwsJsonProtocolFactory(
563-
new JsonClientMetadata()
564-
.withSupportsCbor(supportsCbor)
565-
.withSupportsIon(false)
566-
.withBaseServiceExceptionClass(software.amazon.awssdk.services.json.model.JsonException.class)
567-
.addErrorMetadata(
568-
new JsonErrorShapeMetadata().withErrorCode("InvalidInput").withModeledClass(
569-
InvalidInputException.class)), AwsJsonProtocolMetadata.builder().protocolVersion("1.1")
570-
.protocol(AwsJsonProtocol.REST_JSON).build());
560+
return AwsJsonProtocolFactory
561+
.builder()
562+
.supportsCbor(supportsCbor)
563+
.supportsIon(false)
564+
.baseServiceExceptionClass(JsonException.class)
565+
.protocol(AwsJsonProtocol.REST_JSON)
566+
.protocolVersion("1.1")
567+
.addErrorMetadata(
568+
new JsonErrorShapeMetadata().withErrorCode("InvalidInput").withModeledClass(InvalidInputException.class))
569+
.build();
571570
}
572571

573572
@Override
@@ -595,3 +594,4 @@ private <T extends JsonRequest> T applySignerOverride(T request, Signer signer)
595594
return (T) request.toBuilder().overrideConfiguration(overrideConfiguration).build();
596595
}
597596
}
597+

core/aws-core/src/main/java/software/amazon/awssdk/awscore/protocol/json/AwsJsonProtocolFactory.java

Lines changed: 112 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,16 @@
1515

1616
package software.amazon.awssdk.awscore.protocol.json;
1717

18+
import static software.amazon.awssdk.core.SdkSystemSetting.BINARY_ION_ENABLED;
19+
import static software.amazon.awssdk.core.SdkSystemSetting.CBOR_ENABLED;
20+
1821
import java.util.ArrayList;
1922
import java.util.List;
2023
import java.util.function.Function;
2124
import java.util.function.Supplier;
2225
import software.amazon.awssdk.annotations.SdkProtectedApi;
2326
import software.amazon.awssdk.annotations.SdkTestInternalApi;
2427
import software.amazon.awssdk.annotations.ThreadSafe;
25-
import software.amazon.awssdk.awscore.AwsRequest;
2628
import software.amazon.awssdk.awscore.exception.AwsServiceException;
2729
import software.amazon.awssdk.awscore.http.response.AwsJsonResponseHandler;
2830
import software.amazon.awssdk.awscore.internal.protocol.json.AwsJsonErrorUnmarshaller;
@@ -36,15 +38,14 @@
3638
import software.amazon.awssdk.core.http.NewJsonResponseHandler;
3739
import software.amazon.awssdk.core.internal.protocol.json.unmarshall.JsonProtocolUnmarshaller;
3840
import software.amazon.awssdk.core.protocol.OperationInfo;
41+
import software.amazon.awssdk.core.protocol.ProtocolRequestMarshaller;
3942
import software.amazon.awssdk.core.protocol.SdkPojo;
40-
import software.amazon.awssdk.core.protocol.json.BaseJsonProtocolFactory;
4143
import software.amazon.awssdk.core.protocol.json.JsonClientMetadata;
4244
import software.amazon.awssdk.core.protocol.json.JsonErrorResponseMetadata;
4345
import software.amazon.awssdk.core.protocol.json.JsonErrorShapeMetadata;
4446
import software.amazon.awssdk.core.protocol.json.JsonOperationMetadata;
47+
import software.amazon.awssdk.core.protocol.json.JsonProtocolMarshallerBuilder;
4548
import software.amazon.awssdk.core.protocol.json.StructuredJsonGenerator;
46-
import software.amazon.awssdk.core.runtime.transform.JsonUnmarshallerContext;
47-
import software.amazon.awssdk.core.runtime.transform.Unmarshaller;
4849
import software.amazon.awssdk.http.SdkHttpFullResponse;
4950

5051
/**
@@ -53,59 +54,62 @@
5354
*/
5455
@ThreadSafe
5556
@SdkProtectedApi
56-
public final class AwsJsonProtocolFactory extends BaseJsonProtocolFactory<AwsRequest, AwsServiceException> {
57+
public final class AwsJsonProtocolFactory {
5758

59+
private final JsonClientMetadata jsonClientMetadata;
5860
private final AwsJsonProtocolMetadata protocolMetadata;
5961
private final List<AwsJsonErrorUnmarshaller> errorUnmarshallers = new ArrayList<>();
6062

61-
public AwsJsonProtocolFactory(JsonClientMetadata metadata, AwsJsonProtocolMetadata protocolMetadata) {
62-
super(metadata);
63-
this.protocolMetadata = protocolMetadata;
63+
private AwsJsonProtocolFactory(Builder builder) {
64+
this.jsonClientMetadata = builder.metadata;
65+
this.protocolMetadata = builder.protocolMetadata.build();
6466
createErrorUnmarshallers();
6567
}
6668

6769
/**
68-
* Returns the response handler to be used for handling a successful response.
70+
* Creates a new response handler with the given {@link JsonOperationMetadata} and a supplier of the POJO response
71+
* type.
6972
*
70-
* @param operationMetadata Additional context information about an operation to create the appropriate response handler.
73+
* @param operationMetadata Metadata about operation being unmarshalled.
74+
* @param pojoSupplier {@link Supplier} of the POJO response type.
75+
* @param <T> Type being unmarshalled.
76+
* @return HttpResponseHandler that will handle the HTTP response and unmarshall into a POJO.
7177
*/
72-
@Override
73-
public <T> HttpResponseHandler<T> createResponseHandler(
74-
JsonOperationMetadata operationMetadata,
75-
Unmarshaller<T, JsonUnmarshallerContext> responseUnmarshaller) {
76-
return getSdkFactory().createResponseHandler(operationMetadata, responseUnmarshaller);
78+
public <T extends SdkPojo> HttpResponseHandler<T> createResponseHandler(JsonOperationMetadata operationMetadata,
79+
Supplier<SdkPojo> pojoSupplier) {
80+
return createResponseHandler(operationMetadata, r -> pojoSupplier.get());
7781
}
7882

79-
public <T extends SdkPojo> HttpResponseHandler<T> createResponseHandler(
80-
JsonOperationMetadata operationMetadata, Supplier<SdkPojo> pojoSupplier) {
83+
/**
84+
* Creates a new response handler with the given {@link JsonOperationMetadata} and a supplier of the POJO response
85+
* type.
86+
*
87+
* @param operationMetadata Metadata about operation being unmarshalled.
88+
* @param pojoSupplier {@link Supplier} of the POJO response type. Has access to the HTTP response, primarily for polymorphic
89+
* deserialization as seen in event stream (i.e. unmarshalled event depends on ':event-type' header).
90+
* @param <T> Type being unmarshalled.
91+
* @return HttpResponseHandler that will handle the HTTP response and unmarshall into a POJO.
92+
*/
93+
public <T extends SdkPojo> HttpResponseHandler<T> createResponseHandler(JsonOperationMetadata operationMetadata,
94+
Function<SdkHttpFullResponse, SdkPojo> pojoSupplier) {
8195
JsonProtocolUnmarshaller<T> unmarshaller = new JsonProtocolUnmarshaller<>(getSdkFactory().createObjectMapper());
8296
return new AwsJsonResponseHandler<>(
8397
new NewJsonResponseHandler<>(unmarshaller,
84-
r -> pojoSupplier.get(),
98+
pojoSupplier,
8599
operationMetadata.isHasStreamingSuccessResponse(),
86100
operationMetadata.isPayloadJson()));
87101
}
88102

89-
public <T extends SdkPojo> HttpResponseHandler<T> createResponseHandler(
90-
JsonOperationMetadata operationMetadata, Function<SdkHttpFullResponse, SdkPojo> pojoSupplier) {
91-
JsonProtocolUnmarshaller<T> unmarshaller = new JsonProtocolUnmarshaller<>(getSdkFactory().createObjectMapper());
92-
return new NewJsonResponseHandler<>(unmarshaller,
93-
pojoSupplier,
94-
operationMetadata.isHasStreamingSuccessResponse(),
95-
operationMetadata.isPayloadJson());
96-
}
97-
98103
/**
99104
* Creates a response handler for handling a error response (non 2xx response).
100105
*/
101-
@Override
102106
public HttpResponseHandler<AwsServiceException> createErrorResponseHandler(
103107
JsonErrorResponseMetadata errorResponseMetadata) {
104108
return getSdkFactory().createErrorResponseHandler(errorUnmarshallers, errorResponseMetadata
105109
.getCustomErrorCodeFieldName());
106110
}
107111

108-
protected StructuredJsonGenerator createGenerator(OperationInfo operationInfo) {
112+
private StructuredJsonGenerator createGenerator(OperationInfo operationInfo) {
109113
if (operationInfo.hasPayloadMembers() || protocolMetadata.protocol() == AwsJsonProtocol.AWS_JSON) {
110114
return createGenerator();
111115
} else {
@@ -165,4 +169,83 @@ private AwsStructuredJsonFactory getSdkFactory() {
165169
return AwsStructuredPlainJsonFactory.SDK_JSON_FACTORY;
166170
}
167171
}
172+
173+
public <T extends software.amazon.awssdk.awscore.AwsRequest> ProtocolRequestMarshaller<T> createProtocolMarshaller(
174+
OperationInfo operationInfo, T origRequest) {
175+
return JsonProtocolMarshallerBuilder.<T>standard()
176+
.jsonGenerator(createGenerator(operationInfo))
177+
.contentType(getContentType())
178+
.operationInfo(operationInfo)
179+
.originalRequest(origRequest)
180+
.sendExplicitNullForPayload(false)
181+
.build();
182+
}
183+
184+
private boolean isCborEnabled() {
185+
return jsonClientMetadata.isSupportsCbor() && CBOR_ENABLED.getBooleanValueOrThrow();
186+
}
187+
188+
private boolean isIonEnabled() {
189+
return jsonClientMetadata.isSupportsIon();
190+
}
191+
192+
private boolean isIonBinaryEnabled() {
193+
return BINARY_ION_ENABLED.getBooleanValueOrThrow();
194+
}
195+
196+
public static Builder builder() {
197+
return new Builder();
198+
}
199+
200+
/**
201+
* Builder for {@link AwsJsonProtocolFactory}.
202+
*/
203+
public static final class Builder {
204+
205+
private final JsonClientMetadata metadata = new JsonClientMetadata();
206+
private final AwsJsonProtocolMetadata.Builder protocolMetadata = AwsJsonProtocolMetadata.builder();
207+
208+
private Builder() {
209+
}
210+
211+
public Builder addErrorMetadata(JsonErrorShapeMetadata errorShapeMetadata) {
212+
metadata.addErrorMetadata(errorShapeMetadata);
213+
return this;
214+
}
215+
216+
public Builder contentTypeOverride(String contentType) {
217+
metadata.withContentTypeOverride(contentType);
218+
return this;
219+
}
220+
221+
public Builder supportsCbor(boolean supportsCbor) {
222+
metadata.withSupportsCbor(supportsCbor);
223+
return this;
224+
}
225+
226+
public Builder supportsIon(boolean supportsIon) {
227+
metadata.withSupportsIon(supportsIon);
228+
return this;
229+
}
230+
231+
public Builder baseServiceExceptionClass(Class<? extends RuntimeException> baseServiceExceptionClass) {
232+
metadata.withBaseServiceExceptionClass(baseServiceExceptionClass);
233+
return this;
234+
}
235+
236+
public Builder protocol(AwsJsonProtocol protocol) {
237+
protocolMetadata.protocol(protocol);
238+
return this;
239+
}
240+
241+
public Builder protocolVersion(String protocolVersion) {
242+
protocolMetadata.protocolVersion(protocolVersion);
243+
return this;
244+
}
245+
246+
public AwsJsonProtocolFactory build() {
247+
return new AwsJsonProtocolFactory(this);
248+
}
249+
250+
}
168251
}

core/aws-core/src/test/java/software/amazon/awssdk/awscore/protocol/json/AwsJsonProtocolFactoryTest.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
import org.junit.After;
2222
import org.junit.Assert;
2323
import org.junit.Test;
24-
import software.amazon.awssdk.core.protocol.json.JsonClientMetadata;
2524
import software.amazon.awssdk.core.protocol.json.StructuredJsonGenerator;
2625

2726
public class AwsJsonProtocolFactoryTest {
@@ -69,10 +68,11 @@ public void ionBinaryDisabledUsesIonTextContentType() {
6968
}
7069

7170
private AwsJsonProtocolFactory protocolFactory(IonEnabled ionEnabled, final IonBinaryEnabled ionBinaryEnabled) {
72-
JsonClientMetadata metadata = new JsonClientMetadata()
73-
.withSupportsIon(ionEnabled == IonEnabled.YES);
7471
System.setProperty(BINARY_ION_ENABLED.property(), String.valueOf(ionBinaryEnabled == IonBinaryEnabled.YES));
75-
return new AwsJsonProtocolFactory(metadata, AwsJsonProtocolMetadata.builder().protocolVersion("1.0").build());
72+
return AwsJsonProtocolFactory.builder()
73+
.supportsIon(ionEnabled == IonEnabled.YES)
74+
.protocolVersion("1.0")
75+
.build();
7676
}
7777

7878
private enum IonEnabled {

0 commit comments

Comments
 (0)