From d0d4eaef38892ef141d1b3b226531a483b4c0125 Mon Sep 17 00:00:00 2001 From: Dongie Agnir <261310+dagnir@users.noreply.github.com> Date: Mon, 21 Oct 2024 21:11:33 -0700 Subject: [PATCH] Apply AWS_JSON status code mapping to CBOR (#5670) * Apply AWS_JSON status code mapping to CBOR Note: Kinesis is the only one we currently customize to CBOR. * Fix expected code in test * Add additional testing - Codegen tests - Added tests for CBOR protocol exceptions * Fix depdnency issue --- .../bugfix-AmazonKinesis-05d556d.json | 6 + .../poet/client/specs/ProtocolSpec.java | 5 +- .../awssdk/codegen/poet/ClientTestModels.java | 13 + .../poet/client/AsyncClientClassTest.java | 10 + .../poet/client/SyncClientClassTest.java | 7 + .../poet/client/c2j/cbor/customization.config | 28 + .../sra/test-cbor-async-client-class.java | 1225 ++++++++++++++++ .../client/test-cbor-async-client-class.java | 1255 +++++++++++++++++ .../poet/client/test-cbor-client-class.java | 824 +++++++++++ .../SubscribeToShardUnmarshallingTest.java | 2 +- test/protocol-tests/pom.xml | 10 + .../cbor/customization.config | 32 + .../cbor/endpoint-rule-set.json | 355 +++++ .../cbor/endpoint-tests.json | 5 + .../codegen-resources/cbor/service-2.json | 409 ++++++ .../tests/exception/CborExceptionTest.java | 275 ++++ .../util/exception/ExceptionTestUtils.java | 4 + 17 files changed, 4463 insertions(+), 2 deletions(-) create mode 100644 .changes/next-release/bugfix-AmazonKinesis-05d556d.json create mode 100644 codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/cbor/customization.config create mode 100644 codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/sra/test-cbor-async-client-class.java create mode 100644 codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-cbor-async-client-class.java create mode 100644 codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-cbor-client-class.java create mode 100644 test/protocol-tests/src/main/resources/codegen-resources/cbor/customization.config create mode 100644 test/protocol-tests/src/main/resources/codegen-resources/cbor/endpoint-rule-set.json create mode 100644 test/protocol-tests/src/main/resources/codegen-resources/cbor/endpoint-tests.json create mode 100644 test/protocol-tests/src/main/resources/codegen-resources/cbor/service-2.json create mode 100644 test/protocol-tests/src/test/java/software/amazon/awssdk/protocol/tests/exception/CborExceptionTest.java diff --git a/.changes/next-release/bugfix-AmazonKinesis-05d556d.json b/.changes/next-release/bugfix-AmazonKinesis-05d556d.json new file mode 100644 index 000000000000..a1e6231223dc --- /dev/null +++ b/.changes/next-release/bugfix-AmazonKinesis-05d556d.json @@ -0,0 +1,6 @@ +{ + "type": "bugfix", + "category": "Amazon Kinesis", + "contributor": "", + "description": "Fix an issue where errors that should be `400` are incorrectly classified as `500`." +} diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/ProtocolSpec.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/ProtocolSpec.java index 8dcca1162a72..443a483887eb 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/ProtocolSpec.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/ProtocolSpec.java @@ -90,7 +90,10 @@ default List registerModeledExceptions(IntermediateModel model, PoetE default String populateHttpStatusCode(ShapeModel shapeModel, IntermediateModel model) { Integer statusCode = shapeModel.getHttpStatusCode(); - if (statusCode == null && model.getMetadata().getProtocol() == Protocol.AWS_JSON) { + Protocol protocol = model.getMetadata().getProtocol(); + + if (statusCode == null + && (protocol == Protocol.AWS_JSON || protocol == Protocol.CBOR)) { if (shapeModel.isFault()) { statusCode = 500; } else { diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/ClientTestModels.java b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/ClientTestModels.java index 8dbac88e09b8..9ab222d3b51e 100644 --- a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/ClientTestModels.java +++ b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/ClientTestModels.java @@ -47,6 +47,19 @@ public static IntermediateModel awsJsonServiceModels() { return new IntermediateModelBuilder(models).build(); } + public static IntermediateModel cborServiceModels() { + File serviceModel = new File(ClientTestModels.class.getResource("client/c2j/json/service-2.json").getFile()); + File customizationModel = new File(ClientTestModels.class.getResource("client/c2j/cbor/customization.config").getFile()); + File paginatorsModel = new File(ClientTestModels.class.getResource("client/c2j/json/paginators.json").getFile()); + C2jModels models = C2jModels.builder() + .serviceModel(getServiceModel(serviceModel)) + .customizationConfig(getCustomizationConfig(customizationModel)) + .paginatorsModel(getPaginatorsModel(paginatorsModel)) + .build(); + + return new IntermediateModelBuilder(models).build(); + } + public static IntermediateModel awsQueryCompatibleJsonServiceModels() { File serviceModel = new File(ClientTestModels.class.getResource("client/c2j/query-to-json-errorcode/service-2.json").getFile()); File customizationModel = new File(ClientTestModels.class.getResource("client/c2j/query-to-json-errorcode/customization.config").getFile()); diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/client/AsyncClientClassTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/client/AsyncClientClassTest.java index 3d6922461423..3ba706e256e9 100644 --- a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/client/AsyncClientClassTest.java +++ b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/client/AsyncClientClassTest.java @@ -19,6 +19,7 @@ import static software.amazon.awssdk.codegen.poet.ClientTestModels.awsJsonServiceModels; import static software.amazon.awssdk.codegen.poet.ClientTestModels.awsQueryCompatibleJsonServiceModels; import static software.amazon.awssdk.codegen.poet.ClientTestModels.batchManagerModels; +import static software.amazon.awssdk.codegen.poet.ClientTestModels.cborServiceModels; import static software.amazon.awssdk.codegen.poet.ClientTestModels.customContentTypeModels; import static software.amazon.awssdk.codegen.poet.ClientTestModels.customPackageModels; import static software.amazon.awssdk.codegen.poet.ClientTestModels.endpointDiscoveryModels; @@ -61,6 +62,15 @@ public void asyncClientClassAwsJson() { assertThat(sraAsyncClientClass, generatesTo("sra/test-aws-json-async-client-class.java")); } + @Test + public void asyncClientClassCbor() { + AsyncClientClass asyncClientClass = createAsyncClientClass(cborServiceModels(), false); + assertThat(asyncClientClass, generatesTo("test-cbor-async-client-class.java")); + + AsyncClientClass sraAsyncClientClass = createAsyncClientClass(cborServiceModels(), true); + assertThat(sraAsyncClientClass, generatesTo("sra/test-cbor-async-client-class.java")); + } + @Test public void asyncClientClassAwsQueryCompatibleJson() { AsyncClientClass asyncClientClass = createAsyncClientClass(awsQueryCompatibleJsonServiceModels()); diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/client/SyncClientClassTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/client/SyncClientClassTest.java index 2da02c594bc2..cf7808587d95 100644 --- a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/client/SyncClientClassTest.java +++ b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/client/SyncClientClassTest.java @@ -17,6 +17,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import static software.amazon.awssdk.codegen.poet.ClientTestModels.awsQueryCompatibleJsonServiceModels; +import static software.amazon.awssdk.codegen.poet.ClientTestModels.cborServiceModels; import static software.amazon.awssdk.codegen.poet.ClientTestModels.customContentTypeModels; import static software.amazon.awssdk.codegen.poet.ClientTestModels.customPackageModels; import static software.amazon.awssdk.codegen.poet.ClientTestModels.endpointDiscoveryModels; @@ -89,6 +90,12 @@ public void syncClientClassRpcV2() { assertThat(syncClientCustomServiceMetaData, generatesTo("test-rpcv2-sync.java")); } + @Test + public void syncClientClassCbor() { + ClassSpec syncClientCustomServiceMetaData = createSyncClientClass(cborServiceModels(), true); + assertThat(syncClientCustomServiceMetaData, generatesTo("test-cbor-client-class.java")); + } + private SyncClientClass createSyncClientClass(IntermediateModel model) { return new SyncClientClass(GeneratorTaskParams.create(model, "sources/", "tests/", "resources/")); } diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/cbor/customization.config b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/cbor/customization.config new file mode 100644 index 000000000000..29eb1e7f6981 --- /dev/null +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/cbor/customization.config @@ -0,0 +1,28 @@ +{ + "authPolicyActions" : { + "skip" : true + }, + "presignersFqcn": "software.amazon.awssdk.services.acm.presign.AcmClientPresigners", + "serviceSpecificHttpConfig": "software.amazon.MyServiceHttpConfig", + "serviceConfig": { + "className": "ServiceConfiguration", + "hasDualstackProperty": true, + "hasFipsProperty": true + }, + "customRetryPolicy": "software.amazon.MyServiceRetryPolicy", + "customRetryStrategy": "software.amazon.MyServiceRetryStrategy", + "verifiedSimpleMethods" : ["paginatedOperationWithResultKey"], + "excludedSimpleMethods" : [ + "eventStreamOperation" + ], + "utilitiesMethod": { + "returnType": "software.amazon.awssdk.services.json.JsonUtilities", + "createMethodParams": ["param1", "param2", "param3"] + }, + "useLegacyEventGenerationScheme": { + "EventStream": ["EventOne", "event-two", "eventThree"] + }, + "customServiceMetadata": { + "protocol": "cbor" + } +} diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/sra/test-cbor-async-client-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/sra/test-cbor-async-client-class.java new file mode 100644 index 000000000000..cd713cf630a0 --- /dev/null +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/sra/test-cbor-async-client-class.java @@ -0,0 +1,1225 @@ +package software.amazon.awssdk.services.json; + +import static software.amazon.awssdk.utils.FunctionalUtils.runAndLogError; + +import java.nio.ByteBuffer; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executor; +import java.util.function.Consumer; +import org.reactivestreams.Publisher; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import software.amazon.awssdk.annotations.Generated; +import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.awscore.client.handler.AwsAsyncClientHandler; +import software.amazon.awssdk.awscore.client.handler.AwsClientHandlerUtils; +import software.amazon.awssdk.awscore.eventstream.EventStreamAsyncResponseTransformer; +import software.amazon.awssdk.awscore.eventstream.EventStreamTaggedUnionJsonMarshaller; +import software.amazon.awssdk.awscore.eventstream.EventStreamTaggedUnionPojoSupplier; +import software.amazon.awssdk.awscore.exception.AwsServiceException; +import software.amazon.awssdk.awscore.internal.AwsProtocolMetadata; +import software.amazon.awssdk.awscore.internal.AwsServiceProtocol; +import software.amazon.awssdk.awscore.retry.AwsRetryStrategy; +import software.amazon.awssdk.core.RequestOverrideConfiguration; +import software.amazon.awssdk.core.SdkPlugin; +import software.amazon.awssdk.core.SdkPojoBuilder; +import software.amazon.awssdk.core.SdkRequest; +import software.amazon.awssdk.core.SdkResponse; +import software.amazon.awssdk.core.async.AsyncRequestBody; +import software.amazon.awssdk.core.async.AsyncResponseTransformer; +import software.amazon.awssdk.core.async.AsyncResponseTransformerUtils; +import software.amazon.awssdk.core.async.SdkPublisher; +import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; +import software.amazon.awssdk.core.client.config.SdkAdvancedAsyncClientOption; +import software.amazon.awssdk.core.client.config.SdkClientConfiguration; +import software.amazon.awssdk.core.client.config.SdkClientOption; +import software.amazon.awssdk.core.client.handler.AsyncClientHandler; +import software.amazon.awssdk.core.client.handler.AttachHttpMetadataResponseHandler; +import software.amazon.awssdk.core.client.handler.ClientExecutionParams; +import software.amazon.awssdk.core.http.HttpResponseHandler; +import software.amazon.awssdk.core.interceptor.SdkInternalExecutionAttribute; +import software.amazon.awssdk.core.interceptor.trait.HttpChecksumRequired; +import software.amazon.awssdk.core.internal.interceptor.trait.RequestCompression; +import software.amazon.awssdk.core.metrics.CoreMetric; +import software.amazon.awssdk.core.protocol.VoidSdkResponse; +import software.amazon.awssdk.core.retry.RetryMode; +import software.amazon.awssdk.core.runtime.transform.AsyncStreamingRequestMarshaller; +import software.amazon.awssdk.metrics.MetricCollector; +import software.amazon.awssdk.metrics.MetricPublisher; +import software.amazon.awssdk.metrics.NoOpMetricCollector; +import software.amazon.awssdk.protocols.cbor.AwsCborProtocolFactory; +import software.amazon.awssdk.protocols.core.ExceptionMetadata; +import software.amazon.awssdk.protocols.json.AwsJsonProtocol; +import software.amazon.awssdk.protocols.json.AwsJsonProtocolFactory; +import software.amazon.awssdk.protocols.json.BaseAwsJsonProtocolFactory; +import software.amazon.awssdk.protocols.json.JsonOperationMetadata; +import software.amazon.awssdk.retries.api.RetryStrategy; +import software.amazon.awssdk.services.json.internal.JsonServiceClientConfigurationBuilder; +import software.amazon.awssdk.services.json.model.APostOperationRequest; +import software.amazon.awssdk.services.json.model.APostOperationResponse; +import software.amazon.awssdk.services.json.model.APostOperationWithOutputRequest; +import software.amazon.awssdk.services.json.model.APostOperationWithOutputResponse; +import software.amazon.awssdk.services.json.model.EventStream; +import software.amazon.awssdk.services.json.model.EventStreamOperationRequest; +import software.amazon.awssdk.services.json.model.EventStreamOperationResponse; +import software.amazon.awssdk.services.json.model.EventStreamOperationResponseHandler; +import software.amazon.awssdk.services.json.model.EventStreamOperationWithOnlyInputRequest; +import software.amazon.awssdk.services.json.model.EventStreamOperationWithOnlyInputResponse; +import software.amazon.awssdk.services.json.model.EventStreamOperationWithOnlyOutputRequest; +import software.amazon.awssdk.services.json.model.EventStreamOperationWithOnlyOutputResponse; +import software.amazon.awssdk.services.json.model.EventStreamOperationWithOnlyOutputResponseHandler; +import software.amazon.awssdk.services.json.model.GetWithoutRequiredMembersRequest; +import software.amazon.awssdk.services.json.model.GetWithoutRequiredMembersResponse; +import software.amazon.awssdk.services.json.model.InputEventStream; +import software.amazon.awssdk.services.json.model.InputEventStreamTwo; +import software.amazon.awssdk.services.json.model.InvalidInputException; +import software.amazon.awssdk.services.json.model.JsonException; +import software.amazon.awssdk.services.json.model.OperationWithChecksumRequiredRequest; +import software.amazon.awssdk.services.json.model.OperationWithChecksumRequiredResponse; +import software.amazon.awssdk.services.json.model.OperationWithNoneAuthTypeRequest; +import software.amazon.awssdk.services.json.model.OperationWithNoneAuthTypeResponse; +import software.amazon.awssdk.services.json.model.OperationWithRequestCompressionRequest; +import software.amazon.awssdk.services.json.model.OperationWithRequestCompressionResponse; +import software.amazon.awssdk.services.json.model.PaginatedOperationWithResultKeyRequest; +import software.amazon.awssdk.services.json.model.PaginatedOperationWithResultKeyResponse; +import software.amazon.awssdk.services.json.model.PaginatedOperationWithoutResultKeyRequest; +import software.amazon.awssdk.services.json.model.PaginatedOperationWithoutResultKeyResponse; +import software.amazon.awssdk.services.json.model.ServiceFaultException; +import software.amazon.awssdk.services.json.model.StreamingInputOperationRequest; +import software.amazon.awssdk.services.json.model.StreamingInputOperationResponse; +import software.amazon.awssdk.services.json.model.StreamingInputOutputOperationRequest; +import software.amazon.awssdk.services.json.model.StreamingInputOutputOperationResponse; +import software.amazon.awssdk.services.json.model.StreamingOutputOperationRequest; +import software.amazon.awssdk.services.json.model.StreamingOutputOperationResponse; +import software.amazon.awssdk.services.json.model.inputeventstream.DefaultInputEvent; +import software.amazon.awssdk.services.json.model.inputeventstreamtwo.DefaultInputEventOne; +import software.amazon.awssdk.services.json.model.inputeventstreamtwo.DefaultInputEventTwo; +import software.amazon.awssdk.services.json.transform.APostOperationRequestMarshaller; +import software.amazon.awssdk.services.json.transform.APostOperationWithOutputRequestMarshaller; +import software.amazon.awssdk.services.json.transform.EventStreamOperationRequestMarshaller; +import software.amazon.awssdk.services.json.transform.EventStreamOperationWithOnlyInputRequestMarshaller; +import software.amazon.awssdk.services.json.transform.EventStreamOperationWithOnlyOutputRequestMarshaller; +import software.amazon.awssdk.services.json.transform.GetWithoutRequiredMembersRequestMarshaller; +import software.amazon.awssdk.services.json.transform.InputEventMarshaller; +import software.amazon.awssdk.services.json.transform.InputEventTwoMarshaller; +import software.amazon.awssdk.services.json.transform.OperationWithChecksumRequiredRequestMarshaller; +import software.amazon.awssdk.services.json.transform.OperationWithNoneAuthTypeRequestMarshaller; +import software.amazon.awssdk.services.json.transform.OperationWithRequestCompressionRequestMarshaller; +import software.amazon.awssdk.services.json.transform.PaginatedOperationWithResultKeyRequestMarshaller; +import software.amazon.awssdk.services.json.transform.PaginatedOperationWithoutResultKeyRequestMarshaller; +import software.amazon.awssdk.services.json.transform.StreamingInputOperationRequestMarshaller; +import software.amazon.awssdk.services.json.transform.StreamingInputOutputOperationRequestMarshaller; +import software.amazon.awssdk.services.json.transform.StreamingOutputOperationRequestMarshaller; +import software.amazon.awssdk.utils.CompletableFutureUtils; +import software.amazon.awssdk.utils.HostnameValidator; +import software.amazon.awssdk.utils.Pair; + +/** + * Internal implementation of {@link JsonAsyncClient}. + * + * @see JsonAsyncClient#builder() + */ +@Generated("software.amazon.awssdk:codegen") +@SdkInternalApi +final class DefaultJsonAsyncClient implements JsonAsyncClient { + private static final Logger log = LoggerFactory.getLogger(DefaultJsonAsyncClient.class); + + private static final AwsProtocolMetadata protocolMetadata = AwsProtocolMetadata.builder() + .serviceProtocol(AwsServiceProtocol.CBOR).build(); + + private final AsyncClientHandler clientHandler; + + private final AwsCborProtocolFactory protocolFactory; + + private final SdkClientConfiguration clientConfiguration; + + private final AwsJsonProtocolFactory jsonProtocolFactory; + + private final Executor executor; + + protected DefaultJsonAsyncClient(SdkClientConfiguration clientConfiguration) { + this.clientHandler = new AwsAsyncClientHandler(clientConfiguration); + this.clientConfiguration = clientConfiguration.toBuilder().option(SdkClientOption.SDK_CLIENT, this).build(); + this.protocolFactory = init(AwsCborProtocolFactory.builder()).build(); + this.jsonProtocolFactory = init(AwsJsonProtocolFactory.builder()).build(); + this.executor = clientConfiguration.option(SdkAdvancedAsyncClientOption.FUTURE_COMPLETION_EXECUTOR); + } + + @Override + public JsonUtilities utilities() { + return JsonUtilities.create(param1, param2, param3); + } + + /** + *

+ * Performs a post operation to the query service and has no output + *

+ * + * @param aPostOperationRequest + * @return A Java Future containing the result of the APostOperation operation returned by the service.
+ * The CompletableFuture returned by this method can be completed exceptionally with the following + * exceptions. The exception returned is wrapped with CompletionException, so you need to invoke + * {@link Throwable#getCause} to retrieve the underlying exception. + * + * @sample JsonAsyncClient.APostOperation + * @see AWS + * API Documentation + */ + @Override + public CompletableFuture aPostOperation(APostOperationRequest aPostOperationRequest) { + SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(aPostOperationRequest, this.clientConfiguration); + List metricPublishers = resolveMetricPublishers(clientConfiguration, aPostOperationRequest + .overrideConfiguration().orElse(null)); + MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector + .create("ApiCall"); + try { + apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Json Service"); + apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "APostOperation"); + JsonOperationMetadata operationMetadata = JsonOperationMetadata.builder().hasStreamingSuccessResponse(false) + .isPayloadJson(true).build(); + + HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( + operationMetadata, APostOperationResponse::builder); + + HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, + operationMetadata); + String hostPrefix = "{StringMember}-foo."; + HostnameValidator.validateHostnameCompliant(aPostOperationRequest.stringMember(), "StringMember", + "aPostOperationRequest"); + String resolvedHostExpression = String.format("%s-foo.", aPostOperationRequest.stringMember()); + + CompletableFuture executeFuture = clientHandler + .execute(new ClientExecutionParams() + .withOperationName("APostOperation").withProtocolMetadata(protocolMetadata) + .withMarshaller(new APostOperationRequestMarshaller(protocolFactory)) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) + .hostPrefixExpression(resolvedHostExpression).withInput(aPostOperationRequest)); + CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { + metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + }); + executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); + return executeFuture; + } catch (Throwable t) { + metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + return CompletableFutureUtils.failedFuture(t); + } + } + + /** + *

+ * Performs a post operation to the query service and has modelled output + *

+ * + * @param aPostOperationWithOutputRequest + * @return A Java Future containing the result of the APostOperationWithOutput operation returned by the service.
+ * The CompletableFuture returned by this method can be completed exceptionally with the following + * exceptions. The exception returned is wrapped with CompletionException, so you need to invoke + * {@link Throwable#getCause} to retrieve the underlying exception. + *
    + *
  • InvalidInputException The request was rejected because an invalid or out-of-range value was supplied + * for an input parameter.
  • + *
  • ServiceFaultException
  • + *
  • SdkException Base class for all exceptions that can be thrown by the SDK (both service and client). + * Can be used for catch all scenarios.
  • + *
  • SdkClientException If any client side error occurs such as an IO related failure, failure to get + * credentials, etc.
  • + *
  • JsonException Base class for all service exceptions. Unknown exceptions will be thrown as an instance + * of this type.
  • + *
+ * @sample JsonAsyncClient.APostOperationWithOutput + * @see AWS API Documentation + */ + @Override + public CompletableFuture aPostOperationWithOutput( + APostOperationWithOutputRequest aPostOperationWithOutputRequest) { + SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(aPostOperationWithOutputRequest, + this.clientConfiguration); + List metricPublishers = resolveMetricPublishers(clientConfiguration, aPostOperationWithOutputRequest + .overrideConfiguration().orElse(null)); + MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector + .create("ApiCall"); + try { + apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Json Service"); + apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "APostOperationWithOutput"); + JsonOperationMetadata operationMetadata = JsonOperationMetadata.builder().hasStreamingSuccessResponse(false) + .isPayloadJson(true).build(); + + HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( + operationMetadata, APostOperationWithOutputResponse::builder); + + HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, + operationMetadata); + + CompletableFuture executeFuture = clientHandler + .execute(new ClientExecutionParams() + .withOperationName("APostOperationWithOutput").withProtocolMetadata(protocolMetadata) + .withMarshaller(new APostOperationWithOutputRequestMarshaller(protocolFactory)) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) + .withInput(aPostOperationWithOutputRequest)); + CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { + metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + }); + executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); + return executeFuture; + } catch (Throwable t) { + metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + return CompletableFutureUtils.failedFuture(t); + } + } + + /** + * Invokes the EventStreamOperation operation asynchronously. + * + * @param eventStreamOperationRequest + * @return A Java Future containing the result of the EventStreamOperation operation returned by the service.
+ * The CompletableFuture returned by this method can be completed exceptionally with the following + * exceptions. The exception returned is wrapped with CompletionException, so you need to invoke + * {@link Throwable#getCause} to retrieve the underlying exception. + *
    + *
  • SdkException Base class for all exceptions that can be thrown by the SDK (both service and client). + * Can be used for catch all scenarios.
  • + *
  • SdkClientException If any client side error occurs such as an IO related failure, failure to get + * credentials, etc.
  • + *
  • JsonException Base class for all service exceptions. Unknown exceptions will be thrown as an instance + * of this type.
  • + *
+ * @sample JsonAsyncClient.EventStreamOperation + * @see AWS API Documentation + */ + @Override + public CompletableFuture eventStreamOperation(EventStreamOperationRequest eventStreamOperationRequest, + Publisher requestStream, EventStreamOperationResponseHandler asyncResponseHandler) { + SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(eventStreamOperationRequest, + this.clientConfiguration); + List metricPublishers = resolveMetricPublishers(clientConfiguration, eventStreamOperationRequest + .overrideConfiguration().orElse(null)); + MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector + .create("ApiCall"); + try { + apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Json Service"); + apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "EventStreamOperation"); + JsonOperationMetadata operationMetadata = JsonOperationMetadata.builder().hasStreamingSuccessResponse(false) + .isPayloadJson(true).build(); + + HttpResponseHandler responseHandler = new AttachHttpMetadataResponseHandler( + protocolFactory.createResponseHandler(operationMetadata, EventStreamOperationResponse::builder)); + + HttpResponseHandler voidResponseHandler = protocolFactory.createResponseHandler(JsonOperationMetadata + .builder().isPayloadJson(false).hasStreamingSuccessResponse(true).build(), VoidSdkResponse::builder); + + HttpResponseHandler eventResponseHandler = protocolFactory.createResponseHandler( + JsonOperationMetadata.builder().isPayloadJson(true).hasStreamingSuccessResponse(false).build(), + EventStreamTaggedUnionPojoSupplier.builder().putSdkPojoSupplier("EventOne", EventStream::eventOneBuilder) + .putSdkPojoSupplier("EventTheSecond", EventStream::eventTheSecondBuilder) + .putSdkPojoSupplier("secondEventOne", EventStream::secondEventOneBuilder) + .putSdkPojoSupplier("eventThree", EventStream::eventThreeBuilder) + .defaultSdkPojoSupplier(() -> new SdkPojoBuilder(EventStream.UNKNOWN)).build()); + + HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, + operationMetadata); + EventStreamTaggedUnionJsonMarshaller eventMarshaller = EventStreamTaggedUnionJsonMarshaller.builder() + .putMarshaller(DefaultInputEvent.class, new InputEventMarshaller(protocolFactory)).build(); + SdkPublisher eventPublisher = SdkPublisher.adapt(requestStream); + Publisher adapted = eventPublisher.map(event -> eventMarshaller.marshall(event)).map( + AwsClientHandlerUtils::encodeEventStreamRequestToByteBuffer); + CompletableFuture future = new CompletableFuture<>(); + EventStreamAsyncResponseTransformer asyncResponseTransformer = EventStreamAsyncResponseTransformer + . builder().eventStreamResponseHandler(asyncResponseHandler) + .eventResponseHandler(eventResponseHandler).initialResponseHandler(responseHandler) + .exceptionResponseHandler(errorResponseHandler).future(future).executor(executor).serviceName(serviceName()) + .build(); + + CompletableFuture executeFuture = clientHandler.execute( + new ClientExecutionParams() + .withOperationName("EventStreamOperation").withProtocolMetadata(protocolMetadata) + .withMarshaller(new EventStreamOperationRequestMarshaller(protocolFactory)) + .withAsyncRequestBody(AsyncRequestBody.fromPublisher(adapted)).withFullDuplex(true) + .withInitialRequestEvent(true).withResponseHandler(voidResponseHandler) + .withErrorResponseHandler(errorResponseHandler).withRequestConfiguration(clientConfiguration) + .withMetricCollector(apiCallMetricCollector).withInput(eventStreamOperationRequest), + asyncResponseTransformer); + CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { + if (e != null) { + try { + asyncResponseHandler.exceptionOccurred(e); + } finally { + future.completeExceptionally(e); + } + } + metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + }); + executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); + return CompletableFutureUtils.forwardExceptionTo(future, executeFuture); + } catch (Throwable t) { + runAndLogError(log, "Exception thrown in exceptionOccurred callback, ignoring", + () -> asyncResponseHandler.exceptionOccurred(t)); + metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + return CompletableFutureUtils.failedFuture(t); + } + } + + /** + * Invokes the EventStreamOperationWithOnlyInput operation asynchronously. + * + * @param eventStreamOperationWithOnlyInputRequest + * @return A Java Future containing the result of the EventStreamOperationWithOnlyInput operation returned by the + * service.
+ * The CompletableFuture returned by this method can be completed exceptionally with the following + * exceptions. The exception returned is wrapped with CompletionException, so you need to invoke + * {@link Throwable#getCause} to retrieve the underlying exception. + *
    + *
  • SdkException Base class for all exceptions that can be thrown by the SDK (both service and client). + * Can be used for catch all scenarios.
  • + *
  • SdkClientException If any client side error occurs such as an IO related failure, failure to get + * credentials, etc.
  • + *
  • JsonException Base class for all service exceptions. Unknown exceptions will be thrown as an instance + * of this type.
  • + *
+ * @sample JsonAsyncClient.EventStreamOperationWithOnlyInput + * @see AWS API Documentation + */ + @Override + public CompletableFuture eventStreamOperationWithOnlyInput( + EventStreamOperationWithOnlyInputRequest eventStreamOperationWithOnlyInputRequest, + Publisher requestStream) { + SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(eventStreamOperationWithOnlyInputRequest, + this.clientConfiguration); + List metricPublishers = resolveMetricPublishers(clientConfiguration, + eventStreamOperationWithOnlyInputRequest.overrideConfiguration().orElse(null)); + MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector + .create("ApiCall"); + try { + apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Json Service"); + apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "EventStreamOperationWithOnlyInput"); + JsonOperationMetadata operationMetadata = JsonOperationMetadata.builder().hasStreamingSuccessResponse(false) + .isPayloadJson(true).build(); + + HttpResponseHandler responseHandler = protocolFactory + .createResponseHandler(operationMetadata, EventStreamOperationWithOnlyInputResponse::builder); + + HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, + operationMetadata); + EventStreamTaggedUnionJsonMarshaller eventMarshaller = EventStreamTaggedUnionJsonMarshaller.builder() + .putMarshaller(DefaultInputEventOne.class, new InputEventMarshaller(protocolFactory)) + .putMarshaller(DefaultInputEventTwo.class, new InputEventTwoMarshaller(protocolFactory)).build(); + SdkPublisher eventPublisher = SdkPublisher.adapt(requestStream); + Publisher adapted = eventPublisher.map(event -> eventMarshaller.marshall(event)).map( + AwsClientHandlerUtils::encodeEventStreamRequestToByteBuffer); + + CompletableFuture executeFuture = clientHandler + .execute(new ClientExecutionParams() + .withOperationName("EventStreamOperationWithOnlyInput").withProtocolMetadata(protocolMetadata) + .withMarshaller(new EventStreamOperationWithOnlyInputRequestMarshaller(protocolFactory)) + .withAsyncRequestBody(AsyncRequestBody.fromPublisher(adapted)).withInitialRequestEvent(true) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) + .withInput(eventStreamOperationWithOnlyInputRequest)); + CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { + metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + }); + executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); + return executeFuture; + } catch (Throwable t) { + metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + return CompletableFutureUtils.failedFuture(t); + } + } + + /** + * Invokes the EventStreamOperationWithOnlyOutput operation asynchronously. + * + * @param eventStreamOperationWithOnlyOutputRequest + * @return A Java Future containing the result of the EventStreamOperationWithOnlyOutput operation returned by the + * service.
+ * The CompletableFuture returned by this method can be completed exceptionally with the following + * exceptions. The exception returned is wrapped with CompletionException, so you need to invoke + * {@link Throwable#getCause} to retrieve the underlying exception. + *
    + *
  • SdkException Base class for all exceptions that can be thrown by the SDK (both service and client). + * Can be used for catch all scenarios.
  • + *
  • SdkClientException If any client side error occurs such as an IO related failure, failure to get + * credentials, etc.
  • + *
  • JsonException Base class for all service exceptions. Unknown exceptions will be thrown as an instance + * of this type.
  • + *
+ * @sample JsonAsyncClient.EventStreamOperationWithOnlyOutput + * @see AWS API Documentation + */ + @Override + public CompletableFuture eventStreamOperationWithOnlyOutput( + EventStreamOperationWithOnlyOutputRequest eventStreamOperationWithOnlyOutputRequest, + EventStreamOperationWithOnlyOutputResponseHandler asyncResponseHandler) { + SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(eventStreamOperationWithOnlyOutputRequest, + this.clientConfiguration); + List metricPublishers = resolveMetricPublishers(clientConfiguration, + eventStreamOperationWithOnlyOutputRequest.overrideConfiguration().orElse(null)); + MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector + .create("ApiCall"); + try { + apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Json Service"); + apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "EventStreamOperationWithOnlyOutput"); + JsonOperationMetadata operationMetadata = JsonOperationMetadata.builder().hasStreamingSuccessResponse(false) + .isPayloadJson(true).build(); + + HttpResponseHandler responseHandler = new AttachHttpMetadataResponseHandler( + protocolFactory.createResponseHandler(operationMetadata, EventStreamOperationWithOnlyOutputResponse::builder)); + + HttpResponseHandler voidResponseHandler = protocolFactory.createResponseHandler(JsonOperationMetadata + .builder().isPayloadJson(false).hasStreamingSuccessResponse(true).build(), VoidSdkResponse::builder); + + HttpResponseHandler eventResponseHandler = protocolFactory.createResponseHandler( + JsonOperationMetadata.builder().isPayloadJson(true).hasStreamingSuccessResponse(false).build(), + EventStreamTaggedUnionPojoSupplier.builder().putSdkPojoSupplier("EventOne", EventStream::eventOneBuilder) + .putSdkPojoSupplier("EventTheSecond", EventStream::eventTheSecondBuilder) + .putSdkPojoSupplier("secondEventOne", EventStream::secondEventOneBuilder) + .putSdkPojoSupplier("eventThree", EventStream::eventThreeBuilder) + .defaultSdkPojoSupplier(() -> new SdkPojoBuilder(EventStream.UNKNOWN)).build()); + + HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, + operationMetadata); + CompletableFuture future = new CompletableFuture<>(); + EventStreamAsyncResponseTransformer asyncResponseTransformer = EventStreamAsyncResponseTransformer + . builder() + .eventStreamResponseHandler(asyncResponseHandler).eventResponseHandler(eventResponseHandler) + .initialResponseHandler(responseHandler).exceptionResponseHandler(errorResponseHandler).future(future) + .executor(executor).serviceName(serviceName()).build(); + + CompletableFuture executeFuture = clientHandler.execute( + new ClientExecutionParams() + .withOperationName("EventStreamOperationWithOnlyOutput").withProtocolMetadata(protocolMetadata) + .withMarshaller(new EventStreamOperationWithOnlyOutputRequestMarshaller(protocolFactory)) + .withResponseHandler(voidResponseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) + .withInput(eventStreamOperationWithOnlyOutputRequest), asyncResponseTransformer); + CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { + if (e != null) { + try { + asyncResponseHandler.exceptionOccurred(e); + } finally { + future.completeExceptionally(e); + } + } + metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + }); + executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); + return CompletableFutureUtils.forwardExceptionTo(future, executeFuture); + } catch (Throwable t) { + runAndLogError(log, "Exception thrown in exceptionOccurred callback, ignoring", + () -> asyncResponseHandler.exceptionOccurred(t)); + metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + return CompletableFutureUtils.failedFuture(t); + } + } + + /** + *

+ * Performs a post operation to the query service and has no output + *

+ * + * @param getWithoutRequiredMembersRequest + * @return A Java Future containing the result of the GetWithoutRequiredMembers operation returned by the service.
+ * The CompletableFuture returned by this method can be completed exceptionally with the following + * exceptions. The exception returned is wrapped with CompletionException, so you need to invoke + * {@link Throwable#getCause} to retrieve the underlying exception. + *
    + *
  • InvalidInputException The request was rejected because an invalid or out-of-range value was supplied + * for an input parameter.
  • + *
  • SdkException Base class for all exceptions that can be thrown by the SDK (both service and client). + * Can be used for catch all scenarios.
  • + *
  • SdkClientException If any client side error occurs such as an IO related failure, failure to get + * credentials, etc.
  • + *
  • JsonException Base class for all service exceptions. Unknown exceptions will be thrown as an instance + * of this type.
  • + *
+ * @sample JsonAsyncClient.GetWithoutRequiredMembers + * @see AWS API Documentation + */ + @Override + public CompletableFuture getWithoutRequiredMembers( + GetWithoutRequiredMembersRequest getWithoutRequiredMembersRequest) { + SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(getWithoutRequiredMembersRequest, + this.clientConfiguration); + List metricPublishers = resolveMetricPublishers(clientConfiguration, getWithoutRequiredMembersRequest + .overrideConfiguration().orElse(null)); + MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector + .create("ApiCall"); + try { + apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Json Service"); + apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "GetWithoutRequiredMembers"); + JsonOperationMetadata operationMetadata = JsonOperationMetadata.builder().hasStreamingSuccessResponse(false) + .isPayloadJson(true).build(); + + HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( + operationMetadata, GetWithoutRequiredMembersResponse::builder); + + HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, + operationMetadata); + + CompletableFuture executeFuture = clientHandler + .execute(new ClientExecutionParams() + .withOperationName("GetWithoutRequiredMembers").withProtocolMetadata(protocolMetadata) + .withMarshaller(new GetWithoutRequiredMembersRequestMarshaller(protocolFactory)) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) + .withInput(getWithoutRequiredMembersRequest)); + CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { + metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + }); + executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); + return executeFuture; + } catch (Throwable t) { + metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + return CompletableFutureUtils.failedFuture(t); + } + } + + /** + * Invokes the OperationWithChecksumRequired operation asynchronously. + * + * @param operationWithChecksumRequiredRequest + * @return A Java Future containing the result of the OperationWithChecksumRequired operation returned by the + * service.
+ * The CompletableFuture returned by this method can be completed exceptionally with the following + * exceptions. The exception returned is wrapped with CompletionException, so you need to invoke + * {@link Throwable#getCause} to retrieve the underlying exception. + *
    + *
  • SdkException Base class for all exceptions that can be thrown by the SDK (both service and client). + * Can be used for catch all scenarios.
  • + *
  • SdkClientException If any client side error occurs such as an IO related failure, failure to get + * credentials, etc.
  • + *
  • JsonException Base class for all service exceptions. Unknown exceptions will be thrown as an instance + * of this type.
  • + *
+ * @sample JsonAsyncClient.OperationWithChecksumRequired + * @see AWS API Documentation + */ + @Override + public CompletableFuture operationWithChecksumRequired( + OperationWithChecksumRequiredRequest operationWithChecksumRequiredRequest) { + SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(operationWithChecksumRequiredRequest, + this.clientConfiguration); + List metricPublishers = resolveMetricPublishers(clientConfiguration, + operationWithChecksumRequiredRequest.overrideConfiguration().orElse(null)); + MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector + .create("ApiCall"); + try { + apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Json Service"); + apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "OperationWithChecksumRequired"); + JsonOperationMetadata operationMetadata = JsonOperationMetadata.builder().hasStreamingSuccessResponse(false) + .isPayloadJson(true).build(); + + HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( + operationMetadata, OperationWithChecksumRequiredResponse::builder); + + HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, + operationMetadata); + + CompletableFuture executeFuture = clientHandler + .execute(new ClientExecutionParams() + .withOperationName("OperationWithChecksumRequired") + .withProtocolMetadata(protocolMetadata) + .withMarshaller(new OperationWithChecksumRequiredRequestMarshaller(protocolFactory)) + .withResponseHandler(responseHandler) + .withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration) + .withMetricCollector(apiCallMetricCollector) + .putExecutionAttribute(SdkInternalExecutionAttribute.HTTP_CHECKSUM_REQUIRED, + HttpChecksumRequired.create()).withInput(operationWithChecksumRequiredRequest)); + CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { + metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + }); + executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); + return executeFuture; + } catch (Throwable t) { + metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + return CompletableFutureUtils.failedFuture(t); + } + } + + /** + * Invokes the OperationWithNoneAuthType operation asynchronously. + * + * @param operationWithNoneAuthTypeRequest + * @return A Java Future containing the result of the OperationWithNoneAuthType operation returned by the service.
+ * The CompletableFuture returned by this method can be completed exceptionally with the following + * exceptions. The exception returned is wrapped with CompletionException, so you need to invoke + * {@link Throwable#getCause} to retrieve the underlying exception. + *
    + *
  • SdkException Base class for all exceptions that can be thrown by the SDK (both service and client). + * Can be used for catch all scenarios.
  • + *
  • SdkClientException If any client side error occurs such as an IO related failure, failure to get + * credentials, etc.
  • + *
  • JsonException Base class for all service exceptions. Unknown exceptions will be thrown as an instance + * of this type.
  • + *
+ * @sample JsonAsyncClient.OperationWithNoneAuthType + * @see AWS API Documentation + */ + @Override + public CompletableFuture operationWithNoneAuthType( + OperationWithNoneAuthTypeRequest operationWithNoneAuthTypeRequest) { + SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(operationWithNoneAuthTypeRequest, + this.clientConfiguration); + List metricPublishers = resolveMetricPublishers(clientConfiguration, operationWithNoneAuthTypeRequest + .overrideConfiguration().orElse(null)); + MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector + .create("ApiCall"); + try { + apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Json Service"); + apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "OperationWithNoneAuthType"); + JsonOperationMetadata operationMetadata = JsonOperationMetadata.builder().hasStreamingSuccessResponse(false) + .isPayloadJson(true).build(); + + HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( + operationMetadata, OperationWithNoneAuthTypeResponse::builder); + + HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, + operationMetadata); + + CompletableFuture executeFuture = clientHandler + .execute(new ClientExecutionParams() + .withOperationName("OperationWithNoneAuthType").withProtocolMetadata(protocolMetadata) + .withMarshaller(new OperationWithNoneAuthTypeRequestMarshaller(protocolFactory)) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) + .withInput(operationWithNoneAuthTypeRequest)); + CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { + metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + }); + executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); + return executeFuture; + } catch (Throwable t) { + metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + return CompletableFutureUtils.failedFuture(t); + } + } + + /** + * Invokes the OperationWithRequestCompression operation asynchronously. + * + * @param operationWithRequestCompressionRequest + * @return A Java Future containing the result of the OperationWithRequestCompression operation returned by the + * service.
+ * The CompletableFuture returned by this method can be completed exceptionally with the following + * exceptions. The exception returned is wrapped with CompletionException, so you need to invoke + * {@link Throwable#getCause} to retrieve the underlying exception. + *
    + *
  • SdkException Base class for all exceptions that can be thrown by the SDK (both service and client). + * Can be used for catch all scenarios.
  • + *
  • SdkClientException If any client side error occurs such as an IO related failure, failure to get + * credentials, etc.
  • + *
  • JsonException Base class for all service exceptions. Unknown exceptions will be thrown as an instance + * of this type.
  • + *
+ * @sample JsonAsyncClient.OperationWithRequestCompression + * @see AWS API Documentation + */ + @Override + public CompletableFuture operationWithRequestCompression( + OperationWithRequestCompressionRequest operationWithRequestCompressionRequest) { + SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(operationWithRequestCompressionRequest, + this.clientConfiguration); + List metricPublishers = resolveMetricPublishers(clientConfiguration, + operationWithRequestCompressionRequest.overrideConfiguration().orElse(null)); + MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector + .create("ApiCall"); + try { + apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Json Service"); + apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "OperationWithRequestCompression"); + JsonOperationMetadata operationMetadata = JsonOperationMetadata.builder().hasStreamingSuccessResponse(false) + .isPayloadJson(true).build(); + + HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( + operationMetadata, OperationWithRequestCompressionResponse::builder); + + HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, + operationMetadata); + + CompletableFuture executeFuture = clientHandler + .execute(new ClientExecutionParams() + .withOperationName("OperationWithRequestCompression") + .withProtocolMetadata(protocolMetadata) + .withMarshaller(new OperationWithRequestCompressionRequestMarshaller(protocolFactory)) + .withResponseHandler(responseHandler) + .withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration) + .withMetricCollector(apiCallMetricCollector) + .putExecutionAttribute(SdkInternalExecutionAttribute.REQUEST_COMPRESSION, + RequestCompression.builder().encodings("gzip").isStreaming(false).build()) + .withInput(operationWithRequestCompressionRequest)); + CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { + metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + }); + executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); + return executeFuture; + } catch (Throwable t) { + metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + return CompletableFutureUtils.failedFuture(t); + } + } + + /** + * Some paginated operation with result_key in paginators.json file + * + * @param paginatedOperationWithResultKeyRequest + * @return A Java Future containing the result of the PaginatedOperationWithResultKey operation returned by the + * service.
+ * The CompletableFuture returned by this method can be completed exceptionally with the following + * exceptions. The exception returned is wrapped with CompletionException, so you need to invoke + * {@link Throwable#getCause} to retrieve the underlying exception. + *
    + *
  • SdkException Base class for all exceptions that can be thrown by the SDK (both service and client). + * Can be used for catch all scenarios.
  • + *
  • SdkClientException If any client side error occurs such as an IO related failure, failure to get + * credentials, etc.
  • + *
  • JsonException Base class for all service exceptions. Unknown exceptions will be thrown as an instance + * of this type.
  • + *
+ * @sample JsonAsyncClient.PaginatedOperationWithResultKey + * @see AWS API Documentation + */ + @Override + public CompletableFuture paginatedOperationWithResultKey( + PaginatedOperationWithResultKeyRequest paginatedOperationWithResultKeyRequest) { + SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(paginatedOperationWithResultKeyRequest, + this.clientConfiguration); + List metricPublishers = resolveMetricPublishers(clientConfiguration, + paginatedOperationWithResultKeyRequest.overrideConfiguration().orElse(null)); + MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector + .create("ApiCall"); + try { + apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Json Service"); + apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "PaginatedOperationWithResultKey"); + JsonOperationMetadata operationMetadata = JsonOperationMetadata.builder().hasStreamingSuccessResponse(false) + .isPayloadJson(true).build(); + + HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( + operationMetadata, PaginatedOperationWithResultKeyResponse::builder); + + HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, + operationMetadata); + + CompletableFuture executeFuture = clientHandler + .execute(new ClientExecutionParams() + .withOperationName("PaginatedOperationWithResultKey").withProtocolMetadata(protocolMetadata) + .withMarshaller(new PaginatedOperationWithResultKeyRequestMarshaller(protocolFactory)) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) + .withInput(paginatedOperationWithResultKeyRequest)); + CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { + metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + }); + executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); + return executeFuture; + } catch (Throwable t) { + metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + return CompletableFutureUtils.failedFuture(t); + } + } + + /** + * Some paginated operation without result_key in paginators.json file + * + * @param paginatedOperationWithoutResultKeyRequest + * @return A Java Future containing the result of the PaginatedOperationWithoutResultKey operation returned by the + * service.
+ * The CompletableFuture returned by this method can be completed exceptionally with the following + * exceptions. The exception returned is wrapped with CompletionException, so you need to invoke + * {@link Throwable#getCause} to retrieve the underlying exception. + *
    + *
  • SdkException Base class for all exceptions that can be thrown by the SDK (both service and client). + * Can be used for catch all scenarios.
  • + *
  • SdkClientException If any client side error occurs such as an IO related failure, failure to get + * credentials, etc.
  • + *
  • JsonException Base class for all service exceptions. Unknown exceptions will be thrown as an instance + * of this type.
  • + *
+ * @sample JsonAsyncClient.PaginatedOperationWithoutResultKey + * @see AWS API Documentation + */ + @Override + public CompletableFuture paginatedOperationWithoutResultKey( + PaginatedOperationWithoutResultKeyRequest paginatedOperationWithoutResultKeyRequest) { + SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(paginatedOperationWithoutResultKeyRequest, + this.clientConfiguration); + List metricPublishers = resolveMetricPublishers(clientConfiguration, + paginatedOperationWithoutResultKeyRequest.overrideConfiguration().orElse(null)); + MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector + .create("ApiCall"); + try { + apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Json Service"); + apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "PaginatedOperationWithoutResultKey"); + JsonOperationMetadata operationMetadata = JsonOperationMetadata.builder().hasStreamingSuccessResponse(false) + .isPayloadJson(true).build(); + + HttpResponseHandler responseHandler = protocolFactory + .createResponseHandler(operationMetadata, PaginatedOperationWithoutResultKeyResponse::builder); + + HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, + operationMetadata); + + CompletableFuture executeFuture = clientHandler + .execute(new ClientExecutionParams() + .withOperationName("PaginatedOperationWithoutResultKey").withProtocolMetadata(protocolMetadata) + .withMarshaller(new PaginatedOperationWithoutResultKeyRequestMarshaller(protocolFactory)) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) + .withInput(paginatedOperationWithoutResultKeyRequest)); + CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { + metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + }); + executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); + return executeFuture; + } catch (Throwable t) { + metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + return CompletableFutureUtils.failedFuture(t); + } + } + + /** + * Some operation with a streaming input + * + * @param streamingInputOperationRequest + * @param requestBody + * Functional interface that can be implemented to produce the request content in a non-blocking manner. The + * size of the content is expected to be known up front. See {@link AsyncRequestBody} for specific details on + * implementing this interface as well as links to precanned implementations for common scenarios like + * uploading from a file. The service documentation for the request content is as follows 'This be a stream' + * @return A Java Future containing the result of the StreamingInputOperation operation returned by the service.
+ * The CompletableFuture returned by this method can be completed exceptionally with the following + * exceptions. The exception returned is wrapped with CompletionException, so you need to invoke + * {@link Throwable#getCause} to retrieve the underlying exception. + *
    + *
  • SdkException Base class for all exceptions that can be thrown by the SDK (both service and client). + * Can be used for catch all scenarios.
  • + *
  • SdkClientException If any client side error occurs such as an IO related failure, failure to get + * credentials, etc.
  • + *
  • JsonException Base class for all service exceptions. Unknown exceptions will be thrown as an instance + * of this type.
  • + *
+ * @sample JsonAsyncClient.StreamingInputOperation + * @see AWS API Documentation + */ + @Override + public CompletableFuture streamingInputOperation( + StreamingInputOperationRequest streamingInputOperationRequest, AsyncRequestBody requestBody) { + SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(streamingInputOperationRequest, + this.clientConfiguration); + List metricPublishers = resolveMetricPublishers(clientConfiguration, streamingInputOperationRequest + .overrideConfiguration().orElse(null)); + MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector + .create("ApiCall"); + try { + apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Json Service"); + apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "StreamingInputOperation"); + JsonOperationMetadata operationMetadata = JsonOperationMetadata.builder().hasStreamingSuccessResponse(false) + .isPayloadJson(true).build(); + + HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( + operationMetadata, StreamingInputOperationResponse::builder); + + HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, + operationMetadata); + + CompletableFuture executeFuture = clientHandler + .execute(new ClientExecutionParams() + .withOperationName("StreamingInputOperation") + .withProtocolMetadata(protocolMetadata) + .withMarshaller( + AsyncStreamingRequestMarshaller.builder() + .delegateMarshaller(new StreamingInputOperationRequestMarshaller(protocolFactory)) + .asyncRequestBody(requestBody).build()).withResponseHandler(responseHandler) + .withErrorResponseHandler(errorResponseHandler).withRequestConfiguration(clientConfiguration) + .withMetricCollector(apiCallMetricCollector).withAsyncRequestBody(requestBody) + .withInput(streamingInputOperationRequest)); + CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { + metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + }); + executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); + return executeFuture; + } catch (Throwable t) { + metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + return CompletableFutureUtils.failedFuture(t); + } + } + + /** + * Some operation with streaming input and streaming output + * + * @param streamingInputOutputOperationRequest + * @param requestBody + * Functional interface that can be implemented to produce the request content in a non-blocking manner. The + * size of the content is expected to be known up front. See {@link AsyncRequestBody} for specific details on + * implementing this interface as well as links to precanned implementations for common scenarios like + * uploading from a file. The service documentation for the request content is as follows 'This be a stream' + * @param asyncResponseTransformer + * The response transformer for processing the streaming response in a non-blocking manner. See + * {@link AsyncResponseTransformer} for details on how this callback should be implemented and for links to + * precanned implementations for common scenarios like downloading to a file. The service documentation for + * the response content is as follows 'This be a stream'. + * @return A future to the transformed result of the AsyncResponseTransformer.
+ * The CompletableFuture returned by this method can be completed exceptionally with the following + * exceptions. The exception returned is wrapped with CompletionException, so you need to invoke + * {@link Throwable#getCause} to retrieve the underlying exception. + *
    + *
  • SdkException Base class for all exceptions that can be thrown by the SDK (both service and client). + * Can be used for catch all scenarios.
  • + *
  • SdkClientException If any client side error occurs such as an IO related failure, failure to get + * credentials, etc.
  • + *
  • JsonException Base class for all service exceptions. Unknown exceptions will be thrown as an instance + * of this type.
  • + *
+ * @sample JsonAsyncClient.StreamingInputOutputOperation + * @see AWS API Documentation + */ + @Override + public CompletableFuture streamingInputOutputOperation( + StreamingInputOutputOperationRequest streamingInputOutputOperationRequest, AsyncRequestBody requestBody, + AsyncResponseTransformer asyncResponseTransformer) { + SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(streamingInputOutputOperationRequest, + this.clientConfiguration); + List metricPublishers = resolveMetricPublishers(clientConfiguration, + streamingInputOutputOperationRequest.overrideConfiguration().orElse(null)); + MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector + .create("ApiCall"); + try { + apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Json Service"); + apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "StreamingInputOutputOperation"); + Pair, CompletableFuture> pair = AsyncResponseTransformerUtils + .wrapWithEndOfStreamFuture(asyncResponseTransformer); + asyncResponseTransformer = pair.left(); + CompletableFuture endOfStreamFuture = pair.right(); + JsonOperationMetadata operationMetadata = JsonOperationMetadata.builder().hasStreamingSuccessResponse(true) + .isPayloadJson(false).build(); + + HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( + operationMetadata, StreamingInputOutputOperationResponse::builder); + + HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, + operationMetadata); + + CompletableFuture executeFuture = clientHandler.execute( + new ClientExecutionParams() + .withOperationName("StreamingInputOutputOperation") + .withProtocolMetadata(protocolMetadata) + .withMarshaller( + AsyncStreamingRequestMarshaller + .builder() + .delegateMarshaller( + new StreamingInputOutputOperationRequestMarshaller(protocolFactory)) + .asyncRequestBody(requestBody).transferEncoding(true).build()) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) + .withAsyncRequestBody(requestBody).withInput(streamingInputOutputOperationRequest), + asyncResponseTransformer); + AsyncResponseTransformer finalAsyncResponseTransformer = asyncResponseTransformer; + CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { + if (e != null) { + runAndLogError(log, "Exception thrown in exceptionOccurred callback, ignoring", + () -> finalAsyncResponseTransformer.exceptionOccurred(e)); + } + endOfStreamFuture.whenComplete((r2, e2) -> { + metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + }); + }); + executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); + return executeFuture; + } catch (Throwable t) { + AsyncResponseTransformer finalAsyncResponseTransformer = asyncResponseTransformer; + runAndLogError(log, "Exception thrown in exceptionOccurred callback, ignoring", + () -> finalAsyncResponseTransformer.exceptionOccurred(t)); + metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + return CompletableFutureUtils.failedFuture(t); + } + } + + /** + * Some operation with a streaming output + * + * @param streamingOutputOperationRequest + * @param asyncResponseTransformer + * The response transformer for processing the streaming response in a non-blocking manner. See + * {@link AsyncResponseTransformer} for details on how this callback should be implemented and for links to + * precanned implementations for common scenarios like downloading to a file. The service documentation for + * the response content is as follows 'This be a stream'. + * @return A future to the transformed result of the AsyncResponseTransformer.
+ * The CompletableFuture returned by this method can be completed exceptionally with the following + * exceptions. The exception returned is wrapped with CompletionException, so you need to invoke + * {@link Throwable#getCause} to retrieve the underlying exception. + *
    + *
  • SdkException Base class for all exceptions that can be thrown by the SDK (both service and client). + * Can be used for catch all scenarios.
  • + *
  • SdkClientException If any client side error occurs such as an IO related failure, failure to get + * credentials, etc.
  • + *
  • JsonException Base class for all service exceptions. Unknown exceptions will be thrown as an instance + * of this type.
  • + *
+ * @sample JsonAsyncClient.StreamingOutputOperation + * @see AWS API Documentation + */ + @Override + public CompletableFuture streamingOutputOperation( + StreamingOutputOperationRequest streamingOutputOperationRequest, + AsyncResponseTransformer asyncResponseTransformer) { + SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(streamingOutputOperationRequest, + this.clientConfiguration); + List metricPublishers = resolveMetricPublishers(clientConfiguration, streamingOutputOperationRequest + .overrideConfiguration().orElse(null)); + MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector + .create("ApiCall"); + try { + apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Json Service"); + apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "StreamingOutputOperation"); + Pair, CompletableFuture> pair = AsyncResponseTransformerUtils + .wrapWithEndOfStreamFuture(asyncResponseTransformer); + asyncResponseTransformer = pair.left(); + CompletableFuture endOfStreamFuture = pair.right(); + JsonOperationMetadata operationMetadata = JsonOperationMetadata.builder().hasStreamingSuccessResponse(true) + .isPayloadJson(false).build(); + + HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( + operationMetadata, StreamingOutputOperationResponse::builder); + + HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, + operationMetadata); + + CompletableFuture executeFuture = clientHandler.execute( + new ClientExecutionParams() + .withOperationName("StreamingOutputOperation").withProtocolMetadata(protocolMetadata) + .withMarshaller(new StreamingOutputOperationRequestMarshaller(protocolFactory)) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) + .withInput(streamingOutputOperationRequest), asyncResponseTransformer); + AsyncResponseTransformer finalAsyncResponseTransformer = asyncResponseTransformer; + CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { + if (e != null) { + runAndLogError(log, "Exception thrown in exceptionOccurred callback, ignoring", + () -> finalAsyncResponseTransformer.exceptionOccurred(e)); + } + endOfStreamFuture.whenComplete((r2, e2) -> { + metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + }); + }); + executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); + return executeFuture; + } catch (Throwable t) { + AsyncResponseTransformer finalAsyncResponseTransformer = asyncResponseTransformer; + runAndLogError(log, "Exception thrown in exceptionOccurred callback, ignoring", + () -> finalAsyncResponseTransformer.exceptionOccurred(t)); + metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + return CompletableFutureUtils.failedFuture(t); + } + } + + @Override + public final JsonServiceClientConfiguration serviceClientConfiguration() { + return new JsonServiceClientConfigurationBuilder(this.clientConfiguration.toBuilder()).build(); + } + + @Override + public final String serviceName() { + return SERVICE_NAME; + } + + private > T init(T builder) { + return builder + .clientConfiguration(clientConfiguration) + .defaultServiceExceptionSupplier(JsonException::builder) + .protocol(AwsJsonProtocol.AWS_JSON) + .protocolVersion("1.1") + .registerModeledException( + ExceptionMetadata.builder().errorCode("InvalidInputException") + .exceptionBuilderSupplier(InvalidInputException::builder).httpStatusCode(400).build()) + .registerModeledException( + ExceptionMetadata.builder().errorCode("ServiceFaultException") + .exceptionBuilderSupplier(ServiceFaultException::builder).httpStatusCode(500).build()); + } + + private static List resolveMetricPublishers(SdkClientConfiguration clientConfiguration, + RequestOverrideConfiguration requestOverrideConfiguration) { + List publishers = null; + if (requestOverrideConfiguration != null) { + publishers = requestOverrideConfiguration.metricPublishers(); + } + if (publishers == null || publishers.isEmpty()) { + publishers = clientConfiguration.option(SdkClientOption.METRIC_PUBLISHERS); + } + if (publishers == null) { + publishers = Collections.emptyList(); + } + return publishers; + } + + private void updateRetryStrategyClientConfiguration(SdkClientConfiguration.Builder configuration) { + ClientOverrideConfiguration.Builder builder = configuration.asOverrideConfigurationBuilder(); + RetryMode retryMode = builder.retryMode(); + if (retryMode != null) { + configuration.option(SdkClientOption.RETRY_STRATEGY, AwsRetryStrategy.forRetryMode(retryMode)); + } else { + Consumer> configurator = builder.retryStrategyConfigurator(); + if (configurator != null) { + RetryStrategy.Builder defaultBuilder = AwsRetryStrategy.defaultRetryStrategy().toBuilder(); + configurator.accept(defaultBuilder); + configuration.option(SdkClientOption.RETRY_STRATEGY, defaultBuilder.build()); + } else { + RetryStrategy retryStrategy = builder.retryStrategy(); + if (retryStrategy != null) { + configuration.option(SdkClientOption.RETRY_STRATEGY, retryStrategy); + } + } + } + configuration.option(SdkClientOption.CONFIGURED_RETRY_MODE, null); + configuration.option(SdkClientOption.CONFIGURED_RETRY_STRATEGY, null); + configuration.option(SdkClientOption.CONFIGURED_RETRY_CONFIGURATOR, null); + } + + private SdkClientConfiguration updateSdkClientConfiguration(SdkRequest request, SdkClientConfiguration clientConfiguration) { + List plugins = request.overrideConfiguration().map(c -> c.plugins()).orElse(Collections.emptyList()); + SdkClientConfiguration.Builder configuration = clientConfiguration.toBuilder(); + if (plugins.isEmpty()) { + return configuration.build(); + } + JsonServiceClientConfigurationBuilder serviceConfigBuilder = new JsonServiceClientConfigurationBuilder(configuration); + for (SdkPlugin plugin : plugins) { + plugin.configureClient(serviceConfigBuilder); + } + updateRetryStrategyClientConfiguration(configuration); + return configuration.build(); + } + + private HttpResponseHandler createErrorResponseHandler(BaseAwsJsonProtocolFactory protocolFactory, + JsonOperationMetadata operationMetadata) { + return protocolFactory.createErrorResponseHandler(operationMetadata); + } + + @Override + public void close() { + clientHandler.close(); + } +} diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-cbor-async-client-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-cbor-async-client-class.java new file mode 100644 index 000000000000..6a873ece1377 --- /dev/null +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-cbor-async-client-class.java @@ -0,0 +1,1255 @@ +package software.amazon.awssdk.services.json; + +import static software.amazon.awssdk.utils.FunctionalUtils.runAndLogError; + +import java.nio.ByteBuffer; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executor; +import java.util.function.Consumer; +import org.reactivestreams.Publisher; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import software.amazon.awssdk.annotations.Generated; +import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.auth.signer.AsyncAws4Signer; +import software.amazon.awssdk.auth.signer.Aws4UnsignedPayloadSigner; +import software.amazon.awssdk.auth.signer.EventStreamAws4Signer; +import software.amazon.awssdk.awscore.AwsRequestOverrideConfiguration; +import software.amazon.awssdk.awscore.client.handler.AwsAsyncClientHandler; +import software.amazon.awssdk.awscore.client.handler.AwsClientHandlerUtils; +import software.amazon.awssdk.awscore.eventstream.EventStreamAsyncResponseTransformer; +import software.amazon.awssdk.awscore.eventstream.EventStreamTaggedUnionJsonMarshaller; +import software.amazon.awssdk.awscore.eventstream.EventStreamTaggedUnionPojoSupplier; +import software.amazon.awssdk.awscore.exception.AwsServiceException; +import software.amazon.awssdk.awscore.internal.AwsProtocolMetadata; +import software.amazon.awssdk.awscore.internal.AwsServiceProtocol; +import software.amazon.awssdk.awscore.retry.AwsRetryStrategy; +import software.amazon.awssdk.core.RequestOverrideConfiguration; +import software.amazon.awssdk.core.SdkPlugin; +import software.amazon.awssdk.core.SdkPojoBuilder; +import software.amazon.awssdk.core.SdkRequest; +import software.amazon.awssdk.core.SdkResponse; +import software.amazon.awssdk.core.async.AsyncRequestBody; +import software.amazon.awssdk.core.async.AsyncResponseTransformer; +import software.amazon.awssdk.core.async.AsyncResponseTransformerUtils; +import software.amazon.awssdk.core.async.SdkPublisher; +import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; +import software.amazon.awssdk.core.client.config.SdkAdvancedAsyncClientOption; +import software.amazon.awssdk.core.client.config.SdkClientConfiguration; +import software.amazon.awssdk.core.client.config.SdkClientOption; +import software.amazon.awssdk.core.client.handler.AsyncClientHandler; +import software.amazon.awssdk.core.client.handler.AttachHttpMetadataResponseHandler; +import software.amazon.awssdk.core.client.handler.ClientExecutionParams; +import software.amazon.awssdk.core.http.HttpResponseHandler; +import software.amazon.awssdk.core.interceptor.SdkInternalExecutionAttribute; +import software.amazon.awssdk.core.interceptor.trait.HttpChecksumRequired; +import software.amazon.awssdk.core.internal.interceptor.trait.RequestCompression; +import software.amazon.awssdk.core.metrics.CoreMetric; +import software.amazon.awssdk.core.protocol.VoidSdkResponse; +import software.amazon.awssdk.core.retry.RetryMode; +import software.amazon.awssdk.core.runtime.transform.AsyncStreamingRequestMarshaller; +import software.amazon.awssdk.core.signer.Signer; +import software.amazon.awssdk.metrics.MetricCollector; +import software.amazon.awssdk.metrics.MetricPublisher; +import software.amazon.awssdk.metrics.NoOpMetricCollector; +import software.amazon.awssdk.protocols.cbor.AwsCborProtocolFactory; +import software.amazon.awssdk.protocols.core.ExceptionMetadata; +import software.amazon.awssdk.protocols.json.AwsJsonProtocol; +import software.amazon.awssdk.protocols.json.AwsJsonProtocolFactory; +import software.amazon.awssdk.protocols.json.BaseAwsJsonProtocolFactory; +import software.amazon.awssdk.protocols.json.JsonOperationMetadata; +import software.amazon.awssdk.retries.api.RetryStrategy; +import software.amazon.awssdk.services.json.internal.JsonServiceClientConfigurationBuilder; +import software.amazon.awssdk.services.json.model.APostOperationRequest; +import software.amazon.awssdk.services.json.model.APostOperationResponse; +import software.amazon.awssdk.services.json.model.APostOperationWithOutputRequest; +import software.amazon.awssdk.services.json.model.APostOperationWithOutputResponse; +import software.amazon.awssdk.services.json.model.EventStream; +import software.amazon.awssdk.services.json.model.EventStreamOperationRequest; +import software.amazon.awssdk.services.json.model.EventStreamOperationResponse; +import software.amazon.awssdk.services.json.model.EventStreamOperationResponseHandler; +import software.amazon.awssdk.services.json.model.EventStreamOperationWithOnlyInputRequest; +import software.amazon.awssdk.services.json.model.EventStreamOperationWithOnlyInputResponse; +import software.amazon.awssdk.services.json.model.EventStreamOperationWithOnlyOutputRequest; +import software.amazon.awssdk.services.json.model.EventStreamOperationWithOnlyOutputResponse; +import software.amazon.awssdk.services.json.model.EventStreamOperationWithOnlyOutputResponseHandler; +import software.amazon.awssdk.services.json.model.GetWithoutRequiredMembersRequest; +import software.amazon.awssdk.services.json.model.GetWithoutRequiredMembersResponse; +import software.amazon.awssdk.services.json.model.InputEventStream; +import software.amazon.awssdk.services.json.model.InputEventStreamTwo; +import software.amazon.awssdk.services.json.model.InvalidInputException; +import software.amazon.awssdk.services.json.model.JsonException; +import software.amazon.awssdk.services.json.model.JsonRequest; +import software.amazon.awssdk.services.json.model.OperationWithChecksumRequiredRequest; +import software.amazon.awssdk.services.json.model.OperationWithChecksumRequiredResponse; +import software.amazon.awssdk.services.json.model.OperationWithNoneAuthTypeRequest; +import software.amazon.awssdk.services.json.model.OperationWithNoneAuthTypeResponse; +import software.amazon.awssdk.services.json.model.OperationWithRequestCompressionRequest; +import software.amazon.awssdk.services.json.model.OperationWithRequestCompressionResponse; +import software.amazon.awssdk.services.json.model.PaginatedOperationWithResultKeyRequest; +import software.amazon.awssdk.services.json.model.PaginatedOperationWithResultKeyResponse; +import software.amazon.awssdk.services.json.model.PaginatedOperationWithoutResultKeyRequest; +import software.amazon.awssdk.services.json.model.PaginatedOperationWithoutResultKeyResponse; +import software.amazon.awssdk.services.json.model.ServiceFaultException; +import software.amazon.awssdk.services.json.model.StreamingInputOperationRequest; +import software.amazon.awssdk.services.json.model.StreamingInputOperationResponse; +import software.amazon.awssdk.services.json.model.StreamingInputOutputOperationRequest; +import software.amazon.awssdk.services.json.model.StreamingInputOutputOperationResponse; +import software.amazon.awssdk.services.json.model.StreamingOutputOperationRequest; +import software.amazon.awssdk.services.json.model.StreamingOutputOperationResponse; +import software.amazon.awssdk.services.json.model.inputeventstream.DefaultInputEvent; +import software.amazon.awssdk.services.json.model.inputeventstreamtwo.DefaultInputEventOne; +import software.amazon.awssdk.services.json.model.inputeventstreamtwo.DefaultInputEventTwo; +import software.amazon.awssdk.services.json.transform.APostOperationRequestMarshaller; +import software.amazon.awssdk.services.json.transform.APostOperationWithOutputRequestMarshaller; +import software.amazon.awssdk.services.json.transform.EventStreamOperationRequestMarshaller; +import software.amazon.awssdk.services.json.transform.EventStreamOperationWithOnlyInputRequestMarshaller; +import software.amazon.awssdk.services.json.transform.EventStreamOperationWithOnlyOutputRequestMarshaller; +import software.amazon.awssdk.services.json.transform.GetWithoutRequiredMembersRequestMarshaller; +import software.amazon.awssdk.services.json.transform.InputEventMarshaller; +import software.amazon.awssdk.services.json.transform.InputEventTwoMarshaller; +import software.amazon.awssdk.services.json.transform.OperationWithChecksumRequiredRequestMarshaller; +import software.amazon.awssdk.services.json.transform.OperationWithNoneAuthTypeRequestMarshaller; +import software.amazon.awssdk.services.json.transform.OperationWithRequestCompressionRequestMarshaller; +import software.amazon.awssdk.services.json.transform.PaginatedOperationWithResultKeyRequestMarshaller; +import software.amazon.awssdk.services.json.transform.PaginatedOperationWithoutResultKeyRequestMarshaller; +import software.amazon.awssdk.services.json.transform.StreamingInputOperationRequestMarshaller; +import software.amazon.awssdk.services.json.transform.StreamingInputOutputOperationRequestMarshaller; +import software.amazon.awssdk.services.json.transform.StreamingOutputOperationRequestMarshaller; +import software.amazon.awssdk.utils.CompletableFutureUtils; +import software.amazon.awssdk.utils.HostnameValidator; +import software.amazon.awssdk.utils.Pair; + +/** + * Internal implementation of {@link JsonAsyncClient}. + * + * @see JsonAsyncClient#builder() + */ +@Generated("software.amazon.awssdk:codegen") +@SdkInternalApi +final class DefaultJsonAsyncClient implements JsonAsyncClient { + private static final Logger log = LoggerFactory.getLogger(DefaultJsonAsyncClient.class); + + private static final AwsProtocolMetadata protocolMetadata = AwsProtocolMetadata.builder() + .serviceProtocol(AwsServiceProtocol.CBOR).build(); + + private final AsyncClientHandler clientHandler; + + private final AwsCborProtocolFactory protocolFactory; + + private final SdkClientConfiguration clientConfiguration; + + private final AwsJsonProtocolFactory jsonProtocolFactory; + + private final Executor executor; + + protected DefaultJsonAsyncClient(SdkClientConfiguration clientConfiguration) { + this.clientHandler = new AwsAsyncClientHandler(clientConfiguration); + this.clientConfiguration = clientConfiguration.toBuilder().option(SdkClientOption.SDK_CLIENT, this).build(); + this.protocolFactory = init(AwsCborProtocolFactory.builder()).build(); + this.jsonProtocolFactory = init(AwsJsonProtocolFactory.builder()).build(); + this.executor = clientConfiguration.option(SdkAdvancedAsyncClientOption.FUTURE_COMPLETION_EXECUTOR); + } + + @Override + public JsonUtilities utilities() { + return JsonUtilities.create(param1, param2, param3); + } + + /** + *

+ * Performs a post operation to the query service and has no output + *

+ * + * @param aPostOperationRequest + * @return A Java Future containing the result of the APostOperation operation returned by the service.
+ * The CompletableFuture returned by this method can be completed exceptionally with the following + * exceptions. The exception returned is wrapped with CompletionException, so you need to invoke + * {@link Throwable#getCause} to retrieve the underlying exception. + *
    + *
  • InvalidInputException The request was rejected because an invalid or out-of-range value was supplied + * for an input parameter.
  • + *
  • SdkException Base class for all exceptions that can be thrown by the SDK (both service and client). + * Can be used for catch all scenarios.
  • + *
  • SdkClientException If any client side error occurs such as an IO related failure, failure to get + * credentials, etc.
  • + *
  • JsonException Base class for all service exceptions. Unknown exceptions will be thrown as an instance + * of this type.
  • + *
+ * @sample JsonAsyncClient.APostOperation + * @see AWS + * API Documentation + */ + @Override + public CompletableFuture aPostOperation(APostOperationRequest aPostOperationRequest) { + SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(aPostOperationRequest, this.clientConfiguration); + List metricPublishers = resolveMetricPublishers(clientConfiguration, aPostOperationRequest + .overrideConfiguration().orElse(null)); + MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector + .create("ApiCall"); + try { + apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Json Service"); + apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "APostOperation"); + JsonOperationMetadata operationMetadata = JsonOperationMetadata.builder().hasStreamingSuccessResponse(false) + .isPayloadJson(true).build(); + + HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( + operationMetadata, APostOperationResponse::builder); + + HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, + operationMetadata); + String hostPrefix = "{StringMember}-foo."; + HostnameValidator.validateHostnameCompliant(aPostOperationRequest.stringMember(), "StringMember", + "aPostOperationRequest"); + String resolvedHostExpression = String.format("%s-foo.", aPostOperationRequest.stringMember()); + + CompletableFuture executeFuture = clientHandler + .execute(new ClientExecutionParams() + .withOperationName("APostOperation").withProtocolMetadata(protocolMetadata) + .withMarshaller(new APostOperationRequestMarshaller(protocolFactory)) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) + .hostPrefixExpression(resolvedHostExpression).withInput(aPostOperationRequest)); + CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { + metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + }); + executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); + return executeFuture; + } catch (Throwable t) { + metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + return CompletableFutureUtils.failedFuture(t); + } + } + + /** + *

+ * Performs a post operation to the query service and has modelled output + *

+ * + * @param aPostOperationWithOutputRequest + * @return A Java Future containing the result of the APostOperationWithOutput operation returned by the service.
+ * The CompletableFuture returned by this method can be completed exceptionally with the following + * exceptions. The exception returned is wrapped with CompletionException, so you need to invoke + * {@link Throwable#getCause} to retrieve the underlying exception. + *
    + *
  • InvalidInputException The request was rejected because an invalid or out-of-range value was supplied + * for an input parameter.
  • + *
  • ServiceFaultException
  • + *
  • SdkException Base class for all exceptions that can be thrown by the SDK (both service and client). + * Can be used for catch all scenarios.
  • + *
  • SdkClientException If any client side error occurs such as an IO related failure, failure to get + * credentials, etc.
  • + *
  • JsonException Base class for all service exceptions. Unknown exceptions will be thrown as an instance + * of this type.
  • + *
+ * @sample JsonAsyncClient.APostOperationWithOutput + * @see AWS API Documentation + */ + @Override + public CompletableFuture aPostOperationWithOutput( + APostOperationWithOutputRequest aPostOperationWithOutputRequest) { + SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(aPostOperationWithOutputRequest, + this.clientConfiguration); + List metricPublishers = resolveMetricPublishers(clientConfiguration, aPostOperationWithOutputRequest + .overrideConfiguration().orElse(null)); + MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector + .create("ApiCall"); + try { + apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Json Service"); + apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "APostOperationWithOutput"); + JsonOperationMetadata operationMetadata = JsonOperationMetadata.builder().hasStreamingSuccessResponse(false) + .isPayloadJson(true).build(); + + HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( + operationMetadata, APostOperationWithOutputResponse::builder); + + HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, + operationMetadata); + + CompletableFuture executeFuture = clientHandler + .execute(new ClientExecutionParams() + .withOperationName("APostOperationWithOutput").withProtocolMetadata(protocolMetadata) + .withMarshaller(new APostOperationWithOutputRequestMarshaller(protocolFactory)) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) + .withInput(aPostOperationWithOutputRequest)); + CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { + metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + }); + executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); + return executeFuture; + } catch (Throwable t) { + metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + return CompletableFutureUtils.failedFuture(t); + } + } + + /** + * Invokes the EventStreamOperation operation asynchronously. + * + * @param eventStreamOperationRequest + * @return A Java Future containing the result of the EventStreamOperation operation returned by the service.
+ * The CompletableFuture returned by this method can be completed exceptionally with the following + * exceptions. The exception returned is wrapped with CompletionException, so you need to invoke + * {@link Throwable#getCause} to retrieve the underlying exception. + *
    + *
  • SdkException Base class for all exceptions that can be thrown by the SDK (both service and client). + * Can be used for catch all scenarios.
  • + *
  • SdkClientException If any client side error occurs such as an IO related failure, failure to get + * credentials, etc.
  • + *
  • JsonException Base class for all service exceptions. Unknown exceptions will be thrown as an instance + * of this type.
  • + *
+ * @sample JsonAsyncClient.EventStreamOperation + * @see AWS API Documentation + */ + @Override + public CompletableFuture eventStreamOperation(EventStreamOperationRequest eventStreamOperationRequest, + Publisher requestStream, EventStreamOperationResponseHandler asyncResponseHandler) { + SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(eventStreamOperationRequest, + this.clientConfiguration); + List metricPublishers = resolveMetricPublishers(clientConfiguration, eventStreamOperationRequest + .overrideConfiguration().orElse(null)); + MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector + .create("ApiCall"); + try { + apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Json Service"); + apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "EventStreamOperation"); + eventStreamOperationRequest = applySignerOverride(eventStreamOperationRequest, EventStreamAws4Signer.create()); + JsonOperationMetadata operationMetadata = JsonOperationMetadata.builder().hasStreamingSuccessResponse(false) + .isPayloadJson(true).build(); + + HttpResponseHandler responseHandler = new AttachHttpMetadataResponseHandler( + protocolFactory.createResponseHandler(operationMetadata, EventStreamOperationResponse::builder)); + + HttpResponseHandler voidResponseHandler = protocolFactory.createResponseHandler(JsonOperationMetadata + .builder().isPayloadJson(false).hasStreamingSuccessResponse(true).build(), VoidSdkResponse::builder); + + HttpResponseHandler eventResponseHandler = protocolFactory.createResponseHandler( + JsonOperationMetadata.builder().isPayloadJson(true).hasStreamingSuccessResponse(false).build(), + EventStreamTaggedUnionPojoSupplier.builder().putSdkPojoSupplier("EventOne", EventStream::eventOneBuilder) + .putSdkPojoSupplier("EventTheSecond", EventStream::eventTheSecondBuilder) + .putSdkPojoSupplier("secondEventOne", EventStream::secondEventOneBuilder) + .putSdkPojoSupplier("eventThree", EventStream::eventThreeBuilder) + .defaultSdkPojoSupplier(() -> new SdkPojoBuilder(EventStream.UNKNOWN)).build()); + + HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, + operationMetadata); + EventStreamTaggedUnionJsonMarshaller eventMarshaller = EventStreamTaggedUnionJsonMarshaller.builder() + .putMarshaller(DefaultInputEvent.class, new InputEventMarshaller(protocolFactory)).build(); + SdkPublisher eventPublisher = SdkPublisher.adapt(requestStream); + Publisher adapted = eventPublisher.map(event -> eventMarshaller.marshall(event)).map( + AwsClientHandlerUtils::encodeEventStreamRequestToByteBuffer); + CompletableFuture future = new CompletableFuture<>(); + EventStreamAsyncResponseTransformer asyncResponseTransformer = EventStreamAsyncResponseTransformer + . builder().eventStreamResponseHandler(asyncResponseHandler) + .eventResponseHandler(eventResponseHandler).initialResponseHandler(responseHandler) + .exceptionResponseHandler(errorResponseHandler).future(future).executor(executor).serviceName(serviceName()) + .build(); + + CompletableFuture executeFuture = clientHandler.execute( + new ClientExecutionParams() + .withOperationName("EventStreamOperation").withProtocolMetadata(protocolMetadata) + .withMarshaller(new EventStreamOperationRequestMarshaller(protocolFactory)) + .withAsyncRequestBody(AsyncRequestBody.fromPublisher(adapted)).withFullDuplex(true) + .withInitialRequestEvent(true).withResponseHandler(voidResponseHandler) + .withErrorResponseHandler(errorResponseHandler).withRequestConfiguration(clientConfiguration) + .withMetricCollector(apiCallMetricCollector).withInput(eventStreamOperationRequest), + asyncResponseTransformer); + CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { + if (e != null) { + try { + asyncResponseHandler.exceptionOccurred(e); + } finally { + future.completeExceptionally(e); + } + } + metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + }); + executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); + return CompletableFutureUtils.forwardExceptionTo(future, executeFuture); + } catch (Throwable t) { + runAndLogError(log, "Exception thrown in exceptionOccurred callback, ignoring", + () -> asyncResponseHandler.exceptionOccurred(t)); + metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + return CompletableFutureUtils.failedFuture(t); + } + } + + /** + * Invokes the EventStreamOperationWithOnlyInput operation asynchronously. + * + * @param eventStreamOperationWithOnlyInputRequest + * @return A Java Future containing the result of the EventStreamOperationWithOnlyInput operation returned by the + * service.
+ * The CompletableFuture returned by this method can be completed exceptionally with the following + * exceptions. The exception returned is wrapped with CompletionException, so you need to invoke + * {@link Throwable#getCause} to retrieve the underlying exception. + *
    + *
  • SdkException Base class for all exceptions that can be thrown by the SDK (both service and client). + * Can be used for catch all scenarios.
  • + *
  • SdkClientException If any client side error occurs such as an IO related failure, failure to get + * credentials, etc.
  • + *
  • JsonException Base class for all service exceptions. Unknown exceptions will be thrown as an instance + * of this type.
  • + *
+ * @sample JsonAsyncClient.EventStreamOperationWithOnlyInput + * @see AWS API Documentation + */ + @Override + public CompletableFuture eventStreamOperationWithOnlyInput( + EventStreamOperationWithOnlyInputRequest eventStreamOperationWithOnlyInputRequest, + Publisher requestStream) { + SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(eventStreamOperationWithOnlyInputRequest, + this.clientConfiguration); + List metricPublishers = resolveMetricPublishers(clientConfiguration, + eventStreamOperationWithOnlyInputRequest.overrideConfiguration().orElse(null)); + MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector + .create("ApiCall"); + try { + apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Json Service"); + apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "EventStreamOperationWithOnlyInput"); + eventStreamOperationWithOnlyInputRequest = applySignerOverride(eventStreamOperationWithOnlyInputRequest, + EventStreamAws4Signer.create()); + JsonOperationMetadata operationMetadata = JsonOperationMetadata.builder().hasStreamingSuccessResponse(false) + .isPayloadJson(true).build(); + + HttpResponseHandler responseHandler = protocolFactory + .createResponseHandler(operationMetadata, EventStreamOperationWithOnlyInputResponse::builder); + + HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, + operationMetadata); + EventStreamTaggedUnionJsonMarshaller eventMarshaller = EventStreamTaggedUnionJsonMarshaller.builder() + .putMarshaller(DefaultInputEventOne.class, new InputEventMarshaller(protocolFactory)) + .putMarshaller(DefaultInputEventTwo.class, new InputEventTwoMarshaller(protocolFactory)).build(); + SdkPublisher eventPublisher = SdkPublisher.adapt(requestStream); + Publisher adapted = eventPublisher.map(event -> eventMarshaller.marshall(event)).map( + AwsClientHandlerUtils::encodeEventStreamRequestToByteBuffer); + + CompletableFuture executeFuture = clientHandler + .execute(new ClientExecutionParams() + .withOperationName("EventStreamOperationWithOnlyInput").withProtocolMetadata(protocolMetadata) + .withMarshaller(new EventStreamOperationWithOnlyInputRequestMarshaller(protocolFactory)) + .withAsyncRequestBody(AsyncRequestBody.fromPublisher(adapted)).withInitialRequestEvent(true) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) + .withInput(eventStreamOperationWithOnlyInputRequest)); + CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { + metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + }); + executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); + return executeFuture; + } catch (Throwable t) { + metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + return CompletableFutureUtils.failedFuture(t); + } + } + + /** + * Invokes the EventStreamOperationWithOnlyOutput operation asynchronously. + * + * @param eventStreamOperationWithOnlyOutputRequest + * @return A Java Future containing the result of the EventStreamOperationWithOnlyOutput operation returned by the + * service.
+ * The CompletableFuture returned by this method can be completed exceptionally with the following + * exceptions. The exception returned is wrapped with CompletionException, so you need to invoke + * {@link Throwable#getCause} to retrieve the underlying exception. + *
    + *
  • SdkException Base class for all exceptions that can be thrown by the SDK (both service and client). + * Can be used for catch all scenarios.
  • + *
  • SdkClientException If any client side error occurs such as an IO related failure, failure to get + * credentials, etc.
  • + *
  • JsonException Base class for all service exceptions. Unknown exceptions will be thrown as an instance + * of this type.
  • + *
+ * @sample JsonAsyncClient.EventStreamOperationWithOnlyOutput + * @see AWS API Documentation + */ + @Override + public CompletableFuture eventStreamOperationWithOnlyOutput( + EventStreamOperationWithOnlyOutputRequest eventStreamOperationWithOnlyOutputRequest, + EventStreamOperationWithOnlyOutputResponseHandler asyncResponseHandler) { + SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(eventStreamOperationWithOnlyOutputRequest, + this.clientConfiguration); + List metricPublishers = resolveMetricPublishers(clientConfiguration, + eventStreamOperationWithOnlyOutputRequest.overrideConfiguration().orElse(null)); + MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector + .create("ApiCall"); + try { + apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Json Service"); + apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "EventStreamOperationWithOnlyOutput"); + JsonOperationMetadata operationMetadata = JsonOperationMetadata.builder().hasStreamingSuccessResponse(false) + .isPayloadJson(true).build(); + + HttpResponseHandler responseHandler = new AttachHttpMetadataResponseHandler( + protocolFactory.createResponseHandler(operationMetadata, EventStreamOperationWithOnlyOutputResponse::builder)); + + HttpResponseHandler voidResponseHandler = protocolFactory.createResponseHandler(JsonOperationMetadata + .builder().isPayloadJson(false).hasStreamingSuccessResponse(true).build(), VoidSdkResponse::builder); + + HttpResponseHandler eventResponseHandler = protocolFactory.createResponseHandler( + JsonOperationMetadata.builder().isPayloadJson(true).hasStreamingSuccessResponse(false).build(), + EventStreamTaggedUnionPojoSupplier.builder().putSdkPojoSupplier("EventOne", EventStream::eventOneBuilder) + .putSdkPojoSupplier("EventTheSecond", EventStream::eventTheSecondBuilder) + .putSdkPojoSupplier("secondEventOne", EventStream::secondEventOneBuilder) + .putSdkPojoSupplier("eventThree", EventStream::eventThreeBuilder) + .defaultSdkPojoSupplier(() -> new SdkPojoBuilder(EventStream.UNKNOWN)).build()); + + HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, + operationMetadata); + CompletableFuture future = new CompletableFuture<>(); + EventStreamAsyncResponseTransformer asyncResponseTransformer = EventStreamAsyncResponseTransformer + . builder() + .eventStreamResponseHandler(asyncResponseHandler).eventResponseHandler(eventResponseHandler) + .initialResponseHandler(responseHandler).exceptionResponseHandler(errorResponseHandler).future(future) + .executor(executor).serviceName(serviceName()).build(); + + CompletableFuture executeFuture = clientHandler.execute( + new ClientExecutionParams() + .withOperationName("EventStreamOperationWithOnlyOutput").withProtocolMetadata(protocolMetadata) + .withMarshaller(new EventStreamOperationWithOnlyOutputRequestMarshaller(protocolFactory)) + .withResponseHandler(voidResponseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) + .withInput(eventStreamOperationWithOnlyOutputRequest), asyncResponseTransformer); + CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { + if (e != null) { + try { + asyncResponseHandler.exceptionOccurred(e); + } finally { + future.completeExceptionally(e); + } + } + metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + }); + executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); + return CompletableFutureUtils.forwardExceptionTo(future, executeFuture); + } catch (Throwable t) { + runAndLogError(log, "Exception thrown in exceptionOccurred callback, ignoring", + () -> asyncResponseHandler.exceptionOccurred(t)); + metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + return CompletableFutureUtils.failedFuture(t); + } + } + + /** + *

+ * Performs a post operation to the query service and has no output + *

+ * + * @param getWithoutRequiredMembersRequest + * @return A Java Future containing the result of the GetWithoutRequiredMembers operation returned by the service.
+ * The CompletableFuture returned by this method can be completed exceptionally with the following + * exceptions. The exception returned is wrapped with CompletionException, so you need to invoke + * {@link Throwable#getCause} to retrieve the underlying exception. + *
    + *
  • InvalidInputException The request was rejected because an invalid or out-of-range value was supplied + * for an input parameter.
  • + *
  • SdkException Base class for all exceptions that can be thrown by the SDK (both service and client). + * Can be used for catch all scenarios.
  • + *
  • SdkClientException If any client side error occurs such as an IO related failure, failure to get + * credentials, etc.
  • + *
  • JsonException Base class for all service exceptions. Unknown exceptions will be thrown as an instance + * of this type.
  • + *
+ * @sample JsonAsyncClient.GetWithoutRequiredMembers + * @see AWS API Documentation + */ + @Override + public CompletableFuture getWithoutRequiredMembers( + GetWithoutRequiredMembersRequest getWithoutRequiredMembersRequest) { + SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(getWithoutRequiredMembersRequest, + this.clientConfiguration); + List metricPublishers = resolveMetricPublishers(clientConfiguration, getWithoutRequiredMembersRequest + .overrideConfiguration().orElse(null)); + MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector + .create("ApiCall"); + try { + apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Json Service"); + apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "GetWithoutRequiredMembers"); + JsonOperationMetadata operationMetadata = JsonOperationMetadata.builder().hasStreamingSuccessResponse(false) + .isPayloadJson(true).build(); + + HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( + operationMetadata, GetWithoutRequiredMembersResponse::builder); + + HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, + operationMetadata); + + CompletableFuture executeFuture = clientHandler + .execute(new ClientExecutionParams() + .withOperationName("GetWithoutRequiredMembers").withProtocolMetadata(protocolMetadata) + .withMarshaller(new GetWithoutRequiredMembersRequestMarshaller(protocolFactory)) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) + .withInput(getWithoutRequiredMembersRequest)); + CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { + metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + }); + executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); + return executeFuture; + } catch (Throwable t) { + metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + return CompletableFutureUtils.failedFuture(t); + } + } + + /** + * Invokes the OperationWithChecksumRequired operation asynchronously. + * + * @param operationWithChecksumRequiredRequest + * @return A Java Future containing the result of the OperationWithChecksumRequired operation returned by the + * service.
+ * The CompletableFuture returned by this method can be completed exceptionally with the following + * exceptions. The exception returned is wrapped with CompletionException, so you need to invoke + * {@link Throwable#getCause} to retrieve the underlying exception. + *
    + *
  • SdkException Base class for all exceptions that can be thrown by the SDK (both service and client). + * Can be used for catch all scenarios.
  • + *
  • SdkClientException If any client side error occurs such as an IO related failure, failure to get + * credentials, etc.
  • + *
  • JsonException Base class for all service exceptions. Unknown exceptions will be thrown as an instance + * of this type.
  • + *
+ * @sample JsonAsyncClient.OperationWithChecksumRequired + * @see AWS API Documentation + */ + @Override + public CompletableFuture operationWithChecksumRequired( + OperationWithChecksumRequiredRequest operationWithChecksumRequiredRequest) { + SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(operationWithChecksumRequiredRequest, + this.clientConfiguration); + List metricPublishers = resolveMetricPublishers(clientConfiguration, + operationWithChecksumRequiredRequest.overrideConfiguration().orElse(null)); + MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector + .create("ApiCall"); + try { + apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Json Service"); + apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "OperationWithChecksumRequired"); + JsonOperationMetadata operationMetadata = JsonOperationMetadata.builder().hasStreamingSuccessResponse(false) + .isPayloadJson(true).build(); + + HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( + operationMetadata, OperationWithChecksumRequiredResponse::builder); + + HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, + operationMetadata); + + CompletableFuture executeFuture = clientHandler + .execute(new ClientExecutionParams() + .withOperationName("OperationWithChecksumRequired") + .withProtocolMetadata(protocolMetadata) + .withMarshaller(new OperationWithChecksumRequiredRequestMarshaller(protocolFactory)) + .withResponseHandler(responseHandler) + .withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration) + .withMetricCollector(apiCallMetricCollector) + .putExecutionAttribute(SdkInternalExecutionAttribute.HTTP_CHECKSUM_REQUIRED, + HttpChecksumRequired.create()).withInput(operationWithChecksumRequiredRequest)); + CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { + metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + }); + executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); + return executeFuture; + } catch (Throwable t) { + metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + return CompletableFutureUtils.failedFuture(t); + } + } + + /** + * Invokes the OperationWithNoneAuthType operation asynchronously. + * + * @param operationWithNoneAuthTypeRequest + * @return A Java Future containing the result of the OperationWithNoneAuthType operation returned by the service.
+ * The CompletableFuture returned by this method can be completed exceptionally with the following + * exceptions. The exception returned is wrapped with CompletionException, so you need to invoke + * {@link Throwable#getCause} to retrieve the underlying exception. + *
    + *
  • SdkException Base class for all exceptions that can be thrown by the SDK (both service and client). + * Can be used for catch all scenarios.
  • + *
  • SdkClientException If any client side error occurs such as an IO related failure, failure to get + * credentials, etc.
  • + *
  • JsonException Base class for all service exceptions. Unknown exceptions will be thrown as an instance + * of this type.
  • + *
+ * @sample JsonAsyncClient.OperationWithNoneAuthType + * @see AWS API Documentation + */ + @Override + public CompletableFuture operationWithNoneAuthType( + OperationWithNoneAuthTypeRequest operationWithNoneAuthTypeRequest) { + SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(operationWithNoneAuthTypeRequest, + this.clientConfiguration); + List metricPublishers = resolveMetricPublishers(clientConfiguration, operationWithNoneAuthTypeRequest + .overrideConfiguration().orElse(null)); + MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector + .create("ApiCall"); + try { + apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Json Service"); + apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "OperationWithNoneAuthType"); + JsonOperationMetadata operationMetadata = JsonOperationMetadata.builder().hasStreamingSuccessResponse(false) + .isPayloadJson(true).build(); + + HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( + operationMetadata, OperationWithNoneAuthTypeResponse::builder); + + HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, + operationMetadata); + + CompletableFuture executeFuture = clientHandler + .execute(new ClientExecutionParams() + .withOperationName("OperationWithNoneAuthType").withProtocolMetadata(protocolMetadata) + .withMarshaller(new OperationWithNoneAuthTypeRequestMarshaller(protocolFactory)) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) + .putExecutionAttribute(SdkInternalExecutionAttribute.IS_NONE_AUTH_TYPE_REQUEST, false) + .withInput(operationWithNoneAuthTypeRequest)); + CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { + metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + }); + executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); + return executeFuture; + } catch (Throwable t) { + metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + return CompletableFutureUtils.failedFuture(t); + } + } + + /** + * Invokes the OperationWithRequestCompression operation asynchronously. + * + * @param operationWithRequestCompressionRequest + * @return A Java Future containing the result of the OperationWithRequestCompression operation returned by the + * service.
+ * The CompletableFuture returned by this method can be completed exceptionally with the following + * exceptions. The exception returned is wrapped with CompletionException, so you need to invoke + * {@link Throwable#getCause} to retrieve the underlying exception. + *
    + *
  • SdkException Base class for all exceptions that can be thrown by the SDK (both service and client). + * Can be used for catch all scenarios.
  • + *
  • SdkClientException If any client side error occurs such as an IO related failure, failure to get + * credentials, etc.
  • + *
  • JsonException Base class for all service exceptions. Unknown exceptions will be thrown as an instance + * of this type.
  • + *
+ * @sample JsonAsyncClient.OperationWithRequestCompression + * @see AWS API Documentation + */ + @Override + public CompletableFuture operationWithRequestCompression( + OperationWithRequestCompressionRequest operationWithRequestCompressionRequest) { + SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(operationWithRequestCompressionRequest, + this.clientConfiguration); + List metricPublishers = resolveMetricPublishers(clientConfiguration, + operationWithRequestCompressionRequest.overrideConfiguration().orElse(null)); + MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector + .create("ApiCall"); + try { + apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Json Service"); + apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "OperationWithRequestCompression"); + JsonOperationMetadata operationMetadata = JsonOperationMetadata.builder().hasStreamingSuccessResponse(false) + .isPayloadJson(true).build(); + + HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( + operationMetadata, OperationWithRequestCompressionResponse::builder); + + HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, + operationMetadata); + + CompletableFuture executeFuture = clientHandler + .execute(new ClientExecutionParams() + .withOperationName("OperationWithRequestCompression") + .withProtocolMetadata(protocolMetadata) + .withMarshaller(new OperationWithRequestCompressionRequestMarshaller(protocolFactory)) + .withResponseHandler(responseHandler) + .withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration) + .withMetricCollector(apiCallMetricCollector) + .putExecutionAttribute(SdkInternalExecutionAttribute.REQUEST_COMPRESSION, + RequestCompression.builder().encodings("gzip").isStreaming(false).build()) + .withInput(operationWithRequestCompressionRequest)); + CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { + metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + }); + executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); + return executeFuture; + } catch (Throwable t) { + metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + return CompletableFutureUtils.failedFuture(t); + } + } + + /** + * Some paginated operation with result_key in paginators.json file + * + * @param paginatedOperationWithResultKeyRequest + * @return A Java Future containing the result of the PaginatedOperationWithResultKey operation returned by the + * service.
+ * The CompletableFuture returned by this method can be completed exceptionally with the following + * exceptions. The exception returned is wrapped with CompletionException, so you need to invoke + * {@link Throwable#getCause} to retrieve the underlying exception. + *
    + *
  • SdkException Base class for all exceptions that can be thrown by the SDK (both service and client). + * Can be used for catch all scenarios.
  • + *
  • SdkClientException If any client side error occurs such as an IO related failure, failure to get + * credentials, etc.
  • + *
  • JsonException Base class for all service exceptions. Unknown exceptions will be thrown as an instance + * of this type.
  • + *
+ * @sample JsonAsyncClient.PaginatedOperationWithResultKey + * @see AWS API Documentation + */ + @Override + public CompletableFuture paginatedOperationWithResultKey( + PaginatedOperationWithResultKeyRequest paginatedOperationWithResultKeyRequest) { + SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(paginatedOperationWithResultKeyRequest, + this.clientConfiguration); + List metricPublishers = resolveMetricPublishers(clientConfiguration, + paginatedOperationWithResultKeyRequest.overrideConfiguration().orElse(null)); + MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector + .create("ApiCall"); + try { + apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Json Service"); + apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "PaginatedOperationWithResultKey"); + JsonOperationMetadata operationMetadata = JsonOperationMetadata.builder().hasStreamingSuccessResponse(false) + .isPayloadJson(true).build(); + + HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( + operationMetadata, PaginatedOperationWithResultKeyResponse::builder); + + HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, + operationMetadata); + + CompletableFuture executeFuture = clientHandler + .execute(new ClientExecutionParams() + .withOperationName("PaginatedOperationWithResultKey").withProtocolMetadata(protocolMetadata) + .withMarshaller(new PaginatedOperationWithResultKeyRequestMarshaller(protocolFactory)) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) + .withInput(paginatedOperationWithResultKeyRequest)); + CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { + metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + }); + executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); + return executeFuture; + } catch (Throwable t) { + metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + return CompletableFutureUtils.failedFuture(t); + } + } + + /** + * Some paginated operation without result_key in paginators.json file + * + * @param paginatedOperationWithoutResultKeyRequest + * @return A Java Future containing the result of the PaginatedOperationWithoutResultKey operation returned by the + * service.
+ * The CompletableFuture returned by this method can be completed exceptionally with the following + * exceptions. The exception returned is wrapped with CompletionException, so you need to invoke + * {@link Throwable#getCause} to retrieve the underlying exception. + *
    + *
  • SdkException Base class for all exceptions that can be thrown by the SDK (both service and client). + * Can be used for catch all scenarios.
  • + *
  • SdkClientException If any client side error occurs such as an IO related failure, failure to get + * credentials, etc.
  • + *
  • JsonException Base class for all service exceptions. Unknown exceptions will be thrown as an instance + * of this type.
  • + *
+ * @sample JsonAsyncClient.PaginatedOperationWithoutResultKey + * @see AWS API Documentation + */ + @Override + public CompletableFuture paginatedOperationWithoutResultKey( + PaginatedOperationWithoutResultKeyRequest paginatedOperationWithoutResultKeyRequest) { + SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(paginatedOperationWithoutResultKeyRequest, + this.clientConfiguration); + List metricPublishers = resolveMetricPublishers(clientConfiguration, + paginatedOperationWithoutResultKeyRequest.overrideConfiguration().orElse(null)); + MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector + .create("ApiCall"); + try { + apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Json Service"); + apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "PaginatedOperationWithoutResultKey"); + JsonOperationMetadata operationMetadata = JsonOperationMetadata.builder().hasStreamingSuccessResponse(false) + .isPayloadJson(true).build(); + + HttpResponseHandler responseHandler = protocolFactory + .createResponseHandler(operationMetadata, PaginatedOperationWithoutResultKeyResponse::builder); + + HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, + operationMetadata); + + CompletableFuture executeFuture = clientHandler + .execute(new ClientExecutionParams() + .withOperationName("PaginatedOperationWithoutResultKey").withProtocolMetadata(protocolMetadata) + .withMarshaller(new PaginatedOperationWithoutResultKeyRequestMarshaller(protocolFactory)) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) + .withInput(paginatedOperationWithoutResultKeyRequest)); + CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { + metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + }); + executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); + return executeFuture; + } catch (Throwable t) { + metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + return CompletableFutureUtils.failedFuture(t); + } + } + + /** + * Some operation with a streaming input + * + * @param streamingInputOperationRequest + * @param requestBody + * Functional interface that can be implemented to produce the request content in a non-blocking manner. The + * size of the content is expected to be known up front. See {@link AsyncRequestBody} for specific details on + * implementing this interface as well as links to precanned implementations for common scenarios like + * uploading from a file. The service documentation for the request content is as follows 'This be a stream' + * @return A Java Future containing the result of the StreamingInputOperation operation returned by the service.
+ * The CompletableFuture returned by this method can be completed exceptionally with the following + * exceptions. The exception returned is wrapped with CompletionException, so you need to invoke + * {@link Throwable#getCause} to retrieve the underlying exception. + *
    + *
  • SdkException Base class for all exceptions that can be thrown by the SDK (both service and client). + * Can be used for catch all scenarios.
  • + *
  • SdkClientException If any client side error occurs such as an IO related failure, failure to get + * credentials, etc.
  • + *
  • JsonException Base class for all service exceptions. Unknown exceptions will be thrown as an instance + * of this type.
  • + *
+ * @sample JsonAsyncClient.StreamingInputOperation + * @see AWS API Documentation + */ + @Override + public CompletableFuture streamingInputOperation( + StreamingInputOperationRequest streamingInputOperationRequest, AsyncRequestBody requestBody) { + SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(streamingInputOperationRequest, + this.clientConfiguration); + List metricPublishers = resolveMetricPublishers(clientConfiguration, streamingInputOperationRequest + .overrideConfiguration().orElse(null)); + MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector + .create("ApiCall"); + try { + apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Json Service"); + apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "StreamingInputOperation"); + if (!isSignerOverridden(clientConfiguration)) { + streamingInputOperationRequest = applySignerOverride(streamingInputOperationRequest, AsyncAws4Signer.create()); + } + JsonOperationMetadata operationMetadata = JsonOperationMetadata.builder().hasStreamingSuccessResponse(false) + .isPayloadJson(true).build(); + + HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( + operationMetadata, StreamingInputOperationResponse::builder); + + HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, + operationMetadata); + + CompletableFuture executeFuture = clientHandler + .execute(new ClientExecutionParams() + .withOperationName("StreamingInputOperation") + .withProtocolMetadata(protocolMetadata) + .withMarshaller( + AsyncStreamingRequestMarshaller.builder() + .delegateMarshaller(new StreamingInputOperationRequestMarshaller(protocolFactory)) + .asyncRequestBody(requestBody).build()).withResponseHandler(responseHandler) + .withErrorResponseHandler(errorResponseHandler).withRequestConfiguration(clientConfiguration) + .withMetricCollector(apiCallMetricCollector).withAsyncRequestBody(requestBody) + .withInput(streamingInputOperationRequest)); + CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { + metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + }); + executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); + return executeFuture; + } catch (Throwable t) { + metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + return CompletableFutureUtils.failedFuture(t); + } + } + + /** + * Some operation with streaming input and streaming output + * + * @param streamingInputOutputOperationRequest + * @param requestBody + * Functional interface that can be implemented to produce the request content in a non-blocking manner. The + * size of the content is expected to be known up front. See {@link AsyncRequestBody} for specific details on + * implementing this interface as well as links to precanned implementations for common scenarios like + * uploading from a file. The service documentation for the request content is as follows 'This be a stream' + * @param asyncResponseTransformer + * The response transformer for processing the streaming response in a non-blocking manner. See + * {@link AsyncResponseTransformer} for details on how this callback should be implemented and for links to + * precanned implementations for common scenarios like downloading to a file. The service documentation for + * the response content is as follows 'This be a stream'. + * @return A future to the transformed result of the AsyncResponseTransformer.
+ * The CompletableFuture returned by this method can be completed exceptionally with the following + * exceptions. The exception returned is wrapped with CompletionException, so you need to invoke + * {@link Throwable#getCause} to retrieve the underlying exception. + *
    + *
  • SdkException Base class for all exceptions that can be thrown by the SDK (both service and client). + * Can be used for catch all scenarios.
  • + *
  • SdkClientException If any client side error occurs such as an IO related failure, failure to get + * credentials, etc.
  • + *
  • JsonException Base class for all service exceptions. Unknown exceptions will be thrown as an instance + * of this type.
  • + *
+ * @sample JsonAsyncClient.StreamingInputOutputOperation + * @see AWS API Documentation + */ + @Override + public CompletableFuture streamingInputOutputOperation( + StreamingInputOutputOperationRequest streamingInputOutputOperationRequest, AsyncRequestBody requestBody, + AsyncResponseTransformer asyncResponseTransformer) { + SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(streamingInputOutputOperationRequest, + this.clientConfiguration); + List metricPublishers = resolveMetricPublishers(clientConfiguration, + streamingInputOutputOperationRequest.overrideConfiguration().orElse(null)); + MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector + .create("ApiCall"); + try { + apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Json Service"); + apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "StreamingInputOutputOperation"); + Pair, CompletableFuture> pair = AsyncResponseTransformerUtils + .wrapWithEndOfStreamFuture(asyncResponseTransformer); + asyncResponseTransformer = pair.left(); + CompletableFuture endOfStreamFuture = pair.right(); + streamingInputOutputOperationRequest = applySignerOverride(streamingInputOutputOperationRequest, + Aws4UnsignedPayloadSigner.create()); + JsonOperationMetadata operationMetadata = JsonOperationMetadata.builder().hasStreamingSuccessResponse(true) + .isPayloadJson(false).build(); + + HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( + operationMetadata, StreamingInputOutputOperationResponse::builder); + + HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, + operationMetadata); + + CompletableFuture executeFuture = clientHandler.execute( + new ClientExecutionParams() + .withOperationName("StreamingInputOutputOperation") + .withProtocolMetadata(protocolMetadata) + .withMarshaller( + AsyncStreamingRequestMarshaller + .builder() + .delegateMarshaller( + new StreamingInputOutputOperationRequestMarshaller(protocolFactory)) + .asyncRequestBody(requestBody).transferEncoding(true).build()) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) + .withAsyncRequestBody(requestBody).withInput(streamingInputOutputOperationRequest), + asyncResponseTransformer); + AsyncResponseTransformer finalAsyncResponseTransformer = asyncResponseTransformer; + CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { + if (e != null) { + runAndLogError(log, "Exception thrown in exceptionOccurred callback, ignoring", + () -> finalAsyncResponseTransformer.exceptionOccurred(e)); + } + endOfStreamFuture.whenComplete((r2, e2) -> { + metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + }); + }); + executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); + return executeFuture; + } catch (Throwable t) { + AsyncResponseTransformer finalAsyncResponseTransformer = asyncResponseTransformer; + runAndLogError(log, "Exception thrown in exceptionOccurred callback, ignoring", + () -> finalAsyncResponseTransformer.exceptionOccurred(t)); + metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + return CompletableFutureUtils.failedFuture(t); + } + } + + /** + * Some operation with a streaming output + * + * @param streamingOutputOperationRequest + * @param asyncResponseTransformer + * The response transformer for processing the streaming response in a non-blocking manner. See + * {@link AsyncResponseTransformer} for details on how this callback should be implemented and for links to + * precanned implementations for common scenarios like downloading to a file. The service documentation for + * the response content is as follows 'This be a stream'. + * @return A future to the transformed result of the AsyncResponseTransformer.
+ * The CompletableFuture returned by this method can be completed exceptionally with the following + * exceptions. The exception returned is wrapped with CompletionException, so you need to invoke + * {@link Throwable#getCause} to retrieve the underlying exception. + *
    + *
  • SdkException Base class for all exceptions that can be thrown by the SDK (both service and client). + * Can be used for catch all scenarios.
  • + *
  • SdkClientException If any client side error occurs such as an IO related failure, failure to get + * credentials, etc.
  • + *
  • JsonException Base class for all service exceptions. Unknown exceptions will be thrown as an instance + * of this type.
  • + *
+ * @sample JsonAsyncClient.StreamingOutputOperation + * @see AWS API Documentation + */ + @Override + public CompletableFuture streamingOutputOperation( + StreamingOutputOperationRequest streamingOutputOperationRequest, + AsyncResponseTransformer asyncResponseTransformer) { + SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(streamingOutputOperationRequest, + this.clientConfiguration); + List metricPublishers = resolveMetricPublishers(clientConfiguration, streamingOutputOperationRequest + .overrideConfiguration().orElse(null)); + MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector + .create("ApiCall"); + try { + apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Json Service"); + apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "StreamingOutputOperation"); + Pair, CompletableFuture> pair = AsyncResponseTransformerUtils + .wrapWithEndOfStreamFuture(asyncResponseTransformer); + asyncResponseTransformer = pair.left(); + CompletableFuture endOfStreamFuture = pair.right(); + JsonOperationMetadata operationMetadata = JsonOperationMetadata.builder().hasStreamingSuccessResponse(true) + .isPayloadJson(false).build(); + + HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( + operationMetadata, StreamingOutputOperationResponse::builder); + + HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, + operationMetadata); + + CompletableFuture executeFuture = clientHandler.execute( + new ClientExecutionParams() + .withOperationName("StreamingOutputOperation").withProtocolMetadata(protocolMetadata) + .withMarshaller(new StreamingOutputOperationRequestMarshaller(protocolFactory)) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) + .withInput(streamingOutputOperationRequest), asyncResponseTransformer); + AsyncResponseTransformer finalAsyncResponseTransformer = asyncResponseTransformer; + CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { + if (e != null) { + runAndLogError(log, "Exception thrown in exceptionOccurred callback, ignoring", + () -> finalAsyncResponseTransformer.exceptionOccurred(e)); + } + endOfStreamFuture.whenComplete((r2, e2) -> { + metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + }); + }); + executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); + return executeFuture; + } catch (Throwable t) { + AsyncResponseTransformer finalAsyncResponseTransformer = asyncResponseTransformer; + runAndLogError(log, "Exception thrown in exceptionOccurred callback, ignoring", + () -> finalAsyncResponseTransformer.exceptionOccurred(t)); + metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + return CompletableFutureUtils.failedFuture(t); + } + } + + @Override + public final JsonServiceClientConfiguration serviceClientConfiguration() { + return new JsonServiceClientConfigurationBuilder(this.clientConfiguration.toBuilder()).build(); + } + + @Override + public final String serviceName() { + return SERVICE_NAME; + } + + private > T init(T builder) { + return builder + .clientConfiguration(clientConfiguration) + .defaultServiceExceptionSupplier(JsonException::builder) + .protocol(AwsJsonProtocol.AWS_JSON) + .protocolVersion("1.1") + .registerModeledException( + ExceptionMetadata.builder().errorCode("InvalidInputException") + .exceptionBuilderSupplier(InvalidInputException::builder).httpStatusCode(400).build()) + .registerModeledException( + ExceptionMetadata.builder().errorCode("ServiceFaultException") + .exceptionBuilderSupplier(ServiceFaultException::builder).httpStatusCode(500).build()); + } + + private static List resolveMetricPublishers(SdkClientConfiguration clientConfiguration, + RequestOverrideConfiguration requestOverrideConfiguration) { + List publishers = null; + if (requestOverrideConfiguration != null) { + publishers = requestOverrideConfiguration.metricPublishers(); + } + if (publishers == null || publishers.isEmpty()) { + publishers = clientConfiguration.option(SdkClientOption.METRIC_PUBLISHERS); + } + if (publishers == null) { + publishers = Collections.emptyList(); + } + return publishers; + } + + private T applySignerOverride(T request, Signer signer) { + if (request.overrideConfiguration().flatMap(c -> c.signer()).isPresent()) { + return request; + } + Consumer signerOverride = b -> b.signer(signer).build(); + AwsRequestOverrideConfiguration overrideConfiguration = request.overrideConfiguration() + .map(c -> c.toBuilder().applyMutation(signerOverride).build()) + .orElse((AwsRequestOverrideConfiguration.builder().applyMutation(signerOverride).build())); + return (T) request.toBuilder().overrideConfiguration(overrideConfiguration).build(); + } + + private static boolean isSignerOverridden(SdkClientConfiguration clientConfiguration) { + return Boolean.TRUE.equals(clientConfiguration.option(SdkClientOption.SIGNER_OVERRIDDEN)); + } + + private void updateRetryStrategyClientConfiguration(SdkClientConfiguration.Builder configuration) { + ClientOverrideConfiguration.Builder builder = configuration.asOverrideConfigurationBuilder(); + RetryMode retryMode = builder.retryMode(); + if (retryMode != null) { + configuration.option(SdkClientOption.RETRY_STRATEGY, AwsRetryStrategy.forRetryMode(retryMode)); + } else { + Consumer> configurator = builder.retryStrategyConfigurator(); + if (configurator != null) { + RetryStrategy.Builder defaultBuilder = AwsRetryStrategy.defaultRetryStrategy().toBuilder(); + configurator.accept(defaultBuilder); + configuration.option(SdkClientOption.RETRY_STRATEGY, defaultBuilder.build()); + } else { + RetryStrategy retryStrategy = builder.retryStrategy(); + if (retryStrategy != null) { + configuration.option(SdkClientOption.RETRY_STRATEGY, retryStrategy); + } + } + } + configuration.option(SdkClientOption.CONFIGURED_RETRY_MODE, null); + configuration.option(SdkClientOption.CONFIGURED_RETRY_STRATEGY, null); + configuration.option(SdkClientOption.CONFIGURED_RETRY_CONFIGURATOR, null); + } + + private SdkClientConfiguration updateSdkClientConfiguration(SdkRequest request, SdkClientConfiguration clientConfiguration) { + List plugins = request.overrideConfiguration().map(c -> c.plugins()).orElse(Collections.emptyList()); + SdkClientConfiguration.Builder configuration = clientConfiguration.toBuilder(); + if (plugins.isEmpty()) { + return configuration.build(); + } + JsonServiceClientConfigurationBuilder serviceConfigBuilder = new JsonServiceClientConfigurationBuilder(configuration); + for (SdkPlugin plugin : plugins) { + plugin.configureClient(serviceConfigBuilder); + } + updateRetryStrategyClientConfiguration(configuration); + return configuration.build(); + } + + private HttpResponseHandler createErrorResponseHandler(BaseAwsJsonProtocolFactory protocolFactory, + JsonOperationMetadata operationMetadata) { + return protocolFactory.createErrorResponseHandler(operationMetadata); + } + + @Override + public void close() { + clientHandler.close(); + } +} diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-cbor-client-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-cbor-client-class.java new file mode 100644 index 000000000000..b6b072aad637 --- /dev/null +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-cbor-client-class.java @@ -0,0 +1,824 @@ +package software.amazon.awssdk.services.json; + +import java.util.Collections; +import java.util.List; +import java.util.function.Consumer; +import software.amazon.awssdk.annotations.Generated; +import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.awscore.client.handler.AwsSyncClientHandler; +import software.amazon.awssdk.awscore.exception.AwsServiceException; +import software.amazon.awssdk.awscore.internal.AwsProtocolMetadata; +import software.amazon.awssdk.awscore.internal.AwsServiceProtocol; +import software.amazon.awssdk.awscore.retry.AwsRetryStrategy; +import software.amazon.awssdk.core.RequestOverrideConfiguration; +import software.amazon.awssdk.core.SdkPlugin; +import software.amazon.awssdk.core.SdkRequest; +import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; +import software.amazon.awssdk.core.client.config.SdkClientConfiguration; +import software.amazon.awssdk.core.client.config.SdkClientOption; +import software.amazon.awssdk.core.client.handler.ClientExecutionParams; +import software.amazon.awssdk.core.client.handler.SyncClientHandler; +import software.amazon.awssdk.core.exception.SdkClientException; +import software.amazon.awssdk.core.http.HttpResponseHandler; +import software.amazon.awssdk.core.interceptor.SdkInternalExecutionAttribute; +import software.amazon.awssdk.core.interceptor.trait.HttpChecksumRequired; +import software.amazon.awssdk.core.internal.interceptor.trait.RequestCompression; +import software.amazon.awssdk.core.metrics.CoreMetric; +import software.amazon.awssdk.core.retry.RetryMode; +import software.amazon.awssdk.core.runtime.transform.StreamingRequestMarshaller; +import software.amazon.awssdk.core.sync.RequestBody; +import software.amazon.awssdk.core.sync.ResponseTransformer; +import software.amazon.awssdk.metrics.MetricCollector; +import software.amazon.awssdk.metrics.MetricPublisher; +import software.amazon.awssdk.metrics.NoOpMetricCollector; +import software.amazon.awssdk.protocols.cbor.AwsCborProtocolFactory; +import software.amazon.awssdk.protocols.core.ExceptionMetadata; +import software.amazon.awssdk.protocols.json.AwsJsonProtocol; +import software.amazon.awssdk.protocols.json.BaseAwsJsonProtocolFactory; +import software.amazon.awssdk.protocols.json.JsonOperationMetadata; +import software.amazon.awssdk.retries.api.RetryStrategy; +import software.amazon.awssdk.services.json.internal.JsonServiceClientConfigurationBuilder; +import software.amazon.awssdk.services.json.model.APostOperationRequest; +import software.amazon.awssdk.services.json.model.APostOperationResponse; +import software.amazon.awssdk.services.json.model.APostOperationWithOutputRequest; +import software.amazon.awssdk.services.json.model.APostOperationWithOutputResponse; +import software.amazon.awssdk.services.json.model.GetWithoutRequiredMembersRequest; +import software.amazon.awssdk.services.json.model.GetWithoutRequiredMembersResponse; +import software.amazon.awssdk.services.json.model.InvalidInputException; +import software.amazon.awssdk.services.json.model.JsonException; +import software.amazon.awssdk.services.json.model.OperationWithChecksumRequiredRequest; +import software.amazon.awssdk.services.json.model.OperationWithChecksumRequiredResponse; +import software.amazon.awssdk.services.json.model.OperationWithNoneAuthTypeRequest; +import software.amazon.awssdk.services.json.model.OperationWithNoneAuthTypeResponse; +import software.amazon.awssdk.services.json.model.OperationWithRequestCompressionRequest; +import software.amazon.awssdk.services.json.model.OperationWithRequestCompressionResponse; +import software.amazon.awssdk.services.json.model.PaginatedOperationWithResultKeyRequest; +import software.amazon.awssdk.services.json.model.PaginatedOperationWithResultKeyResponse; +import software.amazon.awssdk.services.json.model.PaginatedOperationWithoutResultKeyRequest; +import software.amazon.awssdk.services.json.model.PaginatedOperationWithoutResultKeyResponse; +import software.amazon.awssdk.services.json.model.ServiceFaultException; +import software.amazon.awssdk.services.json.model.StreamingInputOperationRequest; +import software.amazon.awssdk.services.json.model.StreamingInputOperationResponse; +import software.amazon.awssdk.services.json.model.StreamingInputOutputOperationRequest; +import software.amazon.awssdk.services.json.model.StreamingInputOutputOperationResponse; +import software.amazon.awssdk.services.json.model.StreamingOutputOperationRequest; +import software.amazon.awssdk.services.json.model.StreamingOutputOperationResponse; +import software.amazon.awssdk.services.json.transform.APostOperationRequestMarshaller; +import software.amazon.awssdk.services.json.transform.APostOperationWithOutputRequestMarshaller; +import software.amazon.awssdk.services.json.transform.GetWithoutRequiredMembersRequestMarshaller; +import software.amazon.awssdk.services.json.transform.OperationWithChecksumRequiredRequestMarshaller; +import software.amazon.awssdk.services.json.transform.OperationWithNoneAuthTypeRequestMarshaller; +import software.amazon.awssdk.services.json.transform.OperationWithRequestCompressionRequestMarshaller; +import software.amazon.awssdk.services.json.transform.PaginatedOperationWithResultKeyRequestMarshaller; +import software.amazon.awssdk.services.json.transform.PaginatedOperationWithoutResultKeyRequestMarshaller; +import software.amazon.awssdk.services.json.transform.StreamingInputOperationRequestMarshaller; +import software.amazon.awssdk.services.json.transform.StreamingInputOutputOperationRequestMarshaller; +import software.amazon.awssdk.services.json.transform.StreamingOutputOperationRequestMarshaller; +import software.amazon.awssdk.utils.HostnameValidator; +import software.amazon.awssdk.utils.Logger; + +/** + * Internal implementation of {@link JsonClient}. + * + * @see JsonClient#builder() + */ +@Generated("software.amazon.awssdk:codegen") +@SdkInternalApi +final class DefaultJsonClient implements JsonClient { + private static final Logger log = Logger.loggerFor(DefaultJsonClient.class); + + private static final AwsProtocolMetadata protocolMetadata = AwsProtocolMetadata.builder() + .serviceProtocol(AwsServiceProtocol.CBOR).build(); + + private final SyncClientHandler clientHandler; + + private final AwsCborProtocolFactory protocolFactory; + + private final SdkClientConfiguration clientConfiguration; + + protected DefaultJsonClient(SdkClientConfiguration clientConfiguration) { + this.clientHandler = new AwsSyncClientHandler(clientConfiguration); + this.clientConfiguration = clientConfiguration.toBuilder().option(SdkClientOption.SDK_CLIENT, this).build(); + this.protocolFactory = init(AwsCborProtocolFactory.builder()).build(); + } + + /** + *

+ * Performs a post operation to the query service and has no output + *

+ * + * @param aPostOperationRequest + * @return Result of the APostOperation operation returned by the service. + * @throws InvalidInputException + * The request was rejected because an invalid or out-of-range value was supplied for an input parameter. + * @throws SdkException + * Base class for all exceptions that can be thrown by the SDK (both service and client). Can be used for + * catch all scenarios. + * @throws SdkClientException + * If any client side error occurs such as an IO related failure, failure to get credentials, etc. + * @throws JsonException + * Base class for all service exceptions. Unknown exceptions will be thrown as an instance of this type. + * @sample JsonClient.APostOperation + * @see AWS + * API Documentation + */ + @Override + public APostOperationResponse aPostOperation(APostOperationRequest aPostOperationRequest) throws InvalidInputException, + AwsServiceException, SdkClientException, JsonException { + JsonOperationMetadata operationMetadata = JsonOperationMetadata.builder().hasStreamingSuccessResponse(false) + .isPayloadJson(true).build(); + + HttpResponseHandler responseHandler = protocolFactory.createResponseHandler(operationMetadata, + APostOperationResponse::builder); + + HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, + operationMetadata); + SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(aPostOperationRequest, this.clientConfiguration); + List metricPublishers = resolveMetricPublishers(clientConfiguration, aPostOperationRequest + .overrideConfiguration().orElse(null)); + MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector + .create("ApiCall"); + try { + apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Json Service"); + apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "APostOperation"); + String hostPrefix = "{StringMember}-foo."; + HostnameValidator.validateHostnameCompliant(aPostOperationRequest.stringMember(), "StringMember", + "aPostOperationRequest"); + String resolvedHostExpression = String.format("%s-foo.", aPostOperationRequest.stringMember()); + + return clientHandler.execute(new ClientExecutionParams() + .withOperationName("APostOperation").withProtocolMetadata(protocolMetadata) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .hostPrefixExpression(resolvedHostExpression).withRequestConfiguration(clientConfiguration) + .withInput(aPostOperationRequest).withMetricCollector(apiCallMetricCollector) + .withMarshaller(new APostOperationRequestMarshaller(protocolFactory))); + } finally { + metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + } + } + + /** + *

+ * Performs a post operation to the query service and has modelled output + *

+ * + * @param aPostOperationWithOutputRequest + * @return Result of the APostOperationWithOutput operation returned by the service. + * @throws InvalidInputException + * The request was rejected because an invalid or out-of-range value was supplied for an input parameter. + * @throws ServiceFaultException + * @throws SdkException + * Base class for all exceptions that can be thrown by the SDK (both service and client). Can be used for + * catch all scenarios. + * @throws SdkClientException + * If any client side error occurs such as an IO related failure, failure to get credentials, etc. + * @throws JsonException + * Base class for all service exceptions. Unknown exceptions will be thrown as an instance of this type. + * @sample JsonClient.APostOperationWithOutput + * @see AWS API Documentation + */ + @Override + public APostOperationWithOutputResponse aPostOperationWithOutput( + APostOperationWithOutputRequest aPostOperationWithOutputRequest) throws InvalidInputException, ServiceFaultException, + AwsServiceException, SdkClientException, JsonException { + JsonOperationMetadata operationMetadata = JsonOperationMetadata.builder().hasStreamingSuccessResponse(false) + .isPayloadJson(true).build(); + + HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( + operationMetadata, APostOperationWithOutputResponse::builder); + + HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, + operationMetadata); + SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(aPostOperationWithOutputRequest, + this.clientConfiguration); + List metricPublishers = resolveMetricPublishers(clientConfiguration, aPostOperationWithOutputRequest + .overrideConfiguration().orElse(null)); + MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector + .create("ApiCall"); + try { + apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Json Service"); + apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "APostOperationWithOutput"); + + return clientHandler + .execute(new ClientExecutionParams() + .withOperationName("APostOperationWithOutput").withProtocolMetadata(protocolMetadata) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withInput(aPostOperationWithOutputRequest) + .withMetricCollector(apiCallMetricCollector) + .withMarshaller(new APostOperationWithOutputRequestMarshaller(protocolFactory))); + } finally { + metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + } + } + + /** + *

+ * Performs a post operation to the query service and has no output + *

+ * + * @param getWithoutRequiredMembersRequest + * @return Result of the GetWithoutRequiredMembers operation returned by the service. + * @throws InvalidInputException + * The request was rejected because an invalid or out-of-range value was supplied for an input parameter. + * @throws SdkException + * Base class for all exceptions that can be thrown by the SDK (both service and client). Can be used for + * catch all scenarios. + * @throws SdkClientException + * If any client side error occurs such as an IO related failure, failure to get credentials, etc. + * @throws JsonException + * Base class for all service exceptions. Unknown exceptions will be thrown as an instance of this type. + * @sample JsonClient.GetWithoutRequiredMembers + * @see AWS API Documentation + */ + @Override + public GetWithoutRequiredMembersResponse getWithoutRequiredMembers( + GetWithoutRequiredMembersRequest getWithoutRequiredMembersRequest) throws InvalidInputException, AwsServiceException, + SdkClientException, JsonException { + JsonOperationMetadata operationMetadata = JsonOperationMetadata.builder().hasStreamingSuccessResponse(false) + .isPayloadJson(true).build(); + + HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( + operationMetadata, GetWithoutRequiredMembersResponse::builder); + + HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, + operationMetadata); + SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(getWithoutRequiredMembersRequest, + this.clientConfiguration); + List metricPublishers = resolveMetricPublishers(clientConfiguration, getWithoutRequiredMembersRequest + .overrideConfiguration().orElse(null)); + MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector + .create("ApiCall"); + try { + apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Json Service"); + apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "GetWithoutRequiredMembers"); + + return clientHandler + .execute(new ClientExecutionParams() + .withOperationName("GetWithoutRequiredMembers").withProtocolMetadata(protocolMetadata) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withInput(getWithoutRequiredMembersRequest) + .withMetricCollector(apiCallMetricCollector) + .withMarshaller(new GetWithoutRequiredMembersRequestMarshaller(protocolFactory))); + } finally { + metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + } + } + + /** + * Invokes the OperationWithChecksumRequired operation. + * + * @param operationWithChecksumRequiredRequest + * @return Result of the OperationWithChecksumRequired operation returned by the service. + * @throws SdkException + * Base class for all exceptions that can be thrown by the SDK (both service and client). Can be used for + * catch all scenarios. + * @throws SdkClientException + * If any client side error occurs such as an IO related failure, failure to get credentials, etc. + * @throws JsonException + * Base class for all service exceptions. Unknown exceptions will be thrown as an instance of this type. + * @sample JsonClient.OperationWithChecksumRequired + * @see AWS API Documentation + */ + @Override + public OperationWithChecksumRequiredResponse operationWithChecksumRequired( + OperationWithChecksumRequiredRequest operationWithChecksumRequiredRequest) throws AwsServiceException, + SdkClientException, JsonException { + JsonOperationMetadata operationMetadata = JsonOperationMetadata.builder().hasStreamingSuccessResponse(false) + .isPayloadJson(true).build(); + + HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( + operationMetadata, OperationWithChecksumRequiredResponse::builder); + + HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, + operationMetadata); + SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(operationWithChecksumRequiredRequest, + this.clientConfiguration); + List metricPublishers = resolveMetricPublishers(clientConfiguration, + operationWithChecksumRequiredRequest.overrideConfiguration().orElse(null)); + MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector + .create("ApiCall"); + try { + apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Json Service"); + apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "OperationWithChecksumRequired"); + + return clientHandler + .execute(new ClientExecutionParams() + .withOperationName("OperationWithChecksumRequired") + .withProtocolMetadata(protocolMetadata) + .withResponseHandler(responseHandler) + .withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration) + .withInput(operationWithChecksumRequiredRequest) + .withMetricCollector(apiCallMetricCollector) + .putExecutionAttribute(SdkInternalExecutionAttribute.HTTP_CHECKSUM_REQUIRED, + HttpChecksumRequired.create()) + .withMarshaller(new OperationWithChecksumRequiredRequestMarshaller(protocolFactory))); + } finally { + metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + } + } + + /** + * Invokes the OperationWithNoneAuthType operation. + * + * @param operationWithNoneAuthTypeRequest + * @return Result of the OperationWithNoneAuthType operation returned by the service. + * @throws SdkException + * Base class for all exceptions that can be thrown by the SDK (both service and client). Can be used for + * catch all scenarios. + * @throws SdkClientException + * If any client side error occurs such as an IO related failure, failure to get credentials, etc. + * @throws JsonException + * Base class for all service exceptions. Unknown exceptions will be thrown as an instance of this type. + * @sample JsonClient.OperationWithNoneAuthType + * @see AWS API Documentation + */ + @Override + public OperationWithNoneAuthTypeResponse operationWithNoneAuthType( + OperationWithNoneAuthTypeRequest operationWithNoneAuthTypeRequest) throws AwsServiceException, SdkClientException, + JsonException { + JsonOperationMetadata operationMetadata = JsonOperationMetadata.builder().hasStreamingSuccessResponse(false) + .isPayloadJson(true).build(); + + HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( + operationMetadata, OperationWithNoneAuthTypeResponse::builder); + + HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, + operationMetadata); + SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(operationWithNoneAuthTypeRequest, + this.clientConfiguration); + List metricPublishers = resolveMetricPublishers(clientConfiguration, operationWithNoneAuthTypeRequest + .overrideConfiguration().orElse(null)); + MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector + .create("ApiCall"); + try { + apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Json Service"); + apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "OperationWithNoneAuthType"); + + return clientHandler + .execute(new ClientExecutionParams() + .withOperationName("OperationWithNoneAuthType").withProtocolMetadata(protocolMetadata) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withInput(operationWithNoneAuthTypeRequest) + .withMetricCollector(apiCallMetricCollector) + .withMarshaller(new OperationWithNoneAuthTypeRequestMarshaller(protocolFactory))); + } finally { + metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + } + } + + /** + * Invokes the OperationWithRequestCompression operation. + * + * @param operationWithRequestCompressionRequest + * @return Result of the OperationWithRequestCompression operation returned by the service. + * @throws SdkException + * Base class for all exceptions that can be thrown by the SDK (both service and client). Can be used for + * catch all scenarios. + * @throws SdkClientException + * If any client side error occurs such as an IO related failure, failure to get credentials, etc. + * @throws JsonException + * Base class for all service exceptions. Unknown exceptions will be thrown as an instance of this type. + * @sample JsonClient.OperationWithRequestCompression + * @see AWS API Documentation + */ + @Override + public OperationWithRequestCompressionResponse operationWithRequestCompression( + OperationWithRequestCompressionRequest operationWithRequestCompressionRequest) throws AwsServiceException, + SdkClientException, JsonException { + JsonOperationMetadata operationMetadata = JsonOperationMetadata.builder().hasStreamingSuccessResponse(false) + .isPayloadJson(true).build(); + + HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( + operationMetadata, OperationWithRequestCompressionResponse::builder); + + HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, + operationMetadata); + SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(operationWithRequestCompressionRequest, + this.clientConfiguration); + List metricPublishers = resolveMetricPublishers(clientConfiguration, + operationWithRequestCompressionRequest.overrideConfiguration().orElse(null)); + MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector + .create("ApiCall"); + try { + apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Json Service"); + apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "OperationWithRequestCompression"); + + return clientHandler + .execute(new ClientExecutionParams() + .withOperationName("OperationWithRequestCompression") + .withProtocolMetadata(protocolMetadata) + .withResponseHandler(responseHandler) + .withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration) + .withInput(operationWithRequestCompressionRequest) + .withMetricCollector(apiCallMetricCollector) + .putExecutionAttribute(SdkInternalExecutionAttribute.REQUEST_COMPRESSION, + RequestCompression.builder().encodings("gzip").isStreaming(false).build()) + .withMarshaller(new OperationWithRequestCompressionRequestMarshaller(protocolFactory))); + } finally { + metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + } + } + + /** + * Some paginated operation with result_key in paginators.json file + * + * @param paginatedOperationWithResultKeyRequest + * @return Result of the PaginatedOperationWithResultKey operation returned by the service. + * @throws SdkException + * Base class for all exceptions that can be thrown by the SDK (both service and client). Can be used for + * catch all scenarios. + * @throws SdkClientException + * If any client side error occurs such as an IO related failure, failure to get credentials, etc. + * @throws JsonException + * Base class for all service exceptions. Unknown exceptions will be thrown as an instance of this type. + * @sample JsonClient.PaginatedOperationWithResultKey + * @see AWS API Documentation + */ + @Override + public PaginatedOperationWithResultKeyResponse paginatedOperationWithResultKey( + PaginatedOperationWithResultKeyRequest paginatedOperationWithResultKeyRequest) throws AwsServiceException, + SdkClientException, JsonException { + JsonOperationMetadata operationMetadata = JsonOperationMetadata.builder().hasStreamingSuccessResponse(false) + .isPayloadJson(true).build(); + + HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( + operationMetadata, PaginatedOperationWithResultKeyResponse::builder); + + HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, + operationMetadata); + SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(paginatedOperationWithResultKeyRequest, + this.clientConfiguration); + List metricPublishers = resolveMetricPublishers(clientConfiguration, + paginatedOperationWithResultKeyRequest.overrideConfiguration().orElse(null)); + MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector + .create("ApiCall"); + try { + apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Json Service"); + apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "PaginatedOperationWithResultKey"); + + return clientHandler + .execute(new ClientExecutionParams() + .withOperationName("PaginatedOperationWithResultKey").withProtocolMetadata(protocolMetadata) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withInput(paginatedOperationWithResultKeyRequest) + .withMetricCollector(apiCallMetricCollector) + .withMarshaller(new PaginatedOperationWithResultKeyRequestMarshaller(protocolFactory))); + } finally { + metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + } + } + + /** + * Some paginated operation without result_key in paginators.json file + * + * @param paginatedOperationWithoutResultKeyRequest + * @return Result of the PaginatedOperationWithoutResultKey operation returned by the service. + * @throws SdkException + * Base class for all exceptions that can be thrown by the SDK (both service and client). Can be used for + * catch all scenarios. + * @throws SdkClientException + * If any client side error occurs such as an IO related failure, failure to get credentials, etc. + * @throws JsonException + * Base class for all service exceptions. Unknown exceptions will be thrown as an instance of this type. + * @sample JsonClient.PaginatedOperationWithoutResultKey + * @see AWS API Documentation + */ + @Override + public PaginatedOperationWithoutResultKeyResponse paginatedOperationWithoutResultKey( + PaginatedOperationWithoutResultKeyRequest paginatedOperationWithoutResultKeyRequest) throws AwsServiceException, + SdkClientException, JsonException { + JsonOperationMetadata operationMetadata = JsonOperationMetadata.builder().hasStreamingSuccessResponse(false) + .isPayloadJson(true).build(); + + HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( + operationMetadata, PaginatedOperationWithoutResultKeyResponse::builder); + + HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, + operationMetadata); + SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(paginatedOperationWithoutResultKeyRequest, + this.clientConfiguration); + List metricPublishers = resolveMetricPublishers(clientConfiguration, + paginatedOperationWithoutResultKeyRequest.overrideConfiguration().orElse(null)); + MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector + .create("ApiCall"); + try { + apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Json Service"); + apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "PaginatedOperationWithoutResultKey"); + + return clientHandler + .execute(new ClientExecutionParams() + .withOperationName("PaginatedOperationWithoutResultKey").withProtocolMetadata(protocolMetadata) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withInput(paginatedOperationWithoutResultKeyRequest) + .withMetricCollector(apiCallMetricCollector) + .withMarshaller(new PaginatedOperationWithoutResultKeyRequestMarshaller(protocolFactory))); + } finally { + metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + } + } + + /** + * Some operation with a streaming input + * + * @param streamingInputOperationRequest + * @param requestBody + * The content to send to the service. A {@link RequestBody} can be created using one of several factory + * methods for various sources of data. For example, to create a request body from a file you can do the + * following. + * + *
+     * {@code RequestBody.fromFile(new File("myfile.txt"))}
+     * 
+ * + * See documentation in {@link RequestBody} for additional details and which sources of data are supported. + * The service documentation for the request content is as follows 'This be a stream' + * @return Result of the StreamingInputOperation operation returned by the service. + * @throws SdkException + * Base class for all exceptions that can be thrown by the SDK (both service and client). Can be used for + * catch all scenarios. + * @throws SdkClientException + * If any client side error occurs such as an IO related failure, failure to get credentials, etc. + * @throws JsonException + * Base class for all service exceptions. Unknown exceptions will be thrown as an instance of this type. + * @sample JsonClient.StreamingInputOperation + * @see AWS API Documentation + */ + @Override + public StreamingInputOperationResponse streamingInputOperation(StreamingInputOperationRequest streamingInputOperationRequest, + RequestBody requestBody) throws AwsServiceException, SdkClientException, JsonException { + JsonOperationMetadata operationMetadata = JsonOperationMetadata.builder().hasStreamingSuccessResponse(false) + .isPayloadJson(true).build(); + + HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( + operationMetadata, StreamingInputOperationResponse::builder); + + HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, + operationMetadata); + SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(streamingInputOperationRequest, + this.clientConfiguration); + List metricPublishers = resolveMetricPublishers(clientConfiguration, streamingInputOperationRequest + .overrideConfiguration().orElse(null)); + MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector + .create("ApiCall"); + try { + apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Json Service"); + apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "StreamingInputOperation"); + + return clientHandler + .execute(new ClientExecutionParams() + .withOperationName("StreamingInputOperation") + .withProtocolMetadata(protocolMetadata) + .withResponseHandler(responseHandler) + .withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration) + .withInput(streamingInputOperationRequest) + .withMetricCollector(apiCallMetricCollector) + .withRequestBody(requestBody) + .withMarshaller( + StreamingRequestMarshaller.builder() + .delegateMarshaller(new StreamingInputOperationRequestMarshaller(protocolFactory)) + .requestBody(requestBody).build())); + } finally { + metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + } + } + + /** + * Some operation with streaming input and streaming output + * + * @param streamingInputOutputOperationRequest + * @param requestBody + * The content to send to the service. A {@link RequestBody} can be created using one of several factory + * methods for various sources of data. For example, to create a request body from a file you can do the + * following. + * + *
+     * {@code RequestBody.fromFile(new File("myfile.txt"))}
+     * 
+ * + * See documentation in {@link RequestBody} for additional details and which sources of data are supported. + * The service documentation for the request content is as follows 'This be a stream' + * @param responseTransformer + * Functional interface for processing the streamed response content. The unmarshalled + * StreamingInputOutputOperationResponse and an InputStream to the response content are provided as + * parameters to the callback. The callback may return a transformed type which will be the return value of + * this method. See {@link software.amazon.awssdk.core.sync.ResponseTransformer} for details on implementing + * this interface and for links to pre-canned implementations for common scenarios like downloading to a + * file. The service documentation for the response content is as follows 'This be a stream'. + * @return The transformed result of the ResponseTransformer. + * @throws SdkException + * Base class for all exceptions that can be thrown by the SDK (both service and client). Can be used for + * catch all scenarios. + * @throws SdkClientException + * If any client side error occurs such as an IO related failure, failure to get credentials, etc. + * @throws JsonException + * Base class for all service exceptions. Unknown exceptions will be thrown as an instance of this type. + * @sample JsonClient.StreamingInputOutputOperation + * @see AWS API Documentation + */ + @Override + public ReturnT streamingInputOutputOperation( + StreamingInputOutputOperationRequest streamingInputOutputOperationRequest, RequestBody requestBody, + ResponseTransformer responseTransformer) throws AwsServiceException, + SdkClientException, JsonException { + JsonOperationMetadata operationMetadata = JsonOperationMetadata.builder().hasStreamingSuccessResponse(true) + .isPayloadJson(false).build(); + + HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( + operationMetadata, StreamingInputOutputOperationResponse::builder); + + HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, + operationMetadata); + SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(streamingInputOutputOperationRequest, + this.clientConfiguration); + List metricPublishers = resolveMetricPublishers(clientConfiguration, + streamingInputOutputOperationRequest.overrideConfiguration().orElse(null)); + MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector + .create("ApiCall"); + try { + apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Json Service"); + apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "StreamingInputOutputOperation"); + + return clientHandler.execute( + new ClientExecutionParams() + .withOperationName("StreamingInputOutputOperation") + .withProtocolMetadata(protocolMetadata) + .withResponseHandler(responseHandler) + .withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration) + .withInput(streamingInputOutputOperationRequest) + .withMetricCollector(apiCallMetricCollector) + .withRequestBody(requestBody) + .withMarshaller( + StreamingRequestMarshaller + .builder() + .delegateMarshaller( + new StreamingInputOutputOperationRequestMarshaller(protocolFactory)) + .requestBody(requestBody).transferEncoding(true).build()), responseTransformer); + } finally { + metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + } + } + + /** + * Some operation with a streaming output + * + * @param streamingOutputOperationRequest + * @param responseTransformer + * Functional interface for processing the streamed response content. The unmarshalled + * StreamingOutputOperationResponse and an InputStream to the response content are provided as parameters to + * the callback. The callback may return a transformed type which will be the return value of this method. + * See {@link software.amazon.awssdk.core.sync.ResponseTransformer} for details on implementing this + * interface and for links to pre-canned implementations for common scenarios like downloading to a file. The + * service documentation for the response content is as follows 'This be a stream'. + * @return The transformed result of the ResponseTransformer. + * @throws SdkException + * Base class for all exceptions that can be thrown by the SDK (both service and client). Can be used for + * catch all scenarios. + * @throws SdkClientException + * If any client side error occurs such as an IO related failure, failure to get credentials, etc. + * @throws JsonException + * Base class for all service exceptions. Unknown exceptions will be thrown as an instance of this type. + * @sample JsonClient.StreamingOutputOperation + * @see AWS API Documentation + */ + @Override + public ReturnT streamingOutputOperation(StreamingOutputOperationRequest streamingOutputOperationRequest, + ResponseTransformer responseTransformer) throws AwsServiceException, + SdkClientException, JsonException { + JsonOperationMetadata operationMetadata = JsonOperationMetadata.builder().hasStreamingSuccessResponse(true) + .isPayloadJson(false).build(); + + HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( + operationMetadata, StreamingOutputOperationResponse::builder); + + HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, + operationMetadata); + SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(streamingOutputOperationRequest, + this.clientConfiguration); + List metricPublishers = resolveMetricPublishers(clientConfiguration, streamingOutputOperationRequest + .overrideConfiguration().orElse(null)); + MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector + .create("ApiCall"); + try { + apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Json Service"); + apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "StreamingOutputOperation"); + + return clientHandler.execute( + new ClientExecutionParams() + .withOperationName("StreamingOutputOperation").withProtocolMetadata(protocolMetadata) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withInput(streamingOutputOperationRequest) + .withMetricCollector(apiCallMetricCollector) + .withMarshaller(new StreamingOutputOperationRequestMarshaller(protocolFactory)), responseTransformer); + } finally { + metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + } + } + + /** + * Creates an instance of {@link JsonUtilities} object with the configuration set on this client. + */ + @Override + public JsonUtilities utilities() { + return JsonUtilities.create(param1, param2, param3); + } + + @Override + public final String serviceName() { + return SERVICE_NAME; + } + + private static List resolveMetricPublishers(SdkClientConfiguration clientConfiguration, + RequestOverrideConfiguration requestOverrideConfiguration) { + List publishers = null; + if (requestOverrideConfiguration != null) { + publishers = requestOverrideConfiguration.metricPublishers(); + } + if (publishers == null || publishers.isEmpty()) { + publishers = clientConfiguration.option(SdkClientOption.METRIC_PUBLISHERS); + } + if (publishers == null) { + publishers = Collections.emptyList(); + } + return publishers; + } + + private HttpResponseHandler createErrorResponseHandler(BaseAwsJsonProtocolFactory protocolFactory, + JsonOperationMetadata operationMetadata) { + return protocolFactory.createErrorResponseHandler(operationMetadata); + } + + private void updateRetryStrategyClientConfiguration(SdkClientConfiguration.Builder configuration) { + ClientOverrideConfiguration.Builder builder = configuration.asOverrideConfigurationBuilder(); + RetryMode retryMode = builder.retryMode(); + if (retryMode != null) { + configuration.option(SdkClientOption.RETRY_STRATEGY, AwsRetryStrategy.forRetryMode(retryMode)); + } else { + Consumer> configurator = builder.retryStrategyConfigurator(); + if (configurator != null) { + RetryStrategy.Builder defaultBuilder = AwsRetryStrategy.defaultRetryStrategy().toBuilder(); + configurator.accept(defaultBuilder); + configuration.option(SdkClientOption.RETRY_STRATEGY, defaultBuilder.build()); + } else { + RetryStrategy retryStrategy = builder.retryStrategy(); + if (retryStrategy != null) { + configuration.option(SdkClientOption.RETRY_STRATEGY, retryStrategy); + } + } + } + configuration.option(SdkClientOption.CONFIGURED_RETRY_MODE, null); + configuration.option(SdkClientOption.CONFIGURED_RETRY_STRATEGY, null); + configuration.option(SdkClientOption.CONFIGURED_RETRY_CONFIGURATOR, null); + } + + private SdkClientConfiguration updateSdkClientConfiguration(SdkRequest request, SdkClientConfiguration clientConfiguration) { + List plugins = request.overrideConfiguration().map(c -> c.plugins()).orElse(Collections.emptyList()); + SdkClientConfiguration.Builder configuration = clientConfiguration.toBuilder(); + if (plugins.isEmpty()) { + return configuration.build(); + } + JsonServiceClientConfigurationBuilder serviceConfigBuilder = new JsonServiceClientConfigurationBuilder(configuration); + for (SdkPlugin plugin : plugins) { + plugin.configureClient(serviceConfigBuilder); + } + updateRetryStrategyClientConfiguration(configuration); + return configuration.build(); + } + + private > T init(T builder) { + return builder + .clientConfiguration(clientConfiguration) + .defaultServiceExceptionSupplier(JsonException::builder) + .protocol(AwsJsonProtocol.AWS_JSON) + .protocolVersion("1.1") + .registerModeledException( + ExceptionMetadata.builder().errorCode("InvalidInputException") + .exceptionBuilderSupplier(InvalidInputException::builder).httpStatusCode(400).build()) + .registerModeledException( + ExceptionMetadata.builder().errorCode("ServiceFaultException") + .exceptionBuilderSupplier(ServiceFaultException::builder).httpStatusCode(500).build()); + } + + @Override + public final JsonServiceClientConfiguration serviceClientConfiguration() { + return new JsonServiceClientConfigurationBuilder(this.clientConfiguration.toBuilder()).build(); + } + + @Override + public void close() { + clientHandler.close(); + } +} diff --git a/services/kinesis/src/test/java/software/amazon/awssdk/services/kinesis/SubscribeToShardUnmarshallingTest.java b/services/kinesis/src/test/java/software/amazon/awssdk/services/kinesis/SubscribeToShardUnmarshallingTest.java index 9e65a7ffa4d2..ebaa494f3b26 100644 --- a/services/kinesis/src/test/java/software/amazon/awssdk/services/kinesis/SubscribeToShardUnmarshallingTest.java +++ b/services/kinesis/src/test/java/software/amazon/awssdk/services/kinesis/SubscribeToShardUnmarshallingTest.java @@ -101,7 +101,7 @@ public void exceptionWithMessage_UnmarshalledCorrectly() throws Throwable { fail("Expected ResourceNotFoundException exception"); } catch (ResourceNotFoundException e) { assertThat(e.requestId()).isEqualTo(REQUEST_ID); - assertThat(e.statusCode()).isEqualTo(500); + assertThat(e.statusCode()).isEqualTo(400); assertThat(e.awsErrorDetails().errorCode()).isEqualTo(errorCode); assertThat(e.awsErrorDetails().errorMessage()).isEqualTo("foo"); assertThat(e.awsErrorDetails().serviceName()).isEqualTo("kinesis"); diff --git a/test/protocol-tests/pom.xml b/test/protocol-tests/pom.xml index 6961c44e5600..54f900fb0ef5 100644 --- a/test/protocol-tests/pom.xml +++ b/test/protocol-tests/pom.xml @@ -42,11 +42,21 @@ + + software.amazon.awssdk + third-party-jackson-dataformat-cbor + ${awsjavasdk.version} + software.amazon.awssdk aws-json-protocol ${awsjavasdk.version} + + software.amazon.awssdk + aws-cbor-protocol + ${awsjavasdk.version} + software.amazon.awssdk aws-query-protocol diff --git a/test/protocol-tests/src/main/resources/codegen-resources/cbor/customization.config b/test/protocol-tests/src/main/resources/codegen-resources/cbor/customization.config new file mode 100644 index 000000000000..afc50773a582 --- /dev/null +++ b/test/protocol-tests/src/main/resources/codegen-resources/cbor/customization.config @@ -0,0 +1,32 @@ +{ + "verifiedSimpleMethods" : [ + "allTypes", + "deleteOperation", + "mapOfStringToListOfStringInQueryParams", + "membersInHeaders", + "membersInQueryParams", + "operationWithExplicitPayloadBlob", + "operationWithModeledContentType", + "queryParamWithoutValue", + "restXmlTypes", + "idempotentOperation", + "nestedContainers", + "operationWithNoInputOrOutput", + "furtherNestedContainers" + ], + "shapeModifiers": { + "AllTypesStructure": { + "modify":[ + { + "BigDecimalMember": { + "emitAsType": "bigdecimal" + } + } + ] + } + }, + "skipEndpointTestGeneration": true, + "customServiceMetadata": { + "protocol": "cbor" + } +} diff --git a/test/protocol-tests/src/main/resources/codegen-resources/cbor/endpoint-rule-set.json b/test/protocol-tests/src/main/resources/codegen-resources/cbor/endpoint-rule-set.json new file mode 100644 index 000000000000..f05fbec2e671 --- /dev/null +++ b/test/protocol-tests/src/main/resources/codegen-resources/cbor/endpoint-rule-set.json @@ -0,0 +1,355 @@ +{ + "version": "1.3", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": true, + "documentation": "The AWS region used to dispatch the request.", + "type": "String" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "Boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "Boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "String" + } + }, + "rules": [ + { + "conditions": [ + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + } + ], + "type": "tree", + "rules": [ + { + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "parseURL", + "argv": [ + { + "ref": "Endpoint" + } + ], + "assign": "url" + } + ], + "type": "tree", + "rules": [ + { + "conditions": [ + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + } + ], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "type": "tree", + "rules": [ + { + "conditions": [ + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + } + ], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "{Region}", + "signingName": "jsonrpc" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + } + ] + } + ] + }, + { + "conditions": [ + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + } + ], + "type": "tree", + "rules": [ + { + "conditions": [ + { + "fn": "booleanEquals", + "argv": [ + true, + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + } + ] + }, + { + "fn": "booleanEquals", + "argv": [ + true, + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + } + ] + } + ], + "type": "tree", + "rules": [ + { + "conditions": [], + "endpoint": { + "url": "https://jsonrpc-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "{Region}", + "signingName": "jsonrpc" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + } + ] + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + } + ] + }, + { + "conditions": [ + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + } + ], + "type": "tree", + "rules": [ + { + "conditions": [ + { + "fn": "booleanEquals", + "argv": [ + true, + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + } + ] + } + ], + "type": "tree", + "rules": [ + { + "conditions": [], + "type": "tree", + "rules": [ + { + "conditions": [], + "endpoint": { + "url": "https://jsonrpc-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "{Region}", + "signingName": "jsonrpc" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + } + ] + } + ] + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + } + ] + }, + { + "conditions": [ + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + } + ], + "type": "tree", + "rules": [ + { + "conditions": [ + { + "fn": "booleanEquals", + "argv": [ + true, + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + } + ] + } + ], + "type": "tree", + "rules": [ + { + "conditions": [], + "endpoint": { + "url": "https://jsonrpc.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "{Region}", + "signingName": "jsonrpc" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + } + ] + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + } + ] + }, + { + "conditions": [], + "endpoint": { + "url": "https://jsonrpc.{Region}.{PartitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "{Region}", + "signingName": "jsonrpc" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + } + ] + } + ] +} \ No newline at end of file diff --git a/test/protocol-tests/src/main/resources/codegen-resources/cbor/endpoint-tests.json b/test/protocol-tests/src/main/resources/codegen-resources/cbor/endpoint-tests.json new file mode 100644 index 000000000000..f94902ff9d99 --- /dev/null +++ b/test/protocol-tests/src/main/resources/codegen-resources/cbor/endpoint-tests.json @@ -0,0 +1,5 @@ +{ + "testCases": [ + ], + "version": "1.0" +} \ No newline at end of file diff --git a/test/protocol-tests/src/main/resources/codegen-resources/cbor/service-2.json b/test/protocol-tests/src/main/resources/codegen-resources/cbor/service-2.json new file mode 100644 index 000000000000..e8f86a54d5e6 --- /dev/null +++ b/test/protocol-tests/src/main/resources/codegen-resources/cbor/service-2.json @@ -0,0 +1,409 @@ +{ + "version":"2.0", + "metadata":{ + "apiVersion":"2016-03-11", + "endpointPrefix":"cbor", + "jsonVersion":"1.1", + "protocol":"json", + "serviceAbbreviation":"CborProtocolTests", + "serviceFullName":"AWS DR Tools CBOR Protocol Tests", + "serviceId":"ProtocolCbor", + "signatureVersion":"v4", + "targetPrefix":"ProtocolTestsCborService", + "uid":"cbor-2016-03-11" + }, + "operations":{ + "AllTypes":{ + "name":"AllTypes", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"AllTypesStructure"}, + "output":{"shape":"AllTypesStructure"}, + "errors":[ + {"shape":"EmptyModeledException"}, + {"shape":"ImplicitPayloadException"} + ] + }, + "FurtherNestedContainers":{ + "name":"FurtherNestedContainers", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"FurtherNestedContainersStructure"}, + "output":{"shape":"FurtherNestedContainersStructure"} + }, + "IdempotentOperation":{ + "name":"IdempotentOperation", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"IdempotentOperationStructure"}, + "output":{"shape":"IdempotentOperationStructure"} + }, + "NestedContainers":{ + "name":"NestedContainers", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"NestedContainersStructure"}, + "output":{"shape":"NestedContainersStructure"} + }, + "OperationWithNoInputOrOutput":{ + "name":"OperationWithNoInputOrOutput", + "http":{ + "method":"POST", + "requestUri":"/" + } + } + }, + "shapes":{ + "AllTypesStructure":{ + "type":"structure", + "members":{ + "StringMember":{"shape":"String"}, + "IntegerMember":{"shape":"Integer"}, + "BooleanMember":{"shape":"Boolean"}, + "FloatMember":{"shape":"Float"}, + "DoubleMember":{"shape":"Double"}, + "BigDecimalMember":{"shape":"NumericValue"}, + "LongMember":{"shape":"Long"}, + "ShortMember":{"shape":"Short"}, + "ByteMember":{"shape":"Byte"}, + "SimpleList":{"shape":"ListOfStrings"}, + "ListOfMaps":{"shape":"ListOfMapStringToString"}, + "ListOfStructs":{"shape":"ListOfSimpleStructs"}, + "MapOfStringToIntegerList":{"shape":"MapOfStringToIntegerList"}, + "MapOfStringToString":{"shape":"MapOfStringToString"}, + "MapOfStringToStruct":{"shape":"MapOfStringToSimpleStruct"}, + "TimestampMember":{"shape":"Timestamp"}, + "StructWithNestedTimestampMember":{"shape":"StructWithTimestamp"}, + "TimestampFormatMember":{"shape":"IsoTimestamp"}, + "BlobArg":{"shape":"BlobType"}, + "StructWithNestedBlob":{"shape":"StructWithNestedBlobType"}, + "BlobMap":{"shape":"BlobMapType"}, + "ListOfBlobs":{"shape":"ListOfBlobsType"}, + "RecursiveStruct":{"shape":"RecursiveStructType"}, + "PolymorphicTypeWithSubTypes":{"shape":"BaseType"}, + "PolymorphicTypeWithoutSubTypes":{"shape":"SubTypeOne"}, + "EnumMember":{"shape":"EnumType"}, + "ListOfEnums":{"shape":"ListOfEnums"}, + "MapOfEnumToEnum":{"shape":"MapOfEnumToEnum"}, + "ListOfTimeStamp":{"shape":"ListOfTimeStamp"}, + "MapOfTimeStamp":{"shape":"MapOfTimeStamp"}, + "MyDocument":{"shape":"MyDocument"}, + "UnionMember":{"shape":"AllTypesUnionStructure"} + } + }, + "BaseType":{ + "type":"structure", + "members":{ + "BaseMember":{"shape":"String"} + } + }, + "BlobMapType":{ + "type":"map", + "key":{"shape":"String"}, + "value":{"shape":"BlobType"} + }, + "BlobType":{"type":"blob"}, + "Boolean":{"type":"boolean"}, + "Double":{"type":"double"}, + "EmptyModeledException":{ + "type":"structure", + "members":{ + }, + "exception":true + }, + "EnumType":{ + "type":"string", + "enum":[ + "EnumValue1", + "EnumValue2" + ] + }, + "Float":{"type":"float"}, + "Short":{"type":"short"}, + "Byte":{"type":"byte"}, + "FurtherNestedContainersStructure":{ + "type":"structure", + "members":{ + "ListOfNested":{"shape":"ListOfNested"} + } + }, + "IdempotentOperationStructure":{ + "type":"structure", + "members":{ + "IdempotencyToken":{ + "shape":"String", + "idempotencyToken":true + } + } + }, + "ImplicitPayloadException":{ + "type":"structure", + "members":{ + "StringMember":{"shape":"String"}, + "IntegerMember":{"shape":"Integer"}, + "LongMember":{"shape":"Long"}, + "ShortMember":{"shape":"Short"}, + "DoubleMember":{"shape":"Double"}, + "FloatMember":{"shape":"Float"}, + "TimestampMember":{"shape":"Timestamp"}, + "BooleanMember":{"shape":"Boolean"}, + "BlobMember":{"shape":"BlobType"}, + "ListMember":{"shape":"ListOfStrings"}, + "MapMember":{"shape":"MapOfStringToString"}, + "SimpleStructMember":{"shape":"SimpleStruct"} + }, + "exception":true + }, + "Integer":{"type":"integer"}, + // Shape is customized to BigDecimal in customization.config + "NumericValue": { + "type": "string", + "pattern":"([0-9]*\\.)?[0-9]+" + }, + "IsoTimestamp":{ + "type":"timestamp", + "timestampFormat":"iso8601" + }, + "UnixTimestamp":{ + "type":"timestamp", + "timestampFormat":"unixTimestamp" + }, + "ListOfAllTypesStructs":{ + "type":"list", + "member":{"shape":"AllTypesStructure"} + }, + "ListOfBlobsType":{ + "type":"list", + "member":{"shape":"BlobType"} + }, + "ListOfEnums":{ + "type":"list", + "member":{"shape":"EnumType"} + }, + "ListOfIntegers":{ + "type":"list", + "member":{"shape":"Integer"} + }, + "ListOfListOfListsOfStrings":{ + "type":"list", + "member":{"shape":"ListOfListsOfStrings"} + }, + "ListOfListsOfAllTypesStructs":{ + "type":"list", + "member":{"shape":"ListOfAllTypesStructs"} + }, + "ListOfListsOfStrings":{ + "type":"list", + "member":{"shape":"ListOfStrings"} + }, + "ListOfListsOfStructs":{ + "type":"list", + "member":{"shape":"ListOfSimpleStructs"} + }, + "ListOfMapStringToString":{ + "type":"list", + "member":{"shape":"MapOfStringToString"} + }, + "ListOfNested":{ + "type":"list", + "member":{"shape":"NestedContainersStructure"} + }, + "ListOfSimpleStructs":{ + "type":"list", + "member":{"shape":"SimpleStruct"} + }, + "ListOfStrings":{ + "type":"list", + "member":{"shape":"String"} + }, + "Long":{"type":"long"}, + "MapOfEnumToEnum":{ + "type":"map", + "key":{"shape":"EnumType"}, + "value":{"shape":"EnumType"} + }, + "MapOfStringToIntegerList":{ + "type":"map", + "key":{"shape":"String"}, + "value":{"shape":"ListOfIntegers"} + }, + "MapOfStringToListOfListsOfStrings":{ + "type":"map", + "key":{"shape":"String"}, + "value":{"shape":"ListOfListsOfStrings"} + }, + "MapOfStringToSimpleStruct":{ + "type":"map", + "key":{"shape":"String"}, + "value":{"shape":"SimpleStruct"} + }, + "MapOfStringToString":{ + "type":"map", + "key":{"shape":"String"}, + "value":{"shape":"String"} + }, + "NestedContainersStructure":{ + "type":"structure", + "members":{ + "ListOfListsOfStrings":{"shape":"ListOfListsOfStrings"}, + "ListOfListsOfStructs":{"shape":"ListOfListsOfStructs"}, + "ListOfListsOfAllTypesStructs":{"shape":"ListOfListsOfAllTypesStructs"}, + "ListOfListOfListsOfStrings":{"shape":"ListOfListOfListsOfStrings"}, + "MapOfStringToListOfListsOfStrings":{"shape":"MapOfStringToListOfListsOfStrings"}, + "StringMember":{"shape":"String"} + } + }, + "RecursiveListType":{ + "type":"list", + "member":{"shape":"RecursiveStructType"} + }, + "RecursiveMapType":{ + "type":"map", + "key":{"shape":"String"}, + "value":{"shape":"RecursiveStructType"} + }, + "RecursiveStructType":{ + "type":"structure", + "members":{ + "NoRecurse":{"shape":"String"}, + "RecursiveStruct":{"shape":"RecursiveStructType"}, + "RecursiveList":{"shape":"RecursiveListType"}, + "RecursiveMap":{"shape":"RecursiveMapType"} + } + }, + "SimpleStruct":{ + "type":"structure", + "members":{ + "StringMember":{"shape":"String"} + } + }, + "String":{"type":"string"}, + "StructWithNestedBlobType":{ + "type":"structure", + "members":{ + "NestedBlob":{"shape":"BlobType"} + } + }, + "StructWithTimestamp":{ + "type":"structure", + "members":{ + "NestedTimestamp":{"shape":"Timestamp"} + } + }, + "SubTypeOne":{ + "type":"structure", + "members":{ + "SubTypeOneMember":{"shape":"String"} + } + }, + "Timestamp":{"type":"timestamp"}, + "ListOfTimeStamp":{ + "type":"list", + "member":{"shape":"UnixTimestamp"} + }, + "MapOfTimeStamp":{ + "type":"map", + "key":{"shape":"String"}, + "value":{"shape":"UnixTimestamp"} + }, + "MyDocument": { + "type": "structure", + "document": true + }, + "AllTypesUnionStructure": { + "type": "structure", + "union": true, + "members": { + "StringMember": { + "shape": "String" + }, + "IntegerMember": { + "shape": "Integer" + }, + "BooleanMember": { + "shape": "Boolean" + }, + "FloatMember": { + "shape": "Float" + }, + "DoubleMember": { + "shape": "Double" + }, + "LongMember": { + "shape": "Long" + }, + "ShortMember": { + "shape": "Short" + }, + "EnumMember": { + "shape": "EnumType" + }, + "SimpleList": { + "shape": "ListOfStrings" + }, + "ListOfEnums": { + "shape": "ListOfEnums" + }, + "ListOfMaps": { + "shape": "ListOfMapStringToString" + }, + "ListOfStructs": { + "shape": "ListOfSimpleStructs" + }, + "MapOfStringToIntegerList": { + "shape": "MapOfStringToIntegerList" + }, + "MapOfStringToString": { + "shape": "MapOfStringToString" + }, + "MapOfStringToStruct": { + "shape": "MapOfStringToSimpleStruct" + }, + "MapOfEnumToEnum": { + "shape": "MapOfEnumToEnum" + }, + "TimestampMember": { + "shape": "Timestamp" + }, + "StructWithNestedTimestampMember": { + "shape": "StructWithTimestamp" + }, + "BlobArg": { + "shape": "BlobType" + }, + "StructWithNestedBlob": { + "shape": "StructWithNestedBlobType" + }, + "BlobMap": { + "shape": "BlobMapType" + }, + "ListOfBlobs": { + "shape": "ListOfBlobsType" + }, + "RecursiveStruct": { + "shape": "RecursiveStructType" + }, + "PolymorphicTypeWithSubTypes": { + "shape": "BaseType" + }, + "PolymorphicTypeWithoutSubTypes": { + "shape": "SubTypeOne" + }, + "SetPrefixedMember": { + "shape": "String" + }, + "UnionMember": { + "shape": "AllTypesUnionStructure" + } + } + } + } +} diff --git a/test/protocol-tests/src/test/java/software/amazon/awssdk/protocol/tests/exception/CborExceptionTest.java b/test/protocol-tests/src/test/java/software/amazon/awssdk/protocol/tests/exception/CborExceptionTest.java new file mode 100644 index 000000000000..fe4b83d776c3 --- /dev/null +++ b/test/protocol-tests/src/test/java/software/amazon/awssdk/protocol/tests/exception/CborExceptionTest.java @@ -0,0 +1,275 @@ +/* + * 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.protocol.tests.exception; + +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.post; +import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; +import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static software.amazon.awssdk.protocol.tests.util.exception.ExceptionTestUtils.stub404Response; + +import com.github.tomakehurst.wiremock.junit.WireMockRule; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.math.BigDecimal; +import java.net.URI; +import java.time.Instant; +import java.util.AbstractMap.SimpleEntry; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; +import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; +import software.amazon.awssdk.awscore.exception.AwsErrorDetails; +import software.amazon.awssdk.core.interceptor.Context; +import software.amazon.awssdk.core.interceptor.ExecutionAttributes; +import software.amazon.awssdk.core.interceptor.ExecutionInterceptor; +import software.amazon.awssdk.http.SdkHttpResponse; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.protocolcbor.ProtocolCborClient; +import software.amazon.awssdk.services.protocolcbor.model.AllTypesRequest; +import software.amazon.awssdk.services.protocolcbor.model.EmptyModeledException; +import software.amazon.awssdk.services.protocolcbor.model.ImplicitPayloadException; +import software.amazon.awssdk.services.protocolcbor.model.ProtocolCborException; +import software.amazon.awssdk.thirdparty.jackson.dataformat.cbor.CBORFactory; +import software.amazon.awssdk.thirdparty.jackson.dataformat.cbor.CBORGenerator; +import software.amazon.awssdk.utils.MapUtils; + +/** + * Exception related tests for CBOR. + */ +public class CborExceptionTest { + private static final String PATH = "/"; + + @Rule + public WireMockRule wireMock = new WireMockRule(0); + + private ProtocolCborClient client; + + private CBORFactory cborFactory; + + @Before + public void setupClient() { + client = ProtocolCborClient.builder() + .credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create("akid", "skid"))) + .region(Region.US_EAST_1) + .endpointOverride(URI.create("http://localhost:" + wireMock.port())) + .build(); + + cborFactory = new CBORFactory(); + } + + @Test + public void unmodeledException_UnmarshalledIntoBaseServiceException() throws IOException { + Map obj = MapUtils.of( + "__type", "SomeUnknownType" + ); + + stub404Response(PATH, toCbor(obj)); + assertThatThrownBy(() -> client.allTypes(AllTypesRequest.builder().build())) + .isExactlyInstanceOf(ProtocolCborException.class); + } + + @Test + public void modeledExceptionWithImplicitPayloadMembers_UnmarshalledIntoModeledException() throws IOException { + Map obj = new HashMap(); + obj.put("__type", "ImplicitPayloadException"); + obj.put("StringMember", "foo"); + obj.put("IntegerMember", Integer.valueOf(42)); + obj.put("LongMember", Long.valueOf(9001)); + obj.put("DoubleMember", Double.valueOf(1234.56)); + obj.put("FloatMember", Float.valueOf(789.10f)); + obj.put("TimestampMember", Long.valueOf(1398796238123L)); + obj.put("BooleanMember", true); + obj.put("BlobMember", "dGhlcmUh"); + obj.put("ListMember", Arrays.asList("valOne", "valTwo")); + obj.put("MapMember", MapUtils.of("keyOne", "valOne", "keyTwo", "valTwo")); + obj.put("SimpleStructMember", MapUtils.of("StringMember", "foobar")); + + stubFor(post(urlEqualTo(PATH)).willReturn( + aResponse().withStatus(404) + .withBody(toCbor(obj)))); + try { + client.allTypes(); + } catch (ImplicitPayloadException e) { + assertThat(e.stringMember()).isEqualTo("foo"); + assertThat(e.integerMember()).isEqualTo(42); + assertThat(e.longMember()).isEqualTo(9001); + assertThat(e.doubleMember()).isEqualTo(1234.56); + assertThat(e.floatMember()).isEqualTo(789.10f); + assertThat(e.timestampMember()).isEqualTo(Instant.ofEpochMilli(1398796238123L)); + assertThat(e.booleanMember()).isEqualTo(true); + assertThat(e.blobMember().asUtf8String()).isEqualTo("there!"); + assertThat(e.listMember()).contains("valOne", "valTwo"); + assertThat(e.mapMember()) + .containsOnly(new SimpleEntry<>("keyOne", "valOne"), + new SimpleEntry<>("keyTwo", "valTwo")); + assertThat(e.simpleStructMember().stringMember()).isEqualTo("foobar"); + } + } + + @Test + public void modeledException_UnmarshalledIntoModeledException() throws IOException { + Map obj = new HashMap(); + obj.put("__type", "EmptyModeledException"); + stub404Response(PATH, toCbor(obj)); + assertThatThrownBy(() -> client.allTypes(AllTypesRequest.builder().build())) + .isExactlyInstanceOf(EmptyModeledException.class); + } + + @Test + public void modeledException_HasExceptionMetadataSet() throws IOException { + Map obj = new HashMap(); + obj.put("__type", "EmptyModeledException"); + obj.put("Message", "This is the service message"); + stubFor(post(urlEqualTo(PATH)).willReturn( + aResponse() + .withStatus(404) + .withHeader("x-amzn-RequestId", "1234") + .withBody(toCbor(obj)))); + try { + client.allTypes(); + } catch (EmptyModeledException e) { + AwsErrorDetails awsErrorDetails = e.awsErrorDetails(); + assertThat(awsErrorDetails.errorCode()).isEqualTo("EmptyModeledException"); + assertThat(awsErrorDetails.errorMessage()).isEqualTo("This is the service message"); + assertThat(awsErrorDetails.serviceName()).isEqualTo("ProtocolCbor"); + assertThat(awsErrorDetails.sdkHttpResponse()).isNotNull(); + assertThat(e.requestId()).isEqualTo("1234"); + assertThat(e.extendedRequestId()).isNull(); + assertThat(e.statusCode()).isEqualTo(404); + } + } + + @Test + public void modeledException_HasExceptionMetadataIncludingExtendedRequestIdSet() throws IOException { + Map obj = new HashMap(); + obj.put("__type", "EmptyModeledException"); + obj.put("Message", "This is the service message"); + + stubFor(post(urlEqualTo(PATH)).willReturn( + aResponse() + .withStatus(404) + .withHeader("x-amzn-RequestId", "1234") + .withHeader("x-amz-id-2", "5678") + .withBody(toCbor(obj)))); + try { + client.allTypes(); + } catch (EmptyModeledException e) { + AwsErrorDetails awsErrorDetails = e.awsErrorDetails(); + assertThat(awsErrorDetails.errorCode()).isEqualTo("EmptyModeledException"); + assertThat(awsErrorDetails.errorMessage()).isEqualTo("This is the service message"); + assertThat(awsErrorDetails.serviceName()).isEqualTo("ProtocolCbor"); + assertThat(awsErrorDetails.sdkHttpResponse()).isNotNull(); + assertThat(e.requestId()).isEqualTo("1234"); + assertThat(e.extendedRequestId()).isEqualTo("5678"); + assertThat(e.statusCode()).isEqualTo(404); + } + } + + @Test + public void emptyErrorResponse_UnmarshalledIntoBaseServiceException() { + stub404Response(PATH, ""); + assertThatThrownBy(() -> client.allTypes(AllTypesRequest.builder().build())) + .isExactlyInstanceOf(ProtocolCborException.class); + } + + @Test + public void malformedErrorResponse_UnmarshalledIntoBaseServiceException() { + stub404Response(PATH, "THIS ISN'T CBOR"); + assertThatThrownBy(() -> client.allTypes(AllTypesRequest.builder().build())) + .isExactlyInstanceOf(ProtocolCborException.class); + } + + @Test + public void modeledException_responseCodeNotPresent_usesCodeFromMetadata() throws IOException { + Map obj = new HashMap(); + obj.put("__type", "EmptyModeledException"); + stub404Response(PATH, toCbor(obj)); + + ProtocolCborClient client = ProtocolCborClient.builder() + .credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create("akid", "skid"))) + .region(Region.US_EAST_1) + .endpointOverride(URI.create("http://localhost:" + wireMock.port())).overrideConfiguration(o -> o.addExecutionInterceptor(new ExecutionInterceptor() { + @Override + public SdkHttpResponse modifyHttpResponse(Context.ModifyHttpResponse context, ExecutionAttributes executionAttributes) { + return context.httpResponse().toBuilder().statusCode(0).build(); + } + })) + .build(); + + assertThatThrownBy(() -> client.allTypes(AllTypesRequest.builder().build())) + .isExactlyInstanceOf(EmptyModeledException.class) + .satisfies(e -> { + assertThat(((EmptyModeledException) e).statusCode()).isEqualTo(400); + }); + } + + private void mapToCbor(Map map, CBORGenerator generator) throws IOException { + + generator.writeStartObject(); + for (Map.Entry entry : map.entrySet()) { + generator.writeFieldName((String) entry.getKey()); + toCbor(entry.getValue(), generator); + } + generator.writeEndObject(); + } + + private void listToCbor(List list, CBORGenerator generator) throws IOException { + generator.writeStartArray(); + for (Object e : list) { + toCbor(e, generator); + } + generator.writeEndArray(); + } + + private void toCbor(Object val, CBORGenerator generator) throws IOException { + if (val instanceof String) { + generator.writeString((String) val); + } else if (val instanceof Integer) { + generator.writeNumber((Integer) val); + } else if (val instanceof Long) { + generator.writeNumber((Long) val); + } else if (val instanceof Double) { + generator.writeNumber((Double) val); + } else if (val instanceof Float) { + generator.writeNumber((Float) val); + } else if (val instanceof Boolean) { + generator.writeBoolean((Boolean) val); + } else if (val instanceof Map) { + mapToCbor((Map) val, generator); + } else if (val instanceof List) { + listToCbor((List) val, generator); + } else if (val instanceof BigDecimal) { + generator.writeNumber((BigDecimal) val); + } + } + + private byte[] toCbor(Object o) throws IOException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + CBORGenerator generator = cborFactory.createGenerator(baos); + toCbor(o, generator); + generator.flush(); + generator.close(); + return baos.toByteArray(); + } +} diff --git a/test/protocol-tests/src/test/java/software/amazon/awssdk/protocol/tests/util/exception/ExceptionTestUtils.java b/test/protocol-tests/src/test/java/software/amazon/awssdk/protocol/tests/util/exception/ExceptionTestUtils.java index 2c1a61181bb6..287c5126a331 100644 --- a/test/protocol-tests/src/test/java/software/amazon/awssdk/protocol/tests/util/exception/ExceptionTestUtils.java +++ b/test/protocol-tests/src/test/java/software/amazon/awssdk/protocol/tests/util/exception/ExceptionTestUtils.java @@ -32,4 +32,8 @@ public class ExceptionTestUtils { public static void stub404Response(String path, String body) { stubFor(post(urlEqualTo(path)).willReturn(aResponse().withStatus(404).withBody(body))); } + + public static void stub404Response(String path, byte[] body) { + stubFor(post(urlEqualTo(path)).willReturn(aResponse().withStatus(404).withBody(body))); + } }