有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java TimerService null

我真的错过了一些东西。我不知道如何创建TimerService对象的实例。它总是空的。我没有构造函数,因为它是一个接口。我不能使用create方法@资源似乎没有分配任何东西给它

我正在尝试设置一个简单的编程计时器,它每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或modify:

Start or modify null


编辑: 我通过制作TimerBean @Singleton&@Startup&;用@PostConstruct方法替换构造函数

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


共 (3) 个答案

  1. # 1 楼答案

    @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注入到您想要使用它的类中(例如会话),或者像您那样使用它:

    @Singleton
    @Startup
    public class TimerBean { .. } 
    

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

    顺便说一句,使用@PostConstruct的构造函数是错误的想法,在运行时它的行为可能真的不可预测(不确定是否可能,但您可以使用此组合创建循环实例化)

  2. # 2 楼答案

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

  3. # 3 楼答案

    我最终使用了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;