What''s the correct way to move a user on the Roster

Hi, I was wondering what the correct way is to move a user from one group on the roster to another? The way I’'m trying to do this now is below:

while (itr.hasNext())
        {
            RosterGroup rg = (RosterGroup)itr.next();
            System.out.println("remove from "+rg.getName());
            rg.removeEntry(entry);
        }
                RosterGroup rg = con.getRoster().getGroup(newGroup);
        if (rg == null)
        {
            rg = con.getRoster().createGroup(newGroup);
        }
        rg.addEntry(entry);

However the RosterGroup.removeEntry doesn’‘t send anything to the server so this doesn’'t actually remove the group from a user. I was wondering how I “commit” this change to the server.

Well I found out that using createEntry with the new groups also works, although that function als also requesting presence. Don’'t know if that really matters anyway

Message was edited by: botpad

Hugo,

Which version are you using? Are you using a daily build or 1.2.1?

You can follow this link to learn how to move entries between groups. http://www.jivesoftware.com/jive/thread.jspa?forumID=39&threadID=10602

RosterGroup.removeEntry is not sending any packet to the server because the entry that you are trying to remove does not belong to the group.

Regards,

– Gato

I’'m using 1.2.1. What I should have mentioned is that itr is the RosterEntry.getGroups() iterator and entry is the RosterEntry itself (retrieved using Roster.getEntry("user@host.com"))

So what I did was iterate over the users’’ current groups. Then call RosterGroup.removeEntry(entry). That should have worked right?

If you state however that the entry is not in that group that means that the to be removed entry is another instance, correct? Should it work if I’'d use this snippet in the while loop?

RosterGroup oldGroup = con.getRoster().getGroup(group.getName());
RosterEntry entryToMove = oldGroup.getEntry(entry.getUser());
oldGroup.remove(entryToMove);

(untested, I don’'t have access to a jabber server right now)

I must admit that I haven’‘t had a look at the smack source, I’'ll do so asap

(edit: now I did and I’'m getting jive messenger to test the code)

Message was edited by: botpad

Message was edited by: botpad

OK found the real problem now. When a user belongs to multiple groups there’'s a problem when removing them in a loop.

When adding a user to “Admins” and removing from “x” and “y” the following groups updates are sent:

Adminsz

followed by a

xAdmins

So the second update isn’‘t aware yet the “x” group has been removed already. I can’‘t quite figure out how to fix this. I tried to Thread.sleep for a while but that doesn’'t work and is a flaky solution anyway Any suggestions guys?

Ah okay, I’'m passing the entry every time with the old grouplist in it. That gets converted to a RosterPacket.Item without the to be removed group…that explains a lot. But how to fix it? To be continued

Okay, as the updated entry isn’'t available until after a rostermodified event I fixed it for now using a RosterListener that removes all the unwanted groups one at a time after the roster modified event…

Message was edited by: botpad

Hugo,

I think I understand the problem. When you ask a RosterGroup to remove an entry, Smacks sends a packet to the server specifying the new valid groups for the entry and the entry is actually removed when Smack receives a packet from the server specifying the groups for the entry.

If you try to remove the same entry from another group before Smack receives the “roster removal” packet from the server then the packet that Smack will send will contain the first removed group as a valid group. Is this the problem that you are having?

I’‘ll file a bug report. I have a solution in mind that I’‘ll try to implement today. I’'ll let you know any news on the subject.

Thanks,

– Gato

Thanks Gato! The listener aproach I’'m using now works but is kind of clunky. Maybe the internal roster should be updated when you change it, when modifing the roster fails it could just restore the server state.

Then again you’'d have no error notification.

I think it would be best to have roster modifications to be (optional) blocking and have them throwing an exception if the modification isn’'t accepted.

Gato,

Any news yet? (just curious)

Hugo,

Sorry for the late response but I was away for several days on vacation. You can find the patch in the daily build. AFAIK, you are using Smack 1.2.1 but you can go and download the latest daily build which is quite stable (we plan to release 1.3.0 in the next weeks) and compatible with previous version.

Thanks,

– Gato

Thanks,

I’'ll try the daily build in the next couple of days.

Hi Gato,

Could you please describe your solution here? I think it is pretty well to send change request to the server and update data model after receiving confirmation, just like the way you described above.

Denis.

Hey Denis,

Did you have any problem or side-effect with the modification? The solution was to remove the entry locally after sending the packet removal to the server.

When you update a Roster entry, the server updates the roster information in its persistent storage, and also pushes the change out to all of the user’'s available resources that have requested the roster. This means that the packet that you receive from server is not a confirmation “per se” but an update notification sent to every connection made by the same user. Therefore, the logic used to update the roster when the server sends an update packet remained (almost) unmodified.

Regards,

– Gato

Thanks Dombiak,

Just the design thoughts.