gpt4 book ai didi

java - 在无状态 EJB 计时器中正确使用实例变量

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:55:25 25 4
gpt4 key购买 nike

我知道在无状态 session bean 中使用实例变量是一个流行的讨论主题,并且已经阅读了其中的一些内容,但我特别需要从这个主题中得到的是我的应用程序的实际正确设计。

我的企业应用程序由几个无状态 bean 组成,它们会在特定事件上触发。在此类事件中,我还希望触发几个计时器并跟踪某些事情(例如,数据库中插入的新数据,特定于原始事件)。

@Stateless
public class SpecificFeedbackImpl implements SpecificFeedback {

@Resource
protected TimerService timerService;

//more injections here

public String name;
public String ip;

@Timeout
public void timeoutHandler(Timer timer) {
if (timer.getInfo().toString().startsWith(name)) {

//search db for data of event with identifier "name"
//if anything found, then send to "ip"

}
}

public void stopTimer() {
for (Object o : this.timerService.getTimers())
if (((Timer) o).getInfo().toString().startsWith(name)){
((Timer)o).cancel();
}
}

@Override
public void startTimer(long interval, String eventID, String serverIP){
this.name = eventID;
this.ip = serverIP;
stopTimer();
TimerConfig config = new TimerConfig();
config.setInfo(name);
config.setPersistent(false);
timerService.createIntervalTimer(interval, interval, config);
}

}

但是,当我用不同的时间间隔、eventID 和 serverIP 手动调用多个计时器时,我并没有得到所有计时器的预期行为(其中一些从未超时等)。

上面的源是否适合所需的用途,或者我应该以不同的方式设计/实现它?如果是,能否请您提出一些选择?

最佳答案

我认为您不应该将状态存储在无状态 bean 中。替代方案是将其存储在 db/em 中或将其存储在单例 bean 中。

编辑如下:

在数据库中存储的一种方法是使用 JPA:http://www.vogella.com/articles/JavaPersistenceAPI/article.html

解释为什么在 ejb 中存储状态是个坏主意:
改变你的超时方法是这样的:

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

然后尝试启动几个计时器:

@Singleton
@Startup
public class SingletonBean {

@EJB
LabBean labBean;

@PostConstruct
public void init() {
labBean.startTimer(2000, "123", "1.2.3.4");
labBean.startTimer(2000, "222", "1.2.3.4");
labBean.startTimer(2000, "333", "1.2.3.4");
labBean.startTimer(2000, "444", "1.2.3.4");
labBean.startTimer(2000, "555", "1.2.3.4");
labBean.startTimer(2000, "666", "1.2.3.4");
}
}

您将看到控制台输出显示如下内容:

INFO: actualName=123 storedName=666
INFO: actualName=555 storedName=666
INFO: actualName=333 storedName=null
INFO: actualName=444 storedName=null
INFO: actualName=666 storedName=666
INFO: actualName=222 storedName=null

原因是当您调用 startTimer() 时,无状态 EJB 实例是从 EJB 池中获取的。当 startTimer() 方法返回时,EJB 返回到池中。

当超时发生在 2000 毫秒后,它可能是从池中获取的另一个 EJB 实例来处理 @timeout 注释方法的方法调用。

关于java - 在无状态 EJB 计时器中正确使用实例变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12953371/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com