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 of Local Secondary Indices apparently necessitated breaking changes as per the 1.4.2 release notes.

Has anyone found a guide detailing what changed and what needs to happen to migrate existing code? I am trying to decide when is best to make this change for an existing code base.

2 Answers
2

The new dynamodbv2 namespace of DynamoDB introduces the following incompatible changes (in that they are not simply additive, and require code changes to switch to the new namespace):

HashKeyElement and RangeKeyElement are replaced with a Map<String, AttributeValue>. This includes the structures named ExclusiveStartKey, LastEvaluatedKey, and Key. The main impact on the code with this change is that now in order to call GetItem, for example, your code needs to know the attribute names of the primary keys, and not just the primary key values.

Query now uses a KeyCondition of type Map<String, Condition> to specify the full query, instead of having separate HashKeyValue and RangeKeyCondition fields.

Consumed Capacity in responses is now a structure instead of a single number, and must be asked for in the request. In Batch operations, this is returned in a separate ConsumedCapacity structure, instead of alongside the results.

It is possible to migrate your code to the new Java API incrementally, if desired. If you plan to add functionality to your code that queries Local Secondary Indexes, or creates tables with local secondary indexes, you will need to use the new API for that part of your code.

If you create a table with Local Secondary Indexes with the new API, you can still use your existing code in the dynamodb namespace to perform all of the existing operations on that table. As an example, PutItem with the dynamodb namespace client will work against tables created using the dynamodbv2 client, as well as the other way around.

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:

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:

Find every new Map<String, AttributeValue>, it is an indication that Key was formerly there.

QueryRequest merged withHashKeyValue(AttributeValue)withRangeKeyCondition(Condition) into the mega withKeyConditions(Map<String,Condition>)
This method is the core change for LSI lets you specify things other than hash/range. What it accepts is more restrictive than the interface, but this is logical when you consider DynamoDB only lets you query indexed attributes.

DynamoDBQueryExpression 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: