Changing user availability/presence via API in a clustered environment

Hi All,

We’re trying to write a plugin to change user availability/status via a web service call. This plugin needs to function correctly in a clustered environment so we have set up two dev servers to do simulate that (Server A and B). We’ve tried several different ways to update the user presence and found one that would work. The solution we found is to call LocalMUCRoom.presenceUpdated(MUCRole, Presence) method to propogate the presence changes to other servers in the cluster. One caveat is that the Presence packet passed into the presenceUpdated method needs to include extendedInformation, e.g.

<presence to="mr.j@conference.chat.foo.com/mr.j" from="mr.j@conference.chat.foo.com/mr.j"><priority>0</priority><status>Live</status>&lt ;x xmlns=“http://jabber.org/protocol/muc#user”><item jid="w@chat.foo.com/mr.j" affiliation=“admin” role=“moderator”/></x>

If the extendedInformation is missing, an exception will be thrown from LocalMUCRoom.sendInitialPresence on server B when a second user (user B) joins the room on that server after the first user (user A) in the room changes status on server A. But, if the extendedInformation is included, user A’s role presence would have an extra piece of extendedInformation added to it every time user A changes status in the room.

My question is, is that an expected behavior and could I actually use presenceUpdated method to update presence? If not, what’s the correct way to achieve this?

Thanks in advance!

Hey jialong,

Based on your subject and initial paragraph I was assuming that you wanted to change the presence of a user but when you mentioned your solution I see that you want to change the presence of a user in a room. So my first question is: What are you trying to achieve here?

  1. Simulate that a user changed his presence? This implies that users subscribed to his roster will receive the new updated presence.

  2. Simulate that a user changed his presence in a given room? This implies that the presence of the user in a given room was modified.

In any of both cases I would recommend creating the corresponding Presence packet and ask the PacketRouter to process the packet. That is the safest and most correct way of doing these things.

Regards,

– Gato

Hi Gato,

Thanks a lot for your answer. We want to change a user’s presence in all the rooms in all his sessions through one single web service call so it’s closer to #2. Our first attempt in doing this was creating a new Presence packet according to the MUC extension: http://www.xmpp.org/extensions/xep-0045.html#changepres and use PacketDeliverer to deliver the new Presence packet. It worked in a single server environment. But in a clustered environment, we got Exceptions when some other users join the room from a remote server because of the missing extended information as I described in the original post. From your answer, it looks like I should be using PacketRouter instead of PacketDeliverer. I’ll try that and see if it helps.

Thanks again,

Jialong

Hi Gato,

Tried using PacketRouter to route the updated Presence packet and I’m still seeing the same problem. This is the code I use to generate the packet:

Presence p = new Presence();

p.setFrom(session.getAddress());

p.setTo(role.getRoleAddress());

if (presence.getStatus() != null) {

p.setStatus(presence.getStatus());

} else {

p.setStatus(“Nobody”);

}

This code is inside an implementation of presenceChanged(ClientSession session, Presence presence) method of PresenceEventListener interface. The code above I believe is complaint with the MUC extension. User presence in the room on local server is updated correctly, but the presence on the remote server is missing the extended information portion of the packet. And that missing extended information causes Null Pointer Exception to be thrown when another user tries to join the same room on the remote server when the room is semi-anonymous.

Any suggestions on how I can get this to work? Thanks a lot!

Regards,

Jialong