realm / realm-java

Realm is a mobile database: a replacement for SQLite & ORMs
http://realm.io
Apache License 2.0
11.47k stars 1.75k forks source link

java.lang.AbstractMethodError while upgrading from Realm 1.2.0 to 3.7.2 #5379

Closed sabergeek closed 7 years ago

sabergeek commented 7 years ago

Goal

To upgrade from Realm 1.2.0 (legacy code) to 3.7.2

Expected Results

Smooth upgrade of Realm library

Actual Results

java.lang.AbstractMethodError: abstract method "java.util.Map io.realm.internal.RealmProxyMediator.getExpectedObjectSchemaInfoMap()" at io.realm.Realm.createExpectedSchemaInfo(Realm.java:179) at io.realm.Realm.<init>(Realm.java:150) at io.realm.Realm.createInstance(Realm.java:417) at io.realm.RealmCache.doCreateRealmOrGetFromCache(RealmCache.java:348) at io.realm.RealmCache.createRealmOrGetFromCache(RealmCache.java:281) at io.realm.Realm.getInstance(Realm.java:346) at com.company.Something.app.Something.getRealm(Something.java:380) at com.company.Something.app.HomeActivity.onResume(HomeActivity.java:440) at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1364) at android.app.Activity.performResume(Activity.java:6847) at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3542) at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3612) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2854) at android.app.ActivityThread.-wrap12(ActivityThread.java) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1552) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:154) at android.app.ActivityThread.main(ActivityThread.java:6334) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)

Steps & Code to Reproduce

The legacy code has 5 tables and I simply upgraded the realm version to a new one. I barely understand the error, so i'm not sure how to begin debugging.

Code Sample

public Realm getRealm() { RealmConfiguration realmConfiguration = new RealmConfiguration.Builder().name(DB_NAME).schemaVersion(2).migration(new RealmMigrations()).build(); Realm.setDefaultConfiguration(realmConfiguration); return Realm.getInstance(realmConfiguration); }

This is how the code is configured to fetch the Realm instance. The only change i've made here is additional functions for DB name, schema version and a realm migration code (with basically nothing in it for now).

Version of Realm and tooling

Realm version(s): 1.2.0

Realm sync feature enabled:no

Android Studio version: 2.3.3

Which Android version and device: All devices

cmelchior commented 7 years ago

That looks mostly like a cache/build error. Have you tried cleaning before your entire project?

sabergeek commented 7 years ago

@cmelchior I haven't! Doing it right now. Will report the results shortly.

sabergeek commented 7 years ago

@cmelchior Understood and noted - Always good to clean the project after upgrading the library. But now, I'm receiving a different error as reported here - https://github.com/realm/realm-java/issues/4616

I'm not using Realm Modules. What could I be missing here?

Zhuinden commented 7 years ago

@sabergeek you are most likely not receiving that error because that happened when Proguard is enabled and a problem with obfuscation in the 3.2.X versions.

The current stack trace would be nice to have.

sabergeek commented 7 years ago

@Zhuinden

Acknowledged. But error does talk about the object not being part of the schema.

Here's the stack trace (post-clean build, after the version change) -

FATAL EXCEPTION: main Process: com.company.Something.app.debug, PID: 32275 java.lang.RuntimeException: Unable to resume activity {com.company.Something.app.debug/com.company.Something.app.HomeActivity}: java.lang.IllegalArgumentException: MyBagItems is not part of the schema for this Realm at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3572) at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3612) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2854) at android.app.ActivityThread.-wrap12(ActivityThread.java) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1552) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:154) at android.app.ActivityThread.main(ActivityThread.java:6334) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776) Caused by: java.lang.IllegalArgumentException: MyBagItems is not part of the schema for this Realm at io.realm.internal.modules.CompositeMediator.getMediator(CompositeMediator.java:169) at io.realm.internal.modules.CompositeMediator.getTableName(CompositeMediator.java:87) at io.realm.RealmSchema.getTable(RealmSchema.java:177) at io.realm.RealmSchema.getSchemaForClass(RealmSchema.java:199) at io.realm.RealmQuery.<init>(RealmQuery.java:126) at io.realm.RealmQuery.createQuery(RealmQuery.java:78) at io.realm.Realm.where(Realm.java:1287) at com.company.Something.cart.realmobjects.MyBagItems.getBagItemCount(MyBagItems.java:196) at com.company.Something.app.HomeActivity.onResume(HomeActivity.java:440) at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1364) at android.app.Activity.performResume(Activity.java:6847) at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3542) at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3612)  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2854)  at android.app.ActivityThread.-wrap12(ActivityThread.java)  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1552)  at android.os.Handler.dispatchMessage(Handler.java:102)  at android.os.Looper.loop(Looper.java:154)  at android.app.ActivityThread.main(ActivityThread.java:6334)  at java.lang.reflect.Method.invoke(Native Method)  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776) 

