3

I'm trying to modify Firebase's Android chat example to include Firebase timestamp values. I can send the timestamp just fine using ServerValue.TIMESTAMP; but when Firebase tried to display the message, the app crashes. EDIT: full error output below

To send a message I use

private void sendMessage() {
    EditText inputText = (EditText)findViewById(R.id.messageInput);
    String input = inputText.getText().toString();
    Map timestamp = ServerValue.TIMESTAMP;

    if (!input.equals("")) {
        // Create our 'model', a Chat object
        Chat chat = new Chat(name, input, timestamp, userID);
        // Create a new, auto-generated child of that chat location, and save our chat data there
        chatRef.push().setValue(chat);
        inputText.setText("");
    }
}

The forge's structure is something like this:

->Messenger
  |--> room
      |--> messages
        |--> messageID
          |--> from: "Name"
          |--> text: "Message"
          |--> timestamp: xxxxxxxxxxxxx
          |--> userID: "id"

And Chat.java

public class Chat {

    private String from;
    private String text;
    private int userID;
    private Map<String, String> timestamp = new HashMap<String, String>();

    // Required default constructor for Firebase object mapping
    @SuppressWarnings("unused")
    private Chat() { }

    Chat(String from, String text, Map timestamp, int userID) {
        this.from = from;
        this.text = text;
        this.timestamp = timestamp;
        this.userID = userID;
    }

    public String getFrom() {
        return from;
    }

    public String getText() {
        return text;
    }

    public Map getTimestamp() {
        return timestamp;
    }

    public int getuserID() {
        return userID;
    }
}

If I delete the timestamp field from the messages on Firebase, the app doesn't crash.

The full Error message is below:

08-26 15:08:08.223  18097-18097/com.firebase.androidchat E/AndroidRuntime﹕ FATAL EXCEPTION: main
    Process: com.firebase.androidchat, PID: 18097
    com.firebase.client.FirebaseException: Failed to bounce to type
            at com.firebase.client.DataSnapshot.getValue(DataSnapshot.java:185)
            at com.firebase.androidchat.FirebaseListAdapter$1.onChildAdded(FirebaseListAdapter.java:63)
            at com.firebase.client.core.ChildListenerContainer$1.run(ChildListenerContainer.java:52)
            at android.os.Handler.handleCallback(Handler.java:733)
            at android.os.Handler.dispatchMessage(Handler.java:95)
            at android.os.Looper.loop(Looper.java:136)
            at android.app.ActivityThread.main(ActivityThread.java:5001)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:515)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
            at dalvik.system.NativeStart.main(Native Method)
     Caused by: com.shaded.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.util.LinkedHashMap out of VALUE_NUMBER_INT token
            at [Source: java.io.StringReader@41f8c588; line: 1, column: 2] (through reference chain: com.firebase.androidchat.Chat["timestamp"])
            at com.shaded.fasterxml.jackson.databind.DeserializationContext.mappingException(DeserializationContext.java:575)
            at com.shaded.fasterxml.jackson.databind.DeserializationContext.mappingException(DeserializationContext.java:569)
            at com.shaded.fasterxml.jackson.databind.deser.std.MapDeserializer.deserialize(MapDeserializer.java:310)
            at com.shaded.fasterxml.jackson.databind.deser.std.MapDeserializer.deserialize(MapDeserializer.java:26)
            at com.shaded.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:464)
            at com.shaded.fasterxml.jackson.databind.deser.impl.FieldProperty.deserializeAndSet(FieldProperty.java:107)
            at com.shaded.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:295)
            at com.shaded.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:121)
            at com.shaded.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:2888)
            at com.shaded.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2034)
            at com.firebase.client.DataSnapshot.getValue(DataSnapshot.java:181)
            at com.firebase.androidchat.FirebaseListAdapter$1.onChildAdded(FirebaseListAdapter.java:63)
            at com.firebase.client.core.ChildListenerContainer$1.run(ChildListenerContainer.java:52)
            at android.os.Handler.handleCallback(Handler.java:733)
            at android.os.Handler.dispatchMessage(Handler.java:95)
            at android.os.Looper.loop(Looper.java:136)
            at android.app.ActivityThread.main(ActivityThread.java:5001)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:515)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
            at dalvik.system.NativeStart.main(Native Method)

It looks like it may be caused by another issue which confuses me even more...

Caused by: com.shaded.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.util.LinkedHashMap out of VALUE_NUMBER_INT token
        at [Source: java.io.StringReader@41f8c588; line: 1, column: 2] (through reference chain: com.firebase.androidchat.Chat["timestamp"])
Dr. J
  • 51
  • 2
  • 6
  • does [this](http://stackoverflow.com/a/21709202/1777090) help? or [this](http://stackoverflow.com/questions/14588727/can-not-deserialize-instance-of-java-util-arraylist-out-of-value-string) and [this](http://stackoverflow.com/questions/8388656/java-json-jackson-nested-elements) – MysticMagicϡ Aug 26 '14 at 08:11
  • @Dhruti it does to some extent... but not an incredible amount. I can't see how naming conventions would be a problem at the moment. I'll update my post with the message structure – Dr. J Aug 26 '14 at 08:19

2 Answers2

15

Firebase.ServerValue.TIMESTAMP is set as a Map (containing {.sv: "timestamp"}) which tells Firebase to populate that field with the server's time. When that data is read back, it is the actual unix time stamp which is a Long. When Firebase (using Jackson) tries to deserialize that returned value, it fails since it is not a Map.

You could use Jackson annotations to control how your class is converted to JSON.

For example, something like this should work:

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.firebase.client.ServerValue;

public class Thing {
    private String id;
    private Long creationDate;

    public Thing() {

    }

    public Thing(String id) {
        this.id = id;
    }

    public String getId() {
        return id;
    }

    public java.util.Map<String, String> getCreationDate() {
        return ServerValue.TIMESTAMP;
    }

    @JsonIgnore
    public Long getCreationDateLong() {
       return creationDate;
    }

    public void setId(String id) {
        this.id = id;
    }

    public void setCreationDate(Long creationDate) {
        this.creationDate = creationDate;
    }
}
Ossama
  • 2,417
  • 1
  • 20
  • 20
  • Yeah, I seemed to figure that out, but do you have any suggestions as to what I can do to solve that? – Dr. J Aug 27 '14 at 01:29
  • is there any way using which we get firebase server date and time without pushing any value – Muhammad Younas May 21 '17 at 13:33
  • @MuhammadYounas You can get the *estimated* difference between the device's time and Firebase server time by reading "/.info/serverTimeOffset" see https://firebase.google.com/docs/database/web/offline-capabilities#clock-skew – Ossama May 24 '17 at 00:11
  • Thanks will try but i want to know that if device time is change means inaccurate so it will than give me correct date by adding offset / – Muhammad Younas May 24 '17 at 06:10
13

I know this thread is quite old, but for anyone trying to implement a similar timestamp now, instead of using @JsonIgnore from the Jackson annotations, you can use the Firebase native @Exclude now.

Nick
  • 401
  • 5
  • 18