2015-03-05 2 views
1

Я честно пропустил что-то здесь. Я не знаю, как создать экземпляр объекта TimerService. Он всегда равен нулю. У меня нет конструктора, потому что это интерфейс. Я не могу использовать методы create. @Resource, похоже, ничего не выделяет.TimerService null

Я пытаюсь настроить простой программный таймер, который выполняет задание каждые X минут. Продолжительность таймаута может варьироваться в зависимости от конфигурации, которая может меняться во время выполнения. Я использую веб-приложение WebLogic 12.

То, что я до сих пор:

import javax.annotation.Resource; 
import javax.ejb.Singleton; 
import javax.ejb.Timeout; 
import javax.ejb.Timer; 
import javax.ejb.TimerService; 

@Singleton 
public class TimerBean { 
    @Resource 
    protected TimerService timerService; 

    public TimerBean(){ 
     System.out.println("TimerBean constructor " + timerService); 
    } 

    @Timeout 
    public void timeoutHandler(Timer timer){ 
     String name = timer.getInfo().toString(); 
     System.out.println("Timer ticked. Name=" + name); 
    } 


    public void startOrModifyTimer(long initialExpiration, long interval, String name) { 
     System.out.println("Start or modify " + timerService); 
    } 
} 

Это выходы:

TimerBean конструктор нулевой

& затем после того, как сервер работает, если я позвоню начать или изменить:

Start или изменение нулевой


редактировать: Я получил его на работу, делая TimerBean @Singleton & @Startup & замена конструктор с @PostConstruct методом.

однако пока у него есть объект для TimerService инстанцированный всякий раз, когда я пытаюсь использовать его методы, которые он дает мне java.lang.IllegalArgumentException: Unknown bean state 0, для которых нет никакой информации ...

ответ

1

Я закончил с использованием Timer & TimerTask для этого. Не удалось установить TimerService. Ну что ж. Кажется, хорошо работает.

Для кого любопытным:

long interval = minutes*60*1000; 
    long delay = interval; 

    if(prevTask != null){ 
     delay = System.currentTimeMillis() - prevTask.scheduledExecutionTime(); //time left of previous setting 
     prevTask.cancel(); 
     delay = interval - delay; //difference in time left & new interval 
     if(delay <=0) //if by new setting should've already ran, so run it ASAP... 
      delay = 2000; 

     logger.info(String.format("DB dump was already scheduled before. Set dump delay to %s minutes & setting new schedule to every %s minutes.", delay/60/1000, minutes)); 
    } 

    TimerTask task = new TimerTask(){ 
     private SimpleDateFormat ft = new SimpleDateFormat("yyyy.MM.dd 'at' HH:mm:ss SSS"); 
     private int minutes; 
     public TimerTask initialize(int minutes){ 
      this.minutes = minutes; 
      return this; 
     } 
     public void run() { 
      try { 
       logger.info(String.format("Doing scheduled %s dump to DB. (Configured to occur every %s minutes.)", ft.format(new Date(this.scheduledExecutionTime())), minutes)); 
       dumpToDB(); 
      } catch (NamingException | SQLException e) { 
       e.printStackTrace(); 
      } 
     } 
    }.initialize(minutes); 

    timer.schedule(task, delay, interval); 
    prevTask = task; 
+0

Плохой ответ, поскольку реальной проблемой был ОП, не понимавший, как «бобы» работают в Java EE. Таким образом, всякий раз, когда вы используете аннотацию, такую ​​как '@ Resource',' @ Inject', '@ PersistenceContext' и т. Д., Это должно быть сделано в * управляемом * компоненте, что означает, что экземпляры класса bean-класса могут * только * быть созданный контейнером Java EE, * не * кодом приложения; т. е. вы не можете выполнять 'new MyBean()' и ожидать, что его поля '@ Resource' будут установлены. –

2

Если вы пытаетесь использовать инъекции поля, вы опираясь на фреймворк, который будет создан после того, как объект уже был создан и задан поле, поэтому он будет всегда быть нулевым в конструкторе. Вы можете либо сделать любую логику, которая вам нужна, в методе @PostConstruct, либо, если хотите, введите TimerService в качестве аргумента конструктора, а не непосредственно в поле.

+0

'@ PostConstruct' никогда не называется. '@ Inject' тоже не является (и Im unsure, если я сделал это правильно). Кроме того, когда я выполняю запросы к серверу, он вызывает startOrModify и startOrModify. ALSO видит timerService как null. –

+0

Вы называете 'новый TimerBean()'? – chrylis

+0

да, я? это неправильно? –

2

@PostConstruct никогда не вызывается. @Inject не либо (и Im уверен, если я сделал это правильно)

Я получил его на работу, сделав заменяющего конструктор TimerBean @Singleton & @Startup & с @PostConstruct методом.

chrylis является правильным. Из вашего описания это похоже на создание экземпляра TimerBean через конструктор.

Результат состоит в том, что вы управляете жизненным циклом самостоятельно, и контейнер не может позаботиться об этом экземпляре и вводить больше.

Вводите свой TimerBean в классе, где вы хотите использовать его (Session, например), или использовать его, как вы делали:

@Singleton 
@Startup 
public class TimerBean { .. } 

Сочетание этих аннотаций в основном создают один экземпляр TimerBean во время последовательности запуска сервера приложений.

КПП. Конструктор с @PostConstruct является неправильной идеей, и он может вести себя непредсказуемым во время выполнения (не уверен, что это возможно, но вы создаете круговую инстанцию ​​с этим комбо).

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