Category: Java


Using Amazon SQS Dead Letter Queues

by Jason Fulghum | on | in Java | Permalink | Comments |  Share

Amazon SQS recently introduced support for dead letter queues. This feature is an important tool to help your applications consume messages from SQS queues in a more resilient way.

Dead letter queues allow you to set a limit on the number of times a message in a queue is processed. Consider an application that consumes messages from a queue and does some sort of processing based on the message. A bug in your application may only be triggered by certain types of messages or when working with certain data in your application. If your application receives one of these messages, it won’t be able to successfully process it and remove it from the queue. Instead, your application will continue to try to process the message again and again. While this message is being continually retried, your queue is likely filling up with other messages, which your application is unable to process because it’s stuck repeatedly processing the bad message.

Amazon SQS dead letter queues enable you to configure your application so that if it can’t successfully process a problematic message and remove it from the queue, that message will be automatically removed from your queue and delivered to a different SQS queue that you’ve designated as a dead letter queue. Another part of your application can then periodically monitor the dead letter queue and alert you if it contains any messages, which you can debug separately.

Using Amazon SQS dead letter queues is easy. You just need to configure a RedrivePolicy on your queue to specify when messages are delivered to a dead letter queue and to which dead letter queue they should be delivered. You can use the AWS Management Console, or you can access the Amazon SQS API directly with the AWS SDK for Java.

// First, we'll need an Amazon SQS client object.
AmazonSQSClient sqs = new AmazonSQSClient(myCredentials);

// Create two new queues:
//     one main queue for our application messages
//     and another to use as our dead letter queue
String qUrl = sqs.createQueue("MyApplicationQueue").getQueueUrl();
String dlqUrl = sqs.createQueue("MyDeadLetterQueue").getQueueUrl();

// Next, we need to get the the ARN (Amazon Resource Name) of our dead
// letter queue so we can configure our main queue to deliver messages to it.
Map attributes = sqs.getQueueAttributes(new GetQueueAttributesRequest(dlqUrl)
    .withAttributeNames(QueueAttributeName.QueueArn)).getAttributes();
String dlqArn = attributes.get(QueueAttributeName.QueueArn.toString());

// The last step is setting a RedrivePolicy on our main queue to configure
// it to deliver messages to our dead letter queue if they haven't been
// successfully processed after five attempts.
String redrivePolicy = String.format(
    "{"maxReceiveCount":"%i", "deadLetterTargetArn":"%s"}",
    5, dlqArn);

sqs.setQueueAttributes(new SetQueueAttributesRequest()
    .withQueueUrl(qUrl)
    .addAttributesEntry(QueueAttributeName.RedrivePolicy.toString(),
                        redrivePolicy));

There’s also a new operation in the Amazon SQS API to help you identify which of your queues are setup to deliver messages to a specific dead letter queue. If you want to know what queues are sending messages to a dead letter queue, just use the AmazonSQS#listDeadLetterSourceQueues operation.

List sourceQueues = sqs.listDeadLetterSourceQueues(
	new ListDeadLetterSourceQueuesRequest()
		.withQueueUrl(dlqUrl)).getQueueUrls();
System.out.println("Source Queues Delivering to " + qUrl);
for (String queueUrl : sourceQueues) {
	System.out.println(" * " + queueUrl);
}

Dead letter queues are a great way to add more resiliency to your queue-based applications. Have you set up any dead letter queues in Amazon SQS yet?

Performing Conditional Writes Using the Amazon DynamoDB Transaction Library

by Wade Matveyenko | on | in Java | Permalink | Comments |  Share

Today we’re lucky to have another guest post by David Yanacek from the Amazon DynamoDB team. David is sharing his deep knowledge on the Amazon DynamoDB Transactions library to help explain how to use it with the conditional writes feature of Amazon DynamoDB.


The DynamoDB transaction library provides a convenient way to perform atomic reads and writes across multiple DynamoDB items and tables. The library does all of the nuanced item locking, commits, applies, and rollbacks for you, so that you don’t have to worry about building your own state machines or other schemes to make sure that writes eventually happen across multiple items. In this post, we demonstrate how to use the read-modify-write pattern with the transaction library to accomplish the same atomic checks you were used to getting by using conditional writes with the vanilla DynamoDB API.

The transaction library exposes as much of the low-level Java API as possible, but it does not support conditional writes out of the box. Conditional writes are a way of asking DynamoDB to perform a write operation like PutItem, UpdateItem, or DeleteItem, but only if certain attributes of the item still have the values that you expect, right before the write goes through. Instead of exposing conditional writes directly, the transaction library enables the read-modify-write pattern—just like the pattern you’re used to with transactions in an RDBMS. The idea is to start a transaction, read items using that transaction, validate that those items contain the values you expect to start with, write your changes using that same transaction, and then commit the transaction.  If the commit() call succeeds, it means that the changes were written atomically, and none of the items in the transaction were modified by any other transaction in the meantime, starting from the time when each item was read by your transaction.

Transaction library recap

Let’s say you’re implementing a tic-tac-toe game. You have an Item in a DynamoDB table representing a single match of the game, with an attribute for each position in the board (Top-Left, Bottom-Right, etc.). Also, to make this into a multi-item transaction, let’s add two more items—one per player in the game, each with an attribute saying whether it is currently that player’s turn or not. The items might look something like this:

Games Table Item Users Table Items
{
  " GameId": "cf3df",
  "Turn": "Bob",
  "Top-Right": "O"
}
{
  " UserId": "Alice",
  "IsMyTurn": 0
}
{
  " UserId": "Bob",
  "IsMyTurn": 1
}

