Reputation: 259
I'm to the AWS Android DynamoDB SDK and lately I encounter a problem and still cannot fix it. When trying to get the 'Created' value of my DynamoDB I get the following error message:" Expected S in value {N: 1449848553974,} ". What I know so far from the AWS documentation is that 'N' stand for the Datatype Number.
Here is the code of the Class:
@DynamoDBTable(tableName = "dev.records_log")
public class Record
{
private Created created;
@DynamoDBAttribute(attributeName = "created")
@DynamoDBMarshalling(marshallerClass = TimeStampConverter.class)
public Created getTimestamp_created()
{
return created;
}
@DynamoDBMarshalling(marshallerClass = TimeStampConverter.class)
public void setRecord_created(Created created) {
this.created = created;
}
Hope someone could help me out with this issue. I browse through the internet but with no positive results.
Update: So far I can see in the DynamoDB it is a Unix Timestamp value of the type 'Number'.
TimeStamp Class: For the Timestamp class I just implement the DynamoDBMarshaller interface and put some log File to check if the data is received accordingly.
public class TimeStampConverter implements DynamoDBMarshaller<AdditionalInformation>
{
@Override
public String marshall(Created created)
{
Log.i("LOG","Marshall create value: "+created);
return null;
}
@Override
public Created unmarshall(Class<Created> clazz, String obj) {
Log.i("LOG","Created unmarshall ");
Created date_time_created = new Created();
Log.i("LOG","date_time_created "+date_time_created);
Log.i("LOG","unmarshall s value "+s);
Log.i("LOG","unmarshall s length "+s.length());
try{
if (s != null && s.length() != 0)
{
String[] data = s.split(" ");
date_time_created.setDate_created(data[0].trim());
date_time_created.setTime_created(data[1].trim());
}
}catch (Exception e)
{
Log.i("LOG","unmarshall error "+e.getMessage());
e.printStackTrace();
}
return date_time_created;
}
}
Created Class:
public class Created
{
private String date_created;
private String time_created;
public String getDate_created() {
return date_created;
}
public void setDate_created(String date_created) {
this.date_created = date_created;
}
public String getTime_created() {
return time_created;
}
public void setTime_created(String time_created) {
this.time_created = time_created;
}
}
Thanks in advance.
Upvotes: 2
Views: 1856
Reputation: 259
@Mike: The strange thing is that the same system stores the same value sometimes as String and sometimes as Number. That's why I talk to the web developer to fix this problem so the website and Android app store the Timestamp in the same data type. And I manage to fix the problem.
Solution:
After conducting some research and a experiment I solve the problem. According to the SDK documentation value store as Number are consider as String but I couldn't solve this problem when using Strings since it was expecting an int and not a String. Furthermore, I manage to get my hands on a book (DynamoDB Cookbook) that contain a example that query data of the type Numbers from a DynamoBD and they used int and not Strings.
My experiment was as following:
Set the expect data type in the Android app as int and on the DynamoDB back-end remove one character at a time and after removing 3 character it works.
Current Number value: 1449848553974
New Number value that were accepted: 1449848553
Meaning that 3 characters must be removed in the order for it to work on other words 1449848553974/1000. After conducting a deeper research about timestamp I came to the conclusion that timestamp are stored in milliseconds and not seconds, to convert it to seconds:
Seconds = milliseconds/1000
After looking why the app does not accept the value as the type int I conclude that I was dealing with a 'Integer overflow' and due to this the DynamoDBMapper was expecting a custom type since exceed the maximum value of a integer.
According to Java2s the maximum int value is: 2^31-1
source: http://www.java2s.com/Tutorial/Java/0040__Data-Type/IntegerMAXMINVALUE.htm
If we just pick the the amount of character of the value given as example in the link above and compare it to our value:
int maximum value: 2147483647 (10 characters)
My value: 1446738459378 (13 characters)
As I can see it exceed the maximum and that's why Java does not except this Number value as int and a DynamoDBMarshalling also expect String and not int.
My solution was to replace the timestamp from the type Number to String or if keeping it as Number but convert it from milliseconds to seconds.
This solve my problem if anyone has another solution it is more than welcome since I'm new to this.
Upvotes: 1
Reputation: 55730
When you use a custom DynamoDB marshaller, the data is serialized as a string, not a number. That is a limitation of the way custom marshallers are implemented.
I'm not sure exactly how your TimeStampConverter
class is implementing the serialization and deserialization but most definitely it expects to find the timestamp serialized into a string, so: {S: "1449848553974",}
. The question is, where did the {N: 1449848553974,}
value come from? I'm guessing it wasn't serialized by the TimeStampConverter
class.
Upvotes: 0