I tried migrating too, but it says the class already exists.

Zhuinden commented 7 years ago

....so if you do provide a migration and you don't add the class if it is already found in the schema (schema.get("MyBagItems") != null) then it tells you that it's not part of the schema? 😕

sabergeek commented 7 years ago

@Zhuinden :(

I'll re-iterate the exact flow more coherently -

  1. The legacy code has 5 tables. Realm v1.2.0
  2. Earlier, there was no schema version, nor DB name was specified. So I added it, because the business requirements increased the odds of us adding more keys in the DB. Also, previously Realm was configured with deleteRealmIfMigrationNeeded().
  3. I decided to upgrade Realm to v3.7.2 and make the necessary changes to the way it's initialised.
  4. Now I encounter java.lang.AbstractMethodError. So as suggested by @cmelchior, I cleaned the build and re-ran. The error went away.
  5. Now I get the 'x is not part of the schema for this Realm' error. So I proceeded to add a simple db creation logic to Realm migration with (just to see what happens):
if (oldVersion == 2) {
            schema.create("MyBagItems");
            oldVersion++;
        }
  1. But I got

Exception has been thrown: Illegal Argument: Class already exists: 'class_MyBagItems'.

  1. This seemed contradictory, so I removed it, and the error on step 5th was back.

Let me know if you spot anything odd in these steps that I may have done wrong.

I can provide other details if necessary. :)

sabergeek commented 7 years ago

@Zhuinden Any clue what might be going on?

Zhuinden commented 7 years ago

@sabergeek honestly I'm not sure, so I'd try something like

RealmObjectSchema myBagItems = schema.get("MyBagItems");
if(myBagItems == null) {
    myBagItems = schema.create("MyBagItems");
    myBagItems.addField(...);
    myBagItems.addField(...);
    myBagItems.addField(...);
}
Zhuinden commented 7 years ago

@sabergeek is this something you can reproduce locally?

If so, maybe you could try throwing https://github.com/Zhuinden/realm-auto-migration at it with a schema version increase (just once) to see if it'd still crash out afterwards or not.

I'm really out of ideas about it though.

sabergeek commented 7 years ago

@Zhuinden Yea it's reproducible. I'll try out https://github.com/Zhuinden/realm-auto-migration and report back. Thanks!

sabergeek commented 7 years ago

@Zhuinden I tried the auto-migration tool, but later I felt safer to write my own migration logic for the project (since I noticed the alpha build).

It's sorted now! Our project had apply plugin: 'android-apt' applied way below the chain. So I re-ordered it as mentioned in other similar threads. And all went ok. I had to further manually write the migration logic for all tables.

Thank you!

Zhuinden commented 7 years ago

Agh, I didn't think of that in this context! Glad you found the root of the problem!

With Realm 2.2.0+ you can change apt to annotationProcessor

JirkaKrivanek commented 4 years ago

I have the same problem with 6.0.1. The thread above does not help me at all.

And yes, it is somehow related to obfuscation:? If I disable the obfuscation then it works fine.

Therefore it means that this note

A ProGuard configuration is provided as part of the Realm library. This means that you don’t need to add any Realm specific rules to your ProGuard configuration.

in the realm java guide is NOT true :(

Generally, I do not really like how realm is hiding common things, like dependencies, configurations, processing. It is probably convenient for common use but as soon as one gets out of the happy path, things stop working and it is a hell to fix it...

JirkaKrivanek commented 4 years ago

BTW: This is my stack trace:

java.lang.AbstractMethodError: abstract method "java.util.Map io.realm.internal.RealmProxyMediator.getExpectedObjectSchemaInfoMap()"
        at io.realm.Realm.createExpectedSchemaInfo(Realm.java:192)
        at io.realm.Realm.<init>(Realm.java:163)
        at io.realm.Realm.createInstance(Realm.java:499)
        at io.realm.RealmCache.doCreateRealmOrGetFromCache(RealmCache.java:355)
        at io.realm.RealmCache.createRealmOrGetFromCache(RealmCache.java:285)
        at io.realm.Realm.getInstance(Realm.java:428)
        at com.gemalto.mbi.common.internal.realm.c.open(MbiRealmPersistingFacility.java:149)
        at util.n.ad.open(MbiPersisterImpl.java:91)
        at util.n.X.b(MbiBioOperationManagerImpl.java:738)
        at util.n.X.load(MbiBioOperationManagerImpl.java:728)
        at controller.init.ControllerContextImpl.load(ControllerContextImpl.java:400)
        at controller.di.manager.operations.command.RefreshOperations.execute(RefreshOperations.java:45)
        at controller.di.manager.common.AbstractCommand.run(AbstractCommand.java:59)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at java.lang.Thread.run(Thread.java:764)

Any chance what could be wrong?