Now when Bob plays his turn in the game, all three items need to be updated:

  1. The Bob record needs to be marked as "Not my turn anymore."
  2. The Alice record needs to be marked as "It’s my turn now."
  3. The Game record needs to be marked as "It’s Alice’s turn, and also the Top-Left has an X in it."

If you write your application so that it performs three UpdateItem operations in a row, a few problems could occur. For example, your application could crash after doing one of the writes, and now something else in your application would need to notice this and pick up where it left off before doing anything else in the game. Fortunately, the transaction library can make these three separate operations happen together in a transaction, where either all of the writes go through together, or if there is another transaction overlapping with yours at the same time, only one of those transactions happens.

The code for doing this in a transaction looks like this:

// Start a new transaction
Transaction t = txManager.newTransaction();
 
// Update Alice's record to let him know that it is now her turn.
t.updateItem(
  new UpdateItemRequest()
    .withTableName("Users")
    .addKeyEntry("UserId", new AttributeValue("Alice"))
    .addAttributeUpdatesEntry("IsMyTurn",
            new AttributeValueUpdate(new AttributeValue("1"), AttributeAction.PUT)));
 
// Update Bob's record to let him know that it is not his turn anymore.
t.updateItem(
  new UpdateItemRequest()
    .withTableName("Users")
    .addKeyEntry("UserId", new AttributeValue("Bob"))
    .addAttributeUpdatesEntry("IsMyTurn",
            new AttributeValueUpdate(new AttributeValue("0"), AttributeAction.PUT)));
 
// Update the Game item to mark the spot that was played, and make it Alice's turn now.
t.updateItem(
  new UpdateItemRequest()
    .withTableName("Games")
    .addKeyEntry("GameId", new AttributeValue("cf3df"))
    .addAttributeUpdatesEntry("Top-Left", 
            new AttributeValueUpdate(new AttributeValue("X"), AttributeAction.PUT))
    .addAttributeUpdatesEntry("Turn",
            new AttributeValueUpdate(new AttributeValue("Alice"), AttributeAction.PUT)));
 
// If no exceptions are thrown by this line, it means that the transaction was committed.
t.commit();

What about conditional writes?

The preceding code makes sure that the writes go through atomically, but that’s not enough logic for making a move in the game. We need to make sure that, when the transaction goes through, there wasn’t a transaction right before it where Bob already played his turn. In other words, how do we make sure that Bob doesn’t play twice in a row—for example, by trying to sneak in two turns before Alice has a chance to move? If there was only a single item involved, say the "Games" item, we could accomplish this by using conditional writes (the Expected clause), like so:

// An example of a conditional update using the DynamoDB client (not the transaction library)
dynamodb.updateItem(
  new UpdateItemRequest()
    .withTableName("Games")
    .addKeyEntry("GameId", new AttributeValue("cf3df"))
    .addAttributeUpdatesEntry("Top-Left", 
    		new AttributeValueUpdate(new AttributeValue("X"), AttributeAction.PUT))
    .addAttributeUpdatesEntry("Turn",
    		new AttributeValueUpdate(new AttributeValue("Alice"), AttributeAction.PUT))
    .addExpectedEntry("Turn", new ExpectedAttributeValue(new AttributeValue("Bob"))) // A condition to ensure it's still Bob's turn
    .addExpectedEntry("Top-Left", new ExpectedAttributeValue(false)));               // A condition to ensure the Top-Left hasn't been played

This code now correctly updates the single Game item. However, conditional writes in DynamoDB can only refer to the single item the operation is updating, and our transaction contains three items that need to be updated together, only if the Game is still in the right state. Therefore, we need some way of mixing the original transaction code with these “conditional check” semantics.

Conditional writes with the transaction library

We started off with code for a transaction that coordinated the writes to all three items atomically, but it didn’t ensure that it was still Bob’s turn when it played Bob’s move. Fortunately, adding that check is easy: it’s simply a matter of adding a read to the transaction, and then performing the verification on the client-side. This is sometimes referred to as a "read-modify-write" pattern:

// Start a new transaction, just like before.
Transaction t = txManager.newTransaction();
 
// First, read the Game item.
Map game = t.getItem(
    new GetItemRequest()
        .withTableName("Games")
        .addKeyEntry("GameId", new AttributeValue("cf3df"))).getItem();
 
// Now check the Game item to ensure it's in the state you expect, and bail out if it's not.
// These checks serve as the "expected" clause.  
if (! "Bob".equals(game.get("Turn").getS())) {
    t.rollback();
    throw new ConditionalCheckFailedException("Bob can only play when it's Bob's turn!");
}
 
if (game.containsKey("Top-Left")) {
    t.rollback();
    throw new ConditionalCheckFailedException("Bob cannot play in the Top-Left because it has already been played.");
}
 
// Again, update Alice's record to let her know that it is now her turn.
t.updateItem(
    new UpdateItemRequest()
        .withTableName("Users")
        .addKeyEntry("UserId", new AttributeValue("Alice"))
        .addAttributeUpdatesEntry("IsMyTurn",
            new AttributeValueUpdate(new AttributeValue("1"), AttributeAction.PUT)));
 
// And again, update Bob's record to let him know that it is not his turn anymore.
t.updateItem(
    new UpdateItemRequest()
        .withTableName("Users")
        .addKeyEntry("UserId", new AttributeValue("Bob"))
        .addAttributeUpdatesEntry("IsMyTurn",
            new AttributeValueUpdate(new AttributeValue("0"), AttributeAction.PUT)));
 
