【发布时间】:2020-12-23 18:43:36
【问题描述】:
我有一个带有 TimerService 的无状态会话 Bean。
超时时,它开始使用 JMS 队列。在处理消息时,它需要访问可能暂时不可用的外部资源。 timeout方法循环调用MessageConsumer.receiveNoWait()直到:
- 没有更多消息要处理:它注册了一个新计时器 = 现在 + 10 分钟。结束。
- 处理过程中发生错误:它回滚消息并注册一个新计时器:现在 + 30 分钟。结束。
通过这种方式,我可以控制何时重新启动,并且由于 TimerService 回调,我没有休眠线程。
我希望多次出现此会话 bean 以预测队列中的瓶颈:
+-----<ejb>-------+
| timerService |
| | +---------------------+
----| onTimeout() {} | -----------> | external dependency |
/ | | / +---------------------+
/ +-----------------+ /
/ /
+---------+ / /
|||queue|||K /
+---------+ \ /
\ +-----<ejb>-------+ /
\ | timerService | /
\ | | /
----| onTimeout() {} |
| |
+-----------------+
我的会话 bean 看起来像这样(当然是简化了):
@Stateless
public class MyJob {
@Resource
private TimerService timerService;
@PostConstruct
public void init() {
registerNewTimer(1000L); // -> problem: timerService not accessible
System.out.println("Initial Timer created");
}
private void registerNewTimer(long duration) {
TimerConfig config = new TimerConfig();
config.setPersistent(false);
timerService.createSingleActionTimer(duration, config);
}
@Timeout
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public void execute() {
try {
// instantiate JMS session and consumer
while ((message = consumer.receiveNoWait()) != null) {
// business logic with message
message.acknowledge();
}
// queue empty, let's stop for now and register a new timer + 10min
registerNewTimer(10*60*1000);
} catch (ResourceException re) {
// external resource unavailable, let's wait 30min
registerNewTimer(30*60*1000);
// last message not acknowledged, so rolled back
}
}
}
我不想使用消息驱动 Bean,因为我想控制何时使用消息(请参阅延迟逻辑以防出现错误)。
问题:
错误在@PostConstruct注解init()方法中:此时不允许使用timerService。当我创建会话bean @Singleton 时允许这样做,但随后我失去了并行处理队列的可能性。有谁知道如何解决这个问题?如果 TimerService 不是正确的机制,还有什么可以替代的。是否有 PostConstruct 替代方案允许访问引用的资源并且仅在实例化后调用一次?
提前感谢您提供任何建设性信息。
【问题讨论】:
标签: java jakarta-ee weblogic12c