2014-10-03 70 views
0

我需要每天運行一個進程以便在服務器上執行維護工作(更新記錄)。在TimerTask內部注入服務

我有一個單例作用域類運行一個計時器和一個內部類與注入我需要的服務。當我運行程序時,計時器拋出一個NullPointerException,因爲該服務沒有被注入。

@Named("demonService") 
@Singleton 
public class DemonImpl implements IDemonService 
{ 
    private static Logger log = Logger.getLogger(DemonioImpl.class); 

    @PostConstruct 
    public void init() 
    { 
     log.info("-->Demon"); 

     Calendar today = new GregorianCalendar();//Every day at 2:00am (from now) 
     today.set(Calendar.HOUR_OF_DAY, 2); 
     today.set(Calendar.MINUTE, 0); 
     today.set(Calendar.SECOND, 0); 

     try 
     { 
      Timer timer = new Timer(true); 
      timer.schedule(new Updater(), today.getTime(), 24*60*60*1000); 
     } 
     catch(Exception e) 
     { 
      log.fatal(e.getLocalizedMessage()); 
      e.printStackTrace(); 
     } 
     log.info("--> Demon: exit"); 
} 

private class Updater extends TimerTask 
{ 
    private Logger log = Logger.getLogger(Updater.class); 

    @Inject 
    @Named("updaterService") 
    private IUpdaterService updaterService; 

    @Override 
    public void run() 
    { 
     log.info("Task: update records (start)"); 

     List<Record> list = updaterService.getAll();//<-- This throws the exception 
     for(Record item : list) 
     { 
      updaterService.update(item); 
     } 

     log.info("Task: update records (exit)"); 
    } 
} 

的錯誤是

Exception in thread "Timer-3" java.lang.NullPointerException at test.service.impl.DemonImpl$Updater.run(DemonImpl.java:66) at java.util.TimerThread.mainLoop(Timer.java:555) at java.util.TimerThread.run(Timer.java:505)

應用程序工作正常,除了這個類。如何在應用程序全面運行時注入服務?

+0

如果你希望注入的字段或方法被實例化,那麼它不是用新的Bean()調用bean的正確方法,導致平臺不處理當前bean – AntJavaDev 2014-10-03 13:34:13

+0

由於CDI使用代理和內省,我不確定CDI上下文是否可以訪問「私人」類。通過注入'DemonImpl',然後從'Updater'中訪問,你會更好。 – kolossus 2014-10-03 21:37:15

+0

你是對的,它不能用作私人類。我已經將代碼移到了新的類中。 – user3085884 2014-10-06 07:50:37

回答

0

通常情況下,當類不是CDI Bean時,你有NPE。如果您製作新的更新程序(),CDI不會考慮這一點。你必須@在Singleton中注入更新器。

0

由於您通過自己調用它的構造函數來實例化您的Updater,CDI將不管理該​​實例。

現在有兩種方法來解決這個問題:

  1. 注入Updater類的實例在DemonImpl和使用的那一個。
  2. 在運行時通過在DemonImpl中注入Provider<Updater>實例並從中獲取Updater類的新實例,從而在運行時創建新的CDI受管實例。