// Finally, update the Game item to mark the spot that was played and make it Alice's turn now.
t.updateItem(
    new UpdateItemRequest()
        .withTableName("Games")
        .addKeyEntry("GameId", new AttributeValue("cf3df"))
        .addAttributeUpdatesEntry("Top-Left", 
            new AttributeValueUpdate(new AttributeValue("X"), AttributeAction.PUT))
        .addAttributeUpdatesEntry("Turn",
            new AttributeValueUpdate(new AttributeValue("Alice"), AttributeAction.PUT)));
 
// If no exceptions are thrown by this line, it means that the transaction was committed without interference from any other transactions.
try {
    t.commit();
} catch (TransactionRolledBackException e) {
    // If any of the items in the transaction were changed or read in the meantime by a different transaction, then this will be thrown.
    throw new RuntimeException("The game was changed while this transaction was happening. You probably want to refresh Bob's view of the game.", e);
}

There are two main differences with the first approach.

  • First, the code calls GetItem on the transaction and checks to make sure the item is in the state your application expects it to be in. If not, it rolls back the transaction and returns an error to the caller. This is done in the same transaction as the subsequent updates. When you read an item in a transaction, the transaction library locks the item in the same way as when you modify it in the transaction. Your application can still read an item without interfering with it while it is locked, but it must do so outside of a transaction, using one of the read isolation levels on the TransactionManager. More about read isolation levels is available in the design document for the transaction library.
  • Next, the code checks for TransactionRolledBackException. This check could have been done in the first example as well, but it’s called out in this example to show what will happen if another transaction either reads or writes any of the items involved in the transaction while yours was going on. When this happens, you might want to retry the whole transaction (start from the beginning—don’t skip any steps), or refresh your client’s view so that they can re-evaluate their move, since the state of the game may have changed.

While the preceding code doesn’t literally use the conditional writes API in DynamoDB (through the Expected parameter), it functionally does the same atomic validation—except with the added capability of performing that check and write atomically across multiple items.

More info

You can find the DynamoDB transaction library in the AWS Labs repository on GitHub. You’ll also find a more detailed write-up describing the algorithms it uses. You can find more usage information about the transaction library in the blog post that announced the library. And if you want to see some working code that uses transactions, check out TransactionExamples.java in the same repo.

For a recap on conditional writes, see part of a talk called Amazon DynamoDB Design Patterns for Ultra-High Performance Apps from the 2013 AWS re: Invent conference. You may find the rest of the talk useful as well, but the segment on conditional writes is only five minutes long.

Two New Amazon RDS Database Engines in Eclipse

We’re excited to announce support for two more Amazon RDS database engines in the AWS Toolkit for Eclipse. You can now configure connections to PostgreSQL and Microsoft SQL Server RDS database instances directly from within Eclipse by opening the AWS Explorer view and double-clicking on your RDS database instance.

The first time you select your RDS database instance, you’ll be asked for some basic information about connecting to your database instance, such as: password, JDBC driver, and whether you want Eclipse to automatically open permissions in your security group to allow database connections.

Once you’ve configured a connection to your database, you can use all the tools from the Eclipse Data Tools Platform. You can browse your schemas, export data, run queries in SQL Scrapbook, and more.

If you don’t have any Amazon RDS database instances yet, you can go to the Amazon RDS console and launch a new database instance. With just a few clicks, you can launch a fully managed MySQL, Oracle, PostgreSQL, or Microsoft SQL Server database.

Are you using any of the database tools in Eclipse to work with your RDS databases?

DynamoDB Local Test Tool Integration for Eclipse

We’re excited to announce that the AWS Toolkit for Eclipse now includes integration with the Amazon DynamoDB Local Test Tool. The DynamoDB Local Test Tool allows you to develop and test your application against a DynamoDB-compatible database running locally — no Internet connectivity or credit card required. When your application is ready for prime time, all you need to do is update the endpoint given to your AmazonDynamoDBClient. Neato!

With the DynamoDB Local Test Tool integrated into the AWS Toolkit for Eclipse, using it is easier than ever. Make sure you have a recent version of the Amazon DynamoDB Management plugin (v201311261154 or later) installed and follow along below!

Installing DynamoDB Local

First, head to the Eclipse preferences and make sure you have a JavaSE-1.7 compatible JRE installed. If not, you’ll need to install one and configure Eclipse to know where it is.

Eclipse Execution Environments Preference Page

Then, head to the new DynamoDB Local Test Tool preference page, where you can specify a directory to install the DynamoDB Local Test Tool and a default TCP port for it to bind to.

DynamoDB Local Test Tool Preference Page

The page also lists versions of the DynamoDB Local Test Tool available for installation. There are currently two: the original version (2013-09-12) and a newer version (2013-12-12) which includes support for Global Seconday Indexes. When the DynamoDB team releases future versions of the test tool, they will also show up in this list. Select the latest version and hit the Install button that’s above the list of versions; the DynamoDB Local Test Tool will be downloaded and installed in the directory you specified.

Starting DynamoDB Local

Once the test tool is installed, pop open the AWS Explorer view and switch it to the Local (localhost) region. This psuedo-region represents test tool services running locally on your machine.

Selecting the Local (localhost) Region

For now, you’ll see a single Amazon DynamoDB node representing the DynamoDB Local Test Tool. Right-click this node and select Start DynamoDB Local.

Starting DynamoDB Local

This will bring up a wizard allowing you to pick which version of the DynamoDB Local Test Tool to launch, and the port to which it should bind. Pick the version you just installed, give it a port (if you didn’t specify a default earlier), and hit Finish. A console window will be opened that should print out a few lines similar to the below when the DynamoDB Local Test Tool finishes initializing itself:

