运行时没有onMessage事件(Oracle队列上的Java JMS MessageListener)

时间:2018-11-09 10:13:18

标签: java oracle queue jms listener

目的

我创建了MyListener.java来监视我的Oracle队列MY_QUEUE,并且MyConsumer.java实现了自己的MessageListener.onMessage功能。
一旦将一些条目排队到MY_QUEUE中,我希望MessageListener将“ New Message ...”输出到控制台。

问题

仅在初始应用程序启动时才处理队列条目。如果在应用程序已经运行时将其他条目排入队列,则不会触发MessageListener.onMessage函数。

示例

  1. 运行应用程序,队列中已有5个条目。输出:

      

    已初始化...
      睡觉...
      新消息...
      新消息...
      新消息...
      新消息...
      新消息...
      睡觉...
      睡觉...

  2. 退出应用程序并运行该应用程序。使条目在运行时入队。输出:

      

    已初始化...
      睡觉...
      睡觉...
      睡觉...
      正在睡觉...(此时已插入队列条目)
      睡觉...
      睡觉...
      睡觉...
      睡觉...

  3. 退出应用程序,然后再次运行该应用程序(2中的条目仍在队列中)。输出:

      

    已初始化...
      睡觉...
      新消息...
      新消息...
      新消息...
      新消息...
      新消息...
      睡觉...
      睡觉...

MyListener

package example;

import javax.jms.JMSException;
import javax.jms.MessageConsumer;
import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueSession;
import javax.jms.Session;

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

public class MyListener {

    private static final String QUEUE_NAME = "MY_QUEUE";
    private static final String QUEUE_USER = "myuser";
    private static final String QUEUE_PW = "mypassword";
    private QueueConnection queueConnection;
    private QueueSession queueSession;

    public MyListener() throws JMSException {
        QueueConnectionFactory QFac = AQjmsFactory.getQueueConnectionFactory("xxx.xxx.xxx.xxx", "orcl", 1521, "thin");
        this.queueConnection = QFac.createQueueConnection(QUEUE_USER, QUEUE_PW);
        this.queueSession = this.queueConnection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
    }

    public static void main(String[] args) {

        try {
            MyListener myListener = new MyListener();
            Queue queue = ((AQjmsSession) myListener.queueSession).getQueue(QUEUE_USER, QUEUE_NAME);

            MessageConsumer mq = ((AQjmsSession) myListener.queueSession).createReceiver(queue);
            MyConsumer mc = new MyConsumer();
            mq.setMessageListener(mc);

            myListener.queueConnection.start();

            System.out.println("Initialized...");

            while (true) {
                try {
                    System.out.println("Sleeping...");
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        } catch (JMSException e) {
            e.printStackTrace();
        } finally {
            System.out.println("Application closed");
        }

    }

}

MyConsumer

package example;

import javax.jms.Message;
import javax.jms.MessageListener;

public class MyConsumer implements MessageListener{

    @Override
    public void onMessage(Message arg0) {
        System.out.println("New Message...");

    }

}

PL / SQL脚本使条目入队

DECLARE
   msg                  SYS.aq$_jms_text_message;
   enqueue_options      DBMS_AQ.ENQUEUE_OPTIONS_T;
   message_properties   DBMS_AQ.MESSAGE_PROPERTIES_T;
   message_handle       RAW (16);
   i                    NUMBER;
BEGIN
   msg := sys.aq$_jms_text_message.construct;
   msg.set_text ('Testmessage');
   enqueue_options.visibility := DBMS_AQ.immediate;
   message_properties.priority := 1;
   i := 0;

   WHILE i < 5
   LOOP
      DBMS_AQ.enqueue (queue_name           => 'MY_QUEUE',
                       enqueue_options      => enqueue_options,
                       message_properties   => message_properties,
                       payload              => msg,
                       msgid                => message_handle);
      i := i + 1;
   END LOOP;

   COMMIT;
END;

其他信息

数据库:Oracle 11g2
Java运行时:1.6
Maven依赖关系:

  • oracle-jdbc(11.2.0.4.0)
  • xdb(1.0)
  • aqapi(1.3)
  • jmscommon(1.3.1_02)

有人可以告诉我为什么我在运行时将新条目加入队列后为什么onMessage函数不会被触发吗?

编辑:好的,我停止使用JMS,现在使用旧的AQ出队方法来异步获取消息。我可能会回过头来尝试弄清楚为什么它不能与上面的代码一起使用,但是现在优先级较低。

1 个答案:

答案 0 :(得分:0)

基本上,一旦创建df[' age'].dtype >dtype('O') 并设置其消息侦听器,AQjmsQueueReceiver方法将退出,receive()将超出范围。我假设它是从AQjmsQueueReceiver方法中调用的,这也意味着程序将退出。您需要:

  1. 修改您的应用程序,以使您的JMS对象不会超出范围(因为它们将被垃圾回收)。
  2. 防止程序在等待消息时退出。