Java 如何临时禁用消息侦听器

Java 如何临时禁用消息侦听器,java,jms,Java,Jms,暂时禁用消息侦听器的好方法是什么?我想解决的问题是: JMS消息由消息侦听器接收 我在尝试处理消息时出错 我等待我的系统再次准备好处理消息 在我的系统准备好之前,我不想再收到任何消息,所以 …我想禁用消息侦听器 我的系统已准备好再次处理 处理失败的消息,并确认JMS消息 再次启用消息侦听器 现在,我正在使用Sun App Server。我通过在MessageConsumer中将消息侦听器设置为null禁用了它,并使用setMessageListener(myOldMessageListene

暂时禁用消息侦听器的好方法是什么?我想解决的问题是:

  • JMS消息由消息侦听器接收
  • 我在尝试处理消息时出错
  • 我等待我的系统再次准备好处理消息
  • 在我的系统准备好之前,我不想再收到任何消息,所以
  • …我想禁用消息侦听器
  • 我的系统已准备好再次处理
  • 处理失败的消息,并确认JMS消息
  • 再次启用消息侦听器

现在,我正在使用Sun App Server。我通过在MessageConsumer中将消息侦听器设置为null禁用了它,并使用setMessageListener(myOldMessageListener)再次启用了它,但在此之后,我再也没有收到任何消息。

在我看来,消息正在传递,但由于没有连接侦听器,因此没有任何消息发生。我已经有一段时间没有用JMS做过任何事情了,但您是否希望在修复系统时将消息发送到死信队列或其他东西,然后在准备再次处理时将消息移回原始队列?

在WebLogic上,您可以设置最大重试次数,用于处理超过最大重试限制的消息的错误队列以及其他参数。我不太清楚,但你也可以指定一个等待时间。所有这些都可以在管理控制台中使用。我会查看您拥有的JMS提供程序的管理员,看看它是否可以做类似的事情。

通过一个用receive()循环替换消息侦听器的解决方案,解决了这个问题,但我仍然对如何禁用消息侦听器并很快再次启用它感兴趣。

如果您不从
onMessage()返回,该怎么办
listener方法,直到系统准备好再次处理消息为止?这将阻止JMS在该消费者上传递另一条消息

这与在同步情况下不调用
receive()
是异步等效的

对于给定的JMS会话,没有多线程,因此消息管道将一直保持到
onMessage()
方法返回为止

我不熟悉动态调用
setMessageListener()
的含义。javadoc说如果调用“当消息被现有侦听器或同步消费者使用时”。如果您是从
onMessage()
中调用,听起来就像是遇到了未定义的情况


如果连接级别对您来说不是太粗粒度的话,那么在连接级别上有/方法。

在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
我想你可以打电话

messageConsumer.setMessageListener(null);
在MessageListener实现中,并计划重建任务(例如在ScheduledExecutorService中)。此任务应调用

connection.stop();
messageConsumer.setMessageListener(YOUR_NEW_LISTENER);
connection.start();
它会起作用的。start()和stop()方法用于重新启动传递结构(不是TCP连接)

阅读Javadoc

暂时停止连接传入消息的传递。可以使用连接的start方法重新启动传递。当连接停止时,将禁止向连接的所有消息使用者传递消息:同步接收块,消息不会传递给消息侦听器


要临时停止连接传入消息的传递,您需要使用
connection
接口中的
stop()
方法:


只是不要从
MessageListener
调用
connection.stop()
,因为根据JMS规范,您将获得死锁或异常。相反,您可以从不同的线程调用
connection.stop()
,您只需要同步
MessageListener
和将暂停连接的线程,函数
connection.stop()

,可能就是这样。不幸的是,我无法控制jms服务器,我所能做的就是指定一个队列来获取消息,而不是死信队列。我想我可以停止QueueConnection,但这不能从messagelistener线程完成。为什么您没有访问JMS服务器的权限。正如duffymo正确指出的那样,它是您想要访问的错误队列。否则,您将在JMS服务器为您提供的代码中复制行为我确实有权访问JMS服务器…在我的开发环境中,但我不能期望我正在处理的应用程序(两个消息传递系统之间的桥梁)的用户对JMS服务器具有相同的权限。那个死信队列是处理这些问题的常用方法吗?哦,真的很简单。我希望有更多线程调用onMessage方法。非常感谢!连接是线程安全的。关闭的会话(会话、使用者、生产者)不是线程安全的。您的代码需要避免多线程访问。为了实现这一点,JMS不能在一个使用者上执行多线程侦听器调用。这是JMS 1.0.2规范的第4.4.16节。过去我认为这只是线程规则的暗示。在问题得到解决之前,我们可以使用Thread.sleep()吗?这是最好的设计吗?嗨,你能找到暂停messagelistener接收过程的解决方案吗