Openfire does not always send the presence update containing the role/affiliate change to the user that was the subject of the change. It does (always) send it to all other users in the room as intended.
This issue is hard to reproduce in versions of Openfire prior to 4.6.0. When upgrading to 4.6.0, the problem is more apparent.
Although initially believed to be a client specific issues, we've since been able to reproduce the behaviour on other clients, including Spark, too: this client also didn't receive the presence update associated with a role change. The feeling is that this problem can occur on any client.
What is happening is this:
The IQAdminHandler#handleItemsElement sends the presence update to all room occupants.
This ends up in LocalMucRoom#broadcast where a conditional filters out the sending of the 'self-presence': the presence update send to the user the update is about. It does this by comparing the to JID on the presence stanza with the occupant presence from JID. When they are equal, it is a self-presence and skipped. This is the presence update we are missing.
After LocalMucRoom#broadcast sends the presences to all occupants except the self-presence, it will finally attempt to send the self-presence. However, it will set the 'to' to null, which was retrieved from LocalMUCRoom#RoomRole#getUserAddress. This means that the self-presence does not get delivered.
In some cases the to JID on the presence stanza is the room JID, which means no stanza is recognized as a self-presence. In these cases all occupants receive an update, and all clients reflect the role change.
Further investigation is needed to found out why the from JID is different in some cases, but in any case the code that is intended to explicitly send the self-presence does not work in case of role updates, as in this case the RoomRole is used, and not the role of the destination user. Instead of using presenceRequest.getUserAddressSender(), the presence should be send to the occupant that was skipped earlier in the code.