我想从Oracle AQ队列中取消非持久性(=缓冲(JMS消息的队列。
在 PL/SQL 中,如果我设置
L_DequeueOptions.VISIBILITY := DBMS_AQ.IMMEDIATE;
L_DequeueOptions.DELIVERY_MODE := DBMS_AQ.BUFFERED;
在取消排队器上。
排队程序选项相应地设置为"立即"和"缓冲"。
尽管如此,在Java代码中,我尝试使用JMS和javax.jms.QueueReceiver接收消息,使用
QueueReceiver receiver = session.createReceiver(queue, "JMSDeliveryMode = 'PERSISTENT' or JMSDeliveryMode = 'NON_PERSISTENT'");
// and later on:
Message m = receiver.receive(conf.dequeueTimeout);
我没有在取消队列器/接收方的事务中运行。 如何在 JMS 中设置"可见性"? 知道为什么我没有收到消息吗?
我错过了什么?
有效载荷是系统。AQ$_JMS_TEXT_MESSAGE,非压缩等。
顺便说一句:出列应用程序正在使用持久消息工作...
更新:如果我使用消息选择器,该代码也不适用于持久消息。没有消息选择器和持久消息,它可以工作!
我们发现了如何管理它。 直接在 JMS 上,无法将非持久性消息取消排队。我怀疑非持久性排行是标准的一部分。
唯一的方法是将 QueueReceiver 强制转换为oracle.jms.AQjmsConsumer
,然后调用
receiver.bufferReceive(timeout);
而不是
receiver.receive(timeout);
只有使用 Oracle JMS 代码进行调试才能让我们找到这个解决方案。 网络上关于这方面的文档很差。
顺便说一句:消息选择器将我引向了完全错误的方向。
JMS 规范 (JSR 914( 定义了两种交付模式:PERSISTENT
和NON_PERSISTENT
。关于甲骨文,这些模式是PERSISTENT
和BUFFERED
。
但是,似乎 Oracle JMS 实现默认只接收PERSISTENT
个。
消息选择器本身由 Oracle 实现检查,但似乎对传递模式没有影响。
如您自己所述,可以将QueueReceiver
强制转换为AQjmsConsumer
以处理缓冲的消息。
AQjmsConsumer consumer = (AQjmsConsumer)session.createReceiver(queue);
consumer.bufferReceive(dequeueTimeout);
这同样适用于发送缓冲消息。在这里,必须将QueueSender
强制转换为AQjmsProducer
,以便手头有缓冲消息的方法:
AQjmsProducer producer = (AQjmsProducer)session.createProducer(queue);
producer.bufferSend(queue, msg, priority, timeToLive);