如何暂时禁用消息监听器

问题描述 投票:0回答:8

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

  • 消息侦听器接收 JMS 消息
  • 我在尝试处理消息时收到错误。
  • 我等待系统再次准备好才能处理消息。
  • 在我的系统准备就绪之前,我不想再收到任何消息,所以...
  • ...我想禁用消息监听器。
  • 我的系统已准备好再次处理。
  • 失败的消息得到处理,JMS 消息得到确认。
  • 再次启用消息监听器。

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

java jms
8个回答
15
投票

如果在系统准备好再次处理消息之前不从

onMessage()
侦听器方法返回,会怎么样?这将阻止 JMS 向该消费者传递另一条消息。

这相当于在同步情况下不调用

receive()
的异步。

给定的 JMS 会话没有多线程,因此消息管道将被阻塞,直到

onMessage()
方法返回。

我不熟悉动态调用

setMessageListener()
的含义。 javadoc 说,如果调用“当现有侦听器或同步消费者正在使用消息时”,则存在未定义的行为。 如果您从 onMessage() 内部拨打电话,听起来就像遇到了未定义的情况。

连接级别有

start

/stop 方法(如果这对您来说不是太粗粒度的话)。


5
投票


1
投票

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



0
投票


0
投票


0
投票

messageConsumer.setMessageListener(null);

在 MessageListener 实现中并安排重建任务(例如在 ScheduledExecutorService 中)。这个任务应该调用

connection.stop(); messageConsumer.setMessageListener(YOUR_NEW_LISTENER); connection.start();

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

阅读 Javadoc

https://docs.oracle.com/javaee/7/api/javax/jms/Connection.html#stop--

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


0
投票
stop()

接口中的

Connection
方法:
https://docs.oracle.com/javaee/7/api/javax/jms/Connection.html#stop --
只是不要从

connection.stop()

调用

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


0
投票

通过 JNDI 找到 MBean 并停止它(在 JBoss EAP 中,您可以获取该 bean 并调用其上的方法
    stopDelivery()
  • 同时,创建一个
  • AtomicBoolean()
  • 的标志,名为
    ACCEPTING_MESSAGES
    ,将其设置为false,并在
    onMessage()
    中添加检查其值的逻辑,如果为false,则不接受新消息,直接返回。
    
    
  • 调用 MBean 的方法可能是这样的:

private void stopJmsDelivery(String name) { try { MBeanServer s = ManagementFactory.getPlatformMBeanServer(); ObjectName n = ObjectName.getInstance(name); s.invoke(n, "stopDelivery", null, null); } catch (Exception e) { log.error("Failed to stop JMS: ", e); } catch (Throwable throwable) { log.error("Failed to stop JMS(generic): ", throwable); } }

JBoss EAP 中的 arg 是这样的:

"jboss.as:deployment=my-service.ear,subdeployment=some.jar,subsystem=ejb3,message-driven-bean=MyMDB"

使用 JBoss EAP 管理控制台检查确切的字符串。

© www.soinside.com 2019 - 2024. All rights reserved.