定时器服务空
TimerService null
老实说,我在这里遗漏了一些东西。我不知道如何创建 TimerService 对象的实例。它始终为空。我没有构造函数,因为它是一个接口。我不能使用创建方法。 @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 constructor null
& 然后在服务器之后 运行 如果我调用开始或修改:
Start or modify null
编辑:
我通过制作 TimerBean @Singleton
& @Startup
并用 @PostConstruct
方法替换构造函数来让它工作。
然而,当我尝试使用它的方法时它为 TimerService
实例化了一个对象,它给我 java.lang.IllegalArgumentException: Unknown bean state 0
没有任何信息...
如果您尝试使用字段注入,那么您将依赖框架在对象已经被实例化并设置字段后出现,因此它将始终 在构造函数中为 null。您可以在 @PostConstruct
方法中执行您需要的任何逻辑,或者,我的强烈偏好,将 TimerService
作为构造函数参数而不是直接注入字段。
为此我最终使用了 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;
@PostConstruct
is never called. @Inject
is not either (and Im unsure if I did it right)
I got it to work by making the TimerBean @Singleton
& @Startup
& replacing constructor with @PostConstruct
method.
chrylis 是对的。根据您的描述,您似乎是通过构造函数实例化了 TimerBean。
结果是您自己管理生命周期,容器无法再处理此实例并注入。
将您的 TimerBean 注入到您要使用它的 class 中(例如 Session),或者像您一样使用它:
@Singleton
@Startup
public class TimerBean { .. }
这些注释的组合基本上在应用程序服务器启动序列期间创建一个 TimerBean 实例。
顺便说一句。 @PostConstruct
的构造函数是错误的想法,它在 运行 时间内的行为可能真的不可预测(不确定是否可能,但您使用此组合创建了循环实例化)。
老实说,我在这里遗漏了一些东西。我不知道如何创建 TimerService 对象的实例。它始终为空。我没有构造函数,因为它是一个接口。我不能使用创建方法。 @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 constructor null
& 然后在服务器之后 运行 如果我调用开始或修改:
Start or modify null
编辑:
我通过制作 TimerBean @Singleton
& @Startup
并用 @PostConstruct
方法替换构造函数来让它工作。
然而,当我尝试使用它的方法时它为 TimerService
实例化了一个对象,它给我 java.lang.IllegalArgumentException: Unknown bean state 0
没有任何信息...
如果您尝试使用字段注入,那么您将依赖框架在对象已经被实例化并设置字段后出现,因此它将始终 在构造函数中为 null。您可以在 @PostConstruct
方法中执行您需要的任何逻辑,或者,我的强烈偏好,将 TimerService
作为构造函数参数而不是直接注入字段。
为此我最终使用了 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;
@PostConstruct
is never called.@Inject
is not either (and Im unsure if I did it right)I got it to work by making the TimerBean
@Singleton
&@Startup
& replacing constructor with@PostConstruct
method.
chrylis 是对的。根据您的描述,您似乎是通过构造函数实例化了 TimerBean。
结果是您自己管理生命周期,容器无法再处理此实例并注入。
将您的 TimerBean 注入到您要使用它的 class 中(例如 Session),或者像您一样使用它:
@Singleton
@Startup
public class TimerBean { .. }
这些注释的组合基本上在应用程序服务器启动序列期间创建一个 TimerBean 实例。
顺便说一句。 @PostConstruct
的构造函数是错误的想法,它在 运行 时间内的行为可能真的不可预测(不确定是否可能,但您使用此组合创建了循环实例化)。