Внедрение сервиса внутрь 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)

Приложение работает нормально, кроме этого класса. Как я могу внедрить сервис, когда приложение полностью работает?


person user3085884    schedule 03.10.2014    source источник
comment
если вы хотите, чтобы введенные поля или методы БЫЛИ экземпляром, то это неправильный способ вызова bean-компонента с помощью new Bean() , потому что платформа не обрабатывает текущий bean-компонент   -  person AntJavaDev    schedule 03.10.2014
comment
Поскольку CDI использует прокси и самоанализ, я не уверен, что класс private будет доступен в контексте CDI. Вам будет лучше, если вы сделаете инъекцию в DemonImpl, а затем получите доступ к ней из Updater.   -  person kolossus    schedule 04.10.2014
comment
Вы правы, это не работает как частный класс. Я переместил код в новый класс.   -  person user3085884    schedule 06.10.2014


Ответы (2)


Обычно у вас есть NPE, когда класс не является компонентом CDI. Если вы создаете новый Updater(), это не рассматривается CDI. вам нужно @Inject Updater в вашем синглтоне.

person Lorenzo Tama De Micheli    schedule 03.10.2014

CDI не будет управлять экземпляром, поскольку вы создаете свой экземпляр Updater, вызывая его конструктор самостоятельно.

Теперь есть два способа это исправить:

  1. Вставьте экземпляр класса Updater в DemonImpl и используйте его.
  2. Создайте новый управляемый экземпляр CDI во время выполнения, внедрив экземпляр Provider<Updater> в DemonImpl и получив от него новый экземпляр класса Updater.
person ChristopherS    schedule 03.10.2014