

The AWS SDK for Java 1.x reached end-of-support on December 31, 2025. We recommend that you migrate to the [AWS SDK for Java 2.x](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/home.html) to continue receiving new features, availability improvements, and security updates.

# Using the AWS SDK for Java
<a name="basics"></a>

This section provides important general information about programming with the AWS SDK for Java that applies to all services you might use with the SDK.

For service-specific programming information and examples (for Amazon EC2, Amazon S3, Amazon SWF, etc.), see [AWS SDK for Java Code Examples](prog-services.md).

**Topics**
+ [Best Practices for AWS Development with the AWS SDK for Java](best-practices.md)
+ [Creating Service Clients](creating-clients.md)
+ [Provide temporary credentials](credentials.md)
+ [AWS Region Selection](java-dg-region-selection.md)
+ [Exception Handling](java-dg-exceptions.md)
+ [Asynchronous Programming](basics-async.md)
+ [Logging AWS SDK for Java Calls](java-dg-logging.md)
+ [Client Configuration](section-client-configuration.md)
+ [Access Control Policies](java-dg-access-control.md)
+ [Set the JVM TTL for DNS name lookups](jvm-ttl-dns.md)
+ [Enabling Metrics for the AWS SDK for Java](generating-sdk-metrics.md)

# Best Practices for AWS Development with the AWS SDK for Java
<a name="best-practices"></a>

The following best practices can help you avoid issues or trouble as you develop AWS applications with the AWS SDK for Java. We’ve organized best practices by service.

## S3
<a name="s3"></a>

### Avoid ResetExceptions
<a name="s3-avoid-resetexception"></a>

When you upload objects to Amazon S3 by using streams (either through an `AmazonS3` client or `TransferManager`), you might encounter network connectivity or timeout issues. By default, the AWS SDK for Java attempts to retry failed transfers by marking the input stream before the start of a transfer and then resetting it before retrying.

If the stream doesn’t support mark and reset, the SDK throws a [ResetException](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/ResetException.html) when there are transient failures and retries are enabled.

 **Best Practice** 

We recommend that you use streams that support mark and reset operations.

The most reliable way to avoid a [ResetException](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/ResetException.html) is to provide data by using a [File](https://docs.oracle.com/javase/8/docs/api/index.html?java/io/File.html) or [FileInputStream](https://docs.oracle.com/javase/8/docs/api/index.html?java/io/FileInputStream.html), which the AWS SDK for Java can handle without being constrained by mark and reset limits.

If the stream isn’t a [FileInputStream](https://docs.oracle.com/javase/8/docs/api/index.html?java/io/FileInputStream.html) but does support mark and reset, you can set the mark limit by using the `setReadLimit` method of [RequestClientOptions](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/RequestClientOptions.html). Its default value is 128 KB. Setting the read limit value to *one byte greater than the size of stream* will reliably avoid a [ResetException](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/ResetException.html).

For example, if the maximum expected size of a stream is 100,000 bytes, set the read limit to 100,001 (100,000 \$1 1) bytes. The mark and reset will always work for 100,000 bytes or less. Be aware that this might cause some streams to buffer that number of bytes into memory.

# Creating Service Clients
<a name="creating-clients"></a>

To make requests to Amazon Web Services, you first create a service client object. The recommended way is to use the service client builder.

Each AWS service has a service interface with methods for each action in the service API. For example, the service interface for DynamoDB is named [AmazonDynamoDBClient](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/dynamodbv2/AmazonDynamoDBClient.html). Each service interface has a corresponding client builder you can use to construct an implementation of the service interface. The client builder class for DynamoDB is named [AmazonDynamoDBClientBuilder](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/services/dynamodbv2/AmazonDynamoDBClientBuilder.html).

## Obtaining a Client Builder
<a name="obtaining-a-client-builder"></a>

To obtain an instance of the client builder, use the static factory method `standard`, as shown in the following example.

```
AmazonDynamoDBClientBuilder builder = AmazonDynamoDBClientBuilder.standard();
```

Once you have a builder, you can customize the client’s properties by using many fluent setters in the builder API. For example, you can set a custom region and a custom credentials provider, as follows.

```
AmazonDynamoDB ddb = AmazonDynamoDBClientBuilder.standard()
                        .withRegion(Regions.US_WEST_2)
                        .withCredentials(new ProfileCredentialsProvider("myProfile"))
                        .build();
```

**Note**  
The fluent `withXXX` 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, you can call the `build` method to create the client. Once a client is created, it’s immutable and any calls to `setRegion` or `setEndpoint` will fail.

A builder can create multiple clients with the same configuration. When you’re writing your application, be aware that the builder is mutable and not thread-safe.

The following code uses the builder as a factory for client instances.

```
public class DynamoDBClientFactory {
    private final AmazonDynamoDBClientBuilder builder =
        AmazonDynamoDBClientBuilder.standard()
            .withRegion(Regions.US_WEST_2)
            .withCredentials(new ProfileCredentialsProvider("myProfile"));

    public AmazonDynamoDB createClient() {
        return builder.build();
    }
}
```

The builder also exposes fluent setters for [ClientConfiguration](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/ClientConfiguration.html) and [RequestMetricCollector](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/metrics/RequestMetricCollector.html), and a custom list of [RequestHandler2](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/handlers/RequestHandler2.html).

The following is a complete example that overrides all configurable properties.

```
AmazonDynamoDB ddb = AmazonDynamoDBClientBuilder.standard()
        .withRegion(Regions.US_WEST_2)
        .withCredentials(new ProfileCredentialsProvider("myProfile"))
        .withClientConfiguration(new ClientConfiguration().withRequestTimeout(5000))
        .withMetricsCollector(new MyCustomMetricsCollector())
        .withRequestHandlers(new MyCustomRequestHandler(), new MyOtherCustomRequestHandler)
        .build();
```

## Creating Async Clients
<a name="creating-async-clients"></a>

The AWS SDK for Java has asynchronous (or async) clients for every service (except for Amazon S3), and a corresponding async client builder for every service.

### To create an async DynamoDB client with the default ExecutorService
<a name="w3aab9c13b9b5"></a>

```
AmazonDynamoDBAsync ddbAsync = AmazonDynamoDBAsyncClientBuilder.standard()
        .withRegion(Regions.US_WEST_2)
        .withCredentials(new ProfileCredentialsProvider("myProfile"))
        .build();
```

In addition to the configuration options that the synchronous (or sync) client builder supports, the async client enables you to set a custom [ExecutorFactory](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/client/builder/ExecutorFactory.html) to change the `ExecutorService` that the async client uses. `ExecutorFactory` is a functional interface, so it interoperates with Java 8 lambda expressions and method references.

### To create an async client with a custom executor
<a name="w3aab9c13b9b9"></a>

```
AmazonDynamoDBAsync ddbAsync = AmazonDynamoDBAsyncClientBuilder.standard()
            .withExecutorFactory(() -> Executors.newFixedThreadPool(10))
            .build();
```

## Using DefaultClient
<a name="using-defaultclient"></a>

Both the sync and async client builders have another factory method named `defaultClient`. This method creates a service client with the default configuration, using 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 `defaultClient` fails. See [Working with AWS Credentials](credentials.md) and [AWS Region Selection](java-dg-region-selection.md) for more information about how credentials and region are determined.

### To create a default service client
<a name="w3aab9c13c11b5"></a>

```
AmazonDynamoDB ddb = AmazonDynamoDBClientBuilder.defaultClient();
```

## Client Lifecycle
<a name="client-lifecycle"></a>

Service clients in the SDK are thread-safe and, for best performance, you should treat them as long-lived objects. Each client has its own connection pool resource. Explicitly shut down clients when they are no longer needed to avoid resource leaks.

To explicitly shut down a client, call the `shutdown` method. After calling `shutdown`, all client resources are released and the client is unusable.

### To shut down a client
<a name="w3aab9c13c13b7"></a>

```
AmazonDynamoDB ddb = AmazonDynamoDBClientBuilder.defaultClient();
ddb.shutdown();
// Client is now unusable
```

# Provide temporary credentials to the AWS SDK for Java
<a name="credentials"></a>

To make requests to Amazon Web Services, you must supply AWS temporary credentials for the AWS SDK for Java to use when it calls the services. You can do this in the following ways:
+ Use the default credential provider chain *(recommended)*.
+ Use a specific credential provider or provider chain (or create your own).
+ Supply the temporary credentials yourself in code.

## Using the Default Credential Provider Chain
<a name="credentials-default"></a>

When you initialize a new service client without supplying any arguments, the AWS SDK for Java attempts to find temporary credentials by using the *default credential provider chain* implemented by the [DefaultAWSCredentialsProviderChain](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/auth/DefaultAWSCredentialsProviderChain.html) class. The default credential provider chain looks for credentials in this order:

1.  **Environment variables**-`AWS_ACCESS_KEY_ID`, `AWS_SECRET_KEY` or `AWS_SECRET_ACCESS_KEY`, and `AWS_SESSION_TOKEN`. The AWS SDK for Java uses the [EnvironmentVariableCredentialsProvider](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/auth/EnvironmentVariableCredentialsProvider.html) class to load these credentials.

1.  **Java system properties**-`aws.accessKeyId`, `aws.secretKey` (but not `aws.secretAccessKey`), and `aws.sessionToken`. The AWS SDK for Java uses the [SystemPropertiesCredentialsProvider](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/auth/SystemPropertiesCredentialsProvider.html) to load these credentials.

1.  **Web Identity Token credentials** from the environment or container.

1.  **The default credential profiles file**- typically located at `~/.aws/credentials` (location can vary per platform), and shared by many of the AWS SDKs and by the AWS CLI. The AWS SDK for Java uses the [ProfileCredentialsProvider](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/auth/profile/ProfileCredentialsProvider.html) to load these credentials.

   You can create a credentials file by using the `aws configure` command provided by the AWS CLI, or you can create it by editing the file with a text editor. For information about the credentials file format, see [AWS Credentials File Format](#credentials-file-format).

1.  **Amazon ECS container credentials**- loaded from the Amazon ECS if the environment variable `AWS_CONTAINER_CREDENTIALS_RELATIVE_URI` is set. The AWS SDK for Java uses the [ContainerCredentialsProvider](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/auth/ContainerCredentialsProvider.html) to load these credentials. You can specify the IP address for this value.

1.  **Instance profile credentials**- used on EC2 instances, and delivered through the Amazon EC2 metadata service. The AWS SDK for Java uses the [InstanceProfileCredentialsProvider](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/auth/InstanceProfileCredentialsProvider.html) to load these credentials. You can specify the IP address for this value.
**Note**  
Instance profile credentials are used only if `AWS_CONTAINER_CREDENTIALS_RELATIVE_URI` is not set. See [EC2ContainerCredentialsProviderWrapper](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/auth/EC2ContainerCredentialsProviderWrapper.html) for more information.

### Set temporary credentials
<a name="setting-credentials"></a>

To be able to use AWS temporary credentials, they must be set in *at least one* of the preceding locations. For information about setting credentials, see the following topics:
+ To specify credentials in the *environment* or in the default *credential profiles file*, see [Configure temporary credentials](setup-credentials.md#setup-credentials-setting) .
+ To set Java *system properties*, see the [System Properties](http://docs.oracle.com/javase/tutorial/essential/environment/sysprop.html) tutorial on the official *Java Tutorials* website.
+ To set up and use *instance profile credentials* with your EC2 instances, see [Using IAM Roles to Grant Access to AWS Resources on Amazon EC2](java-dg-roles.md).

### Set an alternate credentials profile
<a name="setting-an-alternate-credentials-profile"></a>

The AWS SDK for Java uses the *default* profile by default, but there are ways to customize which profile is sourced from the credentials file.

You can use the AWS Profile environment variable to change the profile loaded by the SDK.

For example, on Linux, macOS, or Unix you would run the following command to change the profile to *myProfile*.

```
export AWS_PROFILE="myProfile"
```

On Windows you would use the following.

```
set AWS_PROFILE="myProfile"
```

Setting the `AWS_PROFILE` environment variable affects credential loading for all officially supported AWS SDKs and Tools (including the AWS CLI and the AWS Tools for Windows PowerShell). To change only the profile for a Java application, you can use the system property `aws.profile` instead.

**Note**  
The environment variable takes precedence over the system property.

### Set an alternate credentials file location
<a name="setting-an-alternate-credentials-file-location"></a>

The AWS SDK for Java loads AWS temporary credentials automatically from the default credentials file location. However, you can also specify the location by setting the `AWS_CREDENTIAL_PROFILES_FILE` environment variable with the full path to the credentials file.

You can use this feature to temporarily change the location where the AWS SDK for Java looks for your credentials file (for example, by setting this variable with the command line). Or you can set the environment variable in your user or system environment to change it for the user or systemwide.

#### To override the default credentials file location
<a name="w3aab9c15b9c11b7b1"></a>
+ Set the `AWS_CREDENTIAL_PROFILES_FILE` environment variable to the location of your AWS credentials file.
  + On Linux, macOS, or Unix, use:

    ```
    export AWS_CREDENTIAL_PROFILES_FILE=path/to/credentials_file
    ```
  + On Windows, use:

    ```
    set AWS_CREDENTIAL_PROFILES_FILE=path/to/credentials_file
    ```

### `Credentials` file format
<a name="credentials-file-format"></a>

By following the[ instructions in the Basic setup](signup-create-iam-user.md#setup-temp-creds) of this guide, your credentials file should have the following basic format.

```
[default]
aws_access_key_id=<value from AWS access portal>
aws_secret_access_key=<value from AWS access portal>
aws_session_token=<value from AWS access portal>

[profile2]
aws_access_key_id=<value from AWS access portal>
aws_secret_access_key=<value from AWS access portal>
aws_session_token=<value from AWS access portal>
```

The profile name is specified in square brackets (for example, `[default]`), followed by the configurable fields in that profile as key-value pairs. You can have multiple profiles in your `credentials` file, which can be added or edited using `aws configure --profile PROFILE_NAME ` to select the profile to configure.

You can specify additional fields, such as `metadata_service_timeout`, and `metadata_service_num_attempts`. These are not configurable with the CLI—​you must edit the file by hand if you want to use them. For more information about the configuration file and its available fields, see [Configuring the AWS Command Line Interface](http://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html) in the AWS Command Line Interface User Guide.

### Load credentials
<a name="loading-credentials"></a>

After you set temporary credentials, the SDK loads them by using the default credential provider chain.

To do this, you instantiate an AWS service client without explicitly providing credentials to the builder, as follows.

```
AmazonS3 s3Client = AmazonS3ClientBuilder.standard()
                       .withRegion(Regions.US_WEST_2)
                       .build();
```

## Specify a credential provider or provider chain
<a name="credentials-specify-provider"></a>

You can specify a credential provider that is different from the *default* credential provider chain by using the client builder.

You provide an instance of a credentials provider or provider chain to a client builder that takes an [AWSCredentialsProvider](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/auth/AWSCredentialsProvider.html) interface as input. The following example shows how to use *environment* credentials specifically.

```
AmazonS3 s3Client = AmazonS3ClientBuilder.standard()
                       .withCredentials(new EnvironmentVariableCredentialsProvider())
                       .build();
```

For the full list of AWS SDK for Java-supplied credential providers and provider chains, see **All Known Implementing Classes** in [AWSCredentialsProvider](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/auth/AWSCredentialsProvider.html).

**Note**  
You can use this technique to supply credential providers or provider chains that you create by using your own credential provider that implements the `AWSCredentialsProvider` interface, or by subclassing the [AWSCredentialsProviderChain](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/auth/AWSCredentialsProviderChain.html) class.

## Explicitly specify temporary credentials
<a name="credentials-explicit"></a>

If the default credential chain or a specific or custom provider or provider chain doesn’t work for your code, you can set credentials that you supply explicitly. If you’ve retrieved temporary credentials using AWS STS, use this method to specify the credentials for AWS access.

1. Instantiate the [BasicSessionCredentials](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/auth/BasicSessionCredentials.html) class, and supply it with the AWS access key, AWS secret key, and AWS session token that the SDK will use for the connection.

1. Create an [AWSStaticCredentialsProvider](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/auth/AWSStaticCredentialsProvider.html) with the `AWSCredentials` object.

1. Configure the client builder with the `AWSStaticCredentialsProvider` and build the client.

The following is an example.

```
BasicSessionCredentials awsCreds = new BasicSessionCredentials("access_key_id", "secret_key_id", "session_token");
AmazonS3 s3Client = AmazonS3ClientBuilder.standard()
                        .withCredentials(new AWSStaticCredentialsProvider(awsCreds))
                        .build();
```

## More Info
<a name="more-info"></a>
+  [Sign Up for AWS and Create an IAM User](signup-create-iam-user.md) 
+  [Set up AWS Credentials and Region for Development](setup-credentials.md) 
+  [Using IAM Roles to Grant Access to AWS Resources on Amazon EC2](java-dg-roles.md) 

# AWS Region Selection
<a name="java-dg-region-selection"></a>

Regions enable you to access AWS services that physically reside in a specific geographic area. This can be useful both for redundancy and to keep your data and applications running close to where you and your users will access them.

## Checking for Service Availability in a Region
<a name="region-selection-query-service"></a>

To see if a particular AWS service is available in a region, use the `isServiceSupported` method on the region that you’d like to use.

```
Region.getRegion(Regions.US_WEST_2)
    .isServiceSupported(AmazonDynamoDB.ENDPOINT_PREFIX);
```

See the [Regions](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/regions/Regions.html) class documentation for the regions you can specify, and use the endpoint prefix of the service to query. Each service’s endpoint prefix is defined in the service interface. For example, the DynamoDB endpoint prefix is defined in [AmazonDynamoDB](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/services/dynamodbv2/AmazonDynamoDB.html).

## Choosing a Region
<a name="region-selection-choose-region"></a>

Beginning with version 1.4 of the AWS SDK for Java, you can specify a region name and the SDK will automatically choose an appropriate endpoint for you. To choose the endpoint yourself, see [Choosing a Specific Endpoint](#region-selection-choose-endpoint).

To explicitly set a region, we recommend that you use the [Regions](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/regions/Regions.html) enum. This is an enumeration of all publicly available regions. To create a client with a region from the enum, use the following code.

```
AmazonEC2 ec2 = AmazonEC2ClientBuilder.standard()
                    .withRegion(Regions.US_WEST_2)
                    .build();
```

If the region you are attempting to use isn’t in the `Regions` enum, you can set the region using a *string* that represents the name of the region.

```
AmazonEC2 ec2 = AmazonEC2ClientBuilder.standard()
                    .withRegion("{region_api_default}")
                    .build();
```

**Note**  
After you build a client with the builder, it’s *immutable* and the region *cannot be changed*. If you are working with multiple AWS Regions for the same service, you should create multiple clients—​one per region.

## Choosing a Specific Endpoint
<a name="region-selection-choose-endpoint"></a>

Each AWS client can be configured to use a *specific endpoint* within a region by calling the `withEndpointConfiguration` method when creating the client.

For example, to configure the Amazon S3 client to use the Europe (Ireland) Region, use the following code.

```
AmazonS3 s3 = AmazonS3ClientBuilder.standard()
     .withEndpointConfiguration(new EndpointConfiguration(
          "https://s3.eu-west-1.amazonaws.com",
          "eu-west-1"))
     .withCredentials(CREDENTIALS_PROVIDER)
     .build();
```

See [Regions and Endpoints](https://docs.aws.amazon.com/general/latest/gr/rande.html) for the current list of regions and their corresponding endpoints for all AWS services.

## Automatically Determine the Region from the Environment
<a name="automatically-determine-the-aws-region-from-the-environment"></a>

**Important**  
This section applies only when using a [client builder](creating-clients.md) to access AWS services. AWS clients created by using the client constructor will not automatically determine region from the environment and will, instead, use the *default* SDK region (USEast1).

When running on Amazon EC2 or Lambda, you might want to configure clients to use the same region that your code is running on. This decouples your code from the environment it’s running in and makes it easier to deploy your application to multiple regions for lower latency or redundancy.

 *You must use client builders to have the SDK automatically detect the region your code is running in.* 

To use the default credential/region provider chain to determine the region from the environment, use the client builder’s `defaultClient` method.

```
AmazonEC2 ec2 = AmazonEC2ClientBuilder.defaultClient();
```

This is the same as using `standard` followed by `build`.

```
AmazonEC2 ec2 = AmazonEC2ClientBuilder.standard()
                    .build();
```

If you don’t explicitly set a region using the `withRegion` methods, the SDK consults the default region provider chain to try and determine the region to use.

### Default Region Provider Chain
<a name="default-region-provider-chain"></a>

 **The following is the region lookup process:** 

1. Any explicit region set by using `withRegion` or `setRegion` on the builder itself takes precedence over anything else.

1. The `AWS_REGION` environment variable is checked. If it’s set, that region is used to configure the client.
**Note**  
This environment variable is set by the Lambda container.

1. The SDK checks the AWS shared configuration file (usually located at `~/.aws/config`). If the *region* property is present, the SDK uses it.
   + The `AWS_CONFIG_FILE` environment variable can be used to customize the location of the shared config file.
   + The `AWS_PROFILE` environment variable or the `aws.profile` system property can be used to customize the profile that is loaded by the SDK.

1. The SDK attempts to use the Amazon EC2 instance metadata service to determine the region of the currently running Amazon EC2 instance.

1. If the SDK still hasn’t found a region by this point, client creation fails with an exception.

When developing AWS applications, a common approach is to use the *shared configuration file* (described in [Using the Default Credential Provider Chain](credentials.md#credentials-default)) to set the region for local development, and rely on the default region provider chain to determine the region when running on AWS infrastructure. This greatly simplifies client creation and keeps your application portable.

# Exception Handling
<a name="java-dg-exceptions"></a>

Understanding how and when the AWS SDK for Java throws exceptions is important to building high-quality applications using the SDK. The following sections describe the different cases of exceptions that are thrown by the SDK and how to handle them appropriately.

## Why Unchecked Exceptions?
<a name="why-unchecked-exceptions"></a>

The AWS SDK for Java uses runtime (or unchecked) exceptions instead of checked exceptions for these reasons:
+ To allow developers fine-grained control over the errors they want to handle without forcing them to handle exceptional cases they aren’t concerned about (and making their code overly verbose)
+ To prevent scalability issues inherent with checked exceptions in large applications

In general, checked exceptions work well on small scales, but can become troublesome as applications grow and become more complex.

For more information about the use of checked and unchecked exceptions, see:
+  [Unchecked Exceptions—​The Controversy](http://docs.oracle.com/javase/tutorial/essential/exceptions/runtime.html) 
+  [The Trouble with Checked Exceptions](http://www.artima.com/intv/handcuffs2.html) 
+  [Java’s checked exceptions were a mistake (and here’s what I would like to do about it)](http://radio-weblogs.com/0122027/stories/2003/04/01/JavasCheckedExceptionsWereAMistake.html) 

## AmazonServiceException (and Subclasses)
<a name="amazonserviceexception-and-subclasses"></a>

 [AmazonServiceException](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/AmazonServiceException.html) is the most common exception that you’ll experience when using the AWS SDK for Java. This exception represents an error response from an AWS service. For example, if you try to terminate an Amazon EC2 instance that doesn’t exist, EC2 will return an error response and all the details of that error response will be included in the `AmazonServiceException` that’s thrown. For some cases, a subclass of `AmazonServiceException` is thrown to allow developers fine-grained control over handling error cases through catch blocks.

When you encounter an `AmazonServiceException`, you know that your request was successfully sent to the AWS service but couldn’t be successfully processed. This can be because of errors in the request’s parameters or because of issues on the service side.

 `AmazonServiceException` provides you with information such as:
+ Returned HTTP status code
+ Returned AWS error code
+ Detailed error message from the service
+  AWS request ID for the failed request

 `AmazonServiceException` also includes information about whether the failed request was the caller’s fault (a request with illegal values) or the AWS service's fault (an internal service error).

## AmazonClientException
<a name="amazonclientexception"></a>

 [AmazonClientException](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/AmazonClientException.html) indicates that a problem occurred inside the Java client code, either while trying to send a request to AWS or while trying to parse a response from AWS. An `AmazonClientException` is generally more severe than an `AmazonServiceException`, and indicates a major problem that is preventing the client from making service calls to AWS services. For example, the AWS SDK for Java throws an `AmazonClientException` if no network connection is available when you try to call an operation on one of the clients.

# Asynchronous Programming
<a name="basics-async"></a>

You can use either *synchronous* or *asynchronous* methods to call operations on AWS services. Synchronous methods block your thread’s execution until the client receives a response from the service. Asynchronous methods return immediately, giving control back to the calling thread without waiting for a response.

Because an asynchronous method returns before a response is available, you need a way to get the response when it’s ready. The AWS SDK for Java provides two ways: *Future objects* and *callback methods*.

## Java Futures
<a name="basics-async-future"></a>

Asynchronous methods in the AWS SDK for Java return a [Future](https://docs.oracle.com/javase/8/docs/api/index.html?java/util/concurrent/Future.html) object that contains the results of the asynchronous operation *in the future*.

Call the `Future` `isDone()` method to see if the service has provided a response object yet. When the response is ready, you can get the response object by calling the `Future` `get()` method. You can use this mechanism to periodically poll for the asynchronous operation’s results while your application continues to work on other things.

Here is an example of an asynchronous operation that calls a Lambda function, receiving a `Future` that can hold an [InvokeResult](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/services/lambda/model/InvokeResult.html) object. The `InvokeResult` object is retrieved only after `isDone()` is `true`.

```
import com.amazonaws.services.lambda.AWSLambdaAsyncClient;
import com.amazonaws.services.lambda.model.InvokeRequest;
import com.amazonaws.services.lambda.model.InvokeResult;
import java.nio.ByteBuffer;
import java.util.concurrent.Future;
import java.util.concurrent.ExecutionException;

public class InvokeLambdaFunctionAsync
{
    public static void main(String[] args)
    {
        String function_name = "HelloFunction";
        String function_input = "{\"who\":\"SDK for Java\"}";

        AWSLambdaAsync lambda = AWSLambdaAsyncClientBuilder.defaultClient();
        InvokeRequest req = new InvokeRequest()
            .withFunctionName(function_name)
            .withPayload(ByteBuffer.wrap(function_input.getBytes()));

        Future<InvokeResult> future_res = lambda.invokeAsync(req);

        System.out.print("Waiting for future");
        while (future_res.isDone() == false) {
            System.out.print(".");
            try {
                Thread.sleep(1000);
            }
            catch (InterruptedException e) {
                System.err.println("\nThread.sleep() was interrupted!");
                System.exit(1);
            }
        }

        try {
            InvokeResult res = future_res.get();
            if (res.getStatusCode() == 200) {
                System.out.println("\nLambda function returned:");
                ByteBuffer response_payload = res.getPayload();
                System.out.println(new String(response_payload.array()));
            }
            else {
                System.out.format("Received a non-OK response from {AWS}: %d\n",
                        res.getStatusCode());
            }
        }
        catch (InterruptedException | ExecutionException e) {
            System.err.println(e.getMessage());
            System.exit(1);
        }

        System.exit(0);
    }
}
```

## Asynchronous Callbacks
<a name="basics-async-callback"></a>

In addition to using the Java `Future` object to monitor the status of asynchronous requests, the SDK also enables you to implement a class that uses the [AsyncHandler](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/handlers/AsyncHandler.html) interface. `AsyncHandler` provides two methods that are called depending on how the request completed: `onSuccess` and `onError`.

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.

```
import com.amazonaws.services.lambda.AWSLambdaAsync;
import com.amazonaws.services.lambda.AWSLambdaAsyncClientBuilder;
import com.amazonaws.services.lambda.model.InvokeRequest;
import com.amazonaws.services.lambda.model.InvokeResult;
import com.amazonaws.handlers.AsyncHandler;
import java.nio.ByteBuffer;
import java.util.concurrent.Future;

public class InvokeLambdaFunctionCallback
{
    private class AsyncLambdaHandler implements AsyncHandler<InvokeRequest, InvokeResult>
    {
        public void onSuccess(InvokeRequest req, InvokeResult res) {
            System.out.println("\nLambda function returned:");
            ByteBuffer response_payload = res.getPayload();
            System.out.println(new String(response_payload.array()));
            System.exit(0);
        }

        public void onError(Exception e) {
            System.out.println(e.getMessage());
            System.exit(1);
        }
    }

    public static void main(String[] args)
    {
        String function_name = "HelloFunction";
        String function_input = "{\"who\":\"SDK for Java\"}";

        AWSLambdaAsync lambda = AWSLambdaAsyncClientBuilder.defaultClient();
        InvokeRequest req = new InvokeRequest()
            .withFunctionName(function_name)
            .withPayload(ByteBuffer.wrap(function_input.getBytes()));

        Future<InvokeResult> future_res = lambda.invokeAsync(req, new AsyncLambdaHandler());

        System.out.print("Waiting for async callback");
        while (!future_res.isDone() && !future_res.isCancelled()) {
            // perform some other tasks...
            try {
                Thread.sleep(1000);
            }
            catch (InterruptedException e) {
                System.err.println("Thread.sleep() was interrupted!");
                System.exit(0);
            }
            System.out.print(".");
        }
    }
}
```

## Best Practices
<a name="basics-async-tips"></a>

### Callback Execution
<a name="callback-execution"></a>

Your implementation of `AsyncHandler` is executed inside the thread pool owned by the asynchronous client. Short, quickly executed code is most appropriate inside your `AsyncHandler` implementation. Long-running or blocking code inside your handler methods can cause contention for the thread pool used by the asynchronous client, and can prevent the client from executing requests. If you have a long-running task that needs to begin from a callback, have the callback run its task in a new thread or in a thread pool managed by your application.

### Thread Pool Configuration
<a name="thread-pool-configuration"></a>

The asynchronous clients in the AWS SDK for Java provide a default thread pool that should work for most applications. You can implement a custom [ExecutorService](https://docs.oracle.com/javase/8/docs/api/index.html?java/util/concurrent/ExecutorService.html) and pass it to AWS SDK for Java asynchronous clients for more control over how the thread pools are managed.

For example, you could provide an `ExecutorService` implementation that uses a custom [ThreadFactory](https://docs.oracle.com/javase/8/docs/api/index.html?java/util/concurrent/ThreadFactory.html) to control how threads in the pool are named, or to log additional information about thread usage.

### Asynchronous Access
<a name="s3-asynchronous-access"></a>

The [TransferManager](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/services/s3/transfer/TransferManager.html) class in the SDK offers asynchronous support for working with Amazon S3. `TransferManager` manages asynchronous uploads and downloads, provides detailed progress reporting on transfers, and supports callbacks into different events.

# Logging AWS SDK for Java Calls
<a name="java-dg-logging"></a>

The AWS SDK for Java is instrumented with [Apache Commons Logging](http://commons.apache.org/proper/commons-logging/guide.html), which is an abstraction layer that enables the use of any one of several logging systems at runtime.

Supported logging systems include the Java Logging Framework and Apache Log4j, among others. This topic shows you how to use Log4j. You can use the SDK’s logging functionality without making any changes to your application code.

To learn more about [Log4j](http://logging.apache.org/log4j/2.x/), see the [Apache website](http://www.apache.org/).

**Note**  
This topic focuses on Log4j 1.x. Log4j2 doesn’t directly support Apache Commons Logging, but provides an adapter that directs logging calls automatically to Log4j2 using the Apache Commons Logging interface. For more information, see [Commons Logging Bridge](https://logging.apache.org/log4j/2.x/log4j-jcl.html) in the Log4j2 documentation.

## Download the Log4J JAR
<a name="download-the-log4j-jar"></a>

To use Log4j with the SDK, you need to download the Log4j JAR from the Apache website. The SDK doesn’t include the JAR. Copy the JAR file to a location that is on your classpath.

Log4j uses a configuration file, log4j.properties. Example configuration files are shown below. Copy this configuration file to a directory on your classpath. The Log4j JAR and the log4j.properties file don’t have to be in the same directory.

The log4j.properties configuration file specifies properties such as [logging level](http://logging.apache.org/log4j/2.x/manual/configuration.html#Loggers), where logging output is sent (for example, [to a file or to the console](http://logging.apache.org/log4j/2.x/manual/appenders.html)), and the [format of the output](http://logging.apache.org/log4j/2.x/manual/layouts.html). The logging level is the granularity of output that the logger generates. Log4j supports the concept of multiple logging *hierarchies*. The logging level is set independently for each hierarchy. The following two logging hierarchies are available in the AWS SDK for Java:
+ log4j.logger.com.amazonaws
+ log4j.logger.org.apache.http.wire

## Setting the Classpath
<a name="sdk-net-logging-classpath"></a>

Both the Log4j JAR and the log4j.properties file must be located on your classpath. If you’re using [Apache Ant](http://ant.apache.org/manual/), set the classpath in the `path` element in your Ant file. The following example shows a path element from the Ant file for the Amazon S3 [example](https://github.com/aws/aws-sdk-java/blob/master/src/samples/AmazonS3/build.xml) included with the SDK.

```
<path id="aws.java.sdk.classpath">
  <fileset dir="../../third-party" includes="**/*.jar"/>
  <fileset dir="../../lib" includes="**/*.jar"/>
  <pathelement location="."/>
</path>
```

If you’re using the Eclipse IDE, you can set the classpath by opening the menu and navigating to **Project** \$1 **Properties** \$1 **Java Build Path**.

## Service-Specific Errors and Warnings
<a name="sdk-net-logging-service"></a>

We recommend that you always leave the "com.amazonaws" logger hierarchy set to "WARN" to catch any important messages from the client libraries. For example, if the Amazon S3 client detects that your application hasn’t properly closed an `InputStream` and could be leaking resources, the S3 client reports it through a warning message to the logs. This also ensures that messages are logged if the client has any problems handling requests or responses.

The following log4j.properties file sets the `rootLogger` to WARN, which causes warning and error messages from all loggers in the "com.amazonaws" hierarchy to be included. Alternatively, you can explicitly set the com.amazonaws logger to WARN.

```
log4j.rootLogger=WARN, A1
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%d [%t] %-5p %c -  %m%n
# Or you can explicitly enable WARN and ERROR messages for the {AWS} Java clients
log4j.logger.com.amazonaws=WARN
```

## Request/Response Summary Logging
<a name="sdk-net-logging-request-response"></a>

Every request to an AWS service generates a unique AWS request ID that is useful if you run into an issue with how an AWS service is handling a request. AWS request IDs are accessible programmatically through Exception objects in the SDK for any failed service call, and can also be reported through the DEBUG log level in the "com.amazonaws.request" logger.

The following log4j.properties file enables a summary of requests and responses, including AWS request IDs.

```
log4j.rootLogger=WARN, A1
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%d [%t] %-5p %c -  %m%n
# Turn on DEBUG logging in com.amazonaws.request to log
# a summary of requests/responses with {AWS} request IDs
log4j.logger.com.amazonaws.request=DEBUG
```

Here is an example of the log output.

```
2009-12-17 09:53:04,269 [main] DEBUG com.amazonaws.request - Sending
Request: POST https://rds.amazonaws.com / Parameters: (MaxRecords: 20,
Action: DescribeEngineDefaultParameters, SignatureMethod: HmacSHA256,
AWSAccessKeyId: ACCESSKEYID, Version: 2009-10-16, SignatureVersion: 2,
Engine: mysql5.1, Timestamp: 2009-12-17T17:53:04.267Z, Signature:
q963XH63Lcovl5Rr71APlzlye99rmWwT9DfuQaNznkD, ) 2009-12-17 09:53:04,464
[main] DEBUG com.amazonaws.request - Received successful response: 200, {AWS}
Request ID: 694d1242-cee0-c85e-f31f-5dab1ea18bc6 2009-12-17 09:53:04,469
[main] DEBUG com.amazonaws.request - Sending Request: POST
https://rds.amazonaws.com / Parameters: (ResetAllParameters: true, Action:
ResetDBParameterGroup, SignatureMethod: HmacSHA256, DBParameterGroupName:
java-integ-test-param-group-0000000000000, AWSAccessKeyId: ACCESSKEYID,
Version: 2009-10-16, SignatureVersion: 2, Timestamp:
2009-12-17T17:53:04.467Z, Signature:
9WcgfPwTobvLVcpyhbrdN7P7l3uH0oviYQ4yZ+TQjsQ=, )

2009-12-17 09:53:04,646 [main] DEBUG com.amazonaws.request - Received
successful response: 200, {AWS} Request ID:
694d1242-cee0-c85e-f31f-5dab1ea18bc6
```

## Verbose Wire Logging
<a name="sdk-net-logging-verbose"></a>

In some cases, it can be useful to see the exact requests and responses that the AWS SDK for Java sends and receives. You shouldn’t enable this logging in production systems because writing out large requests (e.g., a file being uploaded to Amazon S3) or responses can significantly slow down an application. If you really need access to this information, you can temporarily enable it through the Apache HttpClient 4 logger. Enabling the DEBUG level on the `org.apache.http.wire` logger enables logging for all request and response data.

The following log4j.properties file turns on full wire logging in Apache HttpClient 4 and should only be turned on temporarily because it can have a significant performance impact on your application.

```
log4j.rootLogger=WARN, A1
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%d [%t] %-5p %c -  %m%n
# Log all HTTP content (headers, parameters, content, etc)  for
# all requests and responses. Use caution with this since it can
# be very expensive to log such verbose data!
log4j.logger.org.apache.http.wire=DEBUG
```

## Latency Metrics Logging
<a name="sdk-latency-logging"></a>

If you are troubleshooting and want to see metrics such as which process is taking the most time or whether server or client side has the greater latency, the latency logger can be helpful. Set the `com.amazonaws.latency` logger to DEBUG to enable this logger.

**Note**  
This logger is only available if SDK metrics is enabled. To learn more about the SDK metrics package, see [Enabling Metrics for the AWS SDK for Java](generating-sdk-metrics.md).

```
log4j.rootLogger=WARN, A1
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%d [%t] %-5p %c -  %m%n
log4j.logger.com.amazonaws.latency=DEBUG
```

Here is an example of the log output.

```
com.amazonaws.latency - ServiceName=[{S3}], StatusCode=[200],
ServiceEndpoint=[https://list-objects-integ-test-test.s3.amazonaws.com],
RequestType=[ListObjectsV2Request], AWSRequestID=[REQUESTID], HttpClientPoolPendingCount=0,
RetryCapacityConsumed=0, HttpClientPoolAvailableCount=0, RequestCount=1,
HttpClientPoolLeasedCount=0, ResponseProcessingTime=[52.154], ClientExecuteTime=[487.041],
HttpClientSendRequestTime=[192.931], HttpRequestTime=[431.652], RequestSigningTime=[0.357],
CredentialsRequestTime=[0.011, 0.001], HttpClientReceiveResponseTime=[146.272]
```

# Client Configuration
<a name="section-client-configuration"></a>

The AWS SDK for Java enables you to change the default client configuration, which is helpful when you want to:
+ Connect to the Internet through proxy
+ Change HTTP transport settings, such as connection timeout and request retries
+ Specify TCP socket buffer size hints

## Proxy Configuration
<a name="proxy-configuration"></a>

When constructing a client object, you can pass in an optional [ClientConfiguration](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/ClientConfiguration.html) object to customize the client’s configuration.

If you connect to the Internet through a proxy server, you’ll need to configure your proxy server settings (proxy host, port, and username/password) through the `ClientConfiguration` object.

## HTTP Transport Configuration
<a name="http-transport-configuration"></a>

You can configure several HTTP transport options by using the [ClientConfiguration](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/ClientConfiguration.html) object. New options are occasionally added; to see the full list of options you can retrieve or set, see the AWS SDK for Java API Reference.

**Note**  
Each of the configurable values has a default value defined by a constant. For a list of the constant values for `ClientConfiguration`, see [Constant Field Values](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/constant-values.html) in the AWS SDK for Java API Reference.

### Maximum Connections
<a name="maximum-connections"></a>

You can set the maximum allowed number of open HTTP connections by using the [ClientConfiguration.setMaxConnections](http://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/ClientConfiguration.html#setMaxConnections-int-) method.

**Important**  
Set the maximum connections to the number of concurrent transactions to avoid connection contentions and poor performance. For the default maximum connections value, see [Constant Field Values](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/constant-values.html) in the AWS SDK for Java API Reference.

### Timeouts and Error Handling
<a name="timeouts-and-error-handling"></a>

You can set options related to timeouts and handling errors with HTTP connections.
+  **Connection Timeout** 

  The connection timeout is the amount of time (in milliseconds) that the HTTP connection will wait to establish a connection before giving up. The default is 10,000 ms.

  To set this value yourself, use the [ClientConfiguration.setConnectionTimeout](http://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/ClientConfiguration.html#setConnectionTimeout-int-) method.
+  **Connection Time to Live (TTL)** 

  By default, the SDK will attempt to reuse HTTP connections as long as possible. In failure situations where a connection is established to a server that has been brought out of service, having a finite TTL can help with application recovery. For example, setting a 15 minute TTL will ensure that even if you have a connection established to a server that is experiencing issues, you’ll reestablish a connection to a new server within 15 minutes.

  To set the HTTP connection TTL, use the [ClientConfiguration.setConnectionTTL](http://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/ClientConfiguration.html#setConnectionTTL-long-) method.
+  **Maximum Error Retries** 

  The default maximum retry count for retriable errors is 3. You can set a different value by using the [ClientConfiguration.setMaxErrorRetry](http://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/ClientConfiguration.html#setMaxErrorRetry-int-) method.

### Local Address
<a name="local-address"></a>

To set the local address that the HTTP client will bind to, use [ClientConfiguration.setLocalAddress](http://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/ClientConfiguration.html#setLocalAddress-java.net.InetAddress-).

## TCP Socket Buffer Size Hints
<a name="tcp-socket-buffer-size-hints"></a>

Advanced users who want to tune low-level TCP parameters can additionally set TCP buffer size hints through the [ClientConfiguration](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/ClientConfiguration.html) object. The majority of users will never need to tweak these values, but they are provided for advanced users.

Optimal TCP buffer sizes for an application are highly dependent on network and operating system configuration and capabilities. For example, most modern operating systems provide auto-tuning logic for TCP buffer sizes.This can have a big impact on performance for TCP connections that are held open long enough for the auto-tuning to optimize buffer sizes.

Large buffer sizes (e.g., 2 MB) allow the operating system to buffer more data in memory without requiring the remote server to acknowledge receipt of that information, and so can be particularly useful when the network has high latency.

This is only a *hint*, and the operating system might not honor it. When using this option, users should always check the operating system’s configured limits and defaults. Most operating systems have a maximum TCP buffer size limit configured, and won’t let you go beyond that limit unless you explicitly raise the maximum TCP buffer size limit.

Many resources are available to help with configuring TCP buffer sizes and operating system-specific TCP settings, including the following:
+  [Host Tuning](http://fasterdata.es.net/host-tuning/) 

# Access Control Policies
<a name="java-dg-access-control"></a>

 AWS *access control policies* enable you to specify fine-grained access controls on your AWS resources. An access control policy consists of a collection of *statements*, which take the form:

 *Account A* has permission to perform *action B* on *resource C* where *condition D* applies.

Where:
+  *A* is the *principal*- The AWS account that is making a request to access or modify one of your AWS resources.
+  *B* is the *action*- The way in which your AWS resource is being accessed or modified, such as sending a message to an Amazon SQS queue, or storing an object in an Amazon S3 bucket.
+  *C* is the *resource*- The AWS entity that the principal wants to access, such as an Amazon SQS queue, or an object stored in Amazon S3.
+  *D* is a *set of conditions*- The optional constraints that specify when to allow or deny access for the principal to access your resource. Many expressive conditions are available, some specific to each service. For example, you can use date conditions to allow access to your resources only after or before a specific time.

## Amazon S3 Example
<a name="s3-example"></a>

The following example demonstrates a policy that allows anyone access to read all the objects in a bucket, but restricts access to uploading objects to that bucket to two specific AWS accounts (in addition to the bucket owner’s account).

```
Statement allowPublicReadStatement = new Statement(Effect.Allow)
    .withPrincipals(Principal.AllUsers)
    .withActions(S3Actions.GetObject)
    .withResources(new S3ObjectResource(myBucketName, "*"));
Statement allowRestrictedWriteStatement = new Statement(Effect.Allow)
    .withPrincipals(new Principal("123456789"), new Principal("876543210"))
    .withActions(S3Actions.PutObject)
    .withResources(new S3ObjectResource(myBucketName, "*"));

Policy policy = new Policy()
    .withStatements(allowPublicReadStatement, allowRestrictedWriteStatement);

AmazonS3 s3 = AmazonS3ClientBuilder.defaultClient();
s3.setBucketPolicy(myBucketName, policy.toJson());
```

## Amazon SQS Example
<a name="sqs-example"></a>

One common use of policies is to authorize an Amazon SQS queue to receive messages from an Amazon SNS topic.

```
Policy policy = new Policy().withStatements(
    new Statement(Effect.Allow)
        .withPrincipals(Principal.AllUsers)
        .withActions(SQSActions.SendMessage)
        .withConditions(ConditionFactory.newSourceArnCondition(myTopicArn)));

Map queueAttributes = new HashMap();
queueAttributes.put(QueueAttributeName.Policy.toString(), policy.toJson());

AmazonSQS sqs = AmazonSQSClientBuilder.defaultClient();
sqs.setQueueAttributes(new SetQueueAttributesRequest(myQueueUrl, queueAttributes));
```

## Amazon SNS Example
<a name="sns-example"></a>

Some services offer additional conditions that can be used in policies. Amazon SNS provides conditions for allowing or denying subscriptions to SNS topics based on the protocol (e.g., email, HTTP, HTTPS, Amazon SQS) and endpoint (e.g., email address, URL, Amazon SQS ARN) of the request to subscribe to a topic.

```
Condition endpointCondition =
    SNSConditionFactory.newEndpointCondition("*@mycompany.com");

Policy policy = new Policy().withStatements(
    new Statement(Effect.Allow)
        .withPrincipals(Principal.AllUsers)
        .withActions(SNSActions.Subscribe)
        .withConditions(endpointCondition));

AmazonSNS sns = AmazonSNSClientBuilder.defaultClient();
sns.setTopicAttributes(
    new SetTopicAttributesRequest(myTopicArn, "Policy", policy.toJson()));
```

# Set the JVM TTL for DNS name lookups
<a name="jvm-ttl-dns"></a>

The Java virtual machine (JVM) caches DNS name lookups. When the JVM resolves a hostname to an IP address, it caches the IP address for a specified period of time, known as the *time-to-live* (TTL).

Because AWS resources use DNS name entries that occasionally change, we recommend that you configure your JVM with a TTL value of 5 seconds. This ensures that when a resource’s IP address changes, your application will be able to receive and use the resource’s new IP address by requerying the DNS.

On some Java configurations, the JVM default TTL is set so that it will *never* refresh DNS entries until the JVM is restarted. Thus, if the IP address for an AWS resource changes while your application is still running, it won’t be able to use that resource until you *manually restart* the JVM and the cached IP information is refreshed. In this case, it’s crucial to set the JVM’s TTL so that it will periodically refresh its cached IP information.

## How to set the JVM TTL
<a name="how-to-set-the-jvm-ttl"></a>

To modify the JVM’s TTL, set the [networkaddress.cache.ttl](https://docs.oracle.com/en/java/javase/17/core/java-networking.html#GUID-A680DADB-C4C1-40F1-B568-D9A97C917F5D) security property value. Note that `networkaddress.cache.ttl` is a *security property*, not a system property, i.e., it cannot be set with the `-D` command-line flag.

### Option 1: Set it programmatically in your application
<a name="set-ttl-programmatically"></a>

Call [https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/security/Security.html](https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/security/Security.html) early in your application startup, before any AWS SDK clients are created and before any network requests are made:

```
import java.security.Security;

public class MyApplication {
    public static void main(String[] args) {
        Security.setProperty("networkaddress.cache.ttl", "5");

        // ... create SDK clients and run application
    }
}
```

### Option 2: Set it in the java.security file
<a name="set-ttl-java-security-file"></a>

Set the `networkaddress.cache.ttl` property in the `$JAVA_HOME/jre/lib/security/java.security` file for Java 8 or `$JAVA_HOME/conf/security/java.security` file for Java 11 or higher.

The following is a snippet from a `java.security` file that shows the TTL cache set to 5 seconds.

```
#
# The Java-level namelookup cache policy for successful lookups:
#
# any negative value: caching forever
# any positive value: the number of seconds to cache an address for
# zero: do not cache
#
...
networkaddress.cache.ttl=5
...
```

All applications that run on the JVM represented by the `$JAVA_HOME` environment variable use this setting.

### Option 3: Use the JDK system properties fallback (command-line)
<a name="set-ttl-system-property"></a>

If you cannot modify the security configuration or code, you can use JDK system properties. These act as fallbacks if no security property is defined.
+ `sun.net.inetaddr.ttl` – Controls successful lookups (positive TTL)
+ `sun.net.inetaddr.negative.ttl` – Controls failed lookups (negative TTL)

```
java -Dsun.net.inetaddr.ttl=5 -Dsun.net.inetaddr.negative.ttl=1 -jar myapp.jar
```

**Note**  
These are JDK-internal properties documented in the [Oracle Java 8 Networking Properties](https://docs.oracle.com/javase/8/docs/technotes/guides/net/properties.html) reference as private properties that "may not be supported in future releases". Use Options 1-2 when possible.

# Enabling Metrics for the AWS SDK for Java
<a name="generating-sdk-metrics"></a>

The AWS SDK for Java can generate metrics for visualization and monitoring with [Amazon CloudWatch](https://aws.amazon.com/cloudwatch/) that measure:
+ your application’s performance when accessing AWS 
+ the performance of your JVMs when used with AWS 
+ runtime environment details such as heap memory, number of threads, and opened file descriptors

## How to Enable Java SDK Metric Generation
<a name="how-to-enable-sdk-java-metric-generation"></a>

You need to add the following Maven dependency to enable the SDK to send metrics to CloudWatch.

```
<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>com.amazonaws</groupId>
      <artifactId>aws-java-sdk-bom</artifactId>
      <version>1.12.490*</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>
<dependencies>
  <dependency>
    <groupId>com.amazonaws</groupId>
    <artifactId>aws-java-sdk-cloudwatchmetrics</artifactId>
    <scope>provided</scope>
  </dependency>
  <!-- Other SDK dependencies. -->
</dependencies>
```

 \$1Replace the version number with the latest version of the SDK available at [Maven Central](https://central.sonatype.com/artifact/com.amazonaws/aws-java-sdk-bom).

AWS SDK for Java metrics are *disabled by default*. To enable it for your local development environment, include a system property that points to your AWS security credential file when starting up the JVM. For example:

```
-Dcom.amazonaws.sdk.enableDefaultMetrics=credentialFile=/path/aws.properties
```

You need to specify the path to your credential file so that the SDK can upload the gathered datapoints to CloudWatch for later analysis.

**Note**  
If you are accessing AWS from an Amazon EC2 instance using the Amazon EC2 instance metadata service, you don’t need to specify a credential file. In this case, you need only specify:  

```
-Dcom.amazonaws.sdk.enableDefaultMetrics
```

All metrics captured by the AWS SDK for Java are under the namespace **AWSSDK/Java**, and are uploaded to the CloudWatch default region (*us-east-1*). To change the region, specify it by using the `cloudwatchRegion` attribute in the system property. For example, to set the CloudWatch region to *us-east-1*, use:

```
-Dcom.amazonaws.sdk.enableDefaultMetrics=credentialFile=/path/aws.properties,cloudwatchRegion={region_api_default}
```

Once you enable the feature, every time there is a service request to AWS from the AWS SDK for Java, metric data points will be generated, queued for statistical summary, and uploaded asynchronously to CloudWatch about once every minute. Once metrics have been uploaded, you can visualize them using the [AWS Management Console](https://console.aws.amazon.com/console/home) and set alarms on potential problems such as memory leakage, file descriptor leakage, and so on.

## Available Metric Types
<a name="available-metric-types"></a>

The default set of metrics is divided into three major categories:

 AWS Request Metrics  
+ Covers areas such as the latency of the HTTP request/response, number of requests, exceptions, and retries.  
![\[RequestMetric 131111\]](http://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/images/RequestMetric-131111.png)

 AWS service Metrics  
+ Include AWS service-specific data, such as the throughput and byte count for S3 uploads and downloads.  
![\[ServiceMetric 131111\]](http://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/images/ServiceMetric-131111.png)

Machine Metrics  
+ Cover the runtime environment, including heap memory, number of threads, and open file descriptors.  
![\[MachineMetric 131111\]](http://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/images/MachineMetric-131111.png)

  If you want to exclude Machine Metrics, add `excludeMachineMetrics` to the system property:

  ```
  -Dcom.amazonaws.sdk.enableDefaultMetrics=credentialFile=/path/aws.properties,excludeMachineMetrics
  ```

## More Information
<a name="more-information"></a>
+ See the [amazonaws/metrics package summary](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/metrics/package-summary.html) for a full list of the predefined core metric types.
+ Learn about working with CloudWatch using the AWS SDK for Java in [CloudWatch Examples Using the AWS SDK for Java](examples-cloudwatch.md).
+ Learn more about performance tuning in [Tuning the AWS SDK for Java to Improve Resiliency](https://aws.amazon.com/blogs/developer/tuning-the-aws-sdk-for-java-to-improve-resiliency) blog post.