Use the AWS SDK for Java 2.x - AWS SDK for Java 2.x

Use the AWS SDK for Java 2.x

After completing the steps in Setting up the SDK, you are ready to make requests to AWS services such as Amazon S3, DynamoDB, IAM, Amazon EC2, and more.

Work with service clients

Create a service client

To make a request to an AWS service, you must first instantiate a service client for that service by using the static factory method, builder(). The builder() method returns a builder object that allows you to customize the service client. The fluent setter methods return the builder object, so that you can chain the method calls for convenience and for more readable code. After you configure the properties you want, call the build() method to create the client.

As an example, the following code snippet instantiates an Ec2Client object as a service client for Amazon EC2.

Region region = Region.US_WEST_2; Ec2Client ec2Client = Ec2Client.builder() .region(region) .build();
Note

Service clients in the SDK are thread-safe. For best performance, treat them as long-lived objects. Each client has its own connection pool resource that is released when the client is garbage collected.

A service client object is immutable, so you must create a new client for each service to which you make requests, or if you want to use a different configuration for making requests to the same service.

Specifying the Region in the service client builder is not required for all AWS services; however, it is a best practice to set the Region for the API calls you make in your applications. See AWS region selection for more information.

Default client configuration

The client builders have another factory method named create(). This method creates a service client with the default configuration. It uses the default provider chain to load credentials and the AWS Region. If credentials or the Region can’t be determined from the environment that the application is running in, the call to create fails. See Using credentials and Region selection for more information about how the SDK determines the credentials and Region to use.

For example, the following code snippet instantiates a DynamoDbClient object as a service client for Amazon DynamoDB:

DynamoDbClient dynamoDbClient = DynamoDbClient.create();

Configure service clients

To customize the configuration of a service client, use the setters on the builder() factory method. For convenience and to create more readable code, chain the methods to set multiple configuration options.

The following example shows an S3Client that is configured with several custom settings.

ClientOverrideConfiguration clientOverrideConfiguration = ClientOverrideConfiguration.builder() .apiCallAttemptTimeout(Duration.ofSeconds(1)) .retryPolicy(RetryPolicy.builder().numRetries(10).build()) .addMetricPublisher(CloudWatchMetricPublisher.create()) .build(); Region region = Region.US_WEST_2; S3Client s3Client = S3Client.builder() .region(region) .credentialsProvider(EnvironmentVariableCredentialsProvider.create()) .overrideConfiguration(clientOverrideConfiguration) .httpClientBuilder(ApacheHttpClient.builder() .proxyConfiguration(proxyConfig.build(ProxyConfiguration.builder())) .build()) .build();

Close the service client

As a best practice, you should use a service clients for multiple API service calls during the life of an application. However, if you need a service client for a one-time use or no longer need the service client, close it.

Call the close() method when the service client is no longer needed to free up resources.

ec2Client.close();

If you need a service client for one-time use, you can instantiate the service client as a resource in a try-with-resources statement. Service clients implement the Autoclosable interface, so the JDK automatically calls the close() method at the end of the statement.

The following example demonstrates how to use a service client for a one-off call. The StsClient that calls the AWS Security Token Service is closed after it returns the account ID.

import software.amazon.awssdk.services.sts.StsClient; String getAccountID() { try (StsClient stsClient = StsClient.create()) { return stsClient.getCallerIdentity().account(); } }

Make requests

Use the service client to make requests to the corresponding AWS service.

For example, this code snippet shows how to create a RunInstancesRequest object to create a new Amazon EC2 instance:

// Create the request by using the fluid setter methods of the request builder. RunInstancesRequest runInstancesRequest = RunInstancesRequest.builder() .imageId(amiId) .instanceType(InstanceType.T1_MICRO) .maxCount(1) .minCount(1) .build(); // Use the configured request with the service client. RunInstancesResponse response = ec2Client.runInstances(runInstancesRequest);

Rather than create a request and pass in the instance, the SDK provides a fluent API that you can use to create a request. With the fluent API you can use a Java lambda expressions to create the request 'in-line'.

The following example rewrites the previous example by using the version of the runInstances method that uses a builder to create the request.

// Create the request by using a lambda expression. RunInstancesResponse response = ec2.runInstances(r -> r .imageId(amiId) .instanceType(InstanceType.T1_MICRO) .maxCount(1) .minCount(1));

Use requests to override client configuration

Although a service client is immutable, you can override many of its settings at the request level. When you build a request, you can provide an AwsRequestOverrideConfiguration instance to provide the overridden settings. Some of the methods you can use to override client settings are:

  • apiCallAttemptTimeout

  • apiCallTimeout

  • credentialProvider

  • compressionConfiguration

  • putHeader

For an example of overriding a client setting with a request, assume that you have the following S3 client that uses default settings.

S3Client s3Client = S3Client.create();

You want to download a large file and want to be sure the request doesn't timeout before the download finishes. To accomplish this, increase the timeout values for only a single GetObject request as shown in the following code.

