Realm Blog

Realm Java 0.83 — with Null Support!

Realm files read or written by this version cannot be opened with previous versions of Realm. Please be careful about shipping updates to your existing apps!

We just released a Realm Java update to this website, and to Maven. This release includes support for null values, one of the most-frequently requested Realm features!

Breaking Changes

With this release, fields of the types String, Date, and byte[] are now nullable by default. (In previous versions of Realm Java, no fields could have the value null.) Existing apps will have to either modify model classes or provide a migration step to explicitly support this new feature. Read on for details.

In order to be able to support null values, Realm’s underlying storage engine has changed its file format. Your Realm files will automatically be converted to new file format when you open the Realm file for the first time. The file format conversion is irreversible! It is not possible to open the new Realm file using a previous version of Realm. Furthermore, it is not possible to downgrade a Realm file to the old file format.

If you are going to upgrade existing apps, we recommend that you test carefully before shipping.

Boxed types

Realm Java supports the most common types in Java, including boolean, integer types (byte, short, int, and long), and floating-point numbers (float and double). These primitive (or unboxed) types cannot be assigned to null in Java, and thereby they have served us well. You can still use the primitive types in your model classes. As before, the primitive types indicate that the field cannot be assigned to null.

On the other hand, boxed types are common in Java, and variables and fields of boxed types can be assigned to null. We are introducing boxed types for booleans (Boolean), integers (Byte, Short, Integer, and Long), and floating-point numbers (Float and Double) to Realm Java. When you use these boxed types in your model classes, the field can be assigned to null.

Fields of the types String, Date, and byte[] can be null. Setting a RealmList field to null means that the list is cleared. No objects are removed, only the references to the objects are removed. Moreover, a RealmList field cannot be null. The getter will always return a RealmList object but the length of the list might be zero.

Let us show you a little example. The model class below has two integer fields and one string field.

class Person extends RealmObject {
    String name;
    int age;
    Integer weight; // weight is not required!
}

You can create objects, and assign values to the fields.

Person john = realm.createObject(Person.class);
john.setName("John");
john.setAge(25);
john.setWeight(73);

Person bill = realm.createObject(Person.class);
bill.setName("Bill");
bill.setAge(41);
bill.setWeight(null);

As you can see, we set all three fields for John, while we don’t know the weight of Bill and set it to null (actually, the default value for Person.weight is null so we can skip the line).

The new @Required annotation

Strings, Dates, byte[], and box typed fields can all be assigned to null. As the example above showed, sometimes a proper value (not null) is required. You can specify that a field cannot be null by using the new @Required annotation. Using this annotation, Realm will not allow you to set it to null. If you will always know the name of a person, a better model class is:

class Person extends RealmObject {
    @Required
    String name;
    int age;
    Integer weight;
}

It is possible to add the @Required annotation to boxed typed fields, and Realm will enforce that no null values are saved. The annotation is not used for the primitive types, as a field of a primitive type cannot be null. Moreover, relationships (RealmList and single Realm objects) cannot be required.

Querying

For any field which is not required, you can query with null as a value. Moreover, aggregate functions (sum, min, etc.) will not take null values into account. The Realm interpretation of null implies that every string begins with, ends with, and contains null. This means that the following query will return all objects:

RealmResults<Person> persons = realm.where(Person.class).where().beginsWith("name", null).findAll();

If you query with null as a value for required fields, an exception is thrown.

Migration

With the release supporting null, Realm’s underlying storage engine will automatically convert your Realm files. The conversion is required as the file format used by the storage engine has been changed. The conversion is done even though you don’t intend to use null values in your model classes. The automatic conversion will take time, so the very first access to a Realm file will take a bit longer. After the conversion, files will be opened just as fast as before.

You are likely to do some manual migration as well. If you have string, date or binary (byte[]) fields in your model classes, you will have to migrate them. In previous versions of Realm Java, Strings could not be null. In version 0.83.0 of Realm Java, the semantics of String has been changed. Take the following model class as an example:

class Dog {
    String name;
    int age;
}

If you have created a Realm file which includes Dog, the field name could not be assigned to null. With Realm Java 0.83.0 and later, if you which to disallow null as a value, you must change the model class to:

class Dog {
    @Required
    String name;
    int age;
}

If you don’t wish to change the model class (or wish to use null), you will have to migrate the Realm file. For that purpose, you can use the method Table.convertColumnToNullable() as part of your migration.

RealmMigration migration = new RealmMigration() {
    @Override
    public long execute(Realm realm, long version) {
        Table table = realm.getTable(Dog.class);
        table.convertColumnToNullable(table.getColumnIndex("name"));
        return 1;
    }
};

RealmConfiguration realmConfig = new RealmConfiguration.Builder(getContext())
    .schemaVersion(1)
    .schema(Dog.class)
    .migration(migration)
    .build();

Realm Team

At Realm, our mission is to help developers build better apps faster. We provide a unique set of tools and platform technologies designed to make it easy for developers to build apps with sophisticated, powerful features — things like realtime collaboration, augmented reality, live data synchronization, offline experiences, messaging, and more.

Everything we build is developed with an eye toward enabling developers for what we believe the mobile internet evolves into — an open network of billions of users and trillions of devices, and realtime interactivity across them all.

Get more development news like this