Realm Java 2.0 - Mobile Platform Support

We’re releasing version 2.0 of Realm Java today, adding support for the Realm Mobile Platform as well as some other minor changes and bug fixes.

Realm Mobile Platform Extensions

If you didn’t read the Realm Mobile Platform launch post yet, we suggest you do that now in order to make more sense of the technical details that will soon follow.

First you need to enable the Mobile Platform Extensions by adding the following to your app’s build.gradle file:

realm {
  syncEnabled = true
}

Then, let’s take a quick look at what it takes to configure a synchronized Realm:

// Login a user
Credentials credentials = Credentials.usernamePassword(username, password, true);
User.loginAsync(credentials, "https://realm.example.com:9443", new User.Callback() {
  @Override
  public void onSuccess(User user) {
    // Opening a synchronized Realm
    // All changes to this Realm will be synchronized with all devices
    SyncConfiguration config = new SyncConfiguration.Builder(user, "realm://realm.example.com/~/userRealm").build();
    Realm realm = Realm.getInstance(config);
  }
  
  @Override
  public void onError(ObjectServerError error) {
    // Handle error
  }
});

That’s it! Once a Realm is opened like this, any changes made to it will be automatically synchronized across all other devices for that user.

Back to the technical bits. To support the Realm Mobile Platform, we’ve added some new classes and APIs:

User & Credential

Users are a central concept when dealing with synchronized Realms. Every Realm is associated with a user. The user can be authenticated to a Realm via a username/password credential or through a number of additional authentication methods (Google, Facebook, iCloud, etc.). See docs on users for details.

Sync Configuration

To configure a synchronized Realm, you must create a SyncConfiguration tied to the user and the remote Realm URL (e.g., realm://realm.example.com/~/userRealm). See our docs for more details.

Sync Manager & Session

The SyncManager is a singleton that manages all synchronized Realms. Currently, you will most likely interact with it to specify a global error handler or how users are stored.

Each synchronized Realm has a corresponding Session which can provide additional information about its state. We intend to attach more information to the session in upcoming releases.

Platform Extensions are in Beta

Although the underlying technology for Realm synchronization has been built, refined and stabilized over the last 5 years, we want to make sure we get the APIs right before committing to them. So we’re releasing the platform extensions as a beta. These APIs will change in future releases. We’re doing this to make sure we end up with the best possible product. Feedback on the APIs is appreciated.

If your app doesn’t use the platform extensions, you can continue to count on the reliability of Realm just like you always have. The platform extensions have been designed in a way that clearly differentiates from using Realm entirely locally or using a synchronized Realm. This should make easy to identify if your app relies on any of the beta components.

All APIs that are in beta are marked with a @Beta annotation and tag in respectively code and Javadoc.

Other 2.0 changes

This is a major version bump for our frameworks to reflect the magnitude of the new features and capabilities included in this release. At the same time we have streamlined a few things as well as made a few adjustments to bring the Realm Java more in line with Realm Swift and Realm Objective-C.

Note that Realm Java introduces a new file format that allows us to gain performance improvements and fixes some bugs. Files written by Realm 2.0 cannot be read by 1.x or earlier versions. Old files can still be opened and they will be migrated to the new format automatically. NOTE: If you are shipping prebuild Realm files with your app, you have to upgrade those to the new version. You can use Realm Browser to upgrade to the latest file format.

Global initializer

The Context reference was sneaking into more and more of our APIs, causing unnecessary friction. In the end we took a step back and introduced a global initializer function

Realm.init(context);

This also made it possible to remove the context from other parts of the APIs which means that:

  • Creating a RealmConfiguration.Builder() no longer requires a context.
  • RealmConfiguration.Builder.assetFile() no longer requires a context.
  • Realm.getDefaultInstance() now works without setting a default first.
  • More failsafe loading of native code.

A natural place for calling this method is in an Application subclass:

public class MyApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        Realm.init(this);
        // Other initializers
    }
}

Default Values

With Realm Java 2.0 we support default values when creating objects. This implies that it is possible to define default values for fields and in the default constructor.

public class Person extends RealmObject {
  private String name = "John";
  private int age;
  
  public Person() {
    this.age = 42;
  }
}

Person p = realm.createObject(Person.class);
p.getName(); // John
p.getAge(); // 42

Default values will also be applied when creating objects from JSON data, but not when creating objects using the dynamic API.

RealmLog

A new class has been added to the public API called RealmLog. It makes it possible to customize how much is logged from Realm and how. All events from the Realm Mobile Platform are also routed through this class.

RealmLog.clear(); // Remove all loggers
RealmLog.add(new AndroidLogger(Log.DEBUG)); // Add custom logger

Objects with Primary Keys

In order to support merging objects from other devices, two new restrictions are imposed on objects with primary keys:

1) A primary key must be provided when the object is created. 2) Once a primary key is set it cannot be changed.

First restriction should only be visible if you use realm.createObject(Class) to create objects. In that case it is required to set the value of the primary key by using realm.createObject(Class, Object).

Using realm.copyToRealm() and realm.createObjectFromJson() will continue to work as before.

If you, for some reason, need to change the primary key, it is necessary to create a new object and copy all fields over. copyFromRealm()/copyToRealm() can be used to make that process easier.

Bug fixes and other changes

For a full list of bug fixes and other changes, see the Changelog.


Thanks for reading. Now go forth and build amazing apps with Realm! As always, we’re around on Stack Overflow, GitHub, or Twitter.