我老实说这里遗漏了一些东西。我不知道如何创建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
没有信息......
答案 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;