DynamoDB Local Console Output

Using DynamoDB Local

You can now use the DynamoDB Management features of the toolkit to create tables in your local DynamoDB instance, load some data into them, and perform test queries against your tables.

The DynamoDB Table Editor

To write code against DynamoDB Local, simply set your client’s endpoint and region appropriately:

// The secret key doesn't need to be valid, DynamoDB Local doesn't care.
AWSCredentials credentials = new BasicAWSCredentials(yourAccessKeyId, "bogus");
AmazonDynamoDBClient client = new AmazonDynamoDBClient(credentials);

// Make sure you use the same port as you configured DynamoDB Local to bind to.
client.setEndpoint("http://localhost:8000");

// Sign requests for the "local" region to read data written by the toolkit.
client.setSignerRegionOverride("local");

And away you go! As mentioned above, DynamoDB Local doesn’t care if your credentials are valid, but it DOES create separate local databases for each unique access key ID sent to it, and for each region you say you’re authenticating to. If you have configured the Toolkit with a real set of AWS credentials, you’ll want to use the same access key ID when programmatically interacting with DynamoDBLocal so you read from and write to the same local database. Since the Toolkit uses the "local" region to authenticate to DynamoDBLocal, you’ll also want to override your client to authenticate to the "local" region as well.

Conclusion

DynamoDB Local is a great way to play around with the DynamoDB API locally while you’re first learning how to use it, and it’s also a great way to integration-test your code even if you’re working without a reliable Internet connection. Now that the AWS Toolkit for Eclipse makes it easy to install and use, you should definitely check it out!

Already using DynamoDB Local or the new Eclipse integration? Let us know how you like it and how we can make it even better in the comments!

Taste of JMX Using the AWS SDK for Java

by Hanson Char | on | in Java | Permalink | Comments |  Share

As you may know, starting from Java 5, the JMX technology is available out-of-the-box to monitor and manage the Java VM.  It seems natural to wonder what it would be like to configure and modify the behavior of the AWS Java SDK via JMX in real time.  Imagine, for example, every configuration option related to enabling SDK metrics can also be done via JMX.  The only difference is configuration via system properties is a one-off and static business, whereas configuration via JMX is dynamic, and can be done anytime on-the-fly in real time while the JVM is running!  Since version 1.6.7 of the AWS SDK for Java, you can do exactly that.

Why the need for JMX ?

Here are two use cases I can think of.

  1. You are trying to troubleshoot intermittent latency issues with a running JVM accessing AWS, but didn’t have metrics configured when the JVM was originally started.  Even though you could conceivably shut down, configure the necessary system properties, and then restart the JVM to enable automatic metric generation, you don’t have to!  Via JMX, you can dynamically turn on automatic metric generation and have the metrics uploaded to Amazon CloudWatch for as long as you want, and then have generation turned off afterwards if you desired.  (See sample JConsole screen shots below.)
  2. You are not entirely decided on whether you want to permanently enable metrics, or what the optimal metric configuration would be (for example, per-host-level metrics vs. per-JVM-level metrics).   Via JMX, you can experiment and play around with different options to see what is best for your applications.  Based on actual observation with different options, you can then decide on the best metric configuration and configure the metrics via system properties for long-term use.

To me, it’s simply fun and powerful to be able to manage and administer a fleet of JVMs dynamically on-the-fly, and especially so when remote scripting is involved.  JMX is an enabling technology, and what can be done with the power it offers is only limited by our imagination. 

Example: Metric Configuration via JConsole

Here are the steps to navigate to the Metric Administration MBean via JConsole:

  1. Fire up jconsole.
  2. Connect to a running JVM that accesses AWS via the AWS SDK for Java.
  3. Click the MBeans tab, and expand the name space

         com.amazonaws.management
  4. Click AwsSdkMetrics.
  5. Click Attributes.

Assuming you have no system properties configured for your JVM, you should see all the default values.  Something like:

jmx-attributes

Now, you can modify almost all the attribute values simply by clicking on the value fields. You then change the values directly in-place and press the Enter key.  Almost all changed values will take effect immediately (i.e. without the need to disable/re-enable metric generation).   The only exception is the value of CredentialFile which gets lazily applied as explained below. Here is a sample screenshot of what it looked like after I changed the Region value to "us-west-2", CredentialFile value to "/Users/hchar/.aws/awsTestAccount.properties" and JvmMetricName value to "MyJVM", but before enabling automatic metric generation:

jmx-disabled

To enable automatic metric generation, click Operations to find the enableDefaultMetrics button:

operations

Click the enableDefaultMetrics button to enable automatic metric generation and uploads to Amazon CloudWatch.  Once metric generation is enabled, you should see the values reflected on the Attributes tab:

jmx-enabled

What are the Limitations?

Compared to what you can do with system properties for metric configuration, there are absolutely no limitations!  In other words, for all the one-off metric configuration options that you can make using system properties, such as those described in the Metric Configuration blog, you can achieve the same effect using JMX, but dynamically in real time and as often as you want!

However, if you happened to modify the CredentialFile attribute value, which is the credential file used for uploading metrics to Amazon CloudWatch, you would need to disable and then re-enable the metrics (via invoking the disableMetrics and the enableDefaultMetrics operations) before the credentials would become effective.  This allows the underlying service client to re-initialize itself with the proper credentials.  In JConsole, you can do so by simply clicking the respective buttons on the MBean’s Operations tab.

Finally, have fun using JMX with the AWS SDK for Java, and Merry Christmas!

Eclipse Support for AWS Elastic Beanstalk Worker Environment Tiers

