2

I have made a simple client using SMACK api and OpenFire on localhost. As of now, I have two users say X and Y. Whenever anyone logs in to the client, there is a send button which sends a message to user Y. I've checked the XMPP debug manager and I'm able to send/receive messages there. However, I'm unable to display those messages in a JLabel that I have alloted for displaying the messages. If the User Y hits the send button, as per the functionality it sends a message to himself and that comes up on the JLabel. But when user X hits the send button, the message is received, however it is not displayed/updated on the Y's JLabel.

Interestingly, everything works as it should with gtalk configuration.

The structure is as follows:

WelcomeUser.java: Is the welcome form with username and password prompt. On hitting the login button : it sets the ChatBoard class visible and passes on the username password to the constructor of ChatBoard. Code:

chBoard=new ChatBoard(username.getText(),password.getText());
                chBoard.setVisible(true);
                setVisible(false);

Here is the code for ChatBoard.java:

import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Collection;

import javax.swing.GroupLayout;
import javax.swing.GroupLayout.Alignment;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.LayoutStyle.ComponentPlacement;
import javax.swing.border.EmptyBorder;

import org.jivesoftware.smack.Chat;
import org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.MessageListener;
import org.jivesoftware.smack.Roster;
import org.jivesoftware.smack.RosterEntry;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.packet.Message;

public class ChatBoard extends JFrame implements MessageListener {

    private static final long serialVersionUID = 1L;
    private JPanel contentPane;
    static String username, password;
    static XMPPConnection connection;
    private JTextField textField;
    static JLabel board = new JLabel("");
    static Chat chat;

