在TimerTask中注入服务

时间:2014-10-03 11:10:26

标签: cdi 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)

除了这个类,应用程序工作正常。如何在应用程序完全正常工作时注入服务?

2 个答案:

答案 0 :(得分:0)

CDI将不会管理实例,因为您通过自己调用构造函数来实例化Updater

现在有两种方法可以解决这个问题:

  1. Updater中注入DemonImpl类的实例并使用该实例。
  2. 通过在Provider<Updater>中注入DemonImpl实例并从中获取Updater类的新实例,在运行时创建新的CDI托管实例。

答案 1 :(得分:0)

当Class不是CDI Bean时,通常你有一个NPE。如果您创建新的Updater(),则CDI不会考虑这一点。你必须在Singleton中@Inject the Updater。