delight-im / Android-DDP

[UNMAINTAINED] Meteor's Distributed Data Protocol (DDP) for clients on Android
Apache License 2.0
274 stars 54 forks source link

Error with getting empty arrays #85

Closed romaluca closed 8 years ago

romaluca commented 8 years ago

Hi! I have a publishComposite that has also this:

return Photos.find({_id: action.photoId}, {
           fields: {
                _id: 1, position: 1, commentsCount: 1,
                 votesCount: 1, votedBy: {$elemMatch: {$eq: this.userId}},
                 uploaded: 1, createdAt: 1, userId: 1
            }
});

At start when the user isn't in the votedBy array there arent errors. Thus when the user votes the the photo and his id is inserted in votedBy array, with subscription and onDataChanged i receive the change correctly. But when the user unvote and his id is removed from votedBy i receive an error before onDataChanged execution:


04-05 13:34:16.668 13528-13528/com.shuttertop.app E/METEOR: Exception!!!!
04-05 13:34:16.669 13528-13528/com.shuttertop.app W/System.err: java.lang.IllegalArgumentException: Can not deserialize instance of im.delight.android.ddp.Fields out of START_ARRAY token
04-05 13:34:16.669 13528-13528/com.shuttertop.app W/System.err:  at [Source: N/A; line: -1, column: -1]
04-05 13:34:16.669 13528-13528/com.shuttertop.app W/System.err:     at org.codehaus.jackson.map.ObjectMapper._convert(ObjectMapper.java:2502)
04-05 13:34:16.669 13528-13528/com.shuttertop.app W/System.err:     at org.codehaus.jackson.map.ObjectMapper.convertValue(ObjectMapper.java:2468)
04-05 13:34:16.669 13528-13528/com.shuttertop.app W/System.err:     at im.delight.android.ddp.Meteor.fromJson(Meteor.java:381)
04-05 13:34:16.669 13528-13528/com.shuttertop.app W/System.err:     at im.delight.android.ddp.Meteor.handleMessage(Meteor.java:520)
04-05 13:34:16.669 13528-13528/com.shuttertop.app W/System.err:     at im.delight.android.ddp.Meteor.access$400(Meteor.java:41)
04-05 13:34:16.669 13528-13528/com.shuttertop.app W/System.err:     at im.delight.android.ddp.Meteor$1.onMessage(Meteor.java:176)
04-05 13:34:16.669 13528-13528/com.shuttertop.app W/System.err:     at com.firebase.tubesock.WebSocketReceiver.appendBytes(WebSocketReceiver.java:113)
04-05 13:34:16.669 13528-13528/com.shuttertop.app W/System.err:     at com.firebase.tubesock.WebSocketReceiver.run(WebSocketReceiver.java:69)
04-05 13:34:16.669 13528-13528/com.shuttertop.app W/System.err:     at com.firebase.tubesock.WebSocket.runReader(WebSocket.java:372)
04-05 13:34:16.669 13528-13528/com.shuttertop.app W/System.err:     at com.firebase.tubesock.WebSocket.access$000(WebSocket.java:30)
04-05 13:34:16.669 13528-13528/com.shuttertop.app W/System.err:     at com.firebase.tubesock.WebSocket$2.run(WebSocket.java:108)
04-05 13:34:16.669 13528-13528/com.shuttertop.app W/System.err:     at java.lang.Thread.run(Thread.java:818)
04-05 13:34:16.669 13528-13528/com.shuttertop.app W/System.err: Caused by: org.codehaus.jackson.map.JsonMappingException: Can not deserialize instance of im.delight.android.ddp.Fields out of START_ARRAY token
04-05 13:34:16.669 13528-13528/com.shuttertop.app W/System.err:  at [Source: N/A; line: -1, column: -1]
...

What can i do? Thanks!

ocram commented 8 years ago

Good catch, thanks for spotting this!

Since we try to parse everything into Map instances in Java (which correspond to objects in JavaScript), the parser is looking for primitive values, or { and } which are the start and end of an object in JSON.

But apparently, the parser found a [ token, which is the start of an array, as described in the error log as "START_ARRAY token". Thus the parser doesn't know what to do with that value.

This means we have to modify the parser to turn arrays into Map instances where the keys are 0, 1, 2, etc. in the Java library code. As a temporary solution, you could turn the [ "a", "b", "c" ] arrays into { 0: "a", 1: "b", 2: "c" } objects in JavaScript, but that really shouldn't be necessary. There will be a fix shortly!

romaluca commented 8 years ago

thanks!

ocram commented 8 years ago

@romaluca Sorry, we need the JSON that is causing these problems!

Can you switch off the database temporarily (I assume it's crashing the app?) and log what's being received in onDataChanged that is causing this?

Thank you!

romaluca commented 8 years ago

screenshot from 2016-04-09 18-13-43 in the screenshot there is the row that generates the exception. In meteor i do only this:

Photos.update({_id: photo._id}, {
                        $pull: {votedBy: user._id},
                        $inc: {votesCount: -1}
                    });
romaluca commented 8 years ago

the json that caused the problem is in the variable

removedValuesJson = data.get(Protocol.Field.CLEARED).toString();

that contains this: "[\"votedBy\"]" it isn't json. So the function fromJson(removedValuesJson) generates the exception

ocram commented 8 years ago

Oh, great! Thanks for the debugging information which was very helpful. I thought it would be the updatedValuesJson parameter but, as you showed, it was the removedValuesJson parameter.

The removedValuesJson parameter of the onDataChanged method (or, in the protocol, the cleared property of the changed message) is indeed an array and not an object.

The problem should have been fixed in: https://github.com/delight-im/Android-DDP/commit/4f16bd15e6fbc86457e4a7770dfdc82e74a5be6e

So can you please try 4f16bd15e6fbc86457e4a7770dfdc82e74a5be6e instead of v3.1.1 in the dependency? That means:

compile 'com.github.delight-im:Android-DDP:4f16bd15e6fbc86457e4a7770dfdc82e74a5be6e'

romaluca commented 8 years ago

It works! Thanks!

ocram commented 8 years ago

Thanks for testing, and again for finding this bug :)

The fix is included in the latest release now.