简体   繁体   中英

Unable to receive Message using Smack (Java)?

I am trying to setup a simple example for sending and receiving messages with Smack API using Openfire. I have followed this tutorial

Someone asked the same question about the situation here , but the answer mentions the code which I am already using for receiving the chat. Many of these examples using the same method as well.

public class Receiver {

    public static void main(String a[]) throws XMPPException, InterruptedException {
        XMPPConnection connection = new XMPPConnection("192.168.1.38");
        System.out.println(connection);
        connection.connect();


        connection.login("test2", "123456");
        EFLogger.LogInfo("Receiver", "Connected [ " + connection.isConnected() + " ]");

        connection.getChatManager().addChatListener(new ChatManagerListener() {
            public void chatCreated(Chat chat, boolean b) {
                System.out.println("In Message Listener ! ");
                chat.addMessageListener(new MessageListener() {
                    public void processMessage(Chat chat, Message message) {
                        System.out.println("Message [ " + message.toXML());
                    }
                });
                try {
                    chat.sendMessage("Hello");
                } catch (XMPPException e) {
                    e.printStackTrace();
                }
            }
        });


        while (true) {

        }
    }
} 

For sending, I am using

public class Main {

    public static void main(String[] args) throws Exception {

        String username = "test";
        String password = "123456";

        XmppManager xmppManager = new XmppManager("192.168.1.38", 5222);

        xmppManager.init();
        xmppManager.performLogin(username, password);
        xmppManager.setStatus(true, "Hello everyone");

        //As @MrPk suggested I shouldn't use "/Smack"
        //String buddyJID = "test2@ef-app2/Smack";

        String buddyJID = "test2@ef-app2";
        String buddyName = "test";
        xmppManager.createEntry(buddyJID, buddyName);


        for (int i = 0; i < 10; i++) {
            xmppManager.sendMessage("Hello mate from test " + i, "test2");
        }

        boolean isRunning = true;

        while (isRunning) {
            Thread.sleep(50);
        }

        xmppManager.destroy();

    }
} 

and this class is XMPPManager

/**
   This class is responsible for handling all Actions related to Chat    Management. Connection, Login, Status, Create Entry and Message Listener.
*/
public class XmppManager {

    private static final int packetReplyTimeout = 500; // millis

    private String server;
    private int port;

    private ConnectionConfiguration config;
    private XMPPConnection connection;

    private ChatManager chatManager;
    private MessageListener messageListener;


    public XmppManager(String server, int port) {
        this.server = server;
        this.port = port;
    }

    public void init() throws XMPPException {

        EFLogger.LogInfo("XmppManager", String.format("Initializing connection to server %1$s port %2$d", server, port));

        SmackConfiguration.setPacketReplyTimeout(packetReplyTimeout);
//        SmackConfiguration.DEBUG = true;
        config = new ConnectionConfiguration(server, port);
        config.isDebuggerEnabled();

        connection = new XMPPConnection(config);
        connection.connect();

        EFLogger.LogInfo("XmppManager", "Connected: " + connection.isConnected());

        chatManager = connection.getChatManager();
        //messageListener = new MyMessageListener();

    }

    public void performLogin(String username, String password) throws XMPPException {
        if (connection != null && connection.isConnected()) {
            EFLogger.LogInfo("XmppManager", "Before login userName [ " + username + " ] password [ " + password + " ]");
            connection.login(username, password);
            System.out.printf("Logged in ");

        }
    }

    public void setStatus(boolean available, String status) {

        Presence.Type type = available ? Type.available : Type.unavailable;
        Presence presence = new Presence(type);

        presence.setStatus(status);
        connection.sendPacket(presence);

    }

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

    public void sendMessage(String message, String buddyJID) throws XMPPException {
        EFLogger.LogInfo("XmppManager", String.format("Sending mesage '%1$s' to user %2$s", message, buddyJID));
        Chat chat = chatManager.createChat(buddyJID, messageListener);
        chat.sendMessage(message);
    }

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

    static class MyMessageListener implements MessageListener {

        public void processMessage(Chat chat, Message message) {
            String from = message.getFrom();
            String body = message.getBody();
            EFLogger.LogInfo("XmppManager", String.format("Received message '%1$s' from %2$s", message.getError(), from));
        }

    }

}

First I thought there must be a problem with buddyID, I have these two users test and test2 and XMPPdomain is ef-app2 so I set the buddyJID test2@ef-app2/Smack smack is default resource.

