4
votes

I've been struggling with XMPP chatting a lot through Smack and Openfire server. My problem is as follows:

Whenever a user sends a message to another user, the message is received correctly at the other user. But any reply doesn't show up at the sender of the first message. So User 1 sends to User 2 successfully. User 2 is then unable to send to User 1 any reply. On the other hand, if I restart and let the users login again, User 2 can send to User 1 but not vice versa.

What I'm trying to say is that only the initiator of the chat can send a message, the receiver cannot reply back.

My code looks like this

    package xmpp;


public class XMPPClient{

private static final int packetReplyTimeout = 500; // millis
private XMPPConnection connection;
private ChatManager chatManager;
private MessageListener messageListener;
private ConnectionConfiguration config;
private MyTimer t = MyTimer.getInstance();
private ArrayList<String> threadPool = new ArrayList<String>();

public XMPPClient()
{
    SmackConfiguration.setPacketReplyTimeout(packetReplyTimeout);

    //define openfire server information

    config = new ConnectionConfiguration("localhost",5222);
    config.setSASLAuthenticationEnabled(false);
    config.setSecurityMode(SecurityMode.disabled);

    connection = new XMPPConnection(config);

    //connect to server
    t.start("Connecting to server...");
    try {
        connection.connect();
    } catch (XMPPException e) {
        System.err.println("Failed to connect to server! Connect to VPN!\t"+e.getMessage());
        System.exit(0);
    }
    t.end("Connection took ");

    //setup chat mechanism
    chatManager = connection.getChatManager();
    chatManager.addChatListener(
            new ChatManagerListener() {
                @Override
                public void chatCreated(Chat chat, boolean createdLocally)
                {
                    if (!createdLocally)
                        chat.addMessageListener(new MyMessageListener());
                }
    });
}
public boolean login(String userName, String password, String resource) {       
    t.start("Logging in...");
    try {
        if (connection!=null && connection.isConnected()) 
            connection.login(userName, password, resource);
        //set available presence
        setStatus(true);
    } 
    catch (XMPPException e) {
        if(e.getMessage().contains("auth")){
            System.err.println("Invalid Login Information!\t"+e.getMessage());
        }
        else{
            e.printStackTrace();
        }
        return false;
    }
    t.end("Logging in took ");
    return true;
}
public void setStatus(boolean available) {
    if(available)
        connection.sendPacket(new Presence(Presence.Type.available));
    else
        connection.sendPacket(new Presence(Presence.Type.unavailable));
}

public void sendMessage(String message, String buddyJID) throws XMPPException {
    System.out.println(String.format("Sending mesage '%1$s' to user %2$s", message, buddyJID));
    boolean chatExists = false;
    Chat c = null;
    for(String tid : threadPool)
    {
        if((c = chatManager.getThreadChat(tid)) != null)
        {
            if(c.getParticipant().equals(buddyJID))
            {
                if(checkAvailability(buddyJID))
                {
                    chatExists = true;
                    break;
                }
                else
                {
                    threadPool.remove(tid);
                    break;
                }
            }
        }
    }
    if (chatExists)
    {
        Chat chat = c;
        chat.sendMessage(message);
    }
    else
    {
        Chat chat = chatManager.createChat(buddyJID, messageListener);
        threadPool.add(chat.getThreadID()); System.out.println(chat.getThreadID());
        chat.sendMessage(message);
    }
}

public void createEntry(String user, String name) throws Exception {
    System.out.println(String.format("Creating entry for buddy '%1$s' with name %2$s", user, name));
    Roster roster = connection.getRoster();
    roster.createEntry(user, name, null);
}

public boolean checkAvailability(String jid)
{
    System.out.print("Checking availability for: "+jid+"=");
    System.out.println(connection.getRoster().getPresence(jid).isAvailable());
    return connection.getRoster().getPresence(jid).isAvailable();
}

public void disconnect() {
    if (connection!=null && connection.isConnected()) {
        setStatus(false);
        connection.disconnect();
    }
}

}

import org.jivesoftware.smack.packet.Message;

public class MyMessageListener implements MessageListener {
@Override
public void processMessage(Chat chat, Message message) {
    String from = message.getFrom();
    String body = message.getBody();
    System.out.println(String.format("Received message '%1$s' from %2$s", body, from));
}

}

I'm not sure what the problem is. Any suggestions? Sample code?

Thanks <3

3
How about providing the relevant code here that actually sends and receives (as concise as possible). We don't all want to read through an entire blog with snippets of code littered throughout.Robin

3 Answers

2
votes

I am not sure if this will help you but I can get reply with this code:

public void chat(String AddressedUser) throws NotConnectedException {
    //Create username whom we want to send a message
    String userToSend = AddressedUser + "@" + serverDomain;

    ChatManager chatmanager = ChatManager.getInstanceFor(connection);
    Chat newChat = chatmanager.createChat(userToSend , new MessageListener() {
        @Override
        public void processMessage(Chat chat, Message message   ) {
            // TODO Auto-generated method stub
            System.out.println("Received message: " + message);

        }
    });

    try {
        newChat.sendMessage("Hey");
    }
    catch (XMPPException e) {
        System.out.println("Error Delivering block");
    }

}

I am sending "Hey" then what ever other user writes I will see in my logcat.

1
votes

You haven't specified what the receiver is, for instance, if it is an existing client (like Spark for instance), or more custom code. This would be helpful, as would knowing what version of Smack you are using.

That particular code has several issues with it.

  • It keeps creating new Chat objects for every message sent, instead of simply reusing the same chat.
  • There is no ChatManagerListener registered to handle new Chat messages that are not tied to an existing chat.
0
votes

the is code is very complicated and it seems is meant only to send msgs. Here is a sample code that works perfectly, both sending and receiving:

http://www.javaprogrammingforums.com/java-networking-tutorials/551-how-write-simple-xmpp-jabber-client-using-smack-api.html