JBoss6.0中JMS侦听器(MDB)的延迟启动

JBoss6.0中JMS侦听器(MDB)的延迟启动,jboss,jms,ejb-3.1,hornetq,jboss-mdb,Jboss,Jms,Ejb 3.1,Hornetq,Jboss Mdb,我们在集群环境中有多个JBoss服务器实例。对于后台任务,有一个全局队列可用,用于管理在该队列中注册的所有作业。对于该队列,每个节点上都有一个简单侦听器(MDB),用于管理传入消息。此侦听器对单例bean执行手动查找(无注入),并启动预定义的方法。 到目前为止,一切都很正常,但是singletonbean中的方法使用了一些在某些情况下不可用的其他服务(没有singleton服务)。 例如,如果一个节点将被重新启动,并且队列中还有剩余的消息(尚未处理),那么侦听器将拾取这些消息,并且所有其他bea

我们在集群环境中有多个JBoss服务器实例。对于后台任务,有一个全局队列可用,用于管理在该队列中注册的所有作业。对于该队列,每个节点上都有一个简单侦听器(MDB),用于管理传入消息。此侦听器对单例bean执行手动查找(无注入),并启动预定义的方法。 到目前为止,一切都很正常,但是singletonbean中的方法使用了一些在某些情况下不可用的其他服务(没有singleton服务)。 例如,如果一个节点将被重新启动,并且队列中还有剩余的消息(尚未处理),那么侦听器将拾取这些消息,并且所有其他bean都为空,因此该作业将生成一个NPE。 是否可以在接收消息后在JMS侦听器中定义延迟时间,或者是否可以在其中定义“应用程序完全部署”挂钩?DependsOn注释不起作用,因为使用了非单例

一种可能性是将MDB属性“DeliveryActive”设置为false,并在完全部署后启动bean。是否有一种简单、有效的编程方式(不在jmx控制台中)来实现这一点?我找到的任何手册都会将我重定向到手动jndi查找。我认为必须能够为每个注释注入Bean并调用startDelivery()?在应用程序中有这样做的好地方吗

另一个提示将我带到application.xml中的initialise-in-order属性,因为问题可能与JBoss部署顺序有关(某些EJB将比侦听器更晚可用),但似乎存在一个问题,需要升级到6.1。这不是一种选择。也许有一个关于这个的演练

我希望这个问题解释得足够好,否则请询问更多信息

提前感谢,, 丹尼

其他信息:

  • JBoss 6.0.0最终版
  • Hornetq2.2.5最终版(已经更新,因为JBoss的默认版本有缺陷)
听众:

@MessageDriven(activationConfig =
    {
            @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
            @ActivationConfigProperty(propertyName = "destination", propertyValue = "/queue/SchedulerQueue")
    })
public class SchedulerQueueListener implements MessageListener {
...
@Override
public void onMessage(Message message) {
   ...
   service = (IScheduledWorkerService) new InitialContext().lookup(jndiName);
   EJobResult eJobResult = service.executeJob(message);
   ...
}
样本工人:

@Singleton
@LocalBinding(jndiBinding = SampleJobWorkerService.JNDI_NAME)
public class SampleJobWorkerService implements IScheduledWorkerService {

...
    @EJB(name = "SampleEJB/local")
    private ISampleEJB sampleEjb;
...
    @Override
    public EJobResult executeJob(Message message) {
    int state = sampleEjb.doSomething(message.getLongProperty(A_PROPERTY));
    }
在这种情况下,sampleEjb-member有时将为null

  • 作为一种解决方法,您可以创建一个带有超时和一些延迟的计时器,而不是直接从MDB调用EJB。因此,在执行过程中会有一些延迟

    在Timer的timeout方法中,您可以调用singleton EJB,在这种情况下,它将调用其他非singleton EJB

  • JBoss-specific:可以在发送前尝试在消息对象中设置属性

    msg.setLongProperty(“JMS_JBOSS_SCHEDULED_DELIVERY”,(当前+延迟))

    另一种选择是
    \u JBM\u SCHED\u交付

  • 编辑:

    对于第一部分,您可以使用JTA事务,它可能跨越JMS和EJB。因此,可以相应地处理故障转移和其他事情

    您还可以增加消息对象的重新传递延迟

    <address-setting match="jms.queue.someQueue">
            <redelivery-delay>5000</redelivery-delay>
    </address-setting>
    
    
    5000
    
    我现在也有同样的麻烦


    我建议您在单例bean上使用
    @Startup
    来调用消息侦听器上的
    startDelivery
    方法。

    感谢您的回答Nayan,您第一个回答的缺点是,属于JMS的好处将不再有效,或者必须由自己实现(故障切换、重新排队、死信队列). “JMS_JBOSS_SCHEDULED_DELIVERY”属性将不起作用,因为发送位置太早,无法实现超时。如果消息将以当前时间+延迟排队,并且重新启动后节点将发生故障,则消息将被侦听器占用,并且已到达延迟时间。第2个选项与超时或第1个选项无关,它是一种独立的方式。此外,如果出现故障,您可以延迟消息的重新传递,可以参考编辑部分。