尝试创建计时器时出现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设计模式。这在许多层面上都是错误的。

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

如果要拥有EJB,只需为其提供默认构造函数,然后通过Mcc中的@EJB使用它。然后,容器将实例化它并赋予它EJB性质(具有所有那些管理生命周期,池化,依赖项注入等)。

总结一下,您可以在已发布的代码中找到错误的事情的列表:


您正在无状态EJB中保持状态,
您正在将单例模式实施到按规范池的EJB中,
您正在同步已经是线程安全的(也是按规范的)EJB,
您要将@TransactionAttribute添加到私有方法中;我什至不确定这是否有意义。 @TransactionAttribute表示您正在定义业务方法。同时,此方法是私有的,这意味着它不能成为业务接口的一部分,因此它不是业务方法。


希望对你有帮助!

09-11 19:42
查看更多