2014-10-03 71 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受管实例。