EJB 2.1 に比べて、EJB 3.1 では Enterprise Java™ Bean アプリケーションの作成プロセスが簡単になりました。
J2EE 1.4 アーキテクチャーの複雑性と EJB 2.x
ビジネス・レイヤー J2EE 1.4 のアーキテクチャーでは、セッション Bean を使用して、
ビジネス・ロジックのコンポーネントをラップし、
それらのコンポーネントに、トランザクションの分散型リモート、およびセキュリティー・サービスを提供します。
通常は、ファサード・パターンを実装して、クライアントとサービス・プロバイダー間のネットワーク・トラフィックを削減します。
セッション Bean には、ローカル・クライアント (つまり、同じ JVM 内にあるクライアント) からも、
リモート・クライアントからもアクセスできます。
メッセージ駆動型 Bean を使用して、外部の JMS プロバイダー (MQSeries など) を統合し、
非同期メッセージ処理サービスを使用可能にします。
ビジネス・ロジックのレイヤーは、セッション Bean とメッセージ駆動型 Bean の両方で構成されます。
これらがレイヤーと呼ばれているのは、このエンタープライズ・アーキテクチャーの設計で採用されているもう 1 つの基礎的なパラダイムがレイヤー化であるためです。
このレイヤー化により、責任およびスキルの分離、クラスタリング、コンポーネントの再利用などのコア・フィーチャーが使用可能になります。
パーシスタンス・レイヤー もう 1 つの基本的なレイヤーは、パーシスタンス・レイヤーです。
このレイヤーは、アプリケーション・データをリレーショナル・データベース内で永続化することを可能にするサービスとコンポーネントのセットです。
パーシスタンス・レイヤーは以下の方法で実装できます。
- エンティティー Bean (コンテナー管理 Bean および Bean 管理 Bean)
- JDBC™ データ・アクセス・オブジェクト (DAO)
- オブジェクト・リレーショナル・マッピング (ORM) フレームワーク
EJB 2.x 仕様の問題点
- EJB 2.x 仕様では、コンポーネント・インターフェースは EJB フレームワーク・パッケージからインターフェースを継承する必要 があり、
ビジネス・ロジック実装クラスは EJB フレームワーク・パッケージからインターフェースを実装する必要 があります。
これらの要件は、開発者が作成するコードと、EJB フレームワーク・パッケージから実装するインターフェース・クラスの間に密結合を作成します。
また、EJB の主要な設計目標に直接関係しない複数の不要なコールバック・メソッド (ejbCreate、ejbPassivate、ejbActivate)
の実装と、不要な例外の処理も必要になります。
- EJB デプロイメント記述子は、非常に冗長で、複雑で、エラーの原因になります。
- EJB はテストが困難です。アプリケーションには、EJB コンポーネントを正しく実行するために必要なすべてのサービスを提供する J2EE コンテナーが必要です。
- リソース (データ・ソース、EJB ホーム参照など) にアクセスする必要があるたびに JNDI を利用することは、
J2EE 開発で繰り返し発生する面倒な操作です。
- コンテナー管理パーシスタンス・モデルは、開発および管理が複雑です。
EJB 3.1 のシンプルなモデル
Java EE および EJB 3.1 のアーキテクチャー全体に、
EJB 3.1 モデルの簡素化が反映されています。
EJB 3.1 仕様の基本コンセプトの中心にあるのが、POJO (Plain Old
Java Object)
プログラミング・モデルです。このモデルでは、
Java 注釈を使用して、
従来はデプロイメント記述子に入っていた情報を取り込みます。
デプロイメント記述子は、一般的にはオプションになりました。
また、デフォルト値の自由な使用は、作成して維持しなければならないサポート・コードの削減にもつながります。
これにより、EJB 3.1 コンポーネントを作成および使用する場合のプログラミング作業が大幅に簡素化されます。
このシンプルなモデルの主なフィーチャーは、以下のとおりです。
- EJB は、通常のビジネス・インターフェース (POJI) を公開する POJO (Plain Old Java Object) です。
ホーム・インターフェースは必要ありません。
- メタデータ注釈が使用されます。つまり、拡張可能な、メタデータ駆動型の、属性指向のフレームワークを
使用して、Java コードや XML デプロイメント記述子を生成します。
- 特定のインターフェースおよびデプロイメント記述子が不要になりました
(デプロイメント記述子情報の代わりに注釈を使用できます)。
- インターセプター機能によって、ビジネス・メソッドの呼び出し時またはライフサイクル・イベントの発生時にユーザー・メソッドを呼び出します。
- 可能な限りデフォルト値が使用されます (「例外ごとの構成」アプローチ)。
- チェック例外を使用する必要が削減されます。
- EJB 2.x エンティティー Bean に優先する、まったく新しいパーシスタンス・モデル (JPA 標準ベース) が使用されます。
表 1. EJB 2.1 と EJB 3.1 との Bean の作成ステップの比較. EJB 2.x はデプロイメント記述子を使用し、EJB 3.1 は注釈を使用します。EJB 2.x でステートレス・セッション Bean を定義するステップ |
EJB 3.1 でステートレス・セッション Bean を定義するステップ |
EJB 2.x 仕様に従ってステートレス・セッション Bean を作成するには、以下のコンポーネントを定義します。
- EJB コンポーネント・インターフェース: EJB クライアントが Bean の機能へのアクセスを取得する場合に使用します。
ここで、ビジネス・メソッドが定義されます。
コンポーネント・インターフェースは EJB オブジェクトと呼ばれます。
コンポーネント・インターフェースには、以下の 2 つのタイプがあります。
- リモート・コンポーネント・インターフェース (EJBObject): リモート・クライアントが RMI-IIOP プロトコルを介して EJB にアクセスする場合に使用します。
- ローカル・コンポーネント・インターフェース (EJBLocalObject): ローカル・クライアント (同じ JVM 内で実行されるクライアント) が EJB にアクセスする場合に使用します。
- EJB ホーム・インターフェース: EJB クライアントが Bean へのアクセスを取得する場合に使用します。
ここには、作成、検索、または削除の Bean のライフサイクル・メソッドが含まれます。
ホーム・インターフェースは EJB ホームと呼ばれます。
EJBHome オブジェクトは、ホーム・インターフェースを実装するオブジェクトで、EJBObject の場合のように、デプロイ時にコンテナー・ツールから生成されます。ここには、コンテナー固有のコードが含まれます。
起動時に、EJB コンテナーは、デプロイ済みのエンタープライズ Bean の EJBHome オブジェクトのインスタンスを作成し、ネーム・サービスにホームを登録します。
EJB クライアントは、Java Naming and Directory
Interface (JNDI) を使用して EJBHome オブジェクトにアクセスします。 ホーム・インターフェースには、以下の 2 つのタイプがあります。
- リモート・ホーム・インターフェース (EJBHome): リモート・クライアントが RMI-IIOP プロトコルを介して EJB にアクセスする場合に使用します。
- ローカル・ホーム・インターフェース (EJBLocalHome): ローカル・クライアント (同じ JVM 内で実行されるクライアント) が EJB にアクセスする場合に使用します。
- EJB Bean クラス: Bean の実際のビジネス・ロジックがすべて含まれます。
ビジネス・ロジックの実装を提供するクラスです。
この Bean クラス内のメソッドは、コンポーネント・インターフェースとホーム・インターフェース内のメソッドに関連します。
|
EJB 3.1 仕様に従ってステートレス・セッション Bean を宣言するには、単に POJO を定義するだけです。
@Stateless
public class MySessionBean implements MyBusinessInterface {
// MyBusinessInterface に準拠するビジネス・メソッド
.....
}
- リモート・インターフェースで同じ Bean を公開するには、@Remote 注釈を使用します。
@Remote(MyRemoteBusinessInterface.class)
@Stateless
public class MyBean implements MyRemoteBusinessInterface {
// EJB メソッド
.....
}
|
EJB 2.1 のクラスおよびデプロイメント記述子ファイルと、同等の EJB 3.1 クラスの比較
テーブル 1 の例は機能的に同等です。
表 2. EJB 2.1 と EJB 3.1 の比較. EJB 2.1 はデプロイメント記述子を使用し、EJB 3.1 は注釈を使用します。EJB 2.1 |
EJB
3.1 |
Java クラス
public class AccountBean
implements javax.ejb.SessionBean {
SessionContext ctx;
DataSource accountDB;
public void setSessionContext(SessionContext ctx) {
this.ctx = ctx;
}
public void ejbCreate() {
accountDB = (DataSource)ctx.lookup(
"jdbc/accountDB");
}
public void ejbActivate() { }
public void ejbPassivate() { }
public void ejbRemove() { }
public void setAccountDeposit(int empId,
double deposit) {
...
Connection conn = accountDB.getConnection();
...
}
...
}
|
Java クラス
@Stateless
public class AccountBean implements Account
{
@Resource private DataSource accountDB;
public void setAccountDeposit(int customerId,
double deposit) {
...
Connection conn = accountDB.getConnection();
...
}
...
}
|
デプロイメント記述子
<session>
<ejb-name>AccountBean</ejb-name>
<local-home>AccountHome</local-home>
<local>Account</local>
<ejb-class>com.example.AccountBean</ejb-class>
<session-type>Stateless</session-type>
<transaction-type>Container</transaction-type>
<resource-ref>
<res-ref-name>jdbc/accountDB</res-ref-name>
<res-ref-type>javax.sql.DataSource</res-ref-type>
<res-auth>Container</res-auth>
</resource-ref>
</session>
...
<assembly-descriptor>...</assembly-descriptor>
|
|