Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

java.util.ConcurrentModificationException if i execute the query #117

Open
musriabhijit opened this issue Oct 24, 2016 · 21 comments
Open

java.util.ConcurrentModificationException if i execute the query #117

musriabhijit opened this issue Oct 24, 2016 · 21 comments
Labels

Comments

@musriabhijit
Copy link

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)

@ocram ocram added the question label Nov 1, 2016
@ocram
Copy link
Contributor

ocram commented Nov 1, 2016

Thanks for your report!

Can you share what you're actually doing in that onDataAdded callback with respect to this library?

@musriabhijit
Copy link
Author

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

@ocram
Copy link
Contributor

ocram commented Nov 6, 2016

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.

@kschingiz
Copy link

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

@ocram
Copy link
Contributor

ocram commented Dec 12, 2016

@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?

@kschingiz
Copy link

@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.

@ocram
Copy link
Contributor

ocram commented Dec 16, 2016

@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.

@najeebullahshah
Copy link

najeebullahshah commented Jan 6, 2017

@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?

@ocram
Copy link
Contributor

ocram commented Jan 7, 2017

Is the data read and written in different threads here? Do we have to fix synchronization perhaps?

@kschingiz
Copy link

kschingiz commented Jan 13, 2017

@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

@ocram
Copy link
Contributor

ocram commented Jan 13, 2017

@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?

@ocram
Copy link
Contributor

ocram commented Jan 15, 2017

@musriabhijit @kschingiz Please try changing your dependency to

compile 'com.github.delight-im:Android-DDP:d09cbe43f824846a9cb3ad4eecd2fd1b1a8d73b5'

which does two things:

  • It uses ConcurrentHashMap instead of HashMap in InMemoryDatabase.
  • It uses 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.

@najeebullahshah
Copy link

@ocram Thanks man for the update, i've compiled witht he mentioned one, I am hopeful now the issue will be resolved. Much appreciated.

@ocram
Copy link
Contributor

ocram commented Jan 16, 2017

@najeebullahshah For you, personally, the fix from #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.

@najeebullahshah
Copy link

Ok let me test upload apk to playstore and see if the exception is reported or not?

@ocram
Copy link
Contributor

ocram commented Jan 17, 2017

@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.

@Gurpreet1809
Copy link

@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.

@Gurpreet1809
Copy link

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!

@ocram
Copy link
Contributor

ocram commented Jul 9, 2017

@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?

@Gurpreet1809
Copy link

@ocram yupzz exactly !! it works fine in debug mode, but when it is executed on device without debug mode, onSuccess method is not called.

@ocram
Copy link
Contributor

ocram commented Jul 14, 2017

@Gurpreet1809 That could be an issue with obfuscation (i.e. ProGuard) then. Can you check this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants