您如何建议在JavaEE中实现以下内容:
我需要在app服务器(我正在考虑有状态会话bean)中有一个后台进程,它会持续监视“某些东西”,如果某些条件适用,它会对数据库进行操作。
最重要的是,它必须由各种客户远程操作。
所以,基本上,我需要一个能够持续运行的进程,保持其状态并为许多远程客户端的方法调用打开。
由于我是JavaEE的新手,我有点困惑使用哪种方法/“技术”。我们将不胜感激。
答案 0 :(得分:7)
您可以将无状态会话或单例bean与EJB计时器和计时器服务结合使用。 bean将是远程客户端用来控制后台进程的接口。计时器服务会定期回调bean上的方法以验证条件。计时器由EJB容器自动持久化,因此当bean客户端断开连接时,它们将完成它们的工作。
这是一幅草图:
@Singleton
...
public TimerMangerbean implements TimerManager {
@Resource
private TimerService timerService;
public void startMonitoring() {
//start in 5 sec and timeout every 10 minutes
Timer timer = timerService.createTimer(5000, 60000, "MyTimer");
}
public void stopMonitoring() {
Collection<Timer> timers = timerService.getTimers();
for(Timer timer : timers) {
//look for your timer
if("MyTimer".equals(timer.getInfo())) {
timer.cancel();break;
}
}
}
//called every 10 minutes
@Timeout
public void onTimeout() {
//verify the condition and do your processing
}
}
答案 1 :(得分:1)
Java EE是解决方案。您需要按照以下步骤操作:
构建一个Java EE应用程序,一个包含EJB的jar:
1.1你需要一个IDE:Eclipse Juno是我的最爱, 1.2网上有很多tuto。搜索EJB3,你会发现,
编辑:一个完整的Timer EJB类(如果需要,可以自动重新加载)
package clouderial.saas.commons.utils;
import java.util.Map;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import javax.ejb.ScheduleExpression;
import javax.ejb.Timeout;
import javax.ejb.Timer;
import javax.ejb.TimerConfig;
import javax.ejb.TimerService;
import javax.inject.Inject;
import jmcnet.libcommun.exception.ExceptionTechnique;
import jmcnet.libcommun.utilit.mail.MailException;
import org.apache.commons.configuration.event.ConfigurationEvent;
import org.apache.commons.configuration.event.ConfigurationListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import clouderial.saas.commons.email.EmailSender;
import clouderial.saas.commons.jpamongo.JPAMongoBasePersistenceContextAccessor;
/**
* A base class for a periodic process
* @author jmc
*
*/
public abstract class PeriodicProcessBase extends JPAMongoBasePersistenceContextAccessor implements ConfigurationListener {
private static Logger log = LoggerFactory.getLogger(PeriodicProcessBase.class);
@Resource
private TimerService timerService;
@Inject
protected GlobalConfiguration _config;
@Inject
protected EmailSender _emailSender;
private Timer _timer=null;
private String _processName=null;
private Logger _log = null;
protected void initTimer(String processName, Logger log) {
if (processName != null) _processName = processName;
if (log != null) _log = log;
String second = _config.getString("timer."+_processName+".second","0");
String minute = _config.getString("timer."+_processName+".minute","0");
String hour = _config.getString("timer."+_processName+".hours","4");
String dayOfWeek = _config.getString("timer."+_processName+".dayOfWeek","*");
ScheduleExpression scheduleExp =
new ScheduleExpression().second(second).minute(minute).hour(hour).dayOfWeek(dayOfWeek);
cancelTimer();
if (timerService != null) {
_timer = timerService.createCalendarTimer(scheduleExp, new TimerConfig(_processName, false));
_log.info("{} : timer programmed for '{}'h, '{}'m, '{}'s for days '{}'.", _processName, hour, minute, second, dayOfWeek);
}
else _log.error("{} : no timer programmed because timerService is not initialized. (Normal during tests)", _processName);
// Listen to change
_config.addModificationListener(this); // on timer modification, configurationChanged is called
}
@PreDestroy
private void cancelTimer() {
if (_log != null) _log.info("Stopping timer for '{}'", _processName);
if (_timer != null) _timer.cancel();
_timer = null;
}
@Override
public void configurationChanged(ConfigurationEvent event) {
if (_log != null) _log.info("Configuration have change. Reloading config for ProcessBilling.");
_config.removeModificationListener(this);
initTimer(null, null);
}
@Timeout
private void run(Timer timer) {
runProcess(timer);
}
/**
* The entry point for runner the process. Must be overriden by super class
* @param timer
*/
protected abstract void runProcess(Timer timer); // do the job here
}
我希望这会有所帮助。
答案 2 :(得分:1)
石英怎么样?查看链接 http://rwatsh.blogspot.com/2007/03/using-quartz-scheduler-in-java-ee-web.html http://lanbuithe.blogspot.com/2011/07/using-quartz-scheduler-in-java-ee-web.html http://www.mkyong.com/tutorials/quartz-scheduler-tutorial/
答案 3 :(得分:1)
正如您所说,您有两个要求:1)定期执行一些后台工作,以及2)回应客户请求。
对于1),您可以使用TimerService
或使用ServletContextListener
生成线程。第二个不完全符合,但有效。如果你使用计时器,你可以创建一个定期计时器(如@dcernahoschi所指出的),或者一个重新安排自己的独特计时器:
@Timeout
public void onTimeout() {
//do something
// create a new timer
}
如果您的定期计时器每10秒触发一次并且您的处理时间超过10秒,那么您可能会遇到问题。如果处理时间不固定,那么重新安排计时器的计时器会更好。
对于2)你可以使用无状态或staefull EJB,这正是他们的目的。