Issue with RosterListener during connection establishment

I am expecting non-deterministic behavior with the RosterListener during an initial connection establishment. In my test I have around 200 entries in my roster of which 9 have a presence of available. This was tested with smack 4.1.2

My code looks like this…

XMPPTCPConnection conn = new XMPPTCPConnection(cfg);

final Set availableJIDs = Collections.synchronizedSet(new HashSet<>());

Roster r = Roster.getInstanceFor(conn);

r.addRosterListener(new AbstractRosterListener() {

@Override

public void presenceChanged(Presence presence) {

if (presence.getType() == Presence.Type.available)
availableJIDs.add(presence.getFrom().split("@")[0]);

}

});

r.addRosterLoadedListener(new RosterLoadedListener() {

@Override

public void onRosterLoaded(Roster roster) {

System.out.println("onRosterLoaded " +
roster.getEntries().stream().filter(x -> roster.getPresence(x.getUser()).getType() == Presence.Type.available).count());
}

});

conn.connect();

conn.login(“a”, “b”, “smack4test”);

// wait a little bit

Thread.sleep(5000);

System.out.println("roster listener calls " + availableJIDs.size());

System.out.println("available entries " + r.getEntries().stream().filter(x -> r.getPresence(x.getUser()).getType() == Presence.Type.available).count());

conn.disconnect();

As output of my program I would have expect that I get 9 roster listener calls, however the output ranges from 0 to 9. The available entries determined by inspecting the roster after 5 seconds always yields the correct number of available entries.

Any ideas?

presenceChanged() won’t get invoked if the roster doesn’t find an entry for the originating JID: https://github.com/igniterealtime/Smack/blob/cd3692f329d8e2cb3e9d128c6a5cd473314 7d981/smack-im/src/main/java/org/jivesof… This could be the case when the presence(/s) is(/are) send before the roster result is received on login.

A stanza trace would be helpful, please have a look at https://community.igniterealtime.org/external-link.jspa?url=https://github.com/i gniterealtime/Smack/wiki/How-to-ask-for-…

We may should consider removing the entries.contains(key) checks in Roster’s PresencePacketListener. But first, I’d like to see in which order the stanzas are received.

I’ve turned on the debugger in the connection configuration and retried. Unfortunately I cannot publish them as they are due to some security constraints. Is there an easy way to obfuscate/anonymize them?

However, As far as i can see there is the IQ for the roster query result FOLLOWED BY the presence stanzas.

I tried this a couple of times resulting in different number of calls of the roster listener. Even for identical stanza sequences in the traces (apart from the obvious differences like hashes and stanza ids) I get a different number of calls of the roster listener.

I’ve turned on the debugger in the connection configuration and retried. Unfortunately I cannot publish them as they are due to some security constraints. Is there an easy way to obfuscate/anonymize them?
Depends on what you want to obfuscate. Usually some well chosen substitutions are enough.

However, As far as i can see there is the IQ for the roster query result FOLLOWED BY the presence stanzas.

I noticed that the roster result listener is executed async. This means that the handling of the presences can overtake the roster result handling.

Created SMACK-681. And uploaded Smack 4.1.3-SNAPSHOT with Wait in Roster's presence listener until Roster is loaded · Flowdalic/Smack@3bb06b8 · GitHub 82

Could you try and report back if it solves the issue for you?

Cool. Just tested it around 100 times with the 4.1.3-SNAPSHOT. Now I get a deterministic behavior and the listener is called for every subscription.

Thx!