Has anyone made the change to the new namespaces (com.amazonaws.services.dynamodbv2
) and interfaces for DynamoDB in the AWS Java SDK 1.4.2 (and later)? The release
DynamoDB AWS Java 1.4.1 => 1.4.2 (non-exhaustive) migration steps
Well, I bit the bullet and did it. Here's my experience.
First, change the DynamoDB namespace:
com.amazonaws.services.dynamodb
=> com.amazonaws.services.dynamodbv2
The first thing you notice is there are types missing. The most major is Key is gone. Good riddance as it was too generic of a name.
It is now replaced with Map which makes sense as keys become a lot more malleable with Local Secondary Indexes (LSI).
Unfortunately, working with maps and generics in general sucks in Java (see Bonus at bottom).
Gone are the fluent interfaces of withHashKeyElement
/ withRangeKeyElement
.
Next, very carefully find/replace the DynamoDB types which were replaced by generic collections:
com.amazonaws.services.dynamodb.model.Key
=> Map
com.amazonaws.services.dynamodb.model.BatchResponse
=> List
com.amazonaws.services.dynamodb.model.KeySchema
=> List
Next, find everything that broke. This is a very manual process that requires knowing your code base and the SDK quite well. Specifically, you must know your key schema very well as it's all strings from here on. Luckily in my situation, the first two tasks were about 90% of the changes:
new Map
, it is an indication that Key
was formerly there.QueryRequest
merged withHashKeyValue(AttributeValue)
withRangeKeyCondition(Condition)
into the mega withKeyConditions(MapDynamoDBQueryExpression
became generic and changed its interface (not sure why).KeySchemaElement
no longer needs AttributeType
, but now needs KeyType
Finally, Compile and regression test your entire stack.
P.S. While I was performing all this, version 1.4.4.1 was just released to Maven Central.
Bonus
Since Maps are the common solution to Java's lack of loosely typed classes, they are everywhere. A little helper lib can really go a long way toward building these less verbosely. Here are some bits of my helper:
public class MakeJavaSuckLess { // TODO: find a shorter class name
public static final float MAX_LOAD_FACTOR = 1.0f;
/**
* Builds a mutable Map from an interlaced sequence of key-value pairs
* where keys are strings and values are VType objects
* @param pairs
* @return
*/
public static Map asMap(Object... pairs) {
return mergeMaps(null, pairs);
}
/**
* Builds a mutable Map from an interlaced sequence of key-value pairs
* where keys are strings and values are VType objects
* @param pairs
* @return
*/
public static Map mergeMaps(Map map, Object... pairs) {
final int length = (pairs != null) ? pairs.length/2 : 0;
if (map == null) {
// max out the load factor since most of these don't change
map = new HashMap(length, MAX_LOAD_FACTOR);
}
for (int i=0; i
Now creating your DynamoDB keys is slightly less ugly:
Map key = MakeJavaSuckLess.asMap("hashKey", new AttributeValue("hashVal"), "rangeKey", new AttributeValue("rangeVal"));
Type erasure in Java's generics makes this again uglier in places. You will sometimes need to explicitly specify VType
:
new GetItemRequest().withKey(MakeJavaSuckLess.asMap("hashKey", new AttributeValue("hashVal"), "rangeKey", new AttributeValue("rangeVal")));