java 如何暂时禁用消息侦听器
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/625725/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to temporarily disable a message listener
提问by davidi
What would be a nice and good way to temporarily disable a message listener? The problem I want to solve is:
暂时禁用消息侦听器的好方法是什么?我要解决的问题是:
- A JMS message is received by a message listener
- I get an error when trying to process the message.
- I wait for my system to get ready again to be able to process the message.
- Until my system is ready, I don't want any more messages, so...
- ...I want to disable the message listener.
- My system is ready for processing again.
- The failed message gets processed, and the JMS message gets acknowledged.
- Enable the message listener again.
- 消息侦听器接收 JMS 消息
- 尝试处理消息时出现错误。
- 我等待我的系统再次准备好能够处理消息。
- 在我的系统准备好之前,我不想再收到任何消息,所以...
- ...我想禁用消息侦听器。
- 我的系统已准备好再次处理。
- 失败的消息得到处理,JMS 消息得到确认。
- 再次启用消息侦听器。
Right now, I'm using Sun App Server. I disabled the message listener by setting it to null in the MessageConsumer, and enabled it again using setMessageListener(myOldMessageListener), but after this I don't get any more messages.
现在,我正在使用 Sun App Server。我通过在 MessageConsumer 中将其设置为 null 来禁用消息侦听器,并使用 setMessageListener(myOldMessageListener) 再次启用它,但在此之后我没有收到更多消息。
采纳答案by John M
How about if you don't return from the onMessage()listener method until your system is ready to process messages again? That'll prevent JMS from delivering another message on that consumer.
如果您onMessage()在系统准备好再次处理消息之前不从侦听器方法返回呢?这将阻止 JMS 向该使用者传递另一条消息。
That's the async equivalent of not calling receive()in a synchronous case.
这相当于receive()在同步情况下不调用的异步等价物。
There's no multi-threading for a given JMS session, so the pipeline of messages is held up until the onMessage()method returns.
对于给定的 JMS 会话,没有多线程,因此消息管道会被阻塞,直到onMessage()方法返回。
I'm not familiar with the implications of dynamically calling setMessageListener(). The javadoc says there's undefined behaviorif called "when messages are being consumed by an existing listener or sync consumer". If you're calling from within onMessage(), it sounds like you're hitting that undefined case.
我不熟悉动态调用setMessageListener(). javadoc 说如果调用“当消息被现有侦听器或同步消费者使用时”,则存在未定义的行为。如果您从 inside 调用onMessage(),听起来您遇到了未定义的情况。
There are start/stopmethods at the Connection level, if that's not too coarse-grained for you.
回答by davidi
Problem solved by a workaround replacing the message listener by a receive() loop, but I'm still interested in how to disable a message listener and enable it shortly again.
通过使用 receive() 循环替换消息侦听器的变通方法解决了问题,但我仍然对如何禁用消息侦听器并很快再次启用它感兴趣。
回答by tddmonkey
That looks to me like the messages are being delivered but nothing is happening with them because you have no listener attached. It's been a while since I've done anything with JMS but don't you want to have the message sent to the dead letter queue or something while you fix the system, and then move the messages back onto the original queue once you're ready for processing again?
在我看来,消息正在传递,但它们没有发生任何事情,因为您没有附加侦听器。我已经有一段时间没有使用 JMS 做过任何事情了,但是您是否不希望在修复系统时将消息发送到死信队列或其他内容,然后在您修复系统后将消息移回原始队列准备好再次处理了吗?
回答by duffymo
On WebLogic you can set up max retries, an error queue to handle messages that exceed the max retry limit, and other parameters. I'm not certain off the top of my head, but you also might be able to specify a wait period. All this is available to you in the admin console. I'd look at the admin for the JMS provider you've got and see if it can do something similar.
在 WebLogic 上,您可以设置最大重试次数、处理超过最大重试次数限制的消息的错误队列以及其他参数。我不确定我的头脑,但你也可以指定一个等待期。所有这些都可以在管理控制台中使用。我会查看您拥有的 JMS 提供程序的管理员,看看它是否可以做类似的事情。
回答by Jeremy
In JBoss the following code will do the trick:
在 JBoss 中,以下代码可以解决问题:
MBeanServer mbeanServer = MBeanServerLocator.locateJBoss();
ObjectName objName = new ObjectName("jboss.j2ee:ear=MessageGateway.ear,jar=MessageGateway-EJB.jar,name=MessageSenderMDB,service=EJB3");
JMSContainerInvokerMBean invoker = (JMSContainerInvokerMBean) MBeanProxy.get(JMSContainerInvokerMBean.class, objName, mbeanServer);
invoker.stop(); //Stop MDB
invoker.start(); //Start MDB
回答by mami
I think you can call
我想你可以打电话
messageConsumer.setMessageListener(null);
inside your MessageListener implementation and schedule the reestablishment task (for example in ScheduledExecutorService). This task should call
在 MessageListener 实现中并安排重建任务(例如在 ScheduledExecutorService 中)。这个任务应该调用
connection.stop();
messageConsumer.setMessageListener(YOUR_NEW_LISTENER);
connection.start();
and it will be working. start() and stop() methods are used for restarting delivery structrues (not TCP connection).
它将起作用。start() 和 stop() 方法用于重新启动传递结构(不是 TCP 连接)。
Read the Javadoc https://docs.oracle.com/javaee/7/api/javax/jms/Connection.html#stop--
阅读 Javadoc https://docs.oracle.com/javaee/7/api/javax/jms/Connection.html#stop--
Temporarily stops a connection's delivery of incoming messages. Delivery can be restarted using the connection's start method. When the connection is stopped, delivery to all the connection's message consumers is inhibited: synchronous receives block, and messages are not delivered to message listeners.
暂时停止连接传递传入消息。可以使用连接的 start 方法重新启动传递。当连接停止时,禁止向所有连接的消息使用者传递:同步接收阻塞,并且消息不会传递给消息侦听器。
回答by yaroslavpalamar
For temporarily stops a connection's delivery of incoming messages you need to use stop()method from Connectioninterface: https://docs.oracle.com/javaee/7/api/javax/jms/Connection.html#stop--
要暂时停止连接传递传入消息,您需要使用接口中的stop()方法Connection:https: //docs.oracle.com/javaee/7/api/javax/jms/Connection.html#stop--
Just don't call connection.stop()from MessageListenerbecause according to JMS spec. you will get deadlock or exception. Instead you can call connection.stop()from different thread, you just need to synchronize MessageListenerand thread that going to suspend connection with function connection.stop()
只是不要调用connection.stop()fromMessageListener因为根据 JMS 规范。你会遇到死锁或异常。相反,您可以connection.stop()从不同的线程调用,您只需要同步MessageListener和线程将挂起与函数的连接connection.stop()