A web application is typically concerned with quickly sending responses to incoming queries from its users. This model works really well for things like rendering a web page based on a couple of database queries or validating some user input and storing it to a database. The user makes a request to the application to perform some work, the user’s browser waits while the application does the work, and then the application returns a response, which the user’s browser renders to inform him or her of the result of the action.

In some cases, however, servicing a user request requires some serious computation, such as compiling a month-end report based on multiple large scans over the database. The typical web application model gives a poor user experience in this case—the user’s browser simply “spins” with no feedback until the response is completely ready. In the meantime, the job is taking up resources on your front-end web servers, potentially leading to degraded experience for other users if their requests happen to land on the host running the complicated request.

The Solution: Worker Environment Tiers for Elastic Beanstalk

The solution to these problems is to offload the expensive computations to a back-end application tier asynchronously. The user receives a response from the front-end tier as soon as the work item is queued, indicating that the work is in progress. He or she can check back at his or her leisure to see the progress of the request and view the final result once it becomes available. And since the work is being done by a separate set of back-end hosts which are not serving normal user requests, there’s no chance that running this complicated job will negatively impact other customers.

Recently, the fine folks who make AWS Elastic Beanstalk introduced an exciting new feature called worker environment tiers that make it super easy to implement and deploy these kinds of asynchronous background-processing workers within your application. A worker environment tier accepts work requests from your front-end web environment tier via an Amazon SQS queue. All you have to do is write the business logic to be run when a work request is received, deploy it to an Elastic Beanstalk worker environment tier, then start writing asynchronous work requests to the environment’s queue. You can read some more in-depth information about worker environment tiers here.

The AWS Toolkit for Eclipse now includes support for Elastic Beanstalk worker environment tiers, so you can stand up and start deploying code to a worker environment tier with just a few quick clicks. This post will walk you through the process of setting up a new worker environment tier and deploying code to it, all without leaving the comfort of your favorite IDE!

Create a new worker tier project

The easiest way to get started with worker tiers is to create a new AWS Java Web Project. You can find this new project type under the AWS folder in the New Project dialog; it’s the same application type you may have used in the past to create a web application for Elastic Beanstalk. On the New AWS Java Web Project dialog, select the option to start from a Basic Amazon Elastic Beanstalk Worker Tier Application. This will create a basic Java EE Web Application that accepts work requests via an HTTP POST request to a servlet.

  • From the main menu bar, select File -> New -> Project …. Choose the AWS Java Web Project wizard.

The Eclipse New Project Wizard

 

  • Give your project a name and select the Basic Amazon Elastic Beanstalk Worker Tier Application option.

The New AWS Java Web Project Wizard

 

As with the Basic Java Web Application template, the build path for the newly-created project is preconfigured with the latest version of the AWS SDK for Java, so you’re already set up to interact with AWS services like Amazon S3 and Amazon DynamoDB as part of handling a work request. For example, you may want to have your worker write the result of its processing to Amazon S3 for later retrieval by the front-end tier, or use Amazon DynamoDB to track the progress of any work items that are currently being processed.

The example application demonstrates parsing a simple work request from the POST body, simulates doing some complicated work by sleeping for 10 seconds, then writes the “result” of its work to Amazon S3. Take a quick glance at the code to see how it works.

Create a new Elastic Beanstalk worker tier server

Next, we’ll create a new environment through the Eclipse Web Tools Platform’s Servers view. On the first page of the New Server wizard, select the AWS Elastic Beanstalk for Tomcat 7 server type from within the Amazon Web Services folder. After clicking Next, select the AWS region where your application will be hosted, choose Worker Environment from the Environment Type drop-down, and give your new application and environment names.

  • Right-click on the Servers view and select New -> Server.

 

  • Choose the AWS Elastic Beanstalk for Tomcat 7 option.

 

  • Choose a region, application name, environment name, and environment type.

 

On the next page of the wizard, you can modify other optional settings for the environment. If you have an existing SQS queue you would like your worker environment to read from, you can configure that here; otherwise, a new SQS queue will be automatically created for you.

You can also choose to associate an IAM role with your environment on this page, which is an easy way to give your application permission to access AWS resources such as S3. By default, a new role will be created for you that grants your environment permission to access your SQS queues and publish metrics into Amazon CloudWatch. Your environment won’t be able to function correctly if it doesn’t have these permissions, so if you pick a custom role here, make sure it includes those permissions as well.

  • Configure advanced settings for the environment.

 

On the final page, select your worker project to be deployed to the environment.

 

Now that everything is configured, right-click your new environment in the Servers view and start it. This process may take several minutes as Elastic Beanstalk provisions EC2 instances and deploys your application to them. Once the process has completed and your application is displayed as “Started”, your workers are ready to go!

  • Start your environment.

 

By default, your environment starts out with a single worker process running on a t1.micro EC2 instance, and will auto-scale up to as many as four instances if CPU usage on the workers is high. Double-clicking the environment in the Servers view will open up a configuration page where you can tweak these settings, along with many more.

Testing out your new worker

Unlike a traditional web application, your worker environment cannot be invoked directly from within your web browser to debug it. Instead, you need to send work requests to your environment via the SQS queue it is subscribed to. You can do this programmatically (as you will ultimately do from your front-end application):

 

AmazonSQS sqs = ...;

Sring workRequest =
    "{" +
    "  "bucket": "my-results-bucket"," +
    "  "key": "my-work-item-key"," +
    "  "message": "Hello, World"" +
    "}";

sqs.sendMessage(new SendMessageRequest()
    .withQueueUrl(MY_QUEUE_URL)
    .withMessageBody(workRequest));

 

