Interface TransferListener

All Known Implementing Classes:
LoggingTransferListener, TransferListenerInvoker

public interface TransferListener
The TransferListener interface may be implemented by your application in order to receive event-driven updates on the progress of a transfer initiated by S3TransferManager. When you construct an UploadFileRequest or DownloadFileRequest request to submit to S3TransferManager, you may provide a variable number of TransferListeners to be associated with that request. Then, throughout the lifecycle of the request, S3TransferManager will invoke the provided TransferListeners when important events occur, like additional bytes being transferred, allowing you to monitor the ongoing progress of the transfer.

Each TransferListener callback is invoked with an immutable TransferListener.Context object. Depending on the current lifecycle of the request, different TransferListener.Context objects have different attributes available (indicated by the provided context interface). Most notably, every callback is given access to the current TransferProgressSnapshot, which contains helpful progress-related methods like TransferProgressSnapshot.transferredBytes() and TransferProgressSnapshot.ratioTransferred().

A successful transfer callback lifecycle is sequenced as follows:

  1. transferInitiated(Context.TransferInitiated) - A new transfer has been initiated. This method is called exactly once per transfer.
  2. bytesTransferred(Context.BytesTransferred) - Additional bytes have been submitted or received. This method may be called many times per transfer, depending on the transfer size and I/O buffer sizes.
  3. transferComplete(Context.TransferComplete) - The transfer has completed successfully. This method is called exactly once for a successful transfer.
In the case of a failed transfer, both transferInitiated(Context.TransferInitiated) and transferFailed(Context.TransferFailed) will be called exactly once. There are no guarantees on whether any other callbacks are invoked.

There are a few important rules and best practices that govern the usage of TransferListeners:

  1. TransferListener implementations should not block, sleep, or otherwise delay the calling thread. If you need to perform blocking operations, you should schedule them in a separate thread or executor that you control.
  2. Be mindful that bytesTransferred(Context.BytesTransferred) may be called extremely often (subject to I/O buffer sizes). Be careful in implementing expensive operations as a side effect. Consider rate-limiting your side effect operations, if needed.
  3. In the case of uploads, there may be some delay between the bytes being fully transferred and the transfer successfully completing. Internally, S3TransferManager uses the Amazon S3 multipart upload API and must finalize uploads with a CompleteMultipartUploadRequest.
  4. TransferListeners may be invoked by different threads. If your TransferListener is stateful, ensure that it is also thread-safe.
  5. TransferListeners are not intended to be used for control flow, and therefore your implementation should not throw. Any thrown exceptions will be suppressed and logged as an error.

A classical use case of TransferListener is to create a progress bar to monitor an ongoing transfer's progress. Refer to the implementation of LoggingTransferListener for a basic example, or test it in your application by providing the listener as part of your TransferRequest. E.g.,


 Upload upload = tm.upload(UploadRequest.builder()
                                        .putObjectRequest(b -> b.bucket("bucket").key("key"))
                                        .source(Paths.get(...))
                                        .addTransferListener(LoggingTransferListener.create())
                                        .build());
 
And then a successful transfer may output something similar to:
 Transfer initiated...
 |                    | 0.0%
 |==                  | 12.5%
 |=====               | 25.0%
 |=======             | 37.5%
 |==========          | 50.0%
 |============        | 62.5%
 |===============     | 75.0%
 |=================   | 87.5%
 |====================| 100.0%
 Transfer complete!