Synced queries always return an empty list even when objects exist. Adding objects works


#1

Queries to a synced realm always returns an empty Realmlist. However, adding items works correctly. The same code works for local realms. My code is as follows.

This creates a user successfully.

SyncUser.logInAsync(credentials, AUTH_URL, new SyncUser.Callback<SyncUser>() {
            @Override
            public void onSuccess(SyncUser result) {
                SyncConfiguration configuration = result.createConfiguration(REALM_URL).build();
                Realm.setDefaultConfiguration(configuration);
                //realm = Realm.getInstance(configuration);
                SyncSingleton.getInstance().setEmail(signUpEmail);
            }

            @Override
            public void onError(ObjectServerError error) {
                emailText.setError("Retry Login");
                emailText.requestFocus();
                Log.e("Login Error", error.toString());
            }
        });

This my query

realm = Realm.getInstance(Realm.getDefaultConfiguration());
        realm.refresh();
        
        RealmResults<User> results = realm.where(User.class)
                .equalTo("age", 21)
                .findAllAsync();

When I run this query, I have populated the database with 10 Users all with age 21. However, the size of results is always 0. I have tried adding realm.refresh(). None of the solutions online work for me because I have no write transactions running in the background.


#2

Where are you creating the users?


#3

In the sign in function, I have

realm.beginTransaction();
User user = realm.createObject(User.class, username);
user.setEmail(email);
user.setName(name);
user.setAge(age);
realm.commitTransaction();

After this is done, a new user object is successfully created which we see in realm studio.


#4

I’m seeing the same issue, I posted in Platform. Not really sure the category is correct. I used the .add command, and verified the objects are in the Realm Instance.


#5

Let me know if you ever find a solution. As it stands right now, our project will be switching to a different platform seeing as the docs, forums, and tutorials are all being followed to the letter but the queries do not work.


#6

I’ve been trying different combinations - what I’ve noticed is that if you put in the wrong URL, it doesn’t throw or indicate that it’s wrong. The only indication is positive - when you have the correct URL, you get the message in console:

Sync: Connection[1]: Connected to endpoint

So I thought, well maybe it’s a race condition, so I attached an observer to it, and break out all the options

do {
        self.realm = try Realm(configuration: config!)
        let results = self.realm.objects(Item.self)
        
        notificationToken = results.observe { [weak self] (changes) in
            switch changes {
            case .initial:
                print("Initial", changes)
                print("Initial Results Count", results.count)
                
            case .update(_, let deletions, let insertions, let modifications):
                print("Update", changes)
                print("Update Results Count", results.count)
                
             case .error(let error):
                print("Error")
           
            }
        }
        
    }

If you notice below, when I add a new object the results var is updated. I suspect the documents are wrong and the observers are not returning object as expected in the initial state. I have only basic knowledge of observers. I would expect the results var at this point to contain what was requested, the objects. I’d expect changes to contain the array in the initial state, maybe this is a hot/cold observer thing that I’m not well versed enough to decode?

However - the update shows an insertion at [0], which is incorrect. I’m now up to eight items, so this should have been [7]. This makes me think it’s not even aware of the array on the server side. It’s also odd that the updates observer fires twice. Just to confirm, the new item is in the realm, confirmed via Realm Studio.

	Initial initial(Results<Item> <0x7f907261dee0> (

	))
	Initial Results Count 0
	2019-02-24 20:43:21.014103-0500 [73514:8117607] Sync: Connection[1]: Connected to endpoint 'x.x.x.x:443' (from 'x.x.x.x:55427')
	2019-02-24 20:43:22.784047-0500 [73514:8117406] [MC] System group container for systemgroup.com.apple.configurationprofiles path is //data/Containers/Shared/SystemGroup/systemgroup.com.apple.configurationprofiles
	2019-02-24 20:43:22.784374-0500 [73514:8117406] [MC] Reading from private effective user settings.
	Item "lame" added
	Update update(Results<Item> <0x7f907261dee0> (
		[0] Item {
			id = CAAE0103-D4F8-4DB3-9FE3-5AC436CC6B33;
			owner = x;
			name = lame;
			timestamp = 2019-02-25 01:43:26 +0000;
		}
	), deletions: [], insertions: [0], modifications: [])
	Update Results Count 1
	Update update(Results<Item> <0x7f907261dee0> (

	), deletions: [0], insertions: [], modifications: [])
	Update Results Count 0

#7

FYI, got this link on the special case of ‘first open’.

https://docs.realm.io/sync/additional-resources/how-to-build-an-app-with-realm-sync#opening-realms

Trying it now, but they didn’t address why update would insert and item and then delete it, and why the index didn’t reflect the realm at all.


#8

Realm has access to my realm and is trying to get it working.


#9

