前へ     目次     索引     DocHome     次へ     
iPlanet Application Server 開発者ガイド



第 5 章   セッション EJB によるビジネスルール管理


この章では、アプリケーションのビジネスルールおよびビジネスロジックをカプセル化するセッション EJB の作成方法について説明します。この章では特に、セッション Beans を使って、1 人の特定のユーザの一時的なニーズである繰り返しタスク、時限タスク、およびユーザ依存のタスクをカプセル化する方法について説明します。

この章には次の節があります。



セッション EJB の紹介

標準的な分散アプリケーションの多くは、繰り返しタスク、時限タスク、およびユーザ依存のタスクを実行するコードの論理的な単位から構成されます。これらのタスクには、単純なものと複雑なものがあり、さまざまなアプリケーションで必要です。たとえば、バンキングアプリケーションでは、トランザクションの前には必ず顧客のアカウント ID と残高を照合する必要があります。このようなタスクは、業務上必要なビジネスルールおよびビジネスロジックを定義します。このような個々のタスクは、本来は一時的なものであるためセッション EJB に適していると考えられます。

セッション EJB は、クライアント固有の一般的なオブジェクトのインスタンスを表す自己完結型コードの単位です。本来、これらのオブジェクトは一時的なものであり、アプリケーションの生存期間を通して必要に応じて作成および解放されます。たとえば、Web ベースのオンラインショッピングアプリケーションでよく利用されるショッピングカートは、典型的なセッション Beans です。これは、アイテムが選択されたときにだけ、オンラインショッピングアプリケーションによって作成されます。アイテムの選択が終了すると、カート内のアイテムの価格が計算され、注文が出され、ショッピングカートオブジェクトが解放されます。ユーザはオンラインカタログで商品のブラウズを続けることができ、ユーザが別の商品を注文したい場合には新しいショッピングカートが作成されます。

セッション Beans には、ほかのアプリケーションオブジェクトとの依存関係やコネクションを持たないものもあります。たとえば、ショッピングカートの Bean には、アイテム情報を格納するデータリストメンバー、現在カート内にあるアイテムの総額を格納するデータメンバー、およびアイテムの追加、削除、レポート、総計を行うメソッドがあります。一方、ショッピングカートには、購入可能なすべてのアイテムのデータベースへのライブコネクションはありません。

セッション Beans は、状態があるかないかのどちらかです。状態のないセッション Beans は、限られた時間内に特定のクライアントに必要なビジネスロジックの一時的な部分をカプセル化します。状態のあるセッション Beans も一時的ですが、会話型ステート (状態) を使って、クライアントがコールしている間の内容および値に関する情報を保持します。会話型ステートによって、Bean のコンテナはセッション Beans のステート情報を管理し、必要に応じてプログラム実行中にそのステートを再現できます。

アプリケーション内でパーシスタントでない独立したステータスを使って、セッション Beans の特性を定義する必要があります。セッション Beans は、アプリケーションサーバで動作するクライアントアプリケーションの一時的な論理拡張と考えることもできます。次にセッション Beans の特性を示します。

  • 1 つのクライアントを対象に実行する

  • 基礎となっているデータベースのデータを更新する

  • 短命である

通常、セッション Beans はデータベースの共有データを表しませんが、データのスナップショットを取得します。ただし、Bean はデータを更新できます。オプションで、セッション Beans はトランザクション認識も可能です。このオペレーションは、Bean によって管理されるトランザクションのコンテキストで実行できます。

クライアントは、Bean のリモートインタフェースである EJBObject を介してセッション Beans にアクセスします。EJB オブジェクトは、リモートオブジェクト呼び出しの標準 Java API を介してクライアントからアクセスできる、リモート Java プログラミング言語オブジェクトです。EJB は作成されてから破棄されるまでコンテナ内に存在し、コンテナは EJB のライフサイクルとサポートサービスを管理します。EJB が存在し、実行される場所はクライアントに対して透過的です。さらに、単一のコンテナに複数の EJB を組み込むことができます。コンテナの提供するサービスによって、クライアントは、組み込まれた EJB クラスのインタフェースを Java Naming and Directory Interface (JNDI) を介して検索することができます。

