【问题标题】:@Resource not setting javax.ejb.TimerService@Resource 未设置 javax.ejb.TimerService
【发布时间】:2015-05-07 18:07:05
【问题描述】:

我在尝试创建计时器时收到 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;
   }

}

【问题讨论】:

  • 你有TimerService的ejb声明吗?
  • 尽管注入有整个问题 - 1. 为什么要在无状态 EJB 中保存状态(存储计时器)? 2. 为什么要同步线程安全的 EJB?最后——为什么你将私有方法视为一种商业方法?你如何调用这个 bean 并知道 TimerService 没有设置?
  • @SotiriosDelimanolis 我们有另一个遵循这种模式的类,它以相同的方式注入 TimerService
  • @PiotrNowicki 我从 MessageDrivenBean 调用它。这只是课程的一部分。我存储计时器,以便可以取消和重置它。 resetTimer() 方法是从另一个为简洁起见未显示的方法运行的。
  • 我问你如何调用这个 bean 的原因是你可能不是将它用作 EJB,而是用作常规类,因此不会注入 TimerService。这是第一部分。其次 - 如果你将任何东西存储在 SLSB 中,你无法确定下次它是否会处于与你离开时相同的状态 - 因此你真的不应该这样做。

标签: java timer ejb


【解决方案1】:

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

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

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

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

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

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

希望对您有所帮助!

【讨论】:

  • 你说的有道理,但现在我已将其更改为 @Singleton 并在我的 MDB 中放置了一个 @EJB 字段,我的 MDB 不再接收消息。没有例外,当我发送 JMS 消息时没有任何反应。我可能会遇到什么“陷阱”?
  • 呃,这么简短的描述很难说。您可以显示更多代码(尤其是 MDB 以及与新的 Singleton bean 的交互)或测试它是否与 @EJB 一起使用,并且它的用法已从 MDB 中注释掉并启用它。它是唯一改变的东西吗?
  • 查看 EDIT 说明下的代码。可能应该让它成为一个新问题,但既然你已经熟悉它......
  • 转念一想,这应该是一个新问题。我将编辑移至此链接:stackoverflow.com/questions/18883021/…
【解决方案2】:

在 Oracle 的 Java EE 6 教程中,Canceling and Saving Timers

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-02-07
    • 2014-02-20
    • 2017-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-06
    相关资源
    最近更新 更多