Java MessageListener未侦听Oracle队列中的消息

Java MessageListener未侦听Oracle队列中的消息,java,jakarta-ee,jms,advanced-queuing,Java,Jakarta Ee,Jms,Advanced Queuing,我已经实现了Oracle高级队列&我正在编写一个侦听程序。以下是我的样本: 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.Exc

我已经实现了Oracle高级队列&我正在编写一个侦听程序。以下是我的样本:

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); 
     }
}
}

请注意,此程序是一个独立程序,它将继续运行并侦听oracle队列中的消息

不幸的是,当我为这个类文件创建一个jar并运行它时,它只是运行然后退出并只消耗队列中的一条消息。为什么侦听器不继续运行&侦听队列

我以为它会继续侦听并检索队列中的所有消息,然后永远保持侦听模式,但它的行为不是这样的

如果有人能告诉我出了什么问题,我将不胜感激


感谢

下面是另一个JMS示例如何循环处理多条消息的示例

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.
您可能不需要在while循环中包装此代码。这取决于JMS如何让您处理连接和会话对象,以及它们是否自动关闭,但您可以尝试将其包装起来

while(true) {
       QCon.start();

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

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

       consumer.close();
}

这都是因为您在启动后立即关闭了连接/会话。您需要该进程启动一个守护进程线程,该线程在JVM中永远运行。JMS不负责保持JVM运行。您需要创建一个刚刚休眠的线程来完成此任务。

尝试将所有代码从Try块的开头包装到块的结尾,并保留一段时间(true),以便在它使用消息后,再次运行所有队列设置并等待另一条消息。我认为您可能必须在处理每条消息之后创建该会话,因为它是主会话。这可能不是永久的解决方案,但它可能暂时还可以。@Logan,你指的是哪个try block?是主方法的吗?是的,对不起。在main方法中,我会把它放在Queue Queue之前,在main方法中的catch块之后,基本上包装所有代码。只是想看看它是否一开始运行不止一次,然后你就可以确定是否有任何代码可以被提取出来并且只执行一次。如果我把这个while循环放进去,需要CPU吗???当队列中没有消息时会发生什么?需要CPU吗?我不这么认为。您可以查看流程监视器以查看流程是否执行任何操作,但这几乎是任何流程都执行的操作。我认为当您设置侦听器时,代码会在此时等待消息,但实际上并没有完成while循环。您的问题是,一旦消息传入,它将运行其余代码并关闭。这个循环应该重置监听器,这样一旦它处理完,就可以进行另一个循环了。我能够在不使用while循环的情况下检索队列中的所有消息。我刚刚对Consumer.close()、session.close()和Qcon.close()行进行了注释&它现在可以工作了。但问题是它是否正确&我如何知道它占用了多少内存?有一个很好的工具可以监视javajkd中包含的任何java进程。它叫jconsole。如果你在程序运行时启动它,你可以连接到进程,查看它在运行时使用了多少内存和cpu。一旦创建了线程,它应该什么时候进入睡眠状态?你能为我的上述代码提供一个例子吗?