Hopefully the’re able to figure out what is wrong with it because at this point it feels like I have exhausted my options. I will try working with the link that you posted but if that doesn’t work then I’m out of ideas.


#10

that link didn’t work with me, Realm has my login, haven’t heard back in over 24 hours. I’d assume if it was a basic coding issue, would have heard back immediately.


#11

That would be my thought as well. I hope they manage to get it sorted out and get back to you. It’s just extremely frustrating feeling like I’m completely out of options other than switching platforms. Next leg of project starts next week; hoping I won’t have to implement Firebase before that.


#12

This works!

func example() {
    do {
        let config = SyncUser.current?.configuration(realmURL: URL(string: "realms://<YOUR REALM STUDIO URL>/default"), fullSynchronization: false, enableSSLValidation: false) // default is name of realm
        self.realm = try Realm(configuration: config!)
        
        self.results = self.realm!.objects(Item.self)
        
        print("Before susbcription: \(self.results!.count)") //returns zero (unless the data had been synced from previous session and the data was cached)
        
        
        self.subscription = self.results!.subscribe() //will begin syncing
        
        print("After subscription, but before there is time to sync: \(self.results!.count)") //still returns zero (unless the data had been synced from previous session and the data was cached)
        
        //We are creating a subscription token before creating a results token, because if we immediately create a results token, the results token will hit .initial right away because the subscription object has yet to be registered by the server. So as far as the client knows, we actually have hit .initial because there was nothing expected as the subscription hadn't been registered.
        self.subscriptionToken = self.subscription?.observe(\.state, { (state) in
            if state == .complete {
                self.setResultsObserver()
            }
        })
    }
    catch {
        print(error)
    }
}


func setResultsObserver() -> Void {
    self.notificationToken = self.results!.observe({ (changes) in
        switch changes {
        case .initial(_):
            print("Data has finally completed sync: \(self.results!.count)") //Will return results that satisfy query
            //LOAD TABLE HERE, ETC, 
        case .update(_, _, _, _):
            print("Data has updated: \(self.results!.count)")
        case .error(_):
            return
        }
    })
}

#13

I’m really glad you were able to get this to work! If you don’t mind me asking, what language is this? I am coding in java and I do not recognize the language you’re using.


#14

No problem - swift. If you need anything else feel free to msg me, especially as we’re at the same point.


#15

So, the only change is the self.results!.subscribe() call?


#16

I think there’s an extra level in the two tokens.


#17

I’ve been going back through the documentation after seeing this and here is what i found. There is a part about subscribing to data. So I tried using the java code found there because the swift code at that spot seems to be what fixed your problem. There are multiple problems that arise for me when I try to use that code. Here is their code

RealmResults<Person> persons = realm.where(Person.class).greaterThanOrEqual("age", 18).findAllAsync();
query.addChangeListener(new OrderedRealmCollectionChangeListener<RealmResults<Person>>() {
    @Override
    public void onChange(RealmResults<Person> persons, OrderedCollectionChangeSet changeSet) {
        if (changeSet.isCompleteResult()) {
          // If true, data has been downloaded from the server.
          // If false, the query result is only based on local
          // data.
        }
    }
});

Problem 1: addChangeListener is not a part of the RealmQuery class. It is a part of the Realm class. Okay, so I change it from query.addChangeListener() to realm.addChangeListener(). So I change the class from person to user and change the function call so it is to the correct object type. This code doesn’t work at all. It doesn’t compile. Here is my code, with the few changes.

        SyncUser.logInAsync(credentials, AUTH_URL, new SyncUser.Callback<SyncUser>() {
            @Override
            public void onSuccess(SyncUser result) {
                SyncUser user = result;
                String url = REALM_URL;
                SyncConfiguration config = user.createConfiguration(url).build();
                Realm realm = Realm.getInstance(config);

                RealmQuery<User> query = realm.where(User.class);
                RealmResults<User> users = query.findAllAsync();

                realm.addChangeListener(new OrderedRealmCollectionChangeListener<RealmResults<User>>() {
                    @Override
                    public void onChange(RealmResults<User> persons, OrderedCollectionChangeSet changeSet) {
                        if (changeSet.isCompleteResult()) {
                            // If true, data has been downloaded from the server.
                            // If false, the query result is only based on local
                            // data.
                        }
                    }
                });

                goToHomePage();
            }

            @Override
            public void onError(ObjectServerError error) {
                emailText.setError("Retry SignUp");
                emailText.requestFocus();
                Log.e("Signup Error", error.toString());
            }
        });```

It says "addChangeListener(io.realm.RealmChangeListener<io.realm.Realm>) to (anonymous io.realm.OrderedRealmCollectionChangeListener<io.realm.RealmResults<com.$myappname>>) in **Realm** cannot be applied.