Edit

@MrPk suggested shouldn't use /Smack , but no luck.

but still, it has no impact I am still unable to receive any message. I am not sure what I am missing. If you are interested in reproducing the same issue, you can find the IntelliJ IDEA project here you can get some more details about the issue here

Help!

When I started my chat application I used the same tutorial. It's more or less a good tutorial but really minimalist: let's check point by point major improvements and errors to fix.

Before start, you'll need 2 users: you'll can send from test2@ef-app2 messages to itself (you'll can do only with Broadcast, but it's too adavanced topic). Just register also the second user on your server.

So you'll need test1@ef-app2 (to chat with) and test2@ef-app2 (login in your app).

First of all, I suggest you to install Spark client on your machine. So you'll be able to have a client that "works for sure" and you'll be able to chat with yourself between Spark and your java application in real time, of course using 2 users. I liked Spark because it has a great debugger that allows you to check Stanzas sended and received, so basically when you don't know if you are right, just check what Spark does.

XmppManager

SmackConfiguration.setPacketReplyTimeout(3000); //default

Don't reduce default timeout. I started with 50000, now I have a 7000 (that means 7 seconds).

Before or later you'll need to improve Configuration of connection, more or less like this:

protected XMPPTCPConnectionConfiguration config;
protected AbstractXMPPConnection connection;

this.config = XMPPTCPConnectionConfiguration.builder()
                .setServiceName(serviceName)  //Often is NOT the IP address of Host
                .setHost(server)
                .setPort(port)
                .setSecurityMode(SecurityMode.disabled) //if you don't need
                .setDebuggerEnabled(true)  //really helpfull
                .build();


this.connection = new XMPPTCPConnection(config);
this.connection.connect();

To connect to server without provide user, password and Resource.

Pay attention: config.isDebuggerEnabled(); it's a get, not a set (so you are not enabling it but just cheking...)

To login, I suggest to set a custom Resource idenitifier (there is something that brokes without or with default one) like this -> avoid "Smack" and "Spark" to debug better. Use something like "MyApp".

connection.login(username, password, "MyApp");  

ChatManagerListener - ChatMessageListener

Basic idea is: everytime you start a chat between "me" and "another person", client app has to add a listener for incoming messages of "another person". So you have to add a Listener to ChatManager that manages... single chat listeners. I'll show you "basic all anonymous" version, you'll can split in single defined classes if you'll like.

//add to ChatManager a listener to manage incoming "person"
        ChatManager.getInstanceFor(connection).addChatListener(
                new ChatManagerListener() {
                    @Override
                    public void chatCreated(Chat chat, boolean createdLocally)
                    {
//if it's the first message in session between 2 users
                        if (!createdLocally)
                        {
//add a listeners for those message just once
                            chat.addMessageListener(new ChatMessageListener()
                            {

                                @Override
                                public void processMessage( Chat arg0, Message arg1 )
                                {
//example to read something in standard output
                                    String from = message.getFrom();
            String body = message.getBody();

            if (body != null)
            {
                System.out.println(String.format("============ Received message '%1$s' from %2$s\n============", body, from));
            }
            else
            {
                System.out.println("SYSTEM: ping (body null)");
            }
                                }
                            };
                        }
                    }
                }); 

Main (Chat Application)

Basically you'll have to wait a little more before destroy the client. If you'll have user "test2" connected to server "ef-app2" with a standalone client like Spark I mentonied before, you'll check easly if you received any message. Main will looks like:

xmppManager.performLogin("test2@ef-app2", "123456". "MyApp");
xmppManager.createEntry("test1@ef-app2", "My friend"); //test1 ONE! 

xmppManager.sendMessage("Hello world", "test1@ef-app2");


    boolean isRunning = true;

    while (isRunning) {
        Thread.sleep(50000);
        i++;

        if (i > 2)
        {
            //xmppManager.performLogout();
            isRunning = false; 
             xmppManager.destroy();
        }
    }

Finally

Check in both debug what happenned and what is the final XML sended and received. You'll can compare with Spark one. If default message will not works, try this code:

Message message = new Message();
        message.setBody(body);
        message.setType(Message.Type.chat);
        message.setTo("test2@ef-app2");
        message.setFrom("test1@ef-app2");
        try {
            connection.sendStanza(message);
        } catch (NotConnectedException e) {
            System.out.println("Not connected!");
        }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM