2013-09-18 3 views
1

Я получаю исключение NullPointerException при попытке создать таймер. Очевидно, что TimerService не устанавливается, но мой вопрос: почему? Насколько я могу судить, я следую точной схеме, используемой другим классом в нашей заявке, что делает работы.@Resource не устанавливает javax.ejb.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; 
    } 

} 
+0

У вас есть декларация ejb для 'TimerService'? –

+1

Несмотря на всю проблему с инъекцией - 1. почему вы держите состояние (сохраняете таймер) в EJB без состояния? 2. Почему вы синхронизируете потокобезопасный EJB? И, наконец, почему вы рассматриваете частный метод как бизнес-метод?Как вы даже вызываете этот компонент и знаете, что 'TimerService' не установлен? –

+0

@SotiriosDelimanolis у нас есть еще один класс, который следует за этим шаблоном, который вводит TimerService таким же образом. – StormeHawke

ответ

3

Дополнительный код разместил добавляет еще одну вещь в список неправильных вещей с этим кодом (который я начал в первый комментарий к ваш вопрос.)

Вы пытаетесь реализовать шаблон дизайна Singleton в SLSB. Это неверно на многих уровнях.

Если вам нужен синглтон - просто используйте @Singleton EJB. Если вы делаете это так, как вы писали - вы в основном не создаете экземпляр EJB, а некоторый обычный Java-класс. Неудивительно, почему инъекции не происходит - контейнер ничего не знает о экземпляре, который вы создаете в своем методе.

Если вы хотите иметь EJB - просто дайте ему конструктор по умолчанию и используйте его с вашего MDB с помощью @EJB. Затем контейнер создаст экземпляр и придаст ему характер EJB (со всем этим жизненным циклом управления, пулом, инъекцией зависимостей и т. Д.)

Подводя итог, вы можете найти список неправильных вещей в коде, который вы опубликовали:

  • вы держите состояние в без гражданства EJB,
  • вы реализуете одноплодной шаблон в объединенных-по-спецификации EJB,
  • вы синхронизации уже резьбовых s afe (также по спецификации) EJB,
  • Вы добавляете @TransactionAttribute в частный метод; Я даже не уверен, что это имеет смысл. @TransactionAttribute - это знак того, что вы определяете бизнес-метод. В то же время этот метод является закрытым, что означает, что он не может быть частью бизнес-интерфейса, поэтому он не является бизнес-методом.

Надеюсь, это вам поможет!

+0

То, что вы говорите, имеет смысл, но теперь, когда я изменил его на '@ Singleton' и поместил поле« @ EJB »в мой MDB, мой MDB больше не получает сообщения. Никаких исключений, просто ничего не происходит, когда я отправляю сообщение JMS. На что «getchas» я могу столкнуться? – StormeHawke

+0

Умм, трудно сказать из такого краткого описания. Вы можете показать еще один код (особенно MDB и взаимодействие с вашим новым компонентом Singleton) или проверить, работает ли он с '@ EJB', а его использование закомментировано из MDB и с ним включено. Это единственное, что изменилось? –

+0

См. Код в примечании EDIT. Вероятно, должен был задать новый вопрос, но поскольку вы уже знакомы с этим ... – StormeHawke

0

В Java EE 6 Tutorial Oracle, Canceling and Saving Timers:

Чтобы сохранить объект Timer для дальнейшего использования, вызовите его GetHandle метод и сохранить объект TimerHandle в базе данных

Если вы хотите избавитесь от этой неприятной работы, другой способ - ввести в фасоль синглтон, сохранить экземпляр таймера в свойстве bean-компонента @Singleton и запустить/отменить таймер в компоненте Singleton.

Смежные вопросы