Open musriabhijit opened 7 years ago
Thanks for your report!
Can you share what you're actually doing in that onDataAdded
callback with respect to this library?
if the onDataAdded is called then i calling a method in that method i am writing the query to fetch the user documents but i am getting the about exception at run time in the mongo DB
Sorry, that doesn't really help. It would be necessary to see what exactly you're doing in that callback. Of course, you can and should remove everything that is not related to this library, i.e. all your business logic, etc.
I also have encountered this kind of issue. It happened if we are trying to add documents to collection in one thread and iterating over it in another thread at the same time. So I'm just waiting for finishing adding to collection after I start iterating. Maybe your case is the same. You can read about this exception here: https://docs.oracle.com/javase/7/docs/api/java/util/ConcurrentModificationException.html
@kschingiz Thanks a lot for these additional pieces of information!
It happened if we are trying to add documents to collection in one thread and iterating over it in another thread at the same time.
Are you actually writing to the collections or documents returned by the database? As you can see in the README, writing directly to the database by modifying these collections and documents is not supported, yet. You have to issue calls to the insert
, update
, delete
and call
methods, etc.
Nonetheless, the problem may occur just as well if you are iterating over such an object and the library adds new entries because you called such a method. Is this what you're doing and what's happening?
So I'm just waiting for finishing adding to collection after I start iterating.
This seems to be a reasonable workaround. Did it work?
@ocram
Nonetheless, the problem may occur just as well if you are iterating over such an object and the library adds new entries because you called such a method. Is this what you're doing and what's happening?
Yes, I didn't say that I am inserting to the database by myself, it's done by library.
@kschingiz I know you didn't. That's why I added another paragraph after that. I just wanted to confirm you really aren't doing this.
As far as I can see, the only thing we can do here is return copies of the actual data instead of the objects themselves. This has a small overhead in memory but allows the library to modify the collections and documents while you are iterating over them.
@kschingiz how did you know that all documents are added to in memory database and then start iterating them, onDataAdded is called for each document. If i am wrong plz correct me, when onDataAdded receives a document it means that document is already added to in memory database. Each time i get a ping for new document in onDataAdded i fetch the document by querying it like this:
MeteorSingleton.getInstance().getDatabase().getCollection(collectionName).getDocument(documentId)
Am i doing something wrong?
Is the data read and written in different threads here? Do we have to fix synchronization perhaps?
@najeebullahshah @ocram Sorry for the late reply, I'm just waiting for 3 seconds after onDataAdded occured, but it's bad solution.
So, I have implemented "subscription ready" feature.
MeteorJS sends a websocket message like this:
"{"msg":"ready","subs":["eiyH2CQiWKa3kQzSJ"]}"
I start my business logic only if I get this message. But! in case if you are working with database and at this time MeteorJs sends some data, this exception can occur. I don't know how to fix it.
Thank you and sorry for my bad english
@musriabhijit @kschingiz @najeebullahshah Really sorry for not having a solution to this problem available yet!
Still, this could be something that we could do here:
As far as I can see, the only thing we can do here is return copies of the actual data instead of the objects themselves. This has a small overhead in memory but allows the library to modify the collections and documents while you are iterating over them.
@kschingiz Instead of catching the "msg":"ready"
message yourself, can you try just adding a new SubscribeListener() {}
instance as the third argument to the subscribe
method call?
@musriabhijit @kschingiz Please try changing your dependency to
compile 'com.github.delight-im:Android-DDP:d09cbe43f824846a9cb3ad4eecd2fd1b1a8d73b5'
which does two things:
ConcurrentHashMap
instead of HashMap
in InMemoryDatabase
.ConcurrentHashMap
instead of LinkedHashMap
in InMemoryCollection
, which may be more important here.Perhaps that fixes the bug. I don't think that calling Collections#synchronizedMap(java.util.Map)
or wrapping all operations in synchronized (...) { ... }
is necessary.
@ocram Thanks man for the update, i've compiled witht he mentioned one, I am hopeful now the issue will be resolved. Much appreciated.
@najeebullahshah For you, personally, the fix from https://github.com/delight-im/Android-DDP/issues/125 is probably more relevant, as that was the issue you reported. Unfortunately, you can only test one of the fixes at a time for now. If both issues are reported as being fixed, we can merge back everything into the main branch.
Ok let me test upload apk to playstore and see if the exception is reported or not?
@najeebullahshah Yes, let's continue this discussion in the other issue's thread.
This issue here is only relevant for @musriabhijit and @kschingiz who found a different bug.
@ocram Hello Have you tried new SubscribeListener() {} instance as the third argument to the subscribe method call? because i am getting issue with this interface and not able to get a result.
After writing this code: new SubscribeListener() {}, if I'll debug the app that it works perfectly fine and I am getting the response in success() method but if I am running the app then these methods (onSuccess() and onError )are not called. Please help me out. I am using InMemoryDatabase() for creating database within app. Please help me out!
@Gurpreet1809 What are you referring to exactly? Did you want to say that the SubscribeListener
(which has been tested, of course) does work fine in the emulator or when debugging the app on a device, but does not work when exported as a signed APK and then executed on a device?
@ocram yupzz exactly !! it works fine in debug mode, but when it is executed on device without debug mode, onSuccess method is not called.
@Gurpreet1809 That could be an issue with obfuscation (i.e. ProGuard) then. Can you check this?
if i call the Query in side the on data added i am getting the below exception how to solve this one
java.util.ConcurrentModificationException at java.util.LinkedHashMap$LinkedHashIterator.nextEntry(LinkedHashMap.java:346) at java.util.LinkedHashMap$EntryIterator.next(LinkedHashMap.java:375) at java.util.LinkedHashMap$EntryIterator.next(LinkedHashMap.java:375) at java.util.HashMap.constructorPutAll(HashMap.java:208) at java.util.LinkedHashMap.(LinkedHashMap.java:133)
at im.delight.android.ddp.db.memory.InMemoryCollection$DocumentsMap.(InMemoryCollection.java:0)
at im.delight.android.ddp.db.memory.InMemoryQuery.(InMemoryQuery.java:37)
at im.delight.android.ddp.db.memory.InMemoryCollection.whereEqual(InMemoryCollection.java:65)