2014-10-03 4 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

+0

CDI는 프록시와 인트로 스펙 션을 사용하기 때문에 CDI 컨텍스트에 액세스 할 수있는 'private'클래스가있을 것이라고 확신하지 못합니다. 당신은'DemonImpl'에 주입하여'Updater'에서 액세스하는 것이 더 나을 것입니다. – kolossus

+0

맞습니다. 그것은 개인 클래스로 작동하지 않습니다. 코드를 새로운 클래스로 옮겼습니다. – user3085884

답변

0

일반적으로 클래스가 CDI Bean이 아닌 경우 NPE가 있습니다. 새 Updater()를 만들면 CDI는이를 고려하지 않습니다. 싱글 톤에 @Interater를 설치해야합니다.

0

CDI는 Updater 인스턴스를 직접 생성자를 호출하여 인스턴스화하므로 인스턴스를 관리하지 않습니다.

  1. DemonImplUpdater 클래스의 인스턴스를 주입하고 하나를 사용

    지금이 문제를 해결하는 방법은 두 가지가 있습니다.

  2. Provider<Updater> 인스턴스를 DemonImpl에 삽입하여 런타임에 새 CDI 관리 인스턴스를 만들고이 인스턴스에서 Updater 클래스의 새 인스턴스를 가져옵니다.
관련 문제