Interface AsyncResponseTransformer<ResponseT,ResultT>

Type Parameters:
ResponseT - POJO response type.
ResultT - Type this response handler produces. I.E. the type you are transforming the response into.
All Known Implementing Classes:
AsyncResponseTransformerListener.NotifyingAsyncResponseTransformer, ByteArrayAsyncResponseTransformer, CrtResponseFileResponseTransformer, EventStreamAsyncResponseTransformer, FileAsyncResponseTransformer, InputStreamResponseTransformer, PublisherAsyncResponseTransformer, RestEventStreamAsyncResponseTransformer

@SdkPublicApi @SdkAdvancedApi(cautionWhen=IMPLEMENTED, guidance="prepare() is called on each request attempt; if the CompletableFuture it returned on a previous attempt has already completed, it must return a new instance so the result of a retry is not lost, and exceptionOccurred() should release any resources the attempt opened (for example an open file channel) so retries do not leak them. onStream() receives the response body as a reactive-streams Publisher that the implementation subscribes to, and that subscriber must comply with the reactive-streams specification; a subscriber that never requests data stalls the response.", saferAlternative="Prefer the AsyncResponseTransformer.toFile/toBytes/toBlockingInputStream factories.") public interface AsyncResponseTransformer<ResponseT,ResultT>
Callback interface to handle a streaming asynchronous response.

Synchronization

All operations, including those called on the Subscriber of the stream are guaranteed to be synchronized externally; i.e. no two methods on this interface or on the Subscriber will be invoked concurrently. It is not guaranteed that the methods will being invoked by the same thread.

Invocation Order

The methods are called in the following order:

  • prepare(): This method is always called first. Implementations should use this to setup or perform any cleanup necessary. Note that this will be called upon each request attempt. If the CompletableFuture returned from the previous invocation has already been completed, the implementation should return a new instance.
  • onResponse(ResponseT): If the response was received successfully, this method is called next.
  • onStream(SdkPublisher): Called after onResponse. This is always invoked, even if the service operation response does not contain a body. If the response does not have a body, then the SdkPublisher will complete the subscription without signaling any elements.
  • exceptionOccurred(Throwable): If there is an error sending the request. This method is called before Subscriber.onError(Throwable).
  • Subscriber.onError(Throwable): If an error is encountered while the Publisher is publishing to a Subscriber.

Retries