クライアントがセッション Beans のインスタンスに直接アクセスすることはありません。そうではなく、クライアントはセッション Beans のリモートインタフェースを使って Bean のインスタンスにアクセスします。セッション Beans のリモートインタフェースを実装する EJB オブジェクトクラスは、コンテナによって提供されます。EJB オブジェクトは少なくとも、java.ejb.EJBObject インタフェースのすべてのメソッドをサポートします。これらのメソッドには、セッション Beans のホームインタフェースの取得、オブジェクトのハンドルの取得、そのオブジェクトがほかのオブジェクトと重複していないかどうかを調べるテスト、およびオブジェクトの削除などがあります。これらのメソッドは EJB 仕様書に明記されています。さらに、多くの EJB オブジェクトでは、特定のビジネスロジックメソッドもサポートしています。これらのメソッドはアプリケーションの中枢です。

すべての仕様書については、installdir/ias/docs/index.htm から参照できます。installdir は iPlanet Application Server がインストールされている場所です。



セッション Beans のコンポーネント



セッション Beans をプログラミングするには、次のクラスファイルを準備する必要があります。

  • javax.ejb.EJBObject を拡張する Enterprise JavaBeans リモートインタフェース

  • Enterprise JavaBeans クラス定義

  • javax.ejb.EJBHome を拡張する Enterprise JavaBeans ホームインタフェース

  • Enterprise JavaBeans メタデータ (配置記述子 (DD) およびほかの設定情報)


リモートインタフェースの作成

セッション Beans のリモートインタフェースは、Bean メソッドへのユーザアクセスを定義します。すべてのリモートインタフェースが、javax.ejb.EJBObject を拡張します。次のようにします。

import javax.ejb.*;
import java.rmi.*;
public interface MySessionBean extends EJBObject {
// ここでビジネスメソッドを定義します。
}

リモートインタフェースは、クライアントが呼び出すセッション Beans のビジネスメソッドを定義します。リモートインタフェース内で定義されたビジネスメソッドは、実行時に Bean のコンテナによって実行されます。リモートインタフェースで定義した各メソッドには、Bean クラス内の対応するメソッドを指定する必要があります。Bean クラス内の対応するメソッドには同じシグネチャが必要です。

リモートインタフェースで定義するビジネスメソッド以外に、EJBObject インタフェースはいくつかの抽象的なメソッドを定義します。これらのメソッドを使うと、Bean のホームインタフェースを取得したり、固有の識別子である Bean のハンドルを取得できるだけでなく、重複していないことを確認するためにほかの Bean と比較したり、不要になった Bean を解放または削除できます。

これらの組み込みメソッドとその使用法の詳細については、EJB 仕様書を参照してください。この仕様書は install_dir/ias/docs/index.htm からアクセス可能です。install_dir は、iPlanet Application Server がインストールされている場所です。


リモートインタフェースの宣言と実装

Bean クラス定義には、Bean のリモートインタフェースで定義されるメソッドごとに、一致するメソッド名、引数、および戻り値タイプなどのマッチングメソッド定義が 1 つ以上必要です。EJB 仕様書では、Bean クラスへのリモートインタフェースの直接実装が許可されていますが、一方で、仕様書で述べられているクライアント - コンテナ - EJB プロトコルに違反して、クライアントに this を介して直接参照を不用意に渡さないようにするために、この方法を行わないように勧めています。


クラス定義の作成

セッション Beans のクラスは、abstract ではなく public として定義する必要があります。Bean クラスは、javax.ejb.SessionBean インタフェースを実装する必要があります。次のようにします。

import java.rmi.*;
import java.util.*;
import javax.ejb.*;
public class MySessionBean implements SessionBean {
// エンティティ Beans の実装。これらのメソッドは常に取り込む必要があります。
public void ejbActivate() throws RemoteException {
}
public void ejbPassivate() throws RemoteException {
}
public void ejbRemove() throws RemoteException{
}
public void setSessionContext(SessionContext ctx) throws RemoteException {
}

// 他のコードは省略します。
}

セッション Beans は、1 つまたは複数の ejbCreate(...) メソッドも実装する必要があります。クライアントが Bean を呼び出すときは、必ずこのメソッドを 1 つ使います。次のようにします。

public void ejbCreate() {
String[] userinfo = {"User Name", "Encrypted Password"} ;
}

ejbCreate(...) メソッドは public として宣言し、void を返し、ejbCreate という名前を付ける必要があります。引数は、正しいタイプの Java RMI である必要があります。throws 句は、アプリケーション固有の例外を定義し、java.rmi.RemoteExceptionjava.ejb.CreateException を含めることができます。

すべての有効なセッション Beans も 1 つまたは複数のビジネスメソッドを実装します。これらのメソッドは通常、各 Bean に対して固有であり、その特定の機能を表します。たとえば、セッション Beans がユーザログインを管理する場合、このセッション Beans は ValidateLogin() という名前の固有の関数を取り込みます。

