質問が多いので、すぐに答えて、追加情報へのリンクを提供しようと思います。
アプリコンテナ(私の場合はGlassFish)は、ステートフルであるかどうかに応じて、EJBにどのような異なる制限を課しますか?
あなたの場合の主な違いは、仕様からの次の引用でわかります:
ステートレスセッションBeanは、インスタンスに会話状態がないセッションBeanです。これは、クライアントによって呼び出されたメソッドのサービスに関与していない場合、すべてのBeanインスタンスが同等であることを意味します。「ステートレス」という用語は、インスタンスに特定のクライアントの状態がないことを意味します。ただし、インスタンスのインスタンス変数には、クライアントによって呼び出されたメソッド呼び出し全体の状態を含めることができます。このような状態の例には、開いているデータベース接続やエンタープライズBeanオブジェクトへのオブジェクト参照が含まれます。
@Statefulの場合、同じユーザー/クライアントからのクライアント側のリクエストは、どのようにして正しいBean(前のリクエストからのクライアントの状態を維持しているBean)にマップされますか?
クライアント側では、ステートフルセッションBeanのビジネスインターフェイスへの参照を保存する必要があります。EJBコンテナから取得したこのオブジェクト。これは、サーバー側オブジェクトの検索方法に関する詳細を含むコンテナー作成オブジェクトです。GlassFishのこれらのプロキシに関するいくつかの情報は、次の場所から見つけることができます。
セッションBeanはいつ死にますか?@Statelessのリクエストが行われた直後だと思いますが、@Statefulの手がかりはありません。
いいえ、ステートレスセッションBean(SLSB)は要求後に停止しません。ステートレスセッションBeanの寿命は次のとおりです。
- コンテナがそのように決定したときに作成されます。これは、使用される前のある時点で自然に発生しますが、それ以外の場合はコンテナの手に渡ります。SLSBが作成されると、プールに配置されます。
- 一部のクライアントがSLSBでメソッドを呼び出す必要がある場合、メソッド呼び出しの期間中、1つのインスタンスがプールから削除されます。メソッド呼び出しが終了すると、インスタンスはプールに戻されます。これで、このインスタンス(他のインスタンス)は次のクライアントにサービスを提供する準備が整います。
- コンテナがプールのサイズを調整することを決定すると、SLSBの寿命は終了します
ステートフルセッションBean(SFSB)の寿命は、おおまかに次のとおりです。
- JNDIルックアップまたはインジェクションが発生すると、コンテナーによって新しいインスタンスが作成されます。
- SFSBは、その存続期間中、複数のメソッド呼び出しを処理できます。また、不動態化(基本的にはリソースを節約するためにディスクに保存)して、再度アクティブ化することもできます。
- 削除メソッドが呼び出されるか、タイムアウト(SFSBが一定期間使用されていなかった)が発生すると、SFSBの有効期間は終了します。コンテナには通常、実装固有のデフォルトのタイムアウトがあり、タイムアウトも調整できます。Java EE 6(EJB 3.1)では、このタイムアウトはStatefulTimeoutを介してBeanごとに調整できます。
さらに、システム例外が発生すると、セッションBeanのインスタンスは破棄されます。システム例外は、RuntimeException(アプリケーション例外としてマークされていない)またはjava.rmi.RemoteExceptionです。SLSBのインスタンスが破棄されるという事実は、クライアントに対して透過的です。次の呼び出しは、SLSBの他のインスタンスによって確実に処理されます。SFSBの場合、SFSBのサーバー側インスタンスが存在しないため、将来発生する可能性のあるすべてのビジネスメソッド呼び出しは失敗します。詳細については、EJB3.1仕様の第14章を参照してください。
ライフサイクルの明確で詳細な説明は、EJB 3.1仕様(4.6、4.7)に記載されています。上記よりも詳細でグラフ付きの説明は、JavaEE6チュートリアルにあります。
そして、Helloサービスの設計の主な効果は何ですか?
@Stateless
public class HelloStateless implements HelloRemote {
@Override
public String getGreeting(String name) {
return "Hi " + name;
}
}
/**
* This design is not possible for Stateless, because
* subsequent calls to setName and getGreeting can be
* handled by two different instances. For stateful it
* is fine, because we use one exclusively one instance.
*/
@Stateful
public class HelloStateful {
private String name;
public void setName(String name) {
this.name = name;
}
public String getGreeting() {
return "Hi " + name;
}
}