Realm-java: Realm queries returns null and "Invalid object"

Created on 14 Aug 2018  路  4Comments  路  Source: realm/realm-java

Goal

Get data from synced realm.

Expected Results

Queries return data that exist on ROS.

Actual Results

Queries return null.

Steps & Code to Reproduce

On fresh install after connecting to Realm => sync queries (on separate thread) return null, async queries return "Invalid object".
On second run => sync queries return null, async queries start returning valid data.
On killing app process and restarting => sync queries from now on starts returning data.
Uninstall app and install again to get the same problem.

Code Sample

fun connectRealm() : Realm? {
    var user : SyncUser? = SyncUser.current()
    var realm : Realm? = null

    if (user == null) {
        val creds = SyncCredentials.custom("realm-admin",
                "someprovider",
                mapOf("username" to "[email protected]", "password" to "passwordx"))

        user = SyncUser.logIn(creds, authUrl)
    }

    user?.let {
        val config = SyncConfiguration.Builder(user, realmUri).build()
        realm = Realm.getInstance(config)
    }
    return realm
}

// On separate thread ...
    realm = connectRealm()
    var mydata = realm?.where(MyData::class.java)?.findFirst() // <= returns null
// ...

// On main thread ...
 connectRealmAsync(onSuccess = {
            var myData = it.where(MyData::class.java)?.findFirstAsync()

            myData?.addChangeListener(RealmChangeListener {
                val b = it.isValid() // <= "Invalid object" on first run
            })
        })
// ...

Server log does not contain any errors. On process kill server log has
"sync proxy closed
closed connection"

Version of Realm and tooling

Realm version(s): 5.4.2, 5.1.0 ROS v3.4.3

Realm sync feature enabled: yes

Android Studio version: 3.1.3

Which Android version and device: API 24-27, emulators and real devices

O-Community T-Help

Most helpful comment

It looks like you are using query-based sync (which is the default when creating configurations this way):

val config = user.createConfiguration(realmUri)
  .waitForInitialRemoteData()
  .build()

For this mode of syncing, using waitForInitialRemoteData() doesn't make much sense as we only download data you query, and no queries exist when you open the Realm the first time.

But that aside, we currently have a limitation that only queries created using findAllAsync() are automatically fetched from the server. Specifically findFirstAsync() will not subscribe to the data on the server, but only run a local query. This is the reason you only see null, since nothing is fetched from the server.

We are in the process of adding functionality that can lift this restriction, but for now you can work around it by replacing findFirstAsync() with findAllAsync():

val realm = connectRealm()
val results = realm.where<MyData>().findAllAsync(); // Will subscribe for data
results.addChangeListener( (results, changeset) -> {
  if (!results.isEmpty()) {
    useData(results.first()); // Data should be ready 
  }
});

You can read more here https://docs.realm.io/platform/using-synced-realms/syncing-data

All 4 comments

Tried with newer configuration initialization:

val config = user.createConfiguration(realmUri).build() and with user.createConfiguration(realmUri).waitForInitialRemoteData().build()

With this style of initialization data is never retrieved, even after process kill. Session state in callback is either WAIT_FOR_ACCESS_TOKEN or ACTIVE, but "Invalid object" is always returned in async and null in sync queries.

It looks like you are using query-based sync (which is the default when creating configurations this way):

val config = user.createConfiguration(realmUri)
  .waitForInitialRemoteData()
  .build()

For this mode of syncing, using waitForInitialRemoteData() doesn't make much sense as we only download data you query, and no queries exist when you open the Realm the first time.

But that aside, we currently have a limitation that only queries created using findAllAsync() are automatically fetched from the server. Specifically findFirstAsync() will not subscribe to the data on the server, but only run a local query. This is the reason you only see null, since nothing is fetched from the server.

We are in the process of adding functionality that can lift this restriction, but for now you can work around it by replacing findFirstAsync() with findAllAsync():

val realm = connectRealm()
val results = realm.where<MyData>().findAllAsync(); // Will subscribe for data
results.addChangeListener( (results, changeset) -> {
  if (!results.isEmpty()) {
    useData(results.first()); // Data should be ready 
  }
});

You can read more here https://docs.realm.io/platform/using-synced-realms/syncing-data

Thank you!
findAllAsync() query works (though findAll() doesn't).

Yes, that is by design for now. We are still iterating on how to improve the API regarding this.

Was this page helpful?
0 / 5 - 0 ratings