Standard API
AwsRequestOverrideConfiguration overrideConfiguration = AwsRequestOverrideConfiguration.builder() .apiCallTimeout(Duration.ofSeconds(100L)) .apiCallAttemptTimeout(Duration.ofSeconds(25L)) .build(); GetObjectRequest request = GetObjectRequest.builder() .bucket("DOC-EXAMPLE-BUCKET") .key("DOC-EXAMPLE-KEY") .overrideConfiguration(overrideConfiguration) .build(); s3Client.getObject(request, myPath);
Fluent API
s3Client.getObject(b -> b .bucket("DOC-EXAMPLE-BUCKET") .key("DOC-EXAMPLE-KEY") .overrideConfiguration(c -> c .apiCallTimeout(Duration.ofSeconds(100L)) .apiCallAttemptTimeout(Duration.ofSeconds(25L))), myPath);

Handle responses

The SDK returns a response object for most service operations. Your code can process the information in the response object according to your needs.

For example, the following code snippet prints out the first instance id returned with the RunInstancesResponse object from the previous request.

RunInstancesResponse runInstancesResponse = ec2Client.runInstances(runInstancesRequest); System.out.println(runInstancesResponse.instances().get(0).instanceId());

Not all operations return a response object with service-specific data, however. In these situations, you can query the HTTP response status to learn if the operation was successful.

For example, the code in the following snippet checks the HTTP response to see if the DeleteContactList operation of Amazon Simple Email Service was successful.

SesV2Client sesv2Client = SesV2Client.create(); DeleteContactListRequest request = DeleteContactListRequest.builder() .contactListName("ExampleContactListName") .build(); DeleteContactListResponse response = sesv2Client.deleteContactList(request); if (response.sdkHttpResponse().isSuccessful()) { System.out.println("Contact list deleted successfully"); } else { System.out.println("Failed to delete contact list. Status code: " + response.sdkHttpResponse().statusCode()); }

Handle exceptions

The SDK uses runtime (or unchecked) exceptions, providing you fine-grained control over error handling and ensuring that exception handling will scale with your application.

An SdkServiceException, or one of its sub-classes, is the most common form of exception the SDK will throw. These exceptions represent responses from the AWS service. You can also handle an SdkClientException, which occurs when there’s a problem on the client side (i.e., in your development or application environment), such a network connection failure.

This code snippet demonstrates one way to handle service exceptions when you upload a file to Amazon S3. The example code catches both client and server exceptions, logs the details, and exists the application.

Region region = Region.US_WEST_2; s3Client = S3Client.builder() .region(region) .build(); try { PutObjectRequest putObjectRequest = PutObjectRequest.builder() .bucket(bucketName) .key(key) .build(); s3Client.putObject(putObjectRequest, RequestBody.fromString("SDK for Java test")); } catch (S3Exception se) { System.err.println("Service exception thrown."); System.err.println(se.awsErrorDetails().errorMessage()); } catch (SdkClientExeption ce){ System.err.println("Client exception thrown."); System.err.println(ce.getMessage()); } finally { System.exit(1); }

See Handling exceptions for more information.

Use waiters

Some requests take time to process, such as creating a new table in DynamoDB or creating a new Amazon S3 bucket. To ensure the resource is ready before your code continues to run, use a Waiter.

For example, this code snippet creates a new table ("myTable") in DynamoDB, waits for the table to be in an ACTIVE status, and then prints out the response:

DynamoDbClient dynamoDbClient = DynamoDbClient.create(); DynamoDbWaiter dynamoDbWaiter = dynamoDbClient.waiter(); WaiterResponse<DescribeTableResponse> waiterResponse = dynamoDbWaiter.waitUntilTableExists(r -> r.tableName("myTable")); waiterResponse.matched().response().ifPresent(System.out::println);

See Using waiters for more information.

Set timeouts

You can configure timeouts for each of your service clients using the apiCallTimeout and the apiCallAttemptTimeout setters of the ClientOverrideConfiguration.Builder. The apiCallTimeout setting is the amount of time to allow the client to complete the execution of an API call. The apiCallAttemptTimeout setting is the amount of time to wait for each HTTP request (retry) to complete before giving up.

The following example sets both timeouts for an S3 client.

S3Client s3Client = S3Client.builder() .overrideConfiguration(b -> b .apiCallTimeout(Duration.ofSeconds(105L)) .apiCallAttemptTimeout(Duration.ofSeconds(25L))). build();

You can also set timeouts at the request level by configuring an AwsRequestOverrideConfiguration and providing it to the request object with the overrideConfiguration method.

The following example uses the same timeout settings but at the request level for an S3 PutObject operation.

S3Client basicS3Client = S3Client.create(); // Client with default timeout settings. AwsRequestOverrideConfiguration overrideConfiguration = AwsRequestOverrideConfiguration.builder() .apiCallTimeout(Duration.ofSeconds(105L)) .apiCallAttemptTimeout(Duration.ofSeconds(25L)) .build(); basicS3Client.putObject(b -> b .bucket("DOC-EXAMPLE-BUCKET") .key("DOC-EXAMPLE-KEY") .overrideConfiguration(overrideConfiguration), RequestBody.fromString("test"));

Execution interceptors

You can write code that intercepts the execution of your API requests and responses at different parts of the request/response lifecycle. This enables you to publish metrics, modify a request in-flight, debug request processing, view exceptions, and more. For more information, see the ExecutionInterceptor interface in the AWS SDK for Java API Reference.