The following is a two class example of Amazon’s DynamoDB. The first class is just a Dao (yes, I still prefer Daos over ARs).
package wookets.dynamo
import com.amazonaws.auth.AWSCredentials
import com.amazonaws.auth.PropertiesCredentials
import com.amazonaws.services.dynamodb.AmazonDynamoDBClient
import com.amazonaws.services.dynamodb.model.AttributeValue
import com.amazonaws.services.dynamodb.model.ComparisonOperator
import com.amazonaws.services.dynamodb.model.DeleteItemRequest
import com.amazonaws.services.dynamodb.model.DeleteItemResult
import com.amazonaws.services.dynamodb.model.GetItemRequest
import com.amazonaws.services.dynamodb.model.GetItemResult
import com.amazonaws.services.dynamodb.model.Key
import com.amazonaws.services.dynamodb.model.PutItemRequest
import com.amazonaws.services.dynamodb.model.PutItemResult
class DynamoDao {
AmazonDynamoDBClient client
DynamoDao() {
InputStream credentialsAsStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(“AwsCredentials.properties”);
AWSCredentials credentials = new PropertiesCredentials(credentialsAsStream);
client = new AmazonDynamoDBClient(credentials);
}
// save
def save(Object resource) {
String tableName = resource._type
if(resource._type == null) {
throw new RuntimeException(“You need to specify a _type to be able to save data under”)
}
def item = [:]
resource.each { key, value ->
if(key == “_type”) return;
if(value instanceof Number) {
item.put(key, new AttributeValue().withN(value))
} else if(value instanceof String) {
item.put(key, new AttributeValue().withS(value))
} else if(value instanceof List) {
if(value[0] instanceof Number) {
item.put(key, new AttributeValue().withNS(value))
} else if(value[0] instanceof String) {
item.put(key, new AttributeValue().withSS(value))
}
} else {
throw new RuntimeException(“Unsupported data type for property ${resource._type}.${key}“)
}
}
PutItemRequest putItemRequest = new PutItemRequest().withTableName(tableName).withItem(item)
PutItemResult result = client.putItem(putItemRequest)
}
// read
def load(String resourceType, String resourceId) {
Key lookupKey = new Key().withHashKeyElement(new AttributeValue().withS(resourceId))
GetItemRequest getItemRequest = new GetItemRequest().withTableName(resourceType).withKey(lookupKey)
def item = [_type: resourceType, id: resourceId]
GetItemResult result = client.getItem(getItemRequest);
result.item.each { propName, value ->
if(value.getS() != null) {
item[propName] = value.getS()
} else if(value.getN() != null) {
item[propName] = value.getN()
} else if(value.getSS() != null) {
item[propName] = value.getSS()
} else if(value.getNS() != null) {
item[propName] = value.getNS()
}
}
return item
}
// delete
def delete(String resourceType, String resourceId) {
Key key = new Key().withHashKeyElement(new AttributeValue().withS(resourceId));
DeleteItemRequest deleteItemRequest = new DeleteItemRequest().withTableName(resourceType).withKey(key)
DeleteItemResult result = client.deleteItem(deleteItemRequest);
}
}
The next class is the test harness.
package test.dynamo;
import static org.junit.Assert.*
import java.text.SimpleDateFormat
import org.junit.Test
import wookets.dynamo.DynamoDao
class TestDynamoDao {
DynamoDao dynamoDao = new DynamoDao()
static SimpleDateFormat dateFormatter = new SimpleDateFormat(“yyyy-MM-dd’T’HH:mm:ss.SSS’Z’“);
@Test
void testSave() {
def mock = [_type:“dynamomock”, id: “MOCK1”, name: “Namer”, lister: [“Some1”, “Like”, “U”]]
dynamoDao.save(mock)
}
@Test
void testLoad() {
def mock = dynamoDao.load(“dynamomock”, “MOCK1”)
mock.each { prop, value ->
print “${prop}: ${value}, “
}
println “”
}
@Test
void testDelete() {
dynamoDao.delete(“dynamomock”, “MOCK1”)
}
@Test
void testSaveAll() {
dynamoDao.save([_type:“dynamomock”, id: “MOCK1”, name: “Namer”])
dynamoDao.save([_type:“dynamomock”, id: “MOCK2”, name: “Namer2”])
dynamoDao.save([_type:“dynamomock”, id: “MOCK3”, name: “Namer3”])
dynamoDao.save([_type:“dynamomock”, id: “MOCK4”, name: “Namer4”])
dynamoDao.save([_type:“dynamomock”, id: “MOCK5”, name: “Namer5”])
}
@Test
void testLoadAll() {
[“MOCK1”, “MOCK2”, “MOCK3”, “MOCK4”, “MOCK5”].each {
def mock = dynamoDao.load(“dynamomock”, it)
mock.each { prop, value ->
print “${prop}: ${value}, “
}
println “”
}
}
}
Obviously this is a simple use case, but might help you in your travels…
Btw, the properties (credentials file) looks like…
secretKey=
accessKey=