Marcel50506
Marcel50506

Reputation: 1300

Cannot copy Retrofit generated RealmObject to Realm: IllegalArgumentException

I'm using a combination of Realm (0.88.2) and Retrofit 2 to retrieve some objects. When I try to copy/update the objects to my realm with "copyToRealmOrUpdate", an IllegalArgumentException is thrown, with message "Cannot copy an object from another Realm instance".

The onResponse of my Retrofit call:

    public void onResponse(Call<List<Werkbon>> call, Response<List<Werkbon>> response) {
        if (response.isSuccess()){
            Realm realm = Realm.getDefaultInstance();
            realm.beginTransaction();
            realm.copyToRealmOrUpdate(response.body());
            realm.commitTransaction();
            realm.close();
        }
    }

I've also tried this with a for loop over the response.body(), trying to add the objects one by one, resulting in the same error/message.

And the error thrown:

03-21 15:32:25.754 27465-27465 E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.vl.test, PID: 27465
    java.lang.IllegalArgumentException: Cannot copy an object from another Realm instance.
    at io.realm.RealmList.copyToRealmIfNeeded(RealmList.java:246)
    at io.realm.RealmList.add(RealmList.java:181)
    at io.realm.WerkbonRealmProxy.copy(WerkbonRealmProxy.java:732)
    at io.realm.WerkbonRealmProxy.copyOrUpdate(WerkbonRealmProxy.java:696)
    at io.realm.DefaultRealmModuleMediator.copyOrUpdate(DefaultRealmModuleMediator.java:330)
    at io.realm.Realm.copyOrUpdate(Realm.java:1395)
    at io.realm.Realm.copyToRealmOrUpdate(Realm.java:765)
    at io.realm.Realm.copyToRealmOrUpdate(Realm.java:814)
    at com.example.app.datamodel.werkbon.Werkbon$1.onResponse(Werkbon.java:81)
    at retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall$1$1.run(ExecutorCallAdapterFactory.java:66)
    at android.os.Handler.handleCallback(Handler.java:746)
    at android.os.Handler.dispatchMessage(Handler.java:95)
    at android.os.Looper.loop(Looper.java:148)
    at android.app.ActivityThread.main(ActivityThread.java:5443)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:728)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)

Questions: Why is this error thrown, and how can I get these objects into my realm?

Upvotes: 2

Views: 758

Answers (1)

Marcel50506
Marcel50506

Reputation: 1300

Answering my own question, with help from beeender in the comments.

My Werkbon object contained a RealmList of RealmLong objects. A RealmLong is simply a container for a long value.

In Retrofit, I added a TypeAdapter to convert longs to these RealmLongs. In this adapter, I already added the RealmLong to the realm, as such:

    mGson = new GsonBuilder()
            .registerTypeAdapter(RealmLong.class, new RealmLongDeserializer())
            ...
            .create()

and the TypeAdapter itself, where the RealmLongs are added to a realm:

// Don't copy this, wrong version! Scroll down for correct TypeAdapter
private class RealmLongDeserializer implements JsonDeserializer<RealmLong> {

    @Override
    public RealmLong deserialize(JsonElement jsonElement, Type typeOF,
                            JsonDeserializationContext context) throws JsonParseException {
        Realm realm = Realm.getDefaultInstance();
        realm.beginTransaction();
        RealmLong rl = realm.createObject(RealmLong.class);
        rl.setVal(jsonElement.getAsLong());
        realm.commitTransaction();
        realm.close();
        return rl;
    }
}

However, I did not have to add this to the Realm yet, as the copyToRealmOrUpdate function of the Werkbon already does this in the later stage. The TypeAdapter thus could just be as follows:

private class RealmLongDeserializer implements JsonDeserializer<RealmLong> {

    @Override
    public RealmLong deserialize(JsonElement jsonElement, Type typeOF,
                            JsonDeserializationContext context) throws JsonParseException {
        RealmLong rl = new RealmLong(jsonElement.getAsLong());
        return rl;
    }
}

Upvotes: 3

Related Questions