任意のビジネスメソッド名を付けることができますが、この EJB アーキテクチャで使われるメソッド名と重複しないように注意してください。ビジネスメソッドは、public として宣言する必要があります。メソッドの引数および戻り値は、正しいタイプの Java RMI である必要があります。throws 句は、アプリケーション固有の例外を定義し、java.rmi.RemoteException を含める必要があります。

セッション Beans のクラス定義で許可される 1 つのインタフェース実装があります。特に、javax.ejb.SessionSynchronization によって、セッション Beans インスタンスはトランザクション境界を認識し、ステートとそれらのトランザクションの同期をとることができます。このインタフェースの詳細については、EJB 仕様書を参照してください。この仕様書は install_dir/ias/docs/index.htm からアクセス可能です。install_dir は、iPlanet Application Server がインストールされている場所です。


セッションタイムアウト

コンテナは、指定した (またはデフォルトの) 時間を過ぎてもアクティブにならないセッション Beans を削除します。タイムアウト値は、Bean の配置記述子で設定します。詳細については、「EJB XML DTD」を参照してください。


不活性化と活性化

コンテナは、指定した (またはデフォルトの) 時間を過ぎてもアクティブにならないセッション Beans を不活性化します。タイムアウト値は、Bean の配置記述子で設定します。詳細については、「EJB XML DTD」を参照してください。

不活性化の詳細については、EJB 仕様書を参照してください。この仕様書は install_dir/ias/docs/index.htm からアクセス可能です。install_dir は、iPlanet Application Server がインストールされている場所です。


ホームインタフェースの作成

ホームインタフェースは、クライアントがアプリケーションを使ってセッションオブジェクトの作成および削除を行うメソッドを定義します。ホームインタフェースは通常、javax.ejb.EJBHome を拡張します。次のようにします。

import javax.ejb.*;
import java.rmi.*;

public interface MySessionBeanHome extends EJBHome {
   MySessionBean create() throws CreateException, RemoteException;
}

この例のように、セッション Beans のホームインタフェースは 1 つまたは複数の create メソッドを定義します。各メソッドには create という名前を付け、セッション Beans クラスで定義された ejbCreate メソッドの数および引数のタイプと一致させる必要があります。ただし、各 create メソッドの戻り値タイプは、対応する ejbCreate メソッドの戻り値タイプとは一致しません。代わりに、セッション Beans のリモートインタフェースタイプを返します。

ejbCreate メソッドの throws 句で定義するすべての例外が、リモートインタフェースで一致している create メソッドの throws 句で定義する必要があります。さらに、ホームインタフェースの throws 句には常に、javax.ejb.CreateException を含める必要があります。

すべてのホームインタフェースが、不要になった EJB を破棄する 2 つの remove メソッドを自動的に定義します。



これらのメソッドはオーバーライドしないでください。





セッション Beans の付加的なガイドライン



セッション Beans として表現できるアプリケーションの各部を決める前に、セッション Beans について理解すべき事項がいくつかあります。これらの事項には、セッション Beans の EJB 仕様に関連する事項や、iPlanet Application Server および iPlanet Application Server によるセッション Beans のサポートに固有の事項などがあります。


状態のない、または状態のある Beans の作成

EJB 仕様書には、セッション Beans の 2 つのステート管理モードについて記述されています。

  • 状態なし : Bean はメソッド呼び出し間のステート情報を保持しないので、すべての Bean インスタンスがすべてのクライアントに対応します。

  • 状態あり : Bean はメソッドおよびトランザクション間のステート情報を保持するので、特定の Bean インスタンスを常に 1 つのクライアントと関連付ける必要があります。

状態のあるセッション Beans を使う場合は、状態のある Bean とそのクライアントを同じ場所に配置してください。また、特に頻繁に不活性化および活性化するセッション Beans や、データベースコネクションやハンドルなど多数のリソースを使うセッション Beans については、スティッキーロードバランスを使って RPC の回数を減らします。


iPlanet Application Server 機能へのアクセス

開発可能なセッション Beans には、EJB 仕様に厳密に準拠しているセッション Beans、その仕様と iPlanet Application Server の付加価値機能の両方を活用しているセッション Beans、および iPlanet Application Server 以外の環境における仕様に準拠してはいるが利用できる iPlanet Application Server 機能も活用するセッション Beans があります。希望の配置シナリオに最適なセッション Beans を選択します。


ハンドルと参照の直列化

Bean 参照の直列化を保証するには、EJB への直接参照ではなくハンドルを使うようにと、EJB 仕様書に記述されています。