For testing things out, you can also easily send messages to your application by clicking on the Queue URL in the Environment Resources tab of the server editor (available by double-clicking on the newly-created server in the Servers view). This will bring up a dialog allowing you to quickly send work requests to your environment via the SQS queue in order to test out how it handles them.

 

Conclusion

Now you’re all set up to use an Elastic Beanstalk worker tier in your application. Just fill in the appropriate code to handle the different kinds of asynchronous work requests your application requires, and with a couple mouse-clicks your updated code can be deployed out to a fleet of back-end workers running in the cloud. Nifty! Are you deploying code to Elastic Beanstalk (either worker tiers or traditional web server tiers) from within Eclipse? Let us know how it’s working in the comments below!

Metric Configuration in AWS SDK for Java

by Hanson Char | on | in Java | Permalink | Comments |  Share

As we mentioned in an earlier blog, you can now enable the automatic generation of performance metrics when using the AWS SDK for Java, and have them automatically uploaded to Amazon CloudWatch for monitoring purposes. Sometimes, however, you may want to generate more fine-grained metrics, such as per-host and per-JVM metrics, that are not enabled by default. Or, you may want to customize the name space for the metrics uploaded to Amazon CloudWatch to something more meaningful to your use cases. This is where you may find the metric configuration options helpful.

What options are available?

Here is a quick summary of five metric configuration options that you may find useful:

Option Description Default
metricNameSpace The metric namespace. "AWSSDK/Java"
includePerHostMetrics If specified, additional metrics will be generated on a per-host basis. Per-host level metric is disabled.
jvmMetricName If specified, additional metrics will be generated on a per-JVM basis. Per-JVM level metric is disabled.
credentialFile Used to specify an AWS credential property file for uploading metrics to Amazon CloudWatch. The default mechanism of DefaultAWSCredentialsProviderChain is used.
cloudwatchRegion The Amazon CloudWatch region for metrics uploading purposes. "us-east-1"

Are there any sample metric configurations?

Here are three sample metric configurations via system properties.

Sample 1: How to enable per host metrics

Suppose you are running the same application on multiple hosts, and you want to

  1. specify your own metric name space of "MyApp"
  2. generate additional metrics on a per-host basis
  3. make use of a AWS credential property file that resides at "/path/cred.property" on each host
  4. upload the metrics to the Amazon CloudWatch region "us-west-2"

You can do so by specifying the system property:

-Dcom.amazonaws.sdk.enableDefaultMetrics=metricNameSpace=MyApp,
  includePerHostMetrics,credentialFile=/path/cred.property,
  cloudwatchRegion=us-west-2

(All in a single line with no space.)

That’s it—per host metric will be enabled once the JVM is started.

Sample 2: How to enable both per-host and per-JVM metrics

This is similar to sample 1, but suppose your application involves running two instances of JVMs, both accessing AWS on each host. Now, you may want to generate metrics not only on a per-host basis, but also on a per-JVM basis. We can do so by giving the two JVMs different names. Let’s name the first JVM "Gamma", and the second "Delta". For the first JVM, this translates to specifying the system property:

-Dcom.amazonaws.sdk.enableDefaultMetrics=metricNameSpace=MyApp,
  includePerHostMetrics,credentialFile=/path/cred.property,
  cloudwatchRegion=us-west-2,jvmMetricName=Gamma

Similarly, for the second JVM:

-Dcom.amazonaws.sdk.enableDefaultMetrics=metricNameSpace=MyApp,
  includePerHostMetrics,credentialFile=/path/cred.property,
  cloudwatchRegion=us-west-2,jvmMetricName=Delta

(All in a single line with no space.)

Note the two specifications above differ only in the value of jvmMetricName. You should then be able to visualize the metrics aggregated at the respective levels in the Amazon CloudWatch console.

Sample 3: How to enable per-JVM but not per-host metrics

This is almost the same as sample 2. All you need to do is to remove the includePerHostMetrics option, like so for the first JVM:

-Dcom.amazonaws.sdk.enableDefaultMetrics=metricNameSpace=MyApp,
  credentialFile=/path/cred.property,
  cloudwatchRegion=us-west-2,jvmMetricName=Gamma 

For the second JVM:

-Dcom.amazonaws.sdk.enableDefaultMetrics=metricNameSpace=MyApp,
  credentialFile=/path/cred.property,
  cloudwatchRegion=us-west-2,jvmMetricName=Delta 

(All in a single line with no space.)

More details are available in the javadoc of AwsSdkMetrics, and the metric package summary. That’s all for now. Hope you find these options useful, and happy monitoring !

New, Simplified Method Forms in the AWS SDK for Java

by Jason Fulghum | on | in Java | Permalink | Comments |  Share

We’re always looking for new ways to improve the tools our team builds, like the AWS SDK for Java and the AWS Toolkit for Eclipse. Sometimes those improvements come as brand new functionality, such as Amazon CloudWatch Metrics for the AWS SDK for Java, and sometimes they’re small tweaks to make the tools faster or easier to use.

Today, I want to show off a small tweak that we added recently to make invoking requests with the SDK a little bit easier and more concise. We’ve tweaked the AmazonDynamoDBClient and AmazonSNSClient classes so that lots of common operations are even easier and more succinct to invoke.

For some of the most commonly used operations with Amazon DynamoDB and Amazon SNS, you can now skip constructing request objects and just pass in your request parameters directly. The request objects are still useful in many cases, such as providing access to less common parameters, or allowing you to build your request parameters in one part of your code and pass the request objects to another part of your code to be executed. These new method forms simply provide an alternate way to quickly invoke operations with common parameter combinations.

