S.O.S. trying to update a RealmResults list object is crashing.

1,966 views
Skip to first unread message

Alejandro Moya

unread,
Dec 5, 2014, 11:08:09 PM12/5/14
to realm...@googlegroups.com
Guys, i need some help with this issue, each time i try to update an element from a RealmResults i get:


java.util.ConcurrentModificationException

No outside changes to a Realm is allowed while iterating a RealmResults. Use iterators methods instead.

here's the logic:

for(RealmObject object : RealmResults) {

realm.beginTransaction();

object.setProperty(newValue);

realm.commitTransaction();

}

Please correct me if i'm wrong, but on the docs says that i can modify the elements:

A RealmResults list contains a list of objects of a given type that matches the query. The objects are not copied from the Realm to the RealmResults list, but just references the original objects. This preserves memory and increase speed. It also implies that any modification to any object in a RealmResults is reflected in the objects in the Realm that was queried. Updates to objects must be done within a transaction and the modified object is persisted to the backing Realm file during the commit of the transaction.


I need help asap as i'm working on a project, using realm and trying to get it on production in 2 weeks.

Emanuele Zattin

unread,
Dec 6, 2014, 5:27:12 PM12/6/14
to Alejandro Moya, realm-java
Hello Alejandro,

we isolated the bug and I'll look into it Monday morning so stay tuned for a fix!

--
You received this message because you are subscribed to the Google Groups "Realm Java" group.
To unsubscribe from this group and stop receiving emails from it, send an email to realm-java+...@googlegroups.com.
To post to this group, send email to realm...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/realm-java/a11f1868-f447-4b27-a91c-ca6d3edfb732%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
Emanuele Zattin (@emanuelez)
SW Engineer & CI Specialist

Bernt-Johan Bergshaven

unread,
Dec 8, 2014, 3:06:09 AM12/8/14
to realm...@googlegroups.com, ar.d...@gmail.com
Hello

I think this bug affects me as well.
Could you confirm that the problems I am seeing is related to the same bug.

I have a background service that receives location updates. On these location updates the service loops through objects in the realm database and updates these with new location information like this:
if(location != null){
            RealmResults<RealmPOI> pois = realm.where(RealmPOI.class).findAll();
            realm.beginTransaction();
            for(RealmPOI poi : pois){
                float[] result = new float[2];
                Location.distanceBetween(location.getLatitude(), location.getLongitude(), poi.getLat(), poi.getLon(), result);
                poi.setDistance(result[0]);
            }
            realm.commitTransaction();
        }

I get this error: 

    java.util.ConcurrentModificationException: No outside changes to a Realm is allowed while iterating a RealmResults. Use iterators methods instead.
            at io.realm.RealmResults.assertRealmIsStable(RealmResults.java:405)

When I in some other activity try to write to the realm I get the following error:
Could not dispatch event: class no.isea.kystfiske.models.SyncMessageEvent to subscribing class class no.isea.kystfiske.SyncService
    java.lang.IllegalStateException: Nested transactions are not allowed. Use commitTransaction() after each beginTransaction().

Is this because the first transaction crashed and thus did not call commitTransaction() ?

Please correct me if the following understanding of realm-transactions is wrong:

1. I get a realm instance in a background service by calling Realm realm = Realm.getInstance(getApplicationContext(), MainActivity.REALMDB);
2. I do various reads and writes , all of which are encapsulated in begin- and commitTransaction()
3. In my normal activity I (sometime) simultaneously acquire another realm by doing the same Realm realm = Realm.getInstance(getApplicationContext(), MainActivity.REALMDB) and try to read or write to the realm.
My assumption was the following:
If there is already another write happening it would just block until this one was done and then perform the write?

Best regards
Bernt-Johan

Christian Melchior

unread,
Dec 8, 2014, 3:11:40 AM12/8/14
to realm...@googlegroups.com
Hi Bernt-Johan

It looks like my answer to Alejandro wasn't posted here, so I have copy-pasted it below. I believe it fits your situtation as well:

------
Hi Alejandro

We unfortunately introduced a bug in the iterators last release, which means that writes inside a iterator will throw that exception.
We have identified it however and hope for a quick fix.

Until then you can use:

realm.beginTransaction()
for (int i = 0; results.size(); i++) {
results.get(i).setProperty(newValue)
}
realm.commitTransaction();

-----

Cheers,
Christian

Bernt-Johan Bergshaven

unread,
Dec 8, 2014, 3:17:44 AM12/8/14
to realm...@googlegroups.com
Thank you, this works with a little fix to your code: :)

realm.beginTransaction()
for (int i = 0; i < results.size(); i++) {
results.get(i).setProperty(newValue)
}
realm.commitTransaction();

Could you also comment on my question / assumption in my last post?

Bernt-Johan

Christian Melchior

unread,
Dec 8, 2014, 3:30:27 AM12/8/14
to realm...@googlegroups.com
Ah, sorry. Missed that question.
Yes, your assumption is correct. A write transaction in one thread will block write transactions in other threads until either commitTransaction or cancelTransaction is called.

Cheers,
Christian




On Saturday, December 6, 2014 5:08:09 AM UTC+1, Alejandro Moya wrote:

Bernt-Johan Bergshaven

unread,
Dec 8, 2014, 3:32:31 AM12/8/14
to realm...@googlegroups.com
No problem :)

One more question: 

I just realized that Services in Android are running on the same thread as the activity. 
Will I then get an exception if the service is performing a write and I try to write from the activity as well (which is on the same thread)?

Regards
Bernt-Johan

Christian Melchior

unread,
Dec 8, 2014, 4:14:32 AM12/8/14
to Bernt-Johan Bergshaven, realm...@googlegroups.com
You should not get an exception when trying to write from both an service and an Activity.
The current bug is just about using the Iterator class. Which is why

for (RealmObject o : RealmResults result) {
o.setProperty("foo");
}

fails, but

for (int i = 0; i < result.size(); i++) {
result.get(i).setProperty("foo");
}

works. As it doesn't use an Iterator.

As you correctly pointed out. Services and Activities run on the same thread, which means you have to be careful about potentially long running operations inside the Service. It also means that even if you do writes in both the Service and the Activity they will not block each other as they run in serial instead of parallel.

Did that answer you question?

--
Christian Melchior
Senior Android Developer


--

You received this message because you are subscribed to the Google Groups "Realm Java" group.
To unsubscribe from this group and stop receiving emails from it, send an email to realm-java+...@googlegroups.com.
To post to this group, send email to realm...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.



{#HS:59183520-136#}
Reply all
Reply to author
Forward
0 new messages