Java EJB3.0容器中的单个后台线程

Java EJB3.0容器中的单个后台线程,java,jakarta-ee,ejb-3.0,Java,Jakarta Ee,Ejb 3.0,我们需要在EJB3.0容器中运行内务线程。我们目前有一个“TimerService”@无状态EJB(这是必需的,因为它已经注入了其他@EJB),它在调用startTimer()方法时创建一个间隔EJB计时器。此计时器线程应该只有一个实例。当前的解决方案涉及从我们的一个servlet的init()方法调用startTimer(),在启动时使用web.xml强制加载servlet,但这感觉像是巧合行为,而不是正确的操作方式。我们已经遇到了一个问题,因为其他人将该servlet子类化,这意味着init

我们需要在EJB3.0容器中运行内务线程。我们目前有一个“TimerService”@无状态EJB(这是必需的,因为它已经注入了其他@EJB),它在调用startTimer()方法时创建一个间隔EJB计时器。此计时器线程应该只有一个实例。当前的解决方案涉及从我们的一个servlet的init()方法调用startTimer(),在启动时使用web.xml强制加载servlet,但这感觉像是巧合行为,而不是正确的操作方式。我们已经遇到了一个问题,因为其他人将该servlet子类化,这意味着init()被调用了两次,这意味着两个计时器线程


这感觉好像不是一个不寻常的要求,那么什么是正确的方式来做这件事,如果有的话?在我看来,应该有一种简单的方法让容器在启动时启动线程,而不必将其绑定到容器中的其他资源。

您的应用服务器是否支持“启动bean”?我这样问是因为在WebSphereApplicationServer中,管理控制台中有一个选项可以设置服务器在服务器启动时启动“启动bean”。我们将其用于某些需要大量“重载”和初始化的应用程序,这样我们就可以最大限度地减少最终用户体验的启动时间。 这里是WAS6文档的链接(我知道很旧,但仍然很有用)


我知道这是IBM WebSphere特有的,但也许您的应用服务器(如果不是WebSphere)有类似的功能可以帮助您启动它们?

我想建议两种解决方案

1修复您的实现。 让servlet成为最终版本。这将避免子类化。但是servlet仍然可以部署两次。为了避免这种情况,在servlet中创建静态布尔变量。init应该检查这个变量。如果为假,则将其变为真并继续。否则它抛出异常

这是你现在可以做的快速修复。 但这不是一个“正确”的解决方案。例如,这在集群环境中不起作用

2有两种“正确”的解决方案

2.1。使用石英

2.2。使用JCA实现计时器。连接器是J2EE中唯一可以合法使用线程和计时器的地方

我在本文的其他上下文中提到了JCA:
欢迎您查看它,并查看可能对您有所帮助的简短代码示例

对于EJB<3.1,您必须获得特定于应用程序服务器或黑客的服务。既然您提到您正在使用JBoss,那么您可以使用@Management标记,它定义了生命周期方法。

可能相关吗?谢谢-公认的答案适用于EJB3.1,我们没有使用它,但有趣的是另一个答案,它提到了3.1之前的最佳方式是我们目前使用的解决方案:(我们使用的是JBoss 5.1.0。一个快速的google没有透露任何类似的功能。