powered by Jive Software

Roster problems in beta 3

I am using the following code to get the contact list for a given user. I am not getting the list at all. The Iterator comes back empty. I used Exodus client for the same user, and I am getting the contact list correctly. What am I doing wrong?

XMPPConnection conn1 = new XMPPConnection(“localhost”);

conn1.login(“myself”,“mypass”);

Roster ros = conn1.getRoster();

ros.reload();

Iterator it = ros.getGroups();

while(it.hasNext()) {

RosterGroup rgp = (RosterGroup) it.next();

rgp.getName();

}

Thanks

Rchandran

Silly question, but have you tried turning the debugging mode on with the following (set before you create connection):

XMPPConnection.DEBUG_ENABLED = true;

It worked for me, look at the xml that the server sends you (blue text in debug mode).

Cheers,

ribot.

Actually, trying to print the roster entries out returns nothing like you said…I, will keep trying and report back if I have any success.

Any ideas Matt?

Cheers,

ribot.

So any clues about this problem?

Was there a resolution/workaround found for that problem. I have the exact same issue. Did that use to work on earlier version of the lib?

Hi,

I don’‘t think roster support is complete in beta 3. The release notes indicate that it is only partially implemented. I’'ll try to poke Matt on this to confirm/deny.

-iain

I think that code used to work. However, the roster code definitely needs to be polished up. I’'ll see if I can get to that this weekend.

Regards,

Matt

Great, I eagerly await the ‘‘post-polish’’ era.

Anyone managed to get the roster up and going? My attempts so far have failed.

Has anyone tired hacking around with the Smack source?

I could do with a quick fix solution in case Beta 4 isn’'t released in time for my hand in date.

Thanks

Ben

conn.getRoster() appears to operate async just like the Roster.Reload() method.

I’'m sure someone more knowlegable in Java than me can come up with a better plan than this, but here was my temporary fix:

conn = new XMPPConnection("server", 5222);
conn.login("username","password","resource");
roster=conn.getRoster();
while (!roster.getGroups().hasNext()) {
    System.out.println("wait");
}
updateRosterDisplay(...);

I think you can still get a partial roster doing this…i.e. some items are loaded in the roster but others are still pending from the server.

Probably better to spawn a thread or something to do this but I haven’'t gotten to that section of the book yet

I guess the real solution is to add a simple listener so that you can know when to load the roster after changes. I’'ll try to get this done for the next beta.

Regards,

Matt

Oh, I guess another option is that I could make Smack wait to get the roster back from the server before returning from the login method. Currently, the following method is called during login (from the Roster class)

/** * Reloads the entire roster from the server. This is an asynchronous operation, * which means the method will return immediately, and the roster will be * reloaded at a later point when the server responds to the reload request. */
public void reload() {
    connection.sendPacket(new RosterPacket());
}

I could make another version of that method that waited for a reply instead. Anyone have an opinion on what would be better? I guess I’‘d lean towards making Smack load the roster synchronously during login since we’'ve already seen the confusion that the current behavior causes.

Regards,

Matt

I would say that since the Roster is like the other high-level components of the library, I would make it act like the Message, Chat, GroupChat object with the same type of “PollMessage”/queue type arrangement. Or just add a “loadCompleted()” method call.

John

John,

I would say that since the Roster is like the other

high-level components of the library, I would make it

act like the Message, Chat, GroupChat object with the

same type of “PollMessage”/queue type arrangement. Or

just add a “loadCompleted()” method call.

I guess I was really looking for opinions on the login method. Should login wait for the roster to be loaded before returning, or no?

Regards,

Matt

Matt,

I don’‘t think the login method should block, but the conn.getRoster() probably should. Maybe even eliminate and roster stuff from the login method altogether though I guess it would speed things up if login went ahead and asked for it async but getRoster blocks until it’'s completed.

Take care,

John

John,

Cool, that’‘s a good suggestion and I’'ll implement it that way.

Thanks,

Matt

Hi Matt and John,

I agree with this approach. I have tried to make the getRoster() method blocking and made the GUI application that is loading the roster to execute in a separate thread. Here are some of my suggested codes:

private boolean isRosterReady = false;

public Iterator getGroups() {

while (!isRosterReady) {

try {

wait();

} catch (InterruptedException ie) {

}

}

synchronized (groups) {

List groupsList = Collections.unmodifiableList(new ArrayList(groups.values()));

return groupsList.iterator();

}

}

private class RosterListener implements PacketListener {

public void processPacket(Packet packet) {

isRosterReady = false;

// same as the rest of the code body

// Notify waiting threads that the roster groups are ready.

isRosterReady = true;

notifyAll();

}

}

Hey all,

Just thought you’'d want to know that the latest build fixes the roster problem – it now waits up to two seconds for a reply from the server before returning the roster. Daily builds are at:

http://www.jivesoftware.com/xmpp/smack/dailybuilds.jsp

-Matt

Hi,

I noted a number of other potential problems with the roster.

  1. The roster needs to have a blocking thread operation which fires an event when the roster is completely loaded. This can be done by implementing another static class (such as RosterSynchronizer) to handle roster synchronization. A statement such as “RosterSynchronizer.getRosterSynchronizer().setRosterReady();” can be set at the end of the method “processPacket(Packet packet)” in class RosterListener now.

Similarly, the call to roster.getGroups() should be blocked by a statement like “RosterSynchronizer.getRosterSynchronizer().waitRoster();”

  1. Another problem is that there could be a race problem between Presence messages that are sent by the server even before the roster packet is sent or completely loaded. In this case, all Presence packets need to be pre-stored in an early-queue until the roster ready event is fired. Once the roster is ready, the early Presence packets will need to be processed. Else, the presence info will be lost!

Hope I intepret the potential problems correctly and got the message across correctly

Cheers,

Joe