The transformer has the ability to trigger retries at any time by completing the CompletableFuture with an exception that is deemed retryable by the configured RetryPolicy.

  • Method Details

    • prepare

      Initial call to enable any setup required before the response is handled.

      Note that this will be called for each request attempt, up to the number of retries allowed by the configured RetryPolicy.

      This method is guaranteed to be called before the request is executed, and before onResponse(Object) is signaled.

      Returns:
      The future holding the transformed response.
    • onResponse

      void onResponse(ResponseT response)
      Called when the unmarshalled response object is ready.
      Parameters:
      response - The unmarshalled response.
    • onStream

      void onStream(SdkPublisher<ByteBuffer> publisher)
      Called when the response stream is ready.
      Parameters:
      publisher - The publisher.
    • exceptionOccurred

      void exceptionOccurred(Throwable error)
      Called when an error is encountered while making the request or receiving the response. Implementations should free up any resources in this method. This method may be called multiple times during the lifecycle of a request if automatic retries are enabled.
      Parameters:
      error - Error that occurred.
    • split

      Creates an AsyncResponseTransformer.SplitResult which contains an SplittingTransformer that splits the AsyncResponseTransformer into multiple ones, publishing them as a SdkPublisher.
      Parameters:
      splitConfig - configuration for the split transformer
      Returns:
      SplitAsyncResponseTransformer instance.
      See Also:
    • split

      Creates an AsyncResponseTransformer.SplitResult which contains an SplittingTransformer that splits the AsyncResponseTransformer into multiple ones, publishing them as a SdkPublisher.
      Parameters:
      splitConfig - configuration for the split transformer
      Returns:
      SplitAsyncResponseTransformer instance.
      See Also:
    • name

      default String name()
      Each AsyncResponseTransformer should return a well-formed name that can be used to identify the implementation. The Transformer name should only include alphanumeric characters.
      Returns:
      String containing the identifying name of this AsyncRequestTransformer.
    • toFile

      static <ResponseT> AsyncResponseTransformer<ResponseT,ResponseT> toFile(Path path)
      Creates an AsyncResponseTransformer that writes all the content to the given file. In the event of an error, the SDK will attempt to delete the file (whatever has been written to it so far). If the file already exists, an exception will be thrown.

      The file's parent directories must already exist. The SDK will not auto-create directories, and a NoSuchFileException will be thrown if they are missing.

      Type Parameters:
      ResponseT - Pojo Response type.
      Parameters:
      path - Path to file to write to.
      Returns:
      AsyncResponseTransformer instance.
      See Also:
    • toFile

      static <ResponseT> AsyncResponseTransformer<ResponseT,ResponseT> toFile(Path path, FileTransformerConfiguration config)
      Creates an AsyncResponseTransformer that writes all the content to the given file with the specified FileTransformerConfiguration.

      The file's parent directories must already exist. The SDK will not auto-create directories, and a NoSuchFileException will be thrown if they are missing.

      Type Parameters:
      ResponseT - Pojo Response type.
      Parameters:
      path - Path to file to write to.
      config - configuration for the transformer
      Returns:
      AsyncResponseTransformer instance.
      See Also:
    • toFile

      static <ResponseT> AsyncResponseTransformer<ResponseT,ResponseT> toFile(Path path, Consumer<FileTransformerConfiguration.Builder> config)
      This is a convenience method that creates an instance of the FileTransformerConfiguration builder, avoiding the need to create one manually via FileTransformerConfiguration.builder().
      See Also:
    • toFile

      static <ResponseT> AsyncResponseTransformer<ResponseT,ResponseT> toFile(File file)
      Creates an AsyncResponseTransformer that writes all the content to the given file. In the event of an error, the SDK will attempt to delete the file (whatever has been written to it so far). If the file already exists, an exception will be thrown.

      The file's parent directories must already exist. The SDK will not auto-create directories, and a NoSuchFileException will be thrown if they are missing.

      Type Parameters:
      ResponseT - Pojo Response type.
      Parameters:
      file - File to write to.
      Returns:
      AsyncResponseTransformer instance.
    • toFile

      static <ResponseT> AsyncResponseTransformer<ResponseT,ResponseT> toFile(File file, FileTransformerConfiguration config)
      Creates an AsyncResponseTransformer that writes all the content to the given file with the specified FileTransformerConfiguration.
      Type Parameters:
      ResponseT - Pojo Response type.
      Parameters:
      file - File to write to.
      config - configuration for the transformer
      Returns:
      AsyncResponseTransformer instance.
      See Also:
    • toFile

      static <ResponseT> AsyncResponseTransformer<ResponseT,ResponseT> toFile(File file, Consumer<FileTransformerConfiguration.Builder> config)
      This is a convenience method that creates an instance of the FileTransformerConfiguration builder, avoiding the need to create one manually via FileTransformerConfiguration.builder().
      See Also:
    • toBytes

      static <ResponseT> AsyncResponseTransformer<ResponseT,ResponseBytes<ResponseT>> toBytes()
      Creates an AsyncResponseTransformer that writes all content to a byte array.
      Type Parameters:
      ResponseT - Pojo response type.
      Returns:
      AsyncResponseTransformer instance.
    • toPublisher

      @SdkAdvancedApi(cautionWhen=CALLED, guidance="The returned ResponsePublisher is a reactive-streams Publisher you must subscribe to and drive: your subscriber must obey the reactive-streams specification and honor back-pressure. A subscriber that never requests data stalls the response, and requesting unbounded data can exhaust memory.", saferAlternative="Prefer the fully-managed AsyncResponseTransformer.toFile/toBytes factories, which do not hand you a publisher to drive. If you do consume the publisher, use an established reactive-streams library such as RxJava or Reactor rather than a hand-written Subscriber.") static <ResponseT extends SdkResponse> AsyncResponseTransformer<ResponseT,ResponsePublisher<ResponseT>> toPublisher()
      Creates an AsyncResponseTransformer that publishes the response body content through a ResponsePublisher, which is an SdkPublisher that also contains a reference to the SdkResponse returned by the service.

      When this transformer is used with an async client, the CompletableFuture that the client returns will be completed once the SdkResponse is available and the response body begins streaming. This behavior differs from some other transformers, like toFile(Path) and toBytes(), which only have their CompletableFuture completed after the entire response body has finished streaming.

      The publisher has a default timeout of 60 seconds that starts when the response body begins streaming. If no subscriber is registered within this time, the subscription will be automatically cancelled. Use toPublisher(Duration) to specify a custom timeout.

      You are responsible for subscribing to this publisher and managing the associated back-pressure. Therefore, this transformer is only recommended for advanced use cases.

      Example usage:

       
           CompletableFuture<ResponsePublisher<GetObjectResponse>> responseFuture =
               s3AsyncClient.getObject(getObjectRequest, AsyncResponseTransformer.toPublisher());
           ResponsePublisher<GetObjectResponse> responsePublisher = responseFuture.join();
           System.out.println(responsePublisher.response());
           CompletableFuture<Void> drainPublisherFuture = responsePublisher.subscribe(System.out::println);
           drainPublisherFuture.join();
       
       
      Type Parameters:
      ResponseT - Pojo response type.
      Returns:
      AsyncResponseTransformer instance.
    • toPublisher

      @SdkAdvancedApi(cautionWhen=CALLED, guidance="The returned ResponsePublisher is a reactive-streams Publisher you must subscribe to and drive: your subscriber must obey the reactive-streams specification and honor back-pressure. A subscriber that never requests data stalls the response, and requesting unbounded data can exhaust memory.", saferAlternative="Prefer the fully-managed AsyncResponseTransformer.toFile/toBytes factories, which do not hand you a publisher to drive. If you do consume the publisher, use an established reactive-streams library such as RxJava or Reactor rather than a hand-written Subscriber.") static <ResponseT extends SdkResponse> AsyncResponseTransformer<ResponseT,ResponsePublisher<ResponseT>> toPublisher(Duration timeout)
      Creates an AsyncResponseTransformer with a custom timeout that publishes the response body content through a ResponsePublisher, which is an SdkPublisher that also contains a reference to the SdkResponse returned by the service.

      When this transformer is used with an async client, the CompletableFuture that the client returns will be completed once the SdkResponse is available and the response body begins streaming. This behavior differs from some other transformers, like toFile(Path) and toBytes(), which only have their CompletableFuture completed after the entire response body has finished streaming.

      The timeout starts when the response body begins streaming. If no subscriber is registered within the specified timeout, the subscription will be automatically cancelled. To disable the timeout, pass Duration.ZERO or a negative Duration.

      You are responsible for subscribing to this publisher and managing the associated back-pressure. Therefore, this transformer is only recommended for advanced use cases.

      Type Parameters:
      ResponseT - Pojo response type.
      Parameters:
      timeout - Maximum time to wait for subscription before cancelling. Use Duration.ZERO or a negative Duration to disable timeout.
      Returns:
      AsyncResponseTransformer instance.
      See Also:
    • toBlockingInputStream

      static <ResponseT extends SdkResponse> AsyncResponseTransformer<ResponseT,ResponseInputStream<ResponseT>> toBlockingInputStream()
      Creates an AsyncResponseTransformer that allows reading the response body content as an InputStream.

      When this transformer is used with an async client, the CompletableFuture that the client returns will be completed once the SdkResponse is available and the response body begins streaming. This behavior differs from some other transformers, like toFile(Path) and toBytes(), which only have their CompletableFuture completed after the entire response body has finished streaming.

      You are responsible for performing blocking reads from this input stream and closing the stream when you are finished.

      Example usage:

       
           CompletableFuture<ResponseInputStream<GetObjectResponse>> responseFuture =
               s3AsyncClient.getObject(getObjectRequest, AsyncResponseTransformer.toBlockingInputStream());
           try (ResponseInputStream<GetObjectResponse> responseStream = responseFuture.join()) {
               responseStream.transferTo(System.out); // BLOCKS the calling thread
           }