![]() |
Sun ONE Application Server 7 Enterprise Java Beans 開発者ガイド |
セッション Beans の使用この章では、Sun ONE Application Server 7 の環境でセッション Beans を作成するためのガイドラインを示します。
注 セッション Beans または EJB テクノロジに精通していない場合は、Java Software チュートリアルを参照してください。
http://java.sun.com/j2ee/docs.html
セッション Beans に関する詳細情報は、『Enterprise JavaBeans Specification, v2.0』の第 6 章〜 8 章にあります。
Sun ONE Application Server の概要は、「Sun ONE Application Server Enterprise JavaBeans の紹介」および『Sun ONE Application Server Product Introduction』にあります。
この節には次の項目があります。
セッション Beans に関する詳細情報は、『Enterprise JavaBeans Specification, v2.0』の第 6 章〜 8 章にあります。
セッション Beans について
この節では、ビジネスプロセスに対して効果的なモデルを開発するために、セッション Beans について注意が必要な事項の概要を示します。
この節には次の項目があります。
セッション Bean の特性
セッション Bean の特性を定義することは、アプリケーション内の持続的でない独立したステータスと関係があります。セッション Bean は、Sun ONE Application Server で動作するクライアントアプリケーションの一時的な論理拡張と考えることもできます。通常、セッション Bean はデータベースの共有データを表しませんが、データのスナップショットを取得します。ただし、セッション Bean はデータを更新できます。
セッション Beans には次の特性があります。
- 1 つのクライアントを対象に実行する
- トランザクションを認識できる
- 基礎となるデータベース内の共有データを直接表さないが、このデータのアクセスおよび更新は可能である
- 短命である
- データベース内で持続されない
- コンテナがクラッシュすると削除され、クライアントは新しいセッションを確立する必要がある
標準的な分散アプリケーションの多くは、繰り返しタスク、時限タスク、およびユーザ依存のタスクを実行するコードの論理的な単位から構成されます。これらのタスクには、単純なものと複雑なものがあり、さまざまなアプリケーションで必要です。たとえば、バンキングアプリケーションでは、トランザクションを実行する前に必ず顧客のアカウント ID と残高を照合する必要があります。このような個々のタスクは、本来は一時的なものであるためセッション Beans に適していると考えられます。
サンプルシナリオ
Web ベースのオンラインショッピングアプリケーションでよく利用されるショッピングカートは、典型的なセッション Bean です。これは、ユーザがアイテムを選択した場合にのみ、オンラインショッピングアプリケーションによって作成されます。アイテムの選択が完了すると、カート内のアイテムの価格が計算され、注文が出され、ショッピングカートオブジェクトが解放されます。ユーザはオンラインカタログで商品のブラウズを続けることができ、ユーザが別の商品を注文したい場合には、新しいショッピングカートが作成されます。
セッション Bean には、ほかのアプリケーションオブジェクトとの依存関係やコネクションを持たないものもあります。たとえば、ショッピングカートの Bean には、アイテム情報を格納するデータリストメンバー、現在カート内にあるアイテムの総額を格納するデータメンバー、およびアイテムの追加、削除、レポート、総計を行うメソッドがあります。一方、ショッピングカートには、データベースへのライブコネクションは一切ありません。
コンテナ
エンティティ Bean と同様に、セッション Bean は JDBC 呼び出しを介してデータベースにアクセスすることができます。また、セッション Bean はトランザクション設定も提供できます。これらのトランザクション設定や JDBC 呼び出しは、セッション Bean のコンテナによって参照されます。これにより、セッション Bean はコンテナによって管理されるトランザクションに関与できます。
コンテナ管理によるステートレスセッション Beans は、コンテナ管理によるステートフルセッション Beans とは異なるチャーターを持ちます。
ステートレスコンテナ
ステートレスコンテナは、ステートレスセッション Beans を管理します。ステートレスセッション Beans はクライアントに固有の状態を持ちません。したがって、特定の種類のすべてのセッション Beans は同じであると見なすことができます。
ステートレスセッション Bean コンテナは、Bean プールを使用して要求を処理します。Bean プールを定義するプロパティは、Sun ONE Application Server 固有の XML ファイルに格納されます。
- steady-pool-size
- resize-quantity
- max-pool-size
- pool-idle-timeout-in-seconds
これらのプロパティは、「sun-ejb-jar.xml ファイルの要素」に示された配備記述子用に定義されます。
ステートフルコンテナ
ステートフルコンテナは、ステートフルセッション Beans を管理します。ステートフルセッション Beans はクライアントに固有の状態を持ちます。クライアントとステートフルセッション Beans の関係は、1 対 1 です。ステートフルセッション Bean を作成すると、それぞれに一意のセッション ID が割り当てられ、セッション Bean へのアクセス時に参照されます。ID は一意であるため、ステートフルセッション Bean のインスタンスに 1 つのクライアントだけがアクセスします。
ステートフルセッション Beans は、キャッシュを使って管理されます。ステートフルセッション Beans のキャッシュのサイズと動作は、次のパラメータを指定して制御できます。
- max-cache-size
- resize-quantity
- cache-idle-timeout-in-seconds
- removal-timeout-in-seconds
- victim-selection-policy
max-cache-size はキャッシュに保持できるセッション Beans の最大数を制御します。Beans の数が max-cache-size を超えてキャッシュがオーバーフローすると、コンテナは一部の Beans を非活性化するか、直列化した Bean の状態をファイルに書き出します。このファイルの書き出し先ディレクトリは、設定 API を使用して server.xml ファイルから取得されます。
これらのプロパティは、配備記述子用に定義されています。詳細については、「sun-ejb-jar.xml ファイルの要素」を参照してください。
非活性化された Beans はファイルシステム上に保存されます。非活性化された Beans の保存先ディレクトリは、 server.xml ファイル内の server 要素の session-store 属性を使って指定できます。非活性化されたステートフルセッション Beans は、デフォルトでは instance_dir/session-store の下に作成されるアプリケーション固有のサブディレクトリに保存されます。
セッション Beans の開発
クライアントによるセッション Bean の利用が終了すると、その Bean は解放されます。アプリケーションを設計するとき、一時的な 1 つのクライアントオブジェクトを潜在的なセッション Beans として指定する必要があります。
次の各項では、効果的なセッション Beans を開発する方法を説明します。
開発の要件
セッション Beans を開発するには、次の準備をする必要があります。
- セッション Bean がリモートクライアントビューを提供する場合は、セッション Bean のリモートインタフェースとリモートホームインタフェース
- セッション Bean がローカルクライアントビューを提供する場合は、セッション Bean のローカルインタフェースとローカルホームインタフェース
- Bean クラスの実装
- アセンブルデータと配備のデータ
セッション Bean の実装クラスの要件は次のとおりです。
- javax.ejb.SessionBean インタフェースを実装する
- クラスを public として定義する。abstract または final として定義することはできない
- 引数をとらない ejbCreate メソッドを 1 つ実装する
- ビジネスメソッドを実装する
- パラメータのないパブリックコンストラクタを含める
- finalize メソッドを定義してはならない
セッション Beans の使用法の決定
ここでは、ステートフルセッション Beans を実装するか、ステートレスセッション Beans を実装するかを決定する際のガイドラインを示します。
ステートフルセッション Beans に関する検討事項
次の条件のいずれかに該当する場合は、ステートフルセッション Beans が適しています。
- Bean の状態が、その Bean と特定のクライアントとの間の対話を表す
- Bean が、メソッドの起動に関するクライアントユーザの会話型状態について情報を保持する必要がある、または会話型状態そのものを表す
- クライアントとアプリケーションのその他のコンポーネントとの間に介在して、単純化したビューをクライアントに表示する Bean
- Bean が、いくつかの Enterprise JavaBeans のワークフローをバックグラウンドで管理する
ステートフルセッション Beans は 1 つのクライアント専用であるため、アプリケーションにアクセスするユーザ数が増えるにつれて、サーバーリソースの要求が増えます。この Beans は、クライアントが明示的に削除するか、タイムアウト時にコンテナによって削除されるまでは、コンテナ内に保持されます。
キャッシュファイルがいっぱいになった場合、およびキャッシュ内の Beans がタイムアウトになった場合は、コンテナはステートフルセッション Beans を非活性化して二次ストレージに送る必要があります。その後、クライアントがその Bean にアクセスすると、コンテナはその Bean を活性化し直します。この活性化と非活性化のプロセスは、サーバーのパフォーマンスオーバーヘッドに影響を与えます。
ステートレスセッション Beans に関する検討事項
次の条件のいずれかに該当する場合は、ステートレスセッション Bean が適しています。
- Bean の状態が特定クライアントのデータを持たない。つまり、メソッドの起動に関するユーザの会話型状態を Bean が保持する必要がない
- Bean が、1 つのメソッド起動で、すべてのクライアントに関する汎用タスクを実行する
- Bean が、クライアントがよく使用する読み取り専用データセットをデータベースからフェッチする。たとえば、今月販売している製品を示す表の行を取得する Bean など
データへのアクセスまたはトランザクション操作の実行には、ステートレスセッション Bean を使用します。ステートレスセッション Beans は、少数で多数のクライアントに対応できるので、高いスケーラビリティを実現します。これらの Beans は、ステートレス Bean プールに含まれるコンテナによって管理されます。これは、ステートレス Beans はクライアントに関係付けられないためです。ステートレスセッション Bean が提供するサービスに対する要求を受け取ったコンテナは、プール内のどの Bean インスタンスにもその要求を自由にディスパッチできます。
- リモートホームインタフェースの create メソッドは、セッション Bean のリモートインタフェースに返す必要がある
- ローカルインタフェースの create メソッドは、セッション Bean のローカルインタフェースに返す必要がある
- ホームインタフェースにほかの create メソッドを入れることはできない
- ステートレスセッション Bean には、javax.ejb.SessionSynchronization インタフェースを実装することはできない
インタフェースの提供
開発者は、Bean のインタフェースを提供する必要があります。Bean にリモートビューを実装するときは、リモートコンポーネントインタフェースとリモートホームインタフェースを提供します。ローカルビューを実装するときは、ローカルコンポーネントインタフェースとローカルホームインタフェースを提供します。
インタフェースを安全に使用するためには、考えられる配備シナリオを慎重に検討してから、どのインタフェースをローカルにしてどれをリモートにするかを決定し、それらの選択を念頭においてアプリケーションコードを開発する必要があります。
次の各項で、インタフェースの作成について説明します。
リモートインタフェースの作成
セッション Bean のリモートインタフェースは、Bean のメソッドへのユーザーのアクセスを定義します。すべてのリモートインタフェースは、javax.ejb.EJBObject を拡張します。次に例を示します。
import javax.ejb.*;
import java.rmi.*;
public interface MySession extends EJBObject {
// ここでビジネスメソッドを定義します。
public String getACcountname() throws RemoteException;
}リモートインタフェースでは、クライアントが呼び出すセッション Bean のビジネスメソッドを定義します。リモートインタフェースで定義した各メソッドには、Bean クラス内の対応するメソッドを指定する必要があります。Bean クラス内の対応するメソッドには、同じ署名、同じパラメータタイプ、同じ戻り値タイプを持たせる必要があります。メソッド名の最初には「ejb」と記述します。たとえば、MySession の実装クラスには次のメソッドが含まれます。
String ejbgetAccountname() throws RemoteException
{
method implementation
}ローカルインタフェースの作成
開発中に Bean のローカルインタフェースを定義すると、呼び出し側の Bean が同じコンテナに含まれる場合、つまり同じアドレス空間または同じ Java 仮想マシン (JVM) で実行される場合に、Bean を効率的に呼び出せます。これにより、同じ場所に配置するように設計したアプリケーションのパフォーマンスが向上します。
ただし、ローカルインタフェースの呼び出しのセマンティックは、リモートインタフェースとは異なります。たとえば、リモートインタフェースは pass-by-value セマンティックを使ってパラメータを渡しますが、ローカルインタフェースでは pass-by-reference を使います。開発者は、ローカルインタフェースを通して渡されるオブジェクトは共有される可能性があることに留意する必要があります。特に、ある Enterprise JavaBean の状態が別の Enterprise JavaBean の状態に割り当てられないように注意します。また、トランザクションまたはセキュリティの内容に変化がある場合は特に、ローカルインタフェースを通して渡すオブジェクトを決定する際にも注意が必要です。
ローカルインタフェースで javax.ejb.EJBLocalObject インタフェースを拡張して、特別なインタフェースを提供することができます。ローカルインタフェースで定義されたメソッドの throws 句に、java.rmi.RemoteException を含めることはできません。次に例を示します。
import javax.ejb.*;
public interface MyLocalSession extends EJBLocalObject {
// ここでビジネスメソッドを定義します。
}ローカルインタフェースに定義された各メソッドについて、セッション Bean 内に一致するメソッドがある必要があります。一致するメソッドは、同じ名前、同じ数とタイプの引数、および同じ戻り値タイプを持っている必要があります。セッション Bean クラスの一致するメソッドの throws 句で定義されたすべての例外は、ローカルインタフェースのメソッドの throws 句で定義されている必要があります。これらのメソッドは java.rmi.RemoteException をスローできません。
ローカルホームインタフェースの作成
ホームインタフェースは、クライアントがアプリケーションを使ってセッション Beans の作成および削除を行うためのメソッドを定義します。Enterprise JavaBean のローカルホームインタフェースでは、ローカルクライアントが EJB オブジェクトの作成、検索、および削除を行うことができるようにするメソッドと、Bean インスタンス固有ではないホームビジネスメソッド (セッション Beans が検索メソッドとホームビジネスメソッドを持たない) を定義します。ローカルホームインタフェースは、開発者によって定義され、コンテナによって実装されます。クライアントは、JNDI を使用してセッション Bean のホームインタフェースを検索します。
ローカルホームインタフェースでは、ローカルクライアントは次の操作を実行できます。
- 新しいセッションオブジェクトの作成
- セッションオブジェクトの削除
ローカルホームインタフェースは通常、javax.ejb.EJBLocalHome を拡張します。次に例を示します。
import javax.ejb.*;
import java.rmi.*;public interface MySessionLocalBeanHome extends EJBLocalHome {
MySessionLocalBean create() throws CreateException;
}create メソッド
この例のように、セッション Bean のホームインタフェースでは、1 つまたは複数の create メソッドを定義します。各メソッドには create という名前を付け、セッション Bean クラスで定義された ejbCreate メソッドの数および引数のタイプと一致させる必要があります。ただし、各 create メソッドの戻り値タイプは、対応する ejbCreate メソッドの戻り値タイプとは一致しません。代わりに、セッション Bean のローカルインタフェースタイプを返します。
ejbCreate メソッドの throws 句で定義するすべての例外は、リモートインタフェース内の一致する create メソッドの throws 句で定義されている必要があります。さらに、ホームインタフェースの throws 句には常に、javax.ejb.CreateException を含める必要があります。
remove メソッド
リモートクライアントは、javax.ejb.EJBObject インタフェースの remove メソッド、または javax.ejb.EJBHome インタフェースの remove(Handle handle) メソッドを使ってセッションオブジェクトを削除できます。
セッションオブジェクトはクライアントへのアクセスに必要な主キーを持たないため、セッションで javax.ejb.EBJHome.remove(Object primaryKey) メソッドを呼び出すと、javax.ejbRemoveException が呼び出されます。
リモートホームインタフェースの作成
コンテナは、コンテナに配備されるリモートホームインタフェースを定義する各セッション Bean のリモートホームインタフェースを実装しています。これを実装するオブジェクトは、セッション EJBHome オブジェクトと呼ばれます。リモートホームインタフェースでは、クライアントは次の操作を実行できます。
- 新しいセッションオブジェクトの作成
- セッションオブジェクトの削除
- セッション Beans の javax.ejb.EJBMetaData インタフェースの取得
- リモートホームインタフェースのハンドルの取得
リモートホームインタフェースは javax.ejb.EJBHome インタフェースを拡張する必要があり、特別なインタフェースを持つことができます。このインタフェースに定義されたメソッドは、RMI/IIOP のルールに従う必要があります。
リモートホームインタフェースでは、create<METHOD>(...) メソッドを 1 つ以上定義する必要があります。
リモートホームインタフェースは通常、javax.ejb.EJBHome を拡張します。次に例を示します。
import javax.ejb.*;
import java.rmi.*;public interface MySessionHome extends EJBHome {
MySession create() throws CreateException, RemoteException;
}この例のように、セッション Bean のホームインタフェースでは、1 つまたは複数の create メソッドを定義します。ただし、各 create メソッドの戻り値タイプは、対応する ejbCreate メソッドの戻り値タイプとは一致しません。代わりに、セッション Beans のリモートインタフェースタイプを返します。
ejbCreate メソッドの throws 句で定義するすべての例外は、リモートインタフェース内の一致する create メソッドの throws 句で定義されている必要があります。さらに、ホームインタフェースの throws 句には常に、javax.ejb.CreateException および java.rmi.RemoteException を含める必要があります。
注 ステートレスセッション Beans では、ホームインタフェースは create メソッドを 1 つだけ持ち、その Bean は ejbCreate メソッドを 1 つだけ持つ必要があります。どちらのメソッドも引数をとりません。
Bean クラス定義の作成
セッション Bean のクラスは、final でも abstract でもなく、public として定義する必要があります。Bean クラスは、javax.ejb.SessionBean インタフェースを実装する必要があります。
import java.rmi.*;
import java.util.*;
import javax.ejb.*;
public class MySessionBean implements SessionBean {
// セッション Beans の実装。これらのメソッドは常に取り込む
必要があります。
public void ejbActivate() {
}
public void ejbPassivate() {
}
public void ejbRemove() {
}
public void setSessionContext(SessionContext ctx) {
}
// 他のコードは省略します。
}セッション Bean は、1 つ以上の ejbCreate(...) メソッドを実装する必要があります。クライアントが Bean を呼び出すときは、必ずこのメソッドを 1 つ使います。次に例を示します。
public void ejbCreate() {
string[] userinfo = {"User Name", "Encrypted Password"} ;
}各 ejbCreate(...) メソッドは public として宣言され、void を返し、ejbCreate という名前を付ける必要があります。引数は、正しいタイプの Java RMI である必要があります。throws 句では、アプリケーション固有の例外および java.ejb.CreateException を定義できます。
セッション Beans は、1 つ以上のビジネスメソッドも実装します。これらのメソッドは通常、各 Bean に対して固有であり、その特定の機能を表します。たとえば、セッション Bean がユーザログインを管理する場合に、このセッション Bean に validateLogin という名前の固有の関数を含めることができます。
任意のビジネスメソッド名を付けることができますが、この EJB インタフェースに定義するメソッドの名前と重複しないように注意してください。ビジネスメソッドは、public として宣言する必要があります。メソッドの引数および戻り値は、正しいタイプの Java RMI である必要があります。throws 句では、アプリケーション固有の例外を定義できます。
セッション同期
ステートフルセッション Bean のクラス定義で許可される 1 つのインタフェース実装があります。特に、javax.ejb.SessionSynchronization によって、セッション Bean インスタンスはトランザクション境界を認識し、状態とトランザクションの同期をとることができます。
javax.ejb.SessionSynchronization インタフェースでは、コンテナがステートフルセッション Bean のインスタンスにトランザクション境界を知らせることができます。セッション Bean クラスは、必ずしもこのインタフェースを実装する必要はありません。状態とトランザクションの同期をとる必要がある場合のみ、セッション Bean クラスはこのインタフェースを実装する必要があります。たとえば、このインタフェースを実装した、ステートフルセッション Bean は、トランザクションのコミット前やコミット後ではなく、新しいトランザクションの開始後にコールバックを取得します。
このインタフェースの詳細については、『Enterprise JavaBeans Specification, v2.0』を参照してください。
注 コンテナは、そのコンテナが管理するトランザクションを使用する、ステートフル Beans のセッション同期インタフェースメソッドだけを起動します。
抽象的なメソッド
リモートインタフェースで定義するビジネスメソッドのほかに、EJBObject インタフェースはいくつかの抽象的なメソッドを定義します。これらのメソッドを使うと、次の処理が可能になります。
- Bean のホームインタフェースの取得
- Bean のハンドル (固有の識別子) の取得
- ほかの Bean と比較して、一意かどうかの確認
- 不要になった Bean の解放または削除
これらの組み込みメソッドとその使用法の詳細については、『Enterprise JavaBeans Specification, v2.0』を参照してください。
コンテナが提供する配備ツールは、セッション Bean が配備されたときに追加のクラスを生成します。
制限事項と最適化
セッション Beans の開発に関する制限事項と、最適化に関するガイドラインを示します。
セッション Bean のパフォーマンスの最適化
ステートフルセッション Beans では、クライアントと Bean を同じ場所に配置して、同じプロセスアドレス空間で実行させることで、パフォーマンスを向上できます。
トランザクションの制限
トランザクションについては、コンテナによる次の制限事項があり、セッション Beans を開発するときはこれらを遵守する必要があります。
- セッション Bean が関与できるトランザクションは一度に 1 つだけである
- セッション Bean がトランザクションに関与している場合、配備記述子のトランザクション属性によって、コンテナが別のまたは指定されていないトランザクションコンテキストでメソッドを実行するようなセッション Bean のメソッドをクライアントは呼び出すことができない (呼び出した場合は例外がスローされる)
- セッション Bean のインスタンスがトランザクションに関与している場合、クライアントは、セッションオブジェクトのホームまたはコンポーネントインタフェースオブジェクトの remove メソッドを呼び出すことができない (呼び出した場合は例外がスローされる)