I’‘ve discovered that clients all seem to use the element differently. Some of them don’'t use it at all, e.g., PSI. Some send a different thread id with every message, e.g., the RhombusIM client. And a few, Exodus and Tkabber, reuse the thread id that established a chat throughout the chat. The latter appears to be the only kind of client the Chat class likes.
So, two questions (a) what’‘s the “correct” behavior per the spec and (b) what’'s the best way to deal with this range of client element usage.
Note, I’'ve tried using the two parameter Chat() constructor but I still never see another message from clients other than Exodus and Tkabber.
In a few words I can say that the usage of is OPTIONAL. If used, it MUST be unique to that conversation thread. Therefore, Smack keeps a thread ID for each Chat that you create and all the messages that you send as part of the Chat contains the thread ID specified in the Chat.
Right. The problem is that the Chat() class sets up a PacketFilter that filters on either the thread id that the client sent at the beginning of the conversation or the result of the private nextID() method. Since some of the clients don’‘t include that information on subsequent messages the filter’'s accept() method returns false and my code never gets those messages. I think the Chat() class needs a more flexible/reliable filter.
After thinking about this for a while I think the problem could be easily solved by making the Chat’‘s packet collector accessible. Then you could compose additional filters if the standard ThreadFilter doesn’'t meet your needs:
PacketCollector c = chat.getMessageCollector();
PacketFilter f = new OrFilter(c.getPacketFilter(), myfilter);
Seems pretty tightly bound to the chat use-case to me. I haven’‘t played with the GroupChat class yet so I don’‘t know if it’‘s applicable there or not. Regardless I don’‘t know that it’'s applicable at the packet level.
I’‘m not sure if exposing the Chat’‘s MessageCollector is a good idea since anyone can alter the filter to use and I think that it’'s the responsibility of the Chat to resolve its filter.
I also suspect that we only need to handle two well defined filter cases. 1) Filter using the and 2) Filter using the message type=chat and the sender of the message. Since the filter cases are known I don’‘t think that we need to expose the Chat’'s packet collector. Therefore, I can think of two possible solutions:
modify the Chat class so that it always filters the messages using these two defined filters
be able to configure the Chat in order to use any of these filters
That works for me too. To make sure I implemented a MessageTypeFilter and modified the Chat class per your possible solution #1. That got me all the messages my client sent. Since that approach seems to cover the bases I don’'t see any need to complicate the Chat interface with filter configuration methods.
If you’‘re interested in the code I’‘ll be happy to ZIP it up and send it to you. It’'s pretty simple but might save you a few minutes of typing and testing.
We have to be careful that we solve this problem the right way. For example, it’‘s perfectly legit to have two different s running between the same users. It seems strange to me that if a new message comes through without a id that it would be delivered to both Chat objects (assuming there are two active Chat objects going between the users with different thread ID’‘s). Doesn’‘t it seem better if the message was only delivered to one Chat? Maybe the newest one? To solve the problem this way, we’‘d need to keep an internal list of all Chat objects created and then be able to traverse them to figure out where to deliver errant Message packets. Does this seem like a good approach, or is it just making things more complicated than they should be. I’'m all for simplicity if it makes sense.