Riccardo Montagnin
Riccardo Montagnin

Reputation: 111

Realm Android - Multiple RealmModule for mutiple libraries

I'm composing different libraries in order to create a single application. Each library used uses its own Realm which, when tested individually on specific test applications, do not produce any error.

The project setup is the following

|- app
|- library\
|    |- LibraryOneRealmModule
|
|- library2
|    |- LibraryTwoRealmModule
|

where both LibraryOneRealmModule and LibraryTwoRealmModule are RealmModules declared as follow:

@RealmModule(library = true, allClasses = true)
public class LibraryOneRealmModule{
}



@RealmModule(library = true, allClasses = true)
public class LibraryTwoRealmModule{
}

Now, when I try to put togheter two two module, the code that I'm using is the following:

Realm.init(this);

RealmConfiguration realmConfig = new RealmConfiguration.Builder()
        .modules(Realm.getDefaultModule(), new LibraryOneRealmModule(), new LibraryTwoRealmModule())
        .build();

Realm.setDefaultConfiguration(realmConfig);

When I try to run the application I get an Exception telling me that a migration s needed because LibOneRealmObject has been added. Even if this is strange because the object is inside library1, I tried seting-up the migration object as follows:

class MyMigration implements RealmMigration {

    @Override public void migrate(@NonNull DynamicRealm realm, long oldVersion, long newVersion) {

        if (oldVersion == 0) {
            RealmSchema schema = realm.getSchema();
            RealmObjectSchema missingObject = schema.create("LibOneRealmObject");
            missingObject.addField("value", double.class);
            oldVersion++;
        }

    }

}

and then changing the Realm configuration as follows:

Realm.init(this);
RealmConfiguration realmConfig = new RealmConfiguration.Builder()
        .migration(new SellMigration())
        .schemaVersion(1)
        .modules(Realm.getDefaultModule(), new OrdersRealmModule(), new CartRealmModule())
        .build();

try {
    Realm.setDefaultConfiguration(realmConfig);
    Realm.migrateRealm(realmConfig);
} catch (Exception e) {
     e.printStackTrace();
}

But when I try again to run the application and the code tries to access the Realm instance, the same error appears telling me:

io.realm.exceptions.RealmMigrationNeededException: Migration is required due to the following errors:

- Class 'LibOneRealmObject' has been added.

Please note that the code that throws the exception is inside library1, and is the following:

Realm realm = Realm.getDefaultInstance();
realm.where(MyObject.class).findAllSorted();

What should I do in order to solve this issue? Is it something related to the code inside library1? Or is it something inside the app module during the setup?

Upvotes: 5

Views: 1349

Answers (2)

Riccardo Montagnin
Riccardo Montagnin

Reputation: 111

I've solve my issues as follow.

1. I've created a class in both library1 and library with the following code:

public class Lib1Realm {

    private static final String REALM_NAME = "my.lib1.realm";
    private static RealmConfiguration realmConfiguration;

    private CartRealm(){}

    public static Realm getDefaultInstance() {
        if (realmConfiguration == null) {
            realmConfiguration = new RealmConfiguration.Builder()
                    .name(REALM_NAME)
                    .modules(new LibraryOneRealmModule())
                    .build();
        }

        return Realm.getInstance(realmConfiguration);
    }

}

And

public class Lib2Realm {

    private static final String REALM_NAME = "my.lib2.realm";
    private static RealmConfiguration realmConfiguration;

    private CartRealm(){}

    public static Realm getDefaultInstance() {
        if (realmConfiguration == null) {
            realmConfiguration = new RealmConfiguration.Builder()
                    .name(REALM_NAME)
                    .modules(new LibraryTwoRealmModule())
                    .build();
        }

        return Realm.getInstance(realmConfiguration);
    }

}

2. I've replaced all the Realm.getDefaultInstance() inside the library1 and library2 code with Lib1Realm.getDefaultInstance() and Lib2.getDefaultInstance() respectevly.

3. I let the app module which includes library1 and library2 as dependencies initialize the Realm instance by simply calling Realm.init(this) inside a class which extends com.android.Application.

This is what is working on for me. As it looks like, the problem was that the two modules were creating a single instance of the Realm object, which then lead to conflicts. Separating the libraries configuration adding some code was the best choice that could have been taken in order to make everything work properly.

Upvotes: 3

EpicPandaForce
EpicPandaForce

Reputation: 81539

You could try:

RealmObjectSchema missingObject = schema.get("LibOneRealmObject");
if(missingObject == null) {
    missingObject = schema.create("LibOneRealmObject");    
    missingObject.addField("value", double.class);
}
oldVersion++;

Upvotes: 0

Related Questions