Hi there!
Faced a strange issue: ProGuard build is crashing with next message:
java.lang.IllegalArgumentException: Invalid query: table 'TableNameHere' not found in this schema.
at aig.a(CachedFieldDescriptor.java:72)
at aii.c(FieldDescriptor.java:284)
at aii.a(FieldDescriptor.java:177)
at ahb.b(RealmQuery.java:347)
at ahb.a(RealmQuery.java:339)
Proguard main configuration part:
-dontskipnonpubliclibraryclassmembers
-optimizationpasses 7
-allowaccessmodification
-repackageclasses
-dontpreverify
Realm version(s): 3.2.1
Android Studio version: 2.3.2
Which Android version and device: 7.1.2, Nexus 5X, Pixel XL
Adding
-keep class path.to.model.classes.here.** { *; }
fixes the issue, seems like the next abstract managers usage style:
public T get(Object primaryKey) {
return getPrimaryKeyQuery(getRealm().where(getGenericClass()), primaryKey).findFirst();
}
public abstract RealmQuery<T> getPrimaryKeyQuery(RealmQuery<T> realmQuery, Object primaryKey);
public abstract Class<T> getGenericClass();
public abstract String getPrimaryKeyName();
With the next implementation style:
@Override
public RealmQuery<Model> getPrimaryKeyQuery(RealmQuery<Model> realmQuery, Object primaryKey) {
return realmQuery.equalTo(getPrimaryKeyName(), (int) primaryKey);
}
@Override
public Class<Model> getGenericClass() {
return Model.class;
}
@Override
public String getPrimaryKeyName() {
return "id";
}
Fails in case of model classes obfuscation. Is it normal behavior?
This could looks problematic:
@Override
public Class<Model> getGenericClass() {
return Model.class;
}
Especially if you do getGenericClass.getClass().getSimpleName()
Our proxies actually have a getModelName() method exactly for that reason, which is what allows ProGuard to obfuscate the model class name.
Thank you for such quick response. So in case of getting _RealmQuery_ via _where(Class
Doing
Realm.where(getGenericClass()).findAll()
Should work since Realm internally maps between the Class reference and the proper table name.
But seems like my implementation is doing exactly that thing or am I missing something? I'm not trying to work with _getSimpleName_ or other string stuff as far as I can see.
Ups, yeah. I can see that in you example now. That is a bit strange then. You can try printing the scheama by using realm.getSchema() and see if it reveals anything. Could it be possible that the Realm has a restricted schema somehow that doesn't include Model ?
Just tried to print all the _getClassName_ with _getSchema().getAll()_.
In both of the cases with or without _-keep class_ I'm getting the same list of models
It sounds like your model isn't getting processed by the annotation processor then. Can you verify that in the gradle log. There should be Proccessing: Model line there somewhere
Huh, it's also listed there:
...
Note: Processing class Model
...
Note: Creating DefaultRealmModule
It's fancy but my workmate is facing dat problem too now. I suggest it's related to recent realm updates. Moreover I've tried to keep one problematic model class after another and it seems like that only two of let's say 10 of them are facing this but not obvious reasons for it were found.
Are you also seeing this problem if you do ./gradlew clean uninstallDebug installDebug from the command line?
Yep, clean builds, installs and cache invalidation make no difference
Which version of Gradle do you use?
3.3 for _Gradle_
2.3.2 for _com.android.tools.build:gradle_
UPD: Oh, it works with 3.1.4 Realm version
yo @bmeike that sounds like this came in with https://github.com/realm/realm-java/commit/deb25a87d08d93ebc77c5c8d9e81b8a632485b83
@DummyCo what is the exact name of the RealmObject class you have, and what the exception message gives you?
@Zhuinden classes that are causing that problem are trivial enough:
public class MyUser extends RealmObject {
@PrimaryKey
private int id;
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public MyUser withUser(User user) {
this.user = user;
return this;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public MyUser withId(int id) {
this.id = id;
return this;
}
}
public class SwiperCache extends RealmObject {
@PrimaryKey
private int id;
private RealmList<User> users;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public SwiperCache withId(int id) {
this.id = id;
return this;
}
public RealmList<User> getUsers() {
return users;
}
public void setUsers(RealmList<User> users) {
this.users = users;
}
public SwiperCache withUsers(RealmList<User> users) {
this.users = users;
return this;
}
}
md5-3aaf23fc4eac21515eb9470c41d9ef41
Caused by: java.lang.IllegalArgumentException: Invalid query: table 'MyUser' not found in this schema.
at azf.a(Unknown Source)
at azh.c(Unknown Source)
at azh.a(Unknown Source)
at axz.b(Unknown Source)
at axz.a(Unknown Source)
at aln$a.a(Unknown Source)
at alo.c(Unknown Source)
at aln.c(Unknown Source)
at aln.d(Unknown Source)
@cmelchior this is definitely a bug in Realm because it shouldn't be eaten by Proguard.
I use this proguard setup from the old times,
#realm
-keepnames public class * extends io.realm.RealmObject
-keep @io.realm.annotations.RealmModule class *
-keep class io.realm.** { *; }
-dontwarn javax.**
-dontwarn io.realm.**
#realm 0.84.1+
-keep class io.realm.annotations.RealmModule
-keep @io.realm.annotations.RealmModule class *
-keep class io.realm.internal.Keep
-keep @io.realm.internal.Keep class *
-dontwarn javax.**
-dontwarn io.realm.**
#realm 0.89.0+
-keep class io.realm.RealmCollection
-keep class io.realm.OrderedRealmCollection
But generally it wouldn't be needed...
Had the same issue earlier today with a release build since updating to Realm 3.2.1.
Stack trace:
Fatal Exception: java.lang.RuntimeException: Unable to start activity ComponentInfo{com.my.app/com.my.app.LauncherActivity}: java.lang.IllegalArgumentException: Invalid query: table 'MyTable' not found in this schema.
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2666)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2727)
at android.app.ActivityThread.-wrap12(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1478)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6121)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:889)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:779)
Caused by java.lang.IllegalArgumentException: Invalid query: table 'MyTable' not found in this schema.
at io.realm.internal.fields.CachedFieldDescriptor.compileFieldDescription(CachedFieldDescriptor.java:72)
at io.realm.internal.fields.FieldDescriptor.compileIfNecessary(FieldDescriptor.java:284)
at io.realm.internal.fields.FieldDescriptor.getColumnIndices(FieldDescriptor.java:177)
at io.realm.RealmQuery.greaterThan$1f3d3c8d(RealmQuery.java:904)
at com.my.app.DataService.getSomething(DataService.java:1248)
Adding this to ProGuard did the trick:
-keepnames public class * extends io.realm.RealmObject
@Philio right, but your true model classes names are not getting obfuscated in such way what is not acceptable and does not solve the issue with Realm inner ProGuard configuration or something else there.
Hi, I'm facing the same issue when I update realm version from 3.1.4 to 3.2.1
Stack trace
Caused by java.lang.IllegalArgumentException: Invalid query: table 'Member' not found in this schema.
at io.realm.internal.fields.CachedFieldDescriptor.compileFieldDescription(CachedFieldDescriptor.java:72)
at io.realm.internal.fields.FieldDescriptor.compileIfNecessary(FieldDescriptor.java:284)
at io.realm.internal.fields.FieldDescriptor.getColumnIndices(FieldDescriptor.java:177)
at io.realm.RealmQuery.equalToWithoutThreadValidation(RealmQuery.java:3347)
okay, who's going to mark this as a BUG?
Because this is a bug.
EDIT: thanks @beeender!
@DummyCo We are having problems reproducing this.
Can you post your build.gradle file (the release section`) + you proguard config file?
Ok, I can reproduce this now using out default Proguard setup. It looks like a bug in the query parser that is triggered when fields are being queried.
realm.where(User.class).count(); // works
realm.where(User.class).equalTo("name", "John").findAll(); // Crashes with `User` not found
@cmelchior I'm 100% certain that this came in with https://github.com/realm/realm-java/commit/deb25a87d08d93ebc77c5c8d9e81b8a632485b83 but I couldn't find exactly where.
@Zhuinden I identified at least one bug: https://github.com/realm/realm-java/blob/master/realm/realm-library/src/main/java/io/realm/internal/ColumnIndices.java#L76
Calling getSimpleName() on a Class reference will never do the right thing when classes/fields are obfuscated
@cmelchior then to reproduce the bug, you need to put two RealmObjects in two different packages.
@Zhuinden is right, I almost certainly introduced this. Will have a look in the next couple hours.
Realm Java 3.3.0 was released with a fix for this.
Most helpful comment
okay, who's going to mark this as a BUG?
Because this is a bug.
EDIT: thanks @beeender!