3

ステートレス セッション 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);
    }

}

ただし、複数のタイマーを異なる間隔、イベント ID、およびサーバー IP で手動で呼び出す小さなテストを行ったところ、すべてのタイマーで期待どおりの動作が得られませんでした (一部のタイマーはタイムアウトにならないなど)。

上記のソースは必要な使用法に適していますか、それとも別の方法で設計/実装する必要がありますか? はいの場合、いくつかのオプションを提案していただけますか?

4

1 に答える 1

3

ステートレス Bean に状態を格納するべきではないと思います。別の方法として、db/em に格納するか、シングルトン Bean に格納します。

以下を編集します。

データベースに格納する 1 つの方法は、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 ミリ秒後にタイムアウトが発生した場合、@timeout アノテーション付きメソッドのメソッド呼び出しを処理するためにプールから取得された別の EJB インスタンスである可能性があります。

于 2012-11-13T15:55:34.910 に答える