Smack 4.1.0 RosterEntry setName(..) doesn't change the name

I’m not sure if there is already a definitive patch for this, but this question for 3.2.1 already addressed my issue:

Issue reporting, concerning #SMACK-312 and RosterEntry.setName

Looking at the latest code, it seems kind of obvious that RosterEntry.setName(…) can’t work right:

It’s adding the instance of the entry as a roster item to the packet first :

packet.addRosterItem(toRosterItem(this));

Then, after sending the packet and receiving the result, the name of the instance is changed:

// We have received a result response to the IQ set, the name was successfully changed

this.name = name;

So the packet that’s being sent out to the server doesn’t contain the updated name, but only the old name.

The question referenced above already provides a patch to fix this issue and from what I saw in jira, this patch should have been applied at some point.

But I guess it wasn’t applied to master in the end.

Is there any workaround for changing the name of a roster entry at the moment ?

I’d love to provide/apply this patch by the way, but according to Guidelines for Smack Developers and Contributors · igniterealtime/Smack Wiki · GitHub it seems like it’ll take a bit for me to get used to everything since I’m very new to Smack.

Thank you for your guidance

Thanks for reporting SMACK-662. I’ve uploaded a new version of Smack 4.1.1-SNAPSHOT which should fix the issue: Fix RosterEntry.setName(String) · Flowdalic/Smack@26fe968 · GitHub . Could you try and report back if it fixes the issue for you?

1 Like

Thank you Flow. Storing the old name, then rolling back/checking the name in case of an exception is exactly how I would’ve done it .

I’ll try it with 4.1.1-SNAPSHOT asap.

I tested it and now, but the whole Roster isn’t working properly anymore.

At login, a NoResponseException is logged during reload of the roster : in public void reload() ->

public void processException(Exception exception) {
                LOGGER.log(Level.SEVERE, "Exception reloading roster" , exception);
            }

After that, I’m getting the NoResponseException for pretty much every operation on the roster.

I have a very basic ejabberd test server (with pretty much all configuration as per default) and I didn’t change anything on the server between these tests. General communication works fine.

These are the packets logged by my server concerning the first NoResponseException:

<packet or="send" ljid="testuser@192.168.0.12/Smack" ts="20150429T12:05:14"><iq xml:lang='en' id='MQwww-7' type='get'><query xmlns='jabber:iq:roster'/></iq></packet>
<packet or="recv" ljid="testuser@192.168.0.12/Smack" ts="20150429T12:05:14"><iq from='testuser@192.168.0.12' to='testuser@192.168.0.12/Smack' id='MQwww-7' type='result'><query xmlns='jabber:iq:roster'><item subscription='both' name='stevie' jid='testuser2@192.168.0.12'/></query></iq></packet>

This is the corresponding exception on Smack’s side:

org.jivesoftware.smack.SmackException$NoResponseException: No response received within reply timeout. Timeout was 5000ms (~5s). Used filter: IQReplyFilter: iqAndIdFilter (AndFilter: (OrFilter: (IQTypeFilter: type=error, IQTypeFilter: type=result), StanzaIdFilter: id=MQwww-7)), : fromFilter (OrFilter: (FromMatchesFilter (full): null, FromMatchesFilter (ignoreResourcepart): testuser@192.168.0.12, FromMatchesFilter (full): 192.168.0.12)).

Did the filters change between 4.1.0 and Fix RosterEntry.setName(String) · Flowdalic/Smack@26fe968 · GitHub ?

Did the filters change between 4.1.0 and Fix RosterEntry.setName(String) · Flowdalic/Smack@26fe968 · GitHub ?

The changes between 4.1.0 and the HEAD of the 4.1 branch which is what 4.1.1-SNAPSHOT is build from are Comparing 4.1.0…4.1 · Flowdalic/Smack · GitHub

I didn’t spot any change that looked like it could introduce the behavior you are describing. Please see How to ask for help or report an issue · igniterealtime/Smack Wiki · GitHub how you can provide more information which helps to analyze the situation. Ideally you are able to attach a debugger to the (JVM) process running Smack, determine good places for breakpoint(s), set those, and find out e.g. why the filter doesn’t match the stanza.

Ok so it took me quite a long time to figure out that these no response exceptions were actually normal and occurred because the Android debugger is extremely slow, thus the events would simply not fire as expected even after 5 seconds (default packet reply timeout).

Anyway, so the your change does work, but it won’t fire the updated event of the roster listener which it did before (because the new name was set before the result with the old name came back from the server).

It won’t fire because now, once the server acknowledges the new element, it is equalDeep() with the one having the new name.

If I can assume that the event shouldn’t be fired here (after all, it’s the library user setting the name, he knows that it has changed), then all is fine.

However, it might be more logical to fire the event anyway, because the roster has been updated after all, so in that case, you’d either have to fire the event manually after sending the packet:

// ...
// Set the new name, it's important that the value is set before we send the IQ request
this.name = name;
RosterPacket packet = new RosterPacket();
packet.setType(IQ.Type.set);
packet.addRosterItem(toRosterItem(this));
try {
     connection().createPacketCollectorAndSend(packet).nextResultOrThrow();
     roster.fireUpdateEvent(this);
} catch (...) {
     //...
}
// ...

or you could go back to how it was before but use a different item to send the packet:

// ...
// create a new roster item to update the server
RosterItem updatedItem = new RosterItem(...);
RosterPacket packet = new RosterPacket();
packet.setType(IQ.Type.set);
packet.addRosterItem(toRosterItem(updatedItem));
connection().createPacketCollectorAndSend(packet).nextResultOrThrow(); // Set the new name once the result has been received
this.name = name;
// ...

Thank you for your help so far

If I can assume that the event shouldn’t be fired here
Absolutely. There are multiple reasons why the event should be triggered, for example you may want a single callback on which you update your UI.

I’ve replaced the commit with Fix RosterEntry.setNames(String) · Flowdalic/Smack@9cce2b8 · GitHub and uploaded a new snapshot. Please give it a try.

With this fix, everything’s working as expected now .

Thanks again for your help !