【问题标题】:No onMessage events on Runtime (Java JMS MessageListener on Oracle Queue)运行时没有 onMessage 事件(Oracle 队列上的 Java JMS MessageListener)
【发布时间】:2019-04-12 21:45:12
【问题描述】:

目的

我创建了 MyListener.java 来监控我的 Oracle 队列 MY_QUEUE 和 MyConsumer.java 实现我自己的 MessageListener.onMessage 功能。
一旦我将一些条目排入 MY_QUEUE,我希望 MessageListener 将“新消息 ...”输出到控制台上。

问题

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

示例

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

    已初始化...
    睡觉...
    新消息...
    新消息...
    新消息...
    新消息...
    新消息...
    睡觉...
    睡着了……

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

    已初始化...
    睡觉...
    睡觉...
    睡觉...
    正在睡觉...(大约此时插入了队列条目)
    睡觉...
    睡觉...
    睡觉...
    睡着了……

  3. 退出应用程序并再次运行应用程序(来自 2. 的条目仍在队列中)。输出:

    已初始化...
    睡觉...
    新消息...
    新消息...
    新消息...
    新消息...
    新消息...
    睡觉...
    睡着了……

我的听众

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

    }

}

我的消费者

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 dequeue 方法来异步获取我的消息。我可能会回来尝试弄清楚为什么它不能与上面的代码一起工作,但现在这是低优先级。

【问题讨论】:

    标签: java oracle queue jms listener


    【解决方案1】:

    基本上,只要您创建 AQjmsQueueReceiver 并设置其消息侦听器,receive() 方法就会退出,AQjmsQueueReceiver 将超出范围。我假设它是从main 方法调用的,这也意味着程序将退出。您需要:

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

    【讨论】:

    • 1. & 2. 我通过在 queueConnection.start() 之后的 while(true) 循环中编写 Thread.sleep(1000) 来做到这一点;但之后什么都没有发生。如果我这样做,对象是否仍然超出范围?你能告诉我它应该是什么样子的例子吗?我只是无法通过文档找到正确的解决方案
    • 如果您在与变量相同的范围内循环,那么它们不应超出范围。值得注意的是,您关于该主题的两个问题都没有我认为“正确”的代码。根据您所说的,您编写了正确的代码,但仍然无法正常工作。我想说要么您实际上没有编写正确的代码,要么底层 JMS 客户端/服务器实现中存在错误。至少,请使用您拥有的最新、最正确的代码更新您的问题。
    • 我编辑了这个问题来代表当前(在我看来是正确的)代码。
    猜你喜欢
    • 2014-03-02
    • 1970-01-01
    • 2013-08-08
    • 2011-02-05
    • 1970-01-01
    • 2021-05-31
    • 1970-01-01
    • 2014-09-25
    • 2011-02-01
    相关资源
    最近更新 更多