Here’s an example of using a few of the new, simplified method forms in the Amazon SNS client:

AmazonSNSClient sns = new AmazonSNSClient(myCredentials);
String topicArn = sns.createTopic("myNewTopic").getTopicArn();
String subscriptionArn = sns.subscribe(topicArn, "email", "me@email.com").getSubscriptionArn();
sns.publish(topicArn, "hello SNS world!");
sns.unsubscribe(subscriptionArn);
sns.deleteTopic(topicArn);

We’ll be adding more methods like these to other service clients in the SDK, too. What clients would you like to see updated next? Are there other common request parameter combinations that you’d like us to add?

Credentials Best Practices

by David Murray | on | in Java | Permalink | Comments |  Share

Introduction

Your Amazon Web Services account is (we hope!) pretty important to you. Whether you’re running mission-critical applications that need to be protected from malicious interlopers, or you simply want to ensure that only the people you specify can bill resources to your AWS account, it is vital that you keep your account and its associated AWS resources secure.
 
The client libraries in the AWS SDK for Java almost universally require you to specify a set of AWS security credentials to use when making service requests. These credentials prove that your application has permission to perform any requested actions, keeping your account safe from attackers who do not know these credentials.
 
This blog post is the first in a series in which we will discuss best practices around managing and securing your security credentials and explore features of the AWS SDK for Java that help you do so easily. In this post, I’ll quickly lay out an easy way to securely use credentials with the AWS SDK for Java from applications running on Amazon EC2. In subsequent posts, we’ll dive a bit deeper into some of the principles that make this approach secure and discuss some of the more advanced scenarios enabled by the SDK.
 

Identity and Access Management

Credentials for programmatic access to the AWS APIs come in the form of an Access Key ID (or "access key") and a Secret Access Key (or "secret key"). Similar to the familiar concepts of a username and password, the access key identifies who is making the call, while the secret key proves that the caller is actually who they say they are.
 
Identity — who your callers are — and access management — what those callers are allowed to do — for your account are managed through the appropriately-named AWS Identity and Access Management (IAM) service. This service lets you define "users" (representing either actual human users or autonomous software applications), configure policies granting different permissions to individual users or groups of users, and manage sets of credentials that can be used to authenticate as a particular user.
 

Configuring Credentials Using the AWS SDK for Java

Alright, let’s see some code! In the AWS SDK for Java, the client objects you use to interact with individual services each get credentials to sign their requests using an implementation of the AWSCredentialsProvider interface. When the client makes a request, it internally calls the getCredentials() method on its AWSCredentialsProvider instance to retrieve an appropriate set of credentials to use to sign the request. The SDK provides a number of different implementations of this interface, which attempt to retrieve credentials from various different places.
 
To set the credentials provider used by a client instance, just pass it to the constructor:
 
AWSCredentialsProvider provider = ...;

// This client will authenticate using credentials from the given provider.
AmazonDynamoDBClient client = new AmazonDynamoDBClient(provider);
 

IAM Roles for Amazon EC2

If your application runs on Amazon EC2 instances, a really great way to get a set of credentials to use is via IAM Roles for Amazon EC2. A "role" is an IAM concept similar to a user, but without permanent credentials associated with it. Instead, a user or application can be given permission to "assume" a role, retrieving a temporary set of credentials that allow it to perform actions that the role’s policy allows.
 
When launching an EC2 instance, you can choose to associate it with an IAM role. Any application running on that EC2 instance is then allowed to assume the associated role. Amazon EC2 handles all the legwork of securely authenticating instances to the IAM service to assume the role and periodically refreshing the retrieved role credentials, keeping your application super-secure with almost no work on your part.
 
Using credentials for a role associated with your EC2 Instance from the AWS SDK for Java is super easy — just use the InstanceProfileCredentialsProvider:
 
AWSCredentialsProvider provider = new InstanceProfileCredentialsProvider();
AmazonDynamoDBClient client = new AmazonDynamoDBClient(provider);
 
In fact, if you use one of the client constructors that do not take an AWSCredentialsProvider, the client will also use an InstanceProfileCredentialsProvider (after first checking for overrides specified via an environment variable or system properties).
 

Associating an EC2 Instance with a Role

