1

尝试创建计时器时出现 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;
   }

}
4

2 回答 2

3

您发布的其他代码在此代码的错误列表中添加了另一件事(我在对您的问题的第一条评论中开始。)

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

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

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

总而言之,您可以在您发布的代码中找到错误列表:

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

希望对你有帮助!

于 2013-09-18T20:28:30.663 回答
0

在 Oracle 的 Java EE 6 教程中,取消和保存计时器

要保存 Timer 对象以供将来参考,请调用其 getHandle 方法并将 TimerHandle 对象存储在数据库中

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

于 2013-09-18T20:29:02.660 回答