2012-10-18 25 views
3

我知道在無狀態會話bean中使用實例變量是一個流行的討論主題,並且已經閱讀了其中的一些內容,但是我特別需要的是這個主題我的應用程序的實際設計。在無狀態的EJB定時器中正確使用實例變量

我的企業應用程序由幾個無狀態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); 
    } 

} 

然而,當我做了一個小測試手動調用多個計時器,以不同的間隔,eventIDs和serverIPs,我沒有從所有的定時器預期的行爲(其中一些從未超時等。 )。

上述來源是否適合所需用途,或者我應該如何設計/實施它?如果是的話,你能否提出一些建議?

回答

3

我認爲你不應該在一個無狀態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返回到池中。

當2000ms以後發生超時時,它可能是從池中取出的另一個EJB實例,用於處理@timeout註釋方法的方法調用。

+0

存儲數據的另一種方式是將'name'屬性設置爲'static',或者如果名稱是爲每個定時器指定的,則要使用'static Map '並使用'timer.getInfo() .toString()'作爲'Map'鍵。 –