@资源未设置javax.ejb.TimerService

@资源未设置javax.ejb.TimerService,java,timer,ejb,Java,Timer,Ejb,我在尝试创建计时器时遇到NullPointerException。显然,TimerService没有设置,但我的问题是,为什么?据我所知,我正在遵循我们的应用程序中另一个类所使用的确实有效的模式 注意:我是EJB新手,所以解释很有帮助 @Stateless public class MyClass implements SomeInterface { private static final Logger ourLogger = new Logger(MyClass.class);

我在尝试创建计时器时遇到NullPointerException。显然,TimerService没有设置,但我的问题是,为什么?据我所知,我正在遵循我们的应用程序中另一个类所使用的确实有效的模式

注意:我是EJB新手,所以解释很有帮助

@Stateless
public class MyClass implements SomeInterface
{
   private static final Logger ourLogger = new Logger(MyClass.class);

   private volatile Timer timer = null;
   private volatile static MyClass instance = null;

   @javax.annotation.Resource
   TimerService timerService;


   @Override
   public synchronized void myMethod()
   {
      resetTimer();
      //do other stuff
   }


   /**
    * Creates the timer.
    */
   @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
   private synchronized void resetTimer()
   {
      if (timer != null)
      {
         timer.cancel();
         timer = null;
      }
      //NullPointerException on next line:
      timer = timerService.createTimer(30000, "My Note");
   }

   public static MyClass getInstance()
   {//MDB calls this, then runs instance.myMethod
      if (instance == null)
      {
         instance = new MyClass ();
      }

      return instance;
   }


   @Timeout
   public synchronized void timeout()
   {
       //Do some stuff
       instance = null;
   }

}

您发布的其他代码在错误代码列表中又添加了一项内容(我从您问题的第一条注释开始)

您正在尝试在SLSB中实现单例设计模式。这在很多方面都是错误的

如果您需要单例-只需使用
@singleton
EJB即可。如果您按照发布的方式进行操作,那么您基本上不是在实例化EJB,而是在实例化一些常规Java类。难怪注入没有发生——容器对您在方法中创建的实例一无所知

如果您想要一个EJB,只需给它一个默认构造函数,并从MDB使用它和
@EJB
。然后容器将对其进行实例化,并赋予其EJB特性(包括所有这些管理生命周期、池、依赖注入等)

综上所述,您可以在发布的代码中找到错误内容的列表:

  • 您在一个无状态的EJB中持有一个状态
  • 您正在将一个单例模式实现到由规范汇集的EJB中
  • 您已经在进行线程安全的同步(也按规范)EJB
  • 您正在将
    @TransactionAttribute
    添加到私有方法;我甚至不确定这是否有意义
    @TransactionAttribute
    表示您正在定义业务方法。同时,这个方法是私有的,这意味着它不能成为业务接口的一部分,所以它不是一个业务方法

希望这对你有帮助

在Oracle的Java EE 6教程中:

要保存计时器对象以供将来引用,请调用其getHandle方法并将TimerHandle对象存储在数据库中


如果您想省去这项不愉快的工作,另一种方法是向
@Stateless
bean中注入一个单例bean,将计时器实例存储到
@Singleton
bean的属性中,并在Singleton bean中运行/取消计时器。

您是否有
TimerService
的ejb声明?尽管injection-1存在整个问题。为什么在无状态EJB中保存状态(存储计时器)?2.为什么要同步线程安全EJB?最后,你为什么把私有方法当作一种商业方法?您如何调用这个bean并知道
TimerService
没有设置呢?@SotiriosDelimanolis我们有另一个类遵循这个模式,在同一个模式中注入TimerServicemanner@PiotrNowicki我是从MessageDrivenBean打电话来的。这只是课程的一部分。我存储计时器,以便可以取消和重置计时器。resetTimer()方法是从另一个为简洁起见未显示的方法运行的。我问您如何调用此bean的原因是,您可能不将其用作EJB,而是将其用作常规类,因此不会注入
TimerService
。这是第一部分。第二,如果你在SLSB中存储了任何东西,你不能确定下次它会处于你离开它时的状态,因此你真的不应该这样做。你说的有道理,但现在我已经将它改为
@Singleton
,并在我的MDB中添加了
@EJB
字段,我的MDB不再接收消息。没有例外,只是当我发送JMS消息时什么都没有发生。我可能会遇到什么“怪癖”?嗯,从这么短的描述很难说。您可以显示更多的代码(特别是MDB和与新的单例bean的交互),或者测试它是否与
@EJB
一起工作,以及它的使用是否在MDB中被注释并启用。这是唯一改变的吗?请参见编辑注释下的代码。也许应该让它成为一个新问题,但既然你已经熟悉它了……再想想,这应该是一个新问题。我已将编辑移到此链接: