Roster not functioning correctly?

Hi, everyone,

I am having a problem with the Roster class and I just wanted to see if anyone else is experiencing it, and what they are doing with it. (This is a seperate issue from my earlier post.)

It’'s very simple: the roster is showing that all entries have a null presence. (The problem is not that the requested user is not an entry in the roster.) For instance, the following code is embedded in my application:

for (Iterator i=roster.getEntries(); i.hasNext(); ) {

Object entry = i.next();

System.out.println(entry+": +roster.getPresence(((RosterEntry)entry).getName()));

}

I can run two instances of the application at the same time (using different accounts), and have one, both, or no instances of the application print presence information correctly. This problem persists after calls to roster.reload() .

Here’'s what I know about the problem: I know what the correct presence information is through two sources: first, I have a standard client (psi) that is also monitoring the presence information, and second, the application, when working correctly, will print out the expected presence information. I know that the connection is valid because messages sent to that account are received correctly. Finally, I know that this behaviour would be expected if I had not created roster entries correctly, but the above code shows that I am only checking presence of existing entries.

So: have any of you had this problem? If not, I guess, it’‘s a problem in my code, though I’'ve checked it pretty well.

(I should note that I’‘m using Jive Messenger as a server; it might be the problem, I suppose. I’'ll post to their message boards soon.)

Thanks!

you should be using entry.getUser() which is the JabberID rather then #getName() which is their nickname.

You’'re right, although for reasons like this, I gave the JID as the nickname on entry creation. Any other ideas?

Hey Shawn,

My very first question would be: have you confirmed that Smack is in fact receiving the presence notifications from the server? You can open the Smack debugger to see the incoming (and outgoing) traffic.

My second question would be: Have you subscribed to the contacts’’ presence?

Regards,

– Gato

Hi, Gato,

This is going to be a long post. Sorry =p I don’'t know how to show my problem in any simpler way.

First, you asked if I had subscribed to the contacts’’ presence: I have, using the roster.createEntry method.

Second, you asked if I had confirmed that smack is receiving presence notifications. I didn’‘t know xmpp syntax enough to do that. I did open the smack debug window and note that it was receiving presence packets, but couldn’‘t figure out when (in program excecution) so I wrote a simpler program. This program creates two connections, logs on using the JIDs "autoshawn0@67.52.86.18" and "autoshawn1@67.52.86.18", opens the roster for each, and prints each entry and the associated presence for each. (The JID of each has previously been added to the roster of the other.) (the code is at http://shawndrost.bravehost.com/TestRoster.txt so gato doesn’‘t have to reformat it =) Here’'s the output:

initializing roster0…

autoshawn0@67.52.86.18: autoshawn0@67.52.86.18: available: available

autoshawn1@67.52.86.18: null

initializing roster1…

autoshawn0@67.52.86.18: autoshawn0@67.52.86.18: available: available

(Unrelated question: why is it printing the JID/presence of available users twice? very confusing, given my code.)

So, I thought, I’‘ve reproduced the error in very simple code: autoshawn1 is shown as null, although a scant six or seven lines earlier, I’‘d logged that JID in. It can’‘t be a delay in roster update because autoshawn0 is updating. It can’‘t be that autoshawn0 hasn’'t added autoshawn1 to its roster, because this program is only printing roster entries.

While I was pondering this, I cleared the roster of each, and added code to reinsert each. (see http://shawndrost.bravehost.com/TestRoster2.txt ). After that, it functioned correctly!

initializing roster0…

autoshawn0@67.52.86.18: autoshawn0@67.52.86.18: available: available

autoshawn1@67.52.86.18: autoshawn1@67.52.86.18: available: available

initializing roster1…

autoshawn0@67.52.86.18: autoshawn0@67.52.86.18: available: available

autoshawn1@67.52.86.18: autoshawn1@67.52.86.18: available: available

Of course, when I clear the roster again and run my larger program again (which itself adds roster entries in what seems like the same way), it has the same problem.

Anyway, the point of all this is that I am adding roster entries and recieving presence packets correctly, which makes me think that I’'m adding a roster entry and still not subscribing to that JID. (Both mentioned JIDs are configured to accept all subscriptions.) Can anyone think of anything that would cause this behavior?

Thanks!

-Shawn

if you could post a code sample? that would be great, it might help to diagnose the issue

Well, I made my previous posts in the hope that there was some pretty commonly known way to add entries to your roster without subscribing for the user’‘s presence, or some way to cause this behavior. It’‘s pretty clear that there isn’‘t, and there’'s just some bug in my code, so people with something better to do can go do that now =)

what I’‘ll do for the rest of you is excerpt the XMPP-related stuff so you don’‘t have to wade through the rest. (sorry about the formatting, by the way – I can’'t figure out what to do about it.) After the connection is created, after login, and after getRoster, I clear the roster like so:

Iterator iter = roster.getEntries();

while (iter.hasNext()){

try{

roster.removeEntry((RosterEntry)iter.next());

} catch (Exception e){

//do stuff

}

}

The program has to deliver a message to a certain user and throw an exception if that user is not online. This requires synchronous presence checking, which I do like so:

if (!roster.contains(addr)){

logMsg(logger, Logger.FINEST,addr+" not in roster!");

final boolean inRoster [] = {false};

final Object lock = new Object();

roster.addRosterListener(new RosterListener () {

public void presenceChanged(String updatedAddr){

}

public void rosterModified(){

synchronized(lock){

inRoster[0] = true;

lock.notifyAll();

}

}

});

try{

roster.createEntry(addr, addr, null);

}

catch(XMPPException e){

//do stuff

}

synchronized(lock){

while (inRoster[0] == false) {

try{

lock.wait();

}catch (Exception e){

}

}

}

}

so, after this, roster.getPresence(…) returns incorrect presence information sometimes. More specifically, I am running two copies of this program on different JIDs, and the one that creates a roster entry for the other second seems to detect presence incorrectly.

so… wtf?

Thanks, to those of you that got this far.

-Shawn

I figured it out.

I was confused because I didn’‘t think it was possible to create an entry on your roster without subscribing to its presence. It is: if a user subscribes to your presence, your roster creates an entry for that user, but does not subscribe to its presence. You know you’'re subscribed if:

roster.getEntry(“someuser@someserver”).getType() == RosterPacket.ItemType.TO

or

roster.getEntry(“someuser@someserver”).getType() == RosterPacket.ItemType.FROM

…just in case anyone else was having the same problem I was.

-Shawn