/*
* Copyright 2014-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
package com.amazonaws.services.dynamodbv2.client;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.amazonaws.AmazonClientException;
import com.amazonaws.AmazonServiceException;
import com.amazonaws.auth.DefaultAWSCredentialsProviderChain;
import com.amazonaws.handlers.RequestHandler2;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient;
import com.amazonaws.services.dynamodbv2.model.AttributeDefinition;
import com.amazonaws.services.dynamodbv2.model.AttributeValue;
import com.amazonaws.services.dynamodbv2.model.ComparisonOperator;
import com.amazonaws.services.dynamodbv2.model.Condition;
import com.amazonaws.services.dynamodbv2.model.CreateTableRequest;
import com.amazonaws.services.dynamodbv2.model.CreateTableResult;
import com.amazonaws.services.dynamodbv2.model.DescribeTableRequest;
import com.amazonaws.services.dynamodbv2.model.GetItemRequest;
import com.amazonaws.services.dynamodbv2.model.GetItemResult;
import com.amazonaws.services.dynamodbv2.model.KeySchemaElement;
import com.amazonaws.services.dynamodbv2.model.KeyType;
import com.amazonaws.services.dynamodbv2.model.ProvisionedThroughput;
import com.amazonaws.services.dynamodbv2.model.PutItemRequest;
import com.amazonaws.services.dynamodbv2.model.PutItemResult;
import com.amazonaws.services.dynamodbv2.model.ResourceInUseException;
import com.amazonaws.services.dynamodbv2.model.ScanRequest;
import com.amazonaws.services.dynamodbv2.model.ScanResult;
import com.amazonaws.services.dynamodbv2.model.TableDescription;
import com.amazonaws.services.dynamodbv2.model.TableStatus;
/**
* This sample demonstrates how to inject failures, latencies in your DynamoDB
* client for testing
*/
public class DynamoDBDynamicFaultInjection
{
private static final Logger logger = LoggerFactory.getLogger(DynamoDBDynamicFaultInjection.class);
public static String TABLENAME = "my-favorite-movies-table";
/*
* Important: Be sure to fill in your AWS access credentials in the
* AwsCredentials.properties file before you try to run this sample and
* configure your log4j.properties
*
* http://aws.amazon.com/security-credentials
*/
static AmazonDynamoDBClient dynamoDBClient;
/**
* The only information needed to create a client are security credentials
* consisting of the AWS Access Key ID and Secret Access Key. All other
* configuration, such as the service endpoints, are performed
* automatically. Client parameters, such as proxies, can be specified in an
* optional ClientConfiguration object when constructing a client.
*
* @see com.amazonaws.auth.BasicAWSCredentials
* @see com.amazonaws.auth.PropertiesCredentials
* @see com.amazonaws.ClientConfiguration
*/
private static void init() throws Exception
{
dynamoDBClient = new AmazonDynamoDBClient(new DefaultAWSCredentialsProviderChain());
// pass in the client for access to the cached metadata.
RequestHandler2 requestHandler = new FaultInjectionRequestHandler(dynamoDBClient);
dynamoDBClient.addRequestHandler(requestHandler);
}
public static void main(String[] args) throws Exception
{
init();
try
{
// Create a table with a primary key named 'name', which holds a
// string
createTable();
// Describe our new table
describeTable();
// Add some items
putItem(newItem("Bill & Ted's Excellent Adventure", 1989, "****", "James", "Sara"));
putItem(newItem("Airplane", 1980, "*****", "James", "Billy Bob"));
// Get some items
getItem("Airplane");
getItem("Bill & Ted's Excellent Adventure");
// Scan items for movies with a year attribute greater than 1985
Map<String, Condition> scanFilter = new HashMap<String, Condition>();
Condition condition = new Condition().withComparisonOperator(ComparisonOperator.GT.toString())
.withAttributeValueList(new AttributeValue().withN("1985"));
scanFilter.put("year", condition);
ScanRequest scanRequest = new ScanRequest(TABLENAME).withScanFilter(scanFilter);
ScanResult scanResult = dynamoDBClient.scan(scanRequest);
logger.info("Result: " + scanResult);
}
catch (AmazonServiceException ase)
{
logger.error("Service Exception: " + ase);
}
catch (AmazonClientException ace)
{
logger.error("Client Exception: " + ace);
}
}
/*
* Get an item from the table
*/
private static void getItem(String keyVal)
{
Map<String, AttributeValue> key = new HashMap<String, AttributeValue>();
key.put("name", new AttributeValue(keyVal));
GetItemRequest getItemRequest = new GetItemRequest().withTableName(TABLENAME).withKey(key);
GetItemResult item = dynamoDBClient.getItem(getItemRequest);
logger.info("Get Result: " + item);
}
/*
* Describe the table
*/
private static void describeTable()
{
DescribeTableRequest describeTableRequest = new DescribeTableRequest().withTableName(TABLENAME);
TableDescription tableDescription = dynamoDBClient.describeTable(describeTableRequest).getTable();
logger.info("Table Description: " + tableDescription);
}
/*
* Put given item into the table
*
* @param item
*/
private static void putItem(Map<String, AttributeValue> item)
{
try
{
PutItemRequest putItemRequest = new PutItemRequest(TABLENAME, item);
PutItemResult putItemResult = dynamoDBClient.putItem(putItemRequest);
logger.info("Result: " + putItemResult);
}
catch (Exception e)
{
// TODO: handle exception
}
}
/*
* Create the table if it already does not exist
*/
private static void createTable()
{
List<AttributeDefinition> attributeDefinitions = new ArrayList<AttributeDefinition>();
attributeDefinitions.add(new AttributeDefinition().withAttributeName("name").withAttributeType("S"));
List<KeySchemaElement> ks = new ArrayList<KeySchemaElement>();
ks.add(new KeySchemaElement().withAttributeName("name").withKeyType(KeyType.HASH));
ProvisionedThroughput provisionedThroughput = new ProvisionedThroughput().withReadCapacityUnits(10L)
.withWriteCapacityUnits(10L);
CreateTableRequest request = new CreateTableRequest().withTableName(TABLENAME)
.withAttributeDefinitions(attributeDefinitions).withKeySchema(ks)
.withProvisionedThroughput(provisionedThroughput);
try
{
CreateTableResult createdTableDescription = dynamoDBClient.createTable(request);
logger.info("Created Table: " + createdTableDescription);
// Wait for it to become active
waitForTableToBecomeAvailable(TABLENAME);
}
catch (ResourceInUseException e)
{
logger.warn("Table already existed", e);
}
}
/*
* Create new item helper
*/
private static Map<String, AttributeValue> newItem(String name, int year, String rating, String... fans)
{
Map<String, AttributeValue> item = new HashMap<String, AttributeValue>();
item.put("name", new AttributeValue(name));
item.put("year", new AttributeValue().withN(Integer.toString(year)));
item.put("rating", new AttributeValue(rating));
item.put("fans", new AttributeValue().withSS(fans));
return item;
}
/*
* Waits for the table to become ACTIVE Times out after 10 minutes
*/
private static void waitForTableToBecomeAvailable(String tableName)
{
logger.info("Waiting for " + tableName + " to become ACTIVE...");
long startTime = System.currentTimeMillis();
long endTime = startTime + (10 * 60 * 1000);
while (System.currentTimeMillis() < endTime)
{
try
{
Thread.sleep(1000 * 20);
}
catch (Exception e)
{
}
try
{
DescribeTableRequest request = new DescribeTableRequest().withTableName(tableName);
TableDescription tableDescription = dynamoDBClient.describeTable(request).getTable();
String tableStatus = tableDescription.getTableStatus();
logger.info(" - current state: " + tableStatus);
if (tableStatus.equals(TableStatus.ACTIVE.toString()))
return;
}
catch (AmazonServiceException ase)
{
if (ase.getErrorCode().equalsIgnoreCase("ResourceNotFoundException") == false)
throw ase;
}
}
throw new RuntimeException("Table " + tableName + " never went active");
}
}