JBoss 6.0 中 JMS 侦听器 (MDB) 的延迟启动

发布于 2025-01-04 21:16:58 字数 1977 浏览 2 评论 0原文

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

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

另一个提示将我带到 application.xml 中的按顺序初始化属性,因为问题可能与 JBoss 部署顺序有关(某些 EJB 将晚于侦听器可用),但似乎有一个 JBoss 6.0 中的错误 并升级到 6.1。不是一个选择。也许有一个演练?

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

提前致谢, Danny

附加信息:

  • JBoss 6.0.0 Final
  • HornetQ 2.2.5 Final(已经更新,因为 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 - 成员有时将为 null

we have multiple instances of JBoss-Server in a clustered environment. For background tasks there is a global queue available, that manages all jobs registered at it. For this queue there is a simple listener (MDB) on each node, manages the incoming messages. This listener does a manual lookup (no injection) for a singleton bean and starts a pre defined method.
Everything works fine so far, but the method in the singleton bean uses some other (no singleton services) that are not available under some circumstances.
For example if a node will be restarted and there are left messages in the queue (not processed yet) the messages will be picked up by the listener and all further beans are null, so the job produces a NPE.
Is it possible to define a delay time in JMS-Listener after messages will be picked up or is it possible to define an "application completely deployed" hook in there? The DependsOn-Annotation does not work, because of the usage of non singletons.

A possibility can be to set the MDB-property "DeliveryActive" to false and start the bean after full deployment. Is there a simple, working way to do this programatically (not in jmx-console)? Any manuals for this I found, redirects me to a manual jndi lookup. I think it have to be possible to inject the Bean per annotation and call startDelivery()? Is there a good place to do this in application?

Another hint takes me to the initialise in order property in application.xml, because the problem might be connected to JBoss Deployment order (some EJBs will be later available than the listener), but there seems to be a bug in JBoss 6.0 and upgrading to 6.1. is not an option. Maybe there is a walkthrough for this?

I hope that the problem is well enough explained, otherwise please ask for further informations.

Thanks in advance,
Danny

Additional informations:

  • JBoss 6.0.0 Final
  • HornetQ 2.2.5 Final (already updated, because of the buggy default version of JBoss)

The Listener:

@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);
   ...
}

A sample worker:

@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));
    }

In this case the sampleEjb - member will be null sometimes

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

爱的故事 2025-01-11 21:16:58
  1. 作为解决方法,您可以创建一个具有一定延迟的超时计时器,而不是直接从 MDB 调用 EJB。因此执行时会有一些延迟。

    在 Timer 的超时方法中,您可以调用单例 EJB,以防万一它将调用其他非单例 EJB。

  2. JBoss 特定:可以尝试在发送之前在消息对象中设置属性。

    msg.setLongProperty("JMS_JBOSS_SCHEDULED_DELIVERY", (当前 + 延迟));

    其他替代方案是_JBM_SCHED_DELIVERY

编辑:

对于第一部分,您可以进行 JTA 事务,该事务可能跨越 JMS 和 JMS。 EJB。因此故障转移和其他事项可依此处理。

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

<address-setting match="jms.queue.someQueue">
        <redelivery-delay>5000</redelivery-delay>
</address-setting>
  1. As a workaround, instead of calling EJB's directly from MDB, you can create a timer with a timeout with some delay. Therefore there will be some delay in execution.

    In Timer's timeout method, then you can call singleton EJB, which in case will call other non-singleton EJB's.

  2. JBoss specific : Can try setting the property in the message object before sending.

    msg.setLongProperty("JMS_JBOSS_SCHEDULED_DELIVERY", (current + delay));

    Other alternative is _JBM_SCHED_DELIVERY.

Edit :

For 1st part, you can have JTA transaction, which may span across JMS & EJB. Therefore failover & other things may be handled accordingly.

You can also increase the redelivery delay for the message object.

<address-setting match="jms.queue.someQueue">
        <redelivery-delay>5000</redelivery-delay>
</address-setting>
寂寞美少年 2025-01-11 21:16:58

我现在也遇到同样的麻烦。

我建议您使用 EJB 3 启动 bean 注释 @Startup 在您的单例 bean 上调用 Message 侦听器上的 startDelivery 方法。

I am in the same trouble at the moment.

I propose you use EJB 3 startup bean annotation @Startup on your singleton bean to invoke the startDelivery method on your Message listeners.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文