Search code examples
ejabberdsmack

Static instance of AbstractXmppConnection : slow delivery of messages to ejabberd


I am shooting messages (automated) from smack library (Java) into Ejabberd. How its being done:-

-static object of AbstractXmppConnection is made for one user - with every api hit, post connection, a message is sent to Ejabberd via the connection

Issue: there are around 400 consecutive hits on Java Play Framework from python script. The scrip and the api runs fine, checked via logs. The issue is messages reach the users with delay. between 2 message shoot, there is around one minute delay. If i check the mysql database, archive table, there is only 1 entry for first hit and consecutive entries come very slowly.

However, if I make AbstractXmppConnection an instance of class and follow connect, shootMessage and disconnect flow for every hit, the messages are sent instantly. But connecting and disconnecting same account so fast increases load on Ejabberd.

Question: why is same (static) object of AbstractXmppConnection when reused to send multiple messages very slow in delivering messages? when I have to make new instances with every api hit, its fast

code (multiple instance: works fast but increases load because of connect/disconnect frequency):

public synchronized void sendMessage(String senderId,String receiverId, String SERVER, Message message) throws IOException, XMPPException, SmackException {
+        Logger.debug("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@SENDING MESSAGE TO "+receiverId + " from "+senderId+ " Message "+message.toXML().toString());
+
+        AbstractXMPPConnection abstractXMPPConnection;
+
+        //Making connection
+        EjabberdConnectionQuote ejabberdConnection = new EjabberdConnectionQuote();
+        abstractXMPPConnection = ejabberdConnection.getConnection();
+        abstractXMPPConnection.login(senderId,"secret");
+
+        //Create chat
+        Chat chat = null;
+        ChatManager chatManager = null;
+        chatManager = ChatManager.getInstanceFor(abstractXMPPConnection); //$$$$$NEW INSTANCE$$$$
+        chat = chatManager.createChat(receiverId + SERVER);
+        chat.sendMessage(message);
+
+        abstractXMPPConnection.disconnect();
+
+        if (abstractXMPPConnection.isConnected() ){
+            Logger.info("Still Connected");
+        }else{
+            Logger.info("<---------Disconnected------->");
+        }
+ }

code(static connection object reused for all api hits, mimicing one user and shooting to many users in Roster):

 AbstractXMPPConnection abstractXMPPConnection;
+        SingletonConnection obConn = SingletonConnection.getInstance();
+        if ( obConn.connectionMap.containsKey(senderId) ) {
+            Logger.info("Already Connected");
+            //Remove and update timer
+            obConn.updateTimer(senderId);
+            abstractXMPPConnection = obConn.connectionMap.get(senderId).abstractXMPPConnection;

+        }else{
+            Logger.info("Creating new connection");
+            //Create new connection and put it in map
+            EjabberdConnectionQuote ejabberdConnection = new EjabberdConnectionQuote();
+            abstractXMPPConnection = ejabberdConnection.getConnection();
+            abstractXMPPConnection.login(senderId,"secret");
+            RemoveConnectionTimer removeConnectionTimer = new RemoveConnectionTimer(senderId);
+            StoreData storeData = new StoreData(senderId,abstractXMPPConnection,removeConnectionTimer);
+            obConn.connectionMap.put(senderId,storeData);
+
+        }



 Message message = createMessage(quote, returnDateInIst(), senderId, receiverId);
         String key = receiverId + "$$$" + senderId;

-        SingletonConnection.getInstance().sendMessage(senderId,receiverId,SERVER,message);
+        Chat chat = null;
+        ChatManager chatManager = null;
+        chatManager = ChatManager.getInstanceFor(abstractXMPPConnection); //$$$$$REUSE EXISTING connection$$$$
+        chat = chatManager.createChat(receiverId + SERVER);
+        chat.sendMessage(message);
+
+        //abstractXMPPConnection.disconnect();
+
+        if (abstractXMPPConnection.isConnected() ){
+            Logger.info("Still Connected");
+        }else{
+            Logger.info("<---------Disconnected------->");
+ }

Solution

  • After much logging and checking smack source code, I could find the reason.

        chatManager = ChatManager.getInstanceFor(abstractXMPPConnection); 
        chat = chatManager.createChat(receiverId + SERVER);
        chat.sendMessage(message);
    

    the above code snippet returns an object of chat which can be accessed only by the thread on which abstractXMPPConnection object of instantiated . If object is accessed from other thread, it is null.