It’s really easy to create a role and associate it with your EC2 instances via the AWS Management Console (there’s a nice walkthrough here, but if you want to do so programmatically that’s no sweat either. First, we’ll create a new role. We configure it to allow Amazon EC2 to assume the role on our instances’ behalf, and give the role permission to access a particular S3 bucket (for the sake of example). This probably only needs to be done once when initially setting up your application, after which we can keep reusing the same role for any new EC2 instances we launch.
 
// Requires credentials for an administrative user.

AmazonIdentityManagement iam = new AmazonIdentityManagementClient(...);

iam.createRole(new CreateRoleRequest()
    .withRoleName("test-role")
    .withAssumeRolePolicyDocument(new Policy()
        .withStatements(new Statement(Effect.Allow)
            .withActions(STSActions.AssumeRole)
            .withPrincipals(new Principal(Services.AmazonEC2)))
        .toJson()));

iam.putRolePolicy(new PutRolePolicyRequest()
    .withRoleName("test-role")
    .withPolicyName("allow-s3-read")
    .withPolicyDocument(new Policy()
        .withStatements(new Statement(Effect.Allow)
        .withActions(S3Actions.GetObject)
        .withResources(new S3ObjectResource("top-secret-bucket", "*")))
    .toJson()));
Next, we create an instance profile and add the role to it. An instance profile allows you to associate multiple roles with a particular instance, which is useful in some advanced scenarios. For now, we’ll just add a single role. Like creating a role, this probably only needs to be done once when initially configuring your application.
iam.createInstanceProfile(new CreateInstanceProfileRequest()
    .withInstanceProfileName("test-instance-profile"));

iam.addRoleToInstanceProfile(new AddRoleToInstanceProfileRequest()
    .withInstanceProfileName("test-instance-profile")
    .withRoleName("test-role"));
Once our role and instance profile are set up, we can launch new Amazon EC2 instances associated with our newly-created instance profile, making credentials available to any applications running on the instance via InstanceProfileCredentialsProvider.
 
// Requires credentials for a user (or role) with permission to launch EC2
// instances AND pass roles. See http://docs.aws.amazon.com/IAM/latest/UserGuide/
// role-usecase-ec2app.html#role-usecase-ec2app-permissions for an example.

AmazonEC2 ec2 = new AmazonEC2Client(...);

ec2.runInstances(new RunInstancesRequest()
    .withInstanceType(InstanceType.T1Micro)
    .withImageId("ami-d03ea1e0")    // 64-bit Amazon Linux AMI 2013.09
    .withIamInstanceProfile(new IamInstanceProfileSpecification()
        .withName("test-instance-profile"))
    .withMinCount(1)
    .withMaxCount(1));
 
Instance profiles can also be associated with EC2 instances created indirectly via Auto Scaling, AWS Elastic Beanstalk, AWS CloudFormation, and AWS OpsWorks!
 

Conclusion

That’s all for now! Stay tuned till next time, when we’ll talk in a bit more depth about the principles behind some of the important things that IAM roles for EC2 Instances takes care of for you under the covers, and discuss ways to apply those same principles to securely handle credentials for applications that aren’t running on EC2 instances.
 
Already using roles for EC2? Let us know what you think in the comments!
 

Enabling Metrics with the AWS SDK for Java

by Hanson Char | on | in Java | Permalink | Comments |  Share
Ever thought about generating metrics that measure your application’s performance on accessing AWS, and then having those metrics uploaded to Amazon CloudWatch for visualization or monitoring purposes ? How about generating performance metrics of your JVM’s when used against AWS ? Wouldn’t it be nice to capture and visualize metrics related to the runtime environment such as the heap memory, number of threads, and opened file descriptors all in one place ?
 
We are excited to announce a new feature in the AWS SDK for Java that can do exactly that – automatic metric generation, collection, and uploads to CloudWatch.
 
This feature is disabled by default. To enable it, simply include a system property pointing to your AWS security credential file when starting up the JVM. For example:
      -Dcom.amazonaws.sdk.enableDefaultMetrics=credentialFile=/path/aws.properties
And you are all set!
 
"But," you may ask, "why do I need to specify a credential file ?" Great question! Under the hood, the default SDK metrics collection needs the necessary AWS security credentials to access Amazon CloudWatch. That’s what the credentialFile attribute is for. On the other hand, if you are accessing AWS via the more secure and recommended option of Instance profile credentials through the Amazon EC2 instance metadata service, you don’t even need to specify the credential file. In other words, to enable metrics, you need only specify:
      -Dcom.amazonaws.sdk.enableDefaultMetrics
Once you enable this feature, every time there is a service request to AWS via the SDK for Java, metric data points will get generated, queued for statistical summary, and then uploaded asynchronously to Amazon CloudWatch about once every minute. The default set of metrics is divided into three major categories: AWS Request Metrics, AWS Service Metrics, and Machine Metrics. AWS Request Metrics covers areas such as the latency of the HTTP request/response, number of requests, exceptions, and retries. Examples of AWS Service Metrics include the throughput and byte count metrics for S3 uploads and downloads. Machine Metrics, on the other hand, covers the runtime environment including heap memory, number of threads, and open file descriptors. Even though there is little reason to exclude Machine Metrics, you can do so by including excludeMachineMetrics in the very same system property, like so:
      -Dcom.amazonaws.sdk.enableDefaultMetrics=
        credentialFile=/path/aws.properties,excludeMachineMetrics
(All in a single line with no space.)
 
Once you’ve uploaded metrics to Amazon CloudWatch, not only can you visualize them in the AWS Management Console, you can also set alarms on potential problems like  memory leakage, file descriptor leakage, and so on. All metrics captured by the SDK for Java are under the namespace AWSSDK/Java, and by default are uploaded to the Amazon CloudWatch default region us-east-1. If you want to change the region, simply specify the value for the cloudwatchRegion attribute in the system property. For example, the following line overrides the Amazon CloudWatch region for metric uploads to us-west-2:
      -Dcom.amazonaws.sdk.enableDefaultMetrics=
        credentialFile=/path/aws.properties,cloudwatchRegion=us-west-2
(All in a single line with no space.)
 
Following are some sample screen shots of what the metrics would look like in the AWS Management Console.
 
Request Metrics showing the client-side HTTP response time ( HttpClientReceiveResponseTime) vs. client-side total request execution time ( ClientExecuteTime) of writing to Amazon DynamoDB with PutItemRequest:
 
Request Metrics
 
Machine Metrics sample screenshot, showing the JVM’s heap memory while making those AWS requests:
 
Machine Metrics
 
Service Metrics sample screenshot, showing the S3 download and upload throughput (byte/second):
 
Service Metrics
 
Please see the package summary for a full list of the predefined core metric types. Additional features, such as the dynamic control of the metrics system via JMX, will likely take up more blog space than we have here. If you can’t wait, however, just fire up jconsole and look for MBeans under the namespace com.amazonaws.management. Let us know what you think!