MessageListener not listening to messages in Oracle Queue

6.5k views Asked by At

I've Oracle Advanced Queue implemented & I'm writing a listener program. Below is my sample:

package com.myprog;

import java.io.File;
import java.io.FileInputStream;
import java.io.StringWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.util.Properties;

import javax.jms.ExceptionListener;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageListener;
import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.Session;
import javax.jms.TextMessage;

import oracle.jms.AQjmsFactory;
import oracle.jms.AQjmsSession;

import org.apache.log4j.Logger;

public class abc implements MessageListener, ExceptionListener {
private static String queueUserName = "admin";
private static String queueName = "my_queue";

// Initialize the logger
private static Logger log = Logger.getLogger(abc.class);

public static void main(String[] args) {
    final String METHOD_NAME  = "main()";

    abc a = new abc();              

      Queue queue;
      try {
       QueueConnection QCon = getConnection();  
       Session session = QCon.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
       QCon.start();

       queue = ((AQjmsSession) session).getQueue(queueUserName, queueName);
       MessageConsumer consumer = session.createConsumer(queue);       

       consumer.setMessageListener(a);
       QCon.setExceptionListener(a);

       consumer.close();
       session.close();
       QCon.close();
      } catch (JMSException e) {  
       e.printStackTrace();
      }         

}

public static QueueConnection getConnection() {
  String hostname = "myhost";
  String oracle_sid = "mysid";
  int portno = 1521;
  String userName = "myapp";
  String password = "pwd";
  String driver = "thin";
  QueueConnectionFactory QFac = null;
  QueueConnection QCon = null;
  try {
   // get connection factory , not going through JNDI here
   QFac = AQjmsFactory.getQueueConnectionFactory(hostname, oracle_sid, portno,driver);

   // create connection
   QCon = QFac.createQueueConnection(userName, password);
   } catch (Exception e) {
    e.printStackTrace();
  }
  return QCon;
}

@Override
public void onException(JMSException e) {
    log.error(e);       
}

@Override
public void onMessage(Message message) {
     TextMessage msg = (TextMessage) message;

     try {
         String m = msg.getText();
         System.out.println("m="+m);
         log.info("MESSAGE RECEIVED " + m);
     } catch (JMSException e) {
        log.error(e); 
     }
}

}

Please note that this program is a standalone program which will keep running & listening to messages in oracle queue.

Unfortunately, when I create a jar of this class file & run it, it just runs & then exits & consumes only 1 message in the queue. Why the listener not keep on running & listening to queue?

I thought it'll keep listening & retrieve all the messages in the queue & then will remain in listen mode forever, but its not behaving that way.

Appreciate if some one can tell me what's going wrong.

Thanks

2

There are 2 answers

5
Logan On BEST ANSWER

Here's an example of how another JMS example loops to process multiple messages.

Performs a JNDI lookup of the ConnectionFactory and Destination.
Creates a Connection and a Session.
Creates a MessageConsumer:

consumer = session.createConsumer(dest);
Starts the connection, causing message delivery to begin:

connection.start();
Receives the messages sent to the destination until the end-of-message-stream control message is received:

while (true) {
  Message m = consumer.receive(1);
  if (m != null) {
    if (m instanceof TextMessage) {
      message = (TextMessage) m;
      System.out.println("Reading message: " +
        message.getText());
    } else {
      break;
    }
  }
}

Because the control message is not a TextMessage, the receiving program terminates the while loop and stops receiving messages after the control message arrives.
Closes the connection in a finally block, automatically closing the session and MessageConsumer.

You may be able to get away with just wrapping this code in the while loop. It depends on how JMS makes you handle the connection and session objects and if they automatically close, but you can try to wrap just this.

while(true) {
       QCon.start();

       queue = ((AQjmsSession) session).getQueue(queueUserName, queueName);
       MessageConsumer consumer = session.createConsumer(queue);       

       consumer.setMessageListener(a);
       QCon.setExceptionListener(a);

       consumer.close();
}
1
John Ament On

It's all because you're closing your connection/session immediately after starting up. YOu need the process to start off a daemon thread that runs forever in the JVM. JMS is not responsible for keeping the JVM running. You would need to create a thread that just slept to accomplish that.