4

I am trying to save data into the dynamoDb but that data contains some Map attributes as well.But I am getting error while saving that data. Following is my domain class which I am using for saving data from request:

@DynamoDBTable(tableName = "ottMiddleware_rails")
public class RailsCmsDomain {

@DynamoDBHashKey(attributeName = "railId")
private String railId;

@DynamoDBTyped
@DynamoDBAttribute(attributeName = "railLogic")
private Map<String, Object> railLogic;

@DynamoDBAttribute(attributeName = "railSourceType")
private String railSourceType;

@DynamoDBAttribute(attributeName = "railTitle")
private RailCmsTitleDomain railTitle;

@DynamoDBTyped
@DynamoDBAttribute(attributeName = "restrictions")
private Map<String, Object> restrictions;

I am giving the following request:

{
    "railId": "railOne",
    "railLogic": {
        "programType": 1,
        "railSourceUrl": "http://myUrl"
    },
    "railSourceType": "myRail",
    "railTitle": {
        "tam": "Raan Phan",
        "def": "சிறப்பு கட்டமைப்பு"
    },
    "restrictions": {
        "clients": [
            "abc",
            "xyz"
        ],
        "periodStart": 1506572217
    }
}

I am using following code to save my data into the dynamoDb

public Boolean saveUpdateRailsDetails(RailsCmsDomain railsDomain) {
    DynamoDBUtil dynamoDBUtil = new DynamoDBUtil();
    AmazonDynamoDB dynamoDBClient = dynamoDBUtil.getDynamoDBClient();
    DynamoDBMapper mapper = new DynamoDBMapper(dynamoDBClient);
    mapper.save(railsDomain);
    return true;
}

Please suggest how can I save map into dynamoDb. I am taking data as map because in later stages there are chances more data can be added to those attributes which are map and that data can be of any data type. I am getting following error:

errorMessage": "not supported; requires @DynamoDBTyped or 
@DynamoDBTypeConverted"
"errorType": 
"com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMappingException"
4
  • The problem is on the restrictions attribute definition. What type of data will it contain other than client? The problem coouldn't convert the attribute data if it is defined as Map<String, Object>. Commented Oct 3, 2017 at 12:47
  • Restrictions will contain periodStart which is of type long Commented Oct 3, 2017 at 12:53
  • ok, why don't you define the restrictions similar to railTitle with custom class definition? Commented Oct 3, 2017 at 12:56
  • Because in restrictions it is the scenario that attribute of any type can be added later on which is not the case with railTitle Commented Oct 3, 2017 at 13:00

3 Answers 3

2

I would like to post this answer as an option though it is not going to store the data as map in DynamoDB. However, it will resolve the error.

You can define the restrictions attribute as mentioned below. It will store the data as JSON string in DynamoDB.

@DynamoDBTypeConvertedJson
private Map<String, Object> restrictions;

Drawbacks:-

When you would like to update the restrictions attribute, you need to get the current value from database, update it and save the data in database.

DynamoDB data:-

restrictions attribute saved as JSON string.

enter image description here

Sign up to request clarification or add additional context in comments.

Comments

2

When I needed to store map in dynamodb I just annotated the getter method of the map with @DynamoDBTypeConverted(converter = MapConverter.class) and in the converter just serialized the map into a json string, this way you can retrieve the map and everything but are not going to be able to use it in queryExpressions if you need.

So in case you want to be able to query the objects in the map maybe consider annotating the object you are using in your map with @DynamoDBDocument this way it's going to be automatically serialized by dynamodb as a document and use Set instead of map into your parent object.

Comments

1

The problem is that the DynamoDB Mapper doesn't know how to marshall/unmarshall the Object in this line:

private Map<String, Object> railLogic;

If you don't want to change Object to String, then use the DynamoDBTypeConverted annotation to provide a custom marshaller for Map<String, Object> which you can then (probably) reuse for restrictions. Relevant documentation here.

3 Comments

But I am stuck in one scenario : I will make custom marshaller for Map<String,Object> but then there can be the case where later on if I need to add some more attributes to the railLogic, everytime I will have to make changes in the custom marshaller class. Can't there be any solution where in later stages whether I send request as String or List in Map Object value they both will be stored? As Object can be anything either List or String or anything else.
Not really. The custom marshaller will have to change to handle all possible cases of Object.
I am thinking for another approach, what if I store entire Json request as such in DynamoDb without converting it into string. Is it feasible?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.