iPlanet Application Server の直接参照も直列化が可能です。ただし、すべてのベンダーによってサポートされているわけではないので、この拡張機能を利用できない場合もあります。


トランザクションの管理

多くのセッション Beans がデータベースと対話します。Bean のプロパティファイルの設定値を使って、Bean のトランザクションを制御します。これにより、Bean 配置時にトランザクション属性を指定できます。

コンテナ管理トランザクションまたは Bean 管理トランザクションを選択することができます。

コンテナがトランザクションを管理する場合は、Bean のデータベースアクセスメッソド内で明示してトランザクションを「起動」、「ロールバック」、または「コミット」する必要はありません。

トランザクション管理をコンテナレベルに移すことによって、Bean のアクティビティがデータベースアクセスと直接結び付いていなくても、データベース呼び出しと同じトランザクション制御環境ですべての Bean アクティビティを配置できます。これにより、コンテナによって制御されるアプリケーションのすべての部分が、同じトランザクションの一部として動作しますが、失敗すると、コンテナが管理していたものはすべてコミットされるか、ロールバックされます。実際には、コンテナ管理トランザクションのステートによって、同期ルーチンをプログラミングせずにアプリケーションの同期をとることができます。

セッション Beans が Bean 管理トランザクションを使用する場合は、Bean メソッド内で明示してトランザクションの有効範囲をコーディングする必要があります。


データベースへのアクセス

多くのセッション Beans はデータにアクセスしてデータを更新します。セッション Beans は一時的なので、アクセスがどのように発生するかに注意してください。一般に、JDBC API を使って呼び出しを行い、第 8 章「EJB のトランザクション処理」 に記述されているトランザクションおよびセキュリティ管理メソッドを使ってトランザクション分離レベルおよびトランザクション要件を Bean レベルで管理します。

トランザクションの詳細については、第 9 章「JDBC を使ったデータベースアクセス」を参照してください。


セッション Beans のフェールオーバー

サービスが提供されないために iPlanet Application Server を使用できない場合は、セッション Beans のフェールオーバー機能によって、状態のあるセッション Beans に会話型ステートを回復することができます。状態のあるセッション Beans のフェールオーバーは、iPlanet Application Server の機能です。iPlanet Application Server のフェールオーバー機能をサポートするために J2EE プログラムに変更を加える必要はありません。フェールオーバーはコンテナによって処理され、アプリケーション配置者によって配置記述子内に定義されています。

たとえば、企業の購買担当者が電子商取引の Web サイトでオンライン購入を実行するとします。数時間後、購買担当者はショッピングカート (状態のあるセッション Beans) に何百種類もの商品を入れました。ここで、システムに予期しない致命的な問題が発生し、iPlanet Application Server サーバのインスタンスを使用できなくなりました。フェールオーバー機能がない場合、購買担当者のショッピングカートは空になってしまいます。つまり、状態のあるセッション Beans のステートが失われます。しかし、フェールオーバー機能がある場合は、購買担当者はシステムエラーに気づくことはありません。フェールオーバーメカニズムによって、エラー前の Bean のステートを持つ実行中の iPlanet Application Server サーバのインスタンスに、クライアントがリダイレクトされるためです。購買担当者のショッピングカートには、エラー発生前に選択したものと同じ商品が入っています。

状態のあるセッション Beans のフェールオーバーサポートの注目すべき特徴は次のとおりです。

  • フェールオーバーは、J2EE プログラムをサポートする付加価値機能である

  • フェールオーバーはクライアントに対して透過的であり、特別な API は不要

  • フェールオーバーはコンテナによって処理され、アプリケーション配置者によって設定される

  • 分散ストア (DSync : Distrubuted Store) はシステムエラー後にステートを復元するメカニズムである

  • フェールオーバーのサポートが不要な状態のあるセッション Beans のパフォーマンスへの悪影響が最小限に抑えられる


状態のある Bean のフェールオーバーを設定する方法

フェールオーバーが機能するように状態のあるセッション Beans を設定するには、フェールオーバー機能と分散ストア (DSync) を Bean に組み合わせる必要があります。

  • インストール時または実行時に、DSync 用にサーバを設定する

  • 配置時に、状態のあるセッション Beans のフェールオーバーを設定する

フェールオーバー機能を活用するために、Bean のフェールオーバーと DSync の両方を設定する必要があります。実行時、DSync メカニズムによってセッション Beans の会話型ステートが保存されます。さらに、フェールオーバーメカニズムによって、コンテナは、システムエラーを検出して、保存されたセッション Beans のステートが含まれた別の実行中の iPlanet Application Server インスタンスに接続できます。

配置時に状態のあるセッション Beans のフェールオーバーを設定する方法と、実行時に DSync を設定する方法の詳細については、『管理ガイド』を参照してください。インストール時に DSync を設定する方法の詳細については、『インストールガイド』を参照してください。


フェールオーバープロセスの動作

状態のある Bean のフェールオーバーは、スマートスタブと分散ストアの組み合わせによって実現されます。Bean をフェールオーバー Bean として配置すると、配置ツールによって特殊なスタブが生成されます。メソッドを起動すると、スマートスタブはエラーを検出し、Bean を透過的に新しい場所 (別のエンジン内など) に移動します。スタブは、無効 Bean からコネクション例外を取得することによって、Bean 参照が古くなっていないかどうかを調べます。スタブは、さらに Bean の場所を検索し、リモートインタフェースを取得します。Bean が再配置されると、スタブは、復元された Bean に対してメソッドを再度実行します。コンテナは、メソッドを試行し直した場合、セマンティックを一度限り保証します。

コンテナは、DSync に基づいた分散ストアを使って Bean のステートを維持します。Bean のステートは通常の間隔で保存され、リカバリプロセスの一環として自動的に復帰します。

フェールオーバーが設定された状態のあるセッション Beans によって使われる配置記述子の詳細については、第 11 章「配置のためのパッケージ化」を参照してください。


フェールオーバーのガイドライン

フェールオーバーを実装する場合は、次のガイドラインに従ってください。

  • ejbPassivate() および ejbActivate() を簡潔にします。

  • home.remove(handle) ではなく、obj.remove() を使って Bean を削除します。Bean とその元の場所の関連付けはフェールオーバー後も保持されないことがあります。

  • Bean のフェールオーバーの利点とフェールオーバープロセスのコストパフォーマンスを慎重に比較検討した上で判断してください。



    すべての状態のある Bean にフェールオーバー機能を設定しないようにしてください。



  • セッション Beans のステートは会話型であることを覚えておいてください。トランザクションデータにはエンティティ Beans を使います。

  • 状態のあるセッション Beans のステートを保存する間隔は、EJB タブの管理ツールを使って設定できます。デフォルトでは 10 秒です。

  • Bean がトランザクションの場合、タイマーベースのステートの保存は、トランザクション時に自動的に無効になります。これにより、トランザクション時にサーバエンジンにエラーが発生してもトランザクションデータの安全性が確保されます。エラーが発生すると、トランザクションデータベースの更新は、データベースによりロールバックされます。回復した Bean のステートは、失敗したトランザクションの開始時のステートと同じです。ただし、トランザクションが問題なく処理された場合、Bean のステートはトランザクションの完了時に保存され、次のトランザクションが開始されるまでタイマーベースで再び保存されます。

  • Bean が iPlanet Application Server が提供する com.netscape.server.ejb.IEBFoStateModification インタフェースを実装している場合、ステートセーバは、時間のかかる保存操作を行う前に Bean のステートが変更されているかどうかを確認できます。このインタフェースは次の 2 つのメソッドを定義します。

        package com.netscape.server.ejb;

        public interface IEBFoStateModification {

           /**
            ** Bean インスタンスが正しくない場合、コンテナによってこのメソッドが
            ** 呼び出され、確認を行います。
            **/

           boolean isDirty();

           /**
            ** コンテナが直接保存を実行する場合があります。次にコンテナは、
            ** 変更済みの Bean の不正なステートを呼び出し、リセットします。
            **/

           void setDirty(boolean dirty);

       }

    ユーザが提供する Bean の実装には、Bean の変更済みステートを追跡するブール変数があります。この変数は、ステートの保存前に参照されます。


ステートの保存間隔

フェールオーバーが設定されているコンテナは、実行時、Bean のステートを一定間隔で保存します。ステートを保存するプロセスは次のとおりです。

  • 一定間隔 (間隔は再設定可能) で保存します。

  • Bean がトランザクションに関わっている場合には、トランザクション境界上に保存します。

一定間隔は、管理ツールで設定します。


ステートの保存方法

ステートを保存するプロセスは次のとおりです。

  • 最初に、状態のある各セッション Beans の ejbPassivate() メソッドを呼び出します。

  • 次に、Bean の会話型ステートを直列化し、分散ストアに保存します。

  • 最後に、Bean の ejbActivate() メソッドを呼び出します。



    Bean のステート保存は、関連する操作の規模が大きいため時間がかかります。




前へ     目次     索引     DocHome     次へ     
Copyright © 2002 Sun Microsystems, Inc. All rights reserved.

最新更新日 2002 年 3 月 6 日