TimerService null

时间:2015-03-05 14:38:35

标签: java timer weblogic

我老实说这里遗漏了一些东西。我不知道如何创建TimerService对象的实例。它始终为空。我没有构造函数,因为它是一个接口。我不能使用create方法。 @Resource似乎没有为它分配任何东西。

我正在尝试设置一个简单的程序计时器,每隔X分钟执行一次任务。超时持续时间可根据可在整个运行时间更改的配置而有所不同。我正在使用WebLogic 12 Web应用程序。

到目前为止我所拥有的:

import javax.annotation.Resource;
import javax.ejb.Singleton;
import javax.ejb.Timeout;
import javax.ejb.Timer;
import javax.ejb.TimerService;

@Singleton
public class TimerBean {
    @Resource
    protected TimerService timerService;

    public TimerBean(){
        System.out.println("TimerBean constructor " + timerService);
    }

    @Timeout
    public void timeoutHandler(Timer timer){
        String name = timer.getInfo().toString();
        System.out.println("Timer ticked. Name=" + name);
    }


    public void startOrModifyTimer(long initialExpiration, long interval, String name) {
        System.out.println("Start or modify " + timerService);
    }
}

输出:

  

TimerBean构造函数null

&安培;然后在服务器运行后,如果我调用start或modify:

  

开始或修改null


编辑: 我通过制作TimerBean @Singleton&来实现它。 @Startup&用@PostConstruct方法替换构造函数。

然而,当我尝试使用它的方法时,它有TimerService实例化的对象,它给了我java.lang.IllegalArgumentException: Unknown bean state 0没有信息......

3 个答案:

答案 0 :(得分:2)

如果您正在尝试使用字段注入,那么在对象已经实例化并设置字段后,您依赖于框架,因此始终将为空构造函数。您可以在@PostConstruct方法中执行所需的任何逻辑,或者,我强烈的偏好,将TimerService作为构造函数参数注入,而不是直接注入字段。

答案 1 :(得分:2)

  永远不会调用

@PostConstruct@Inject也不是(我不确定我是否做得对)

     

我通过制作TimerBean @Singleton&来实现它。 @Startup&用@PostConstruct方法替换构造函数。

chrylis是对的。从您的描述看起来,您通过构造函数实例化 TimerBean

结果是您自己管理生命周期,容器无法处理此实例并再次注入。

TimerBean 注入要使用它的类(例如Session),或者像你一样使用它:

@Singleton
@Startup
public class TimerBean { .. } 

这些注释的组合基本上会在应用服务器启动序列中创建一个 TimerBean 实例。

顺便说一下。使用@PostConstruct的构造函数是错误的想法,并且它在运行时可能表现得非常不可预测(不确定是否可行,但是您使用此组合创建循环实例化)。

答案 2 :(得分:1)

我最终使用了Timer& TimerTask为此。无法算出TimerService。那好吧。似乎工作正常。

对于任何好奇的人:

    long interval = minutes*60*1000;
    long delay = interval;

    if(prevTask != null){
        delay = System.currentTimeMillis() - prevTask.scheduledExecutionTime(); //time left of previous setting
        prevTask.cancel();
        delay = interval - delay; //difference in time left & new interval
        if(delay <=0) //if by new setting should've already ran, so run it ASAP...
            delay = 2000;

        logger.info(String.format("DB dump was already scheduled before. Set dump delay to %s minutes & setting new schedule to every %s minutes.", delay/60/1000, minutes));
    }

    TimerTask task = new TimerTask(){
        private SimpleDateFormat ft = new SimpleDateFormat("yyyy.MM.dd 'at' HH:mm:ss SSS");
        private int minutes;
        public TimerTask initialize(int minutes){
            this.minutes = minutes;
            return this;
        }
        public void run() {
            try {
                logger.info(String.format("Doing scheduled %s dump to DB. (Configured to occur every %s minutes.)", ft.format(new Date(this.scheduledExecutionTime())), minutes));
                dumpToDB();
            } catch (NamingException | SQLException e) {
                e.printStackTrace();
            }
        }
    }.initialize(minutes);

    timer.schedule(task, delay, interval);
    prevTask = task;