This article describes the various synchronous and asynchronous approaches for making requests with the AWS SDK for Java. The article concludes with some additional information to help you successfully use the asynchronous operations in the SDK.
The AWS SDK for Java provides synchronous and asynchronous methods that developers can use to call operations on AWS services. The synchronous methods block until the client receives the final response from the service. The asynchronous methods allow you to send a request to a service, and then immediately have control passed back to your code, instead of blocking until the remote service returns a response. This is convenient for many applications, particularly when you are writing user interfaces.
The basic pattern for calling an operation on an AWS web service, using the synchronous/blocking clients looks like this:
In the preceding example, when the
dynamoDB.describeTable operation is called, the SDK sends the HTTP request to Amazon DynamoDB, sits and waits for the service to return a response, parses it, and returns a
DescribeTableResult back to the caller, which can then continue executing.
The synchronous approach is an easy way to call AWS services, but in some applications, it can be problematic to block until the service has returned a response. For these situations, you can use the asynchronous methods. These methods are non-blocking, that is, they return immediately. The asynchronous methods provide two easy ways for developers to access the service response, once the remote server has finished processing the request:
- Java Futures—poll the status of the asynchronous request using the standard Java Future interface.
- Async Callbacks—implement a callback interface and the SDK will call methods on that interface when certain events occur in the lifecycle of the asynchronous request. For example, the SDK calls the interface when a request completes successfully or when a request fails with an error.
One of the most common ways to deal with asynchronous operations in Java is through the java.util.concurrent.Future class. Java Futures allow asynchronous operations to immediately return a result (a Future object) that the caller can poll for the status of the operation. When the caller detects that the operation has completed, the caller can use the Future object to access either the result or any error that might have occurred.
The following code demonstrates how to use Futures to asynchronously perform the same call to Amazon DynamoDB that was shown in the preceding synchronous access section:
Java Futures allow you to execute operations asynchronously and check on their status, but they still require the developer to poll the Future object to determine if the operation has completed. The next section describes an even easier way to work with asynchronous operations in the SDK: Async Callbacks.
In addition to using Java Futures to monitor the status of asynchronous requests, the SDK also allows you to implement a simple asynchronous callback interface that you can pass to the asynchronous method.
When various events occur in the asynchronous request's lifecycle, such as when the request completes successfully—or when it fails, the SDK invokes the associated methods in the
AsyncHandler implementation, allowing you to easily handle the event.
This code demonstrates how to implement the
AsyncHandler interface to have the SDK alert you when your asynchronous request has either completed or failed:
Java Futures and the
AsyncHandler callback interface are completely compatible.
You can use both Futures and the callback interface in your code if you want to, but typically one approach will suffice.
The major advantage of the callback interface approach is that it frees you from having to poll the
Future object to find out when the request has completed.
Instead, your code can immediately start its next activity, and rely on the SDK to call your handler at the right time.
Tips and Tricks
AsyncHandler callbacks is ideal for updating a UI with the result of an operation.
Keep in mind though that your implementation of
AsyncHandler is executed inside the thread pool owned by the asynchronous client.
Short, quickly executed code is most appropriate inside your
Long running or blocking code inside the
AsyncHandler implementation can cause contention for the thread pool used by the asynchronous client and can prevent the client from being able to execute requests.
If you have a long-running task that needs to begin from a callback, then simply have the callback run the task in a new thread or another thread pool managed by your application.
Thread Pool Configuration
The asynchronous clients in the SDK provide a default thread pool that should work for most applications,
but you are also free to supply your own ExecutorService to the asynchronous clients if you want more control over how the thread pools are managed.
For example, you could provide your own
ExecutorService that uses a custom
ThreadFactory to control how threads in the pool are named or to log additional information about thread usage.
Amazon S3 Asynchronous Access
The TransferManager class in the SDK offers asynchronous support for working with the Amazon Simple Storage Service (Amazon S3). The TransferManager manages asynchronous uploads and downloads, provides detailed progress reporting on transfers, and supports callbacks into different events.