2013-04-07 46 views
5

實現持續運行過程中,你會如何建議實施的JavaEE如下:如何在JavaEE的

  1. 我需要在應用服務器後臺進程(我在想一個有狀態會話bean)不斷監控「某些事情」,如果有一些條件適用,它會對數據庫進行操作。

  2. 最重要的是它必須由各種客戶遠程操縱。

所以,基本上,我需要將不斷運行,保持其狀態,並通過一些遠程客戶端開放給方法調用的過程。

因爲我是JavaEE的新手,我對使用哪種方法/「技術」感到困惑。幫助將不勝感激。

回答

6

可以將無狀態會話或單例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 
    } 
} 

參見:Using the timer service on Oracle JavaEE tutorial

+0

一個TimerEJB欣賞你的答案完全反應,但我希望做一個更根本的辦法,解決你的建議看起來更像是一招。是否還有另一個更基礎的解決方案可以適用於更廣泛的連續過程及其操作問題。 – 2013-04-07 09:36:53

+0

不,不是訣竅,'TimerService'和'Timer'(s)是JEE中控制和執行重複過程的標準方法。他們不會將您與特定類型的問題聯繫起來。你在這個方法中看到了什麼限制?如你所說,這個問題似乎是一個完美的匹配。 – dcernahoschi 2013-04-07 10:04:56

+0

+1對Java EE中長時間運行的後臺進程沒有直接的支持。相反,他們使用'TimerService'支持定期計時器。 – ewernli 2013-04-07 11:20:32

1

Java EE是解決方案。您將需要按照放入系統的步驟:

  1. 構建Java EE應用程序,包含EJB罐子:

    1.1,您將需要一個IDE:Eclipse的朱諾是我的FAVORIT, 1.2許多政黨成員存在於網絡。搜索EJB3,你會發現,

  2. 有一個應用程序服務器來運行你的EJB。 JBoss是一個不錯的選擇,Glassfish是另一個不錯的選擇。使用安裝了JBoss和JBoss Tools插件的Eclipse,您將能夠快速構建和運行基本應用程序。

編輯:一個完整​​的計時器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 

} 

我希望這有助於。

+0

是的,我實際上使用JBoss工具運行JBoss 7.1.1和Eclipse Juno。問題是要使用哪個特定的API,以便進程不斷運行,並且例如,客戶端斷開連接(SLSB)後不會銷燬。 – 2013-04-07 08:23:05

+0

OK讓檢查上面實現到JBoss 7.1.1 – jmcollin92 2013-04-07 14:37:08

1

正如你說你自己,你有兩個要求:1)定期進行一些後臺作業,以及2)響應客戶端請求。

對於1),您可以使用TimerService或產生帶ServletContextListener的線程。第二個不完全符合,但有效。如果您使用的定時器,您可以創建一個週期定時器(由@dcernahoschi指出的),或唯一計時器,重新安排自己:

@Timeout 
public void onTimeout() { 
    //do something 
    // create a new timer 
} 

如果你的週期定時器火災每10秒,你有最後的處理超過10秒鐘,你可能會遇到問題。如果處理時間不固定,那麼重新計劃自己的計時器會更好。

對於2),您可以用statelesss或staefull EJB去,這正是他們的目的。