    public void sendChat() {
        try {
            chat = connection.getChatManager().createChat(
                    "userY@my-pc/Smack", this);
            chat.sendMessage("Hello, This is " + username);
        } catch (XMPPException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }


    /**
     * Create the frame.
     */
    public ChatBoard(String user, String pass) {

        username = user;
        password = pass;

        ////  
                   ///JFrame creation code ommited for this thread.
        // ////////////////////////////////////////////

        XMPPConnection.DEBUG_ENABLED = true;

        ConnectionConfiguration config = new ConnectionConfiguration(
                "127.0.0.1");


        connection = new XMPPConnection(config);

        try {
            connection.connect();
            System.out.println("Connected...");
        } catch (XMPPException e) {

            e.printStackTrace();
            System.out.println("Not Connected. Error :" + e.getMessage());
        }

        try {
            connection.login(username, password);
            System.out.println("Logged in...");
        } catch (XMPPException e) {

            e.printStackTrace();
            System.out.println("Not Logged in. Error :" + e.getMessage());
        }

        Roster roster = connection.getRoster();
        Collection<RosterEntry> entries = roster.getEntries();

        System.out.println("\n\n" + entries.size() + " buddy(ies):");
        for (RosterEntry r : entries) {
            System.out.println(r.getUser());
        }

        // /////////////////////////////////

    }

    @Override
    public void processMessage(Chat arg0, Message arg1) {
        // TODO Auto-generated method stub

        board.setText(board.getText() + arg1.getBody());
        System.out.println(arg1.getFrom() + ":" + arg1.getBody().toString());

    }

}

I'm new to this, so forgive me if there are any silly mistakes. Your help would be really appreciated.

Misc. Details: OpenFire 3.7.1 on localhost with SMACK 3.2.2

harsh8888
  • 477
  • 9
  • 22

3 Answers3

1

Have a look at the bottom of http://www.igniterealtime.org/builds/smack/docs/latest/documentation/messaging.html. For incoming chats from another user you have to override ChatManagerListener

Can you set a breakpoint on processMessage and does it hit that breakpoint? If so it might just be a matter of making sure the:

board.setText()

occurs on the Swing event dispatch thread

So try making your processMessage like this :

@Override
public void processMessage(Chat arg0, Message arg1) {
    // TODO Auto-generated method stub

    try
    {
        SwingUtilities.invokeAndWait(new Runnable()
        {

            @Override
            public void run()
            {
                board.setText(board.getText() + arg1.getBody());
            }
        });
    }
    catch (InvocationTargetException e)
    {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    catch (InterruptedException e)
    {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    System.out.println(arg1.getFrom() + ":" + arg1.getBody().toString());

}
alex.p
  • 2,627
  • 17
  • 28
  • Hello, thank you for replying. I tried the code you gave and same thing persists. I only get the console output for user Y hitting the send button. Interestingly everything works very well when working when communicating with gtalk client :-/ I'm unable to figure out what is wrong – harsh8888 Dec 13 '12 at 11:15
  • 1
    Have a look at the bottom of http://www.igniterealtime.org/builds/smack/docs/latest/documentation/messaging.html. For incoming chats from another user you have to override ChatManagerListener – alex.p Dec 13 '12 at 11:44
  • Cool i'll put my comment in the answer. – alex.p Dec 13 '12 at 12:58
  • Hi alex. I'm receving messages bidirectionally and are logged in my console. However the JLabel is displaying the messages which are received only once! Putting up your code gives me error saying :Cannot refer to a non-final variable message inside an inner class defined in a different method and the suggested fix is turning Message message to final, which I suppose is not advisable. Any comments? – harsh8888 Dec 13 '12 at 13:31
  • Almost all the problem is solved except updating the JLabel with the received message. – harsh8888 Dec 13 '12 at 13:40
  • Normally the only way to use a variable within an anonymous class is to make it final. There's nothing wrong with making stuff final ideally if the variable is never going to get changed - make it final. If you don't want to make it final then you'd have to create another class that implemented runnable rather than use the anon class – alex.p Dec 13 '12 at 14:14
  • Made it final. Doesn't seem to have any change. Only the first message received is updated on the JLabel. Messages following are not getting updated, however are getting properly logged in the console. – harsh8888 Dec 13 '12 at 16:20
  • Create a new class that implements runnable and the only thing it does should be 'board.setText(board.getText() + arg1.getBody());' within it's run method, then you can remove the final – alex.p Dec 13 '12 at 18:01
  • Hey alex I tweaked in something and it is working now. The tweak wasn't really something substantial. But thanks a lot for your help. I appreciate it! Didn't create a new class. Somehow it is working now. – harsh8888 Dec 13 '12 at 18:10
0

I added this code in chatBoard just at the end of the constructor mentioned in my code and it seems to work now :-) Thanks alex.p!

connection.getChatManager().addChatListener(new ChatManagerListener() {



                public void chatCreated(final Chat chat, final boolean createdLocally) {

                    chat.addMessageListener(new MessageListener() {



                        public void processMessage(Chat chat, Message message) {

                            //JOptionPane.showMessageDialog(null, "Rec: For " + chat.getParticipant() + " from " + message.getFrom() + "\n" + message.getBody());

                            String sender=message.getFrom();

                            String senderNames=sender;

                            System.out.println("Received message: " + (message != null ? message.getBody() : "NULL"));

                            board.setText(board.getText()+"\n "+ message.getFrom()+" : "+ message.getBody());
                            //PrivateChatManager.receiveMessage(sender, senderNames, message.getBody());



                        }

                    });

                }
        });
harsh8888
  • 477
  • 9
  • 22
0

Hope this code can help you:

public void processMessage(Chat aChat, Message aMessage) {

    final XmppBot bot = this.xmppBot;
    final Chat chat = aChat;
    final Message message = aMessage;

    log.debug("message received, type {}", message.getType().toString());


    if (message.getBody() != null) {

        Runnable runnable = new Runnable() {

            public void run() {

                Thread.currentThread().setName("Chat: "+chat.getParticipant()+ " Message: "+ message.getBody());

                PrintWriter threadPrintWriter = null;

                threadPrintWriter = new PrintWriter(new ChatWriter(chat));

                bot.getContext().setChat(chat);
                bot.getContext().setPrintWriter(threadPrintWriter);

                bot.processCommand(message.getBody());

                bot.getContext().removeMultiUserChat();
                bot.getContext().removePrintWriter();

            }
        };

        Thread t = new Thread(runnable);
        t.start();
    }

}
Coillu
  • 1
  • 1