WebLogic エンタープライズ JavaBeans バージョン 3.0 プログラマーズ ガイド

     前  次    新しいウィンドウで目次を開く     
ここから内容の開始

アノテーション付き EJB 3.0 クラスのプログラミング

以下の節では、アノテーション付き EJB 3.0 クラス ファイルをプログラミングする方法について説明します。

 


メタデータ アノテーションと EJB 3.0 Bean ファイルの概要

新しい EJB 3.0 プログラミング モデルでは、JDK 5.0 メタデータ アノテーション機能を使用して、アノテーション付き EJB 3.0 Bean ファイルを作成します。次に、WebLogic コンパイル ツール weblogic.appc (またはこれと同等の Ant タスク wlappc) を使用して Bean ファイルを Java クラス ファイルにコンパイルし、必要となる EJB インタフェースやデプロイメント記述子など、関連する EJB アーティファクトを生成します。

アノテーション付き 3.0 Bean ファイルは、EJB の中核部分です。このファイルには EJB の動作を決定する Java コードが含まれています。3.0 Bean ファイルは、EJB のビジネス メソッドを形作る EJB ビジネス インタフェースを実装した通常の Java クラス ファイルです。この Bean ファイルに JDK 5.0 メタデータ アノテーションを追加することで、EJB の構造や特性を指定し、EJB を文書化し、実行時の特別なサービス (ビジネス レベルの拡張セキュリティ、特別なビジネス ロジックなど) を提供します。

メタデータ アノテーションの機能別一覧」には、Bean ファイル内で指定できるアノテーションを機能別にまとめてあります。これらのアノテーションには、Enterprise JavaBeans 3.0 仕様 (JSR-220) に記述されているアノテーションと、「Common Annotations for the Java Platform (JSR-250)」に記述されているアノテーションが含まれます。「EJB 3.0 メタデータ アノテーション リファレンス」には、これらのアノテーションのリファレンス情報をアルファベット順にまとめてあります。

このトピックは、EJB 3.0 を作成するための反復的な開発手順の一部です。詳細な開発手順については、「エンタープライズ JavaBeans 3.0 の反復的な開発」を参照してください。

 


Bean ファイルのプログラミング : 要件および 2.X からの変更点

3.0 Bean クラス ファイルをプログラミングする上での要件は、基本的には 2.X での要件と同じです。この節では、Bean クラスの基本的な必須要件について簡単に説明し、2.X と 3.0 の要件の相違点について説明します。

Bean クラスをプログラミングする上での必須要件と任意要件の詳細については、『WebLogic エンタープライズ JavaBeans (EJB) プログラマーズ ガイド』を参照してください。

Bean ファイルの要件と 2.X からの変更点

以下に、3.0 で Bean クラスをプログラミングする上での新しい要件と、2.X の要件のうち 3.0 には適用されなくなったものをまとめます。

以下の要件は EJB 2.X から変更されていませんが、念のため簡単にまとめておきます。

Bean クラス メソッドの要件

メソッドの要件は EJB 2.X から変更されていませんが、念のため簡単にまとめておきます。

セッション Bean クラスのメソッド (ビジネス インタフェース メソッドを実装するメソッド) の要件は以下のとおりです。

メッセージ駆動型 Bean クラスのメソッドの要件は以下のとおりです。

 


Bean ファイルのプログラミング : 一般的な手順

次の手順では、EJB の 3.0 Bean ファイルをプログラミングする場合の一般的で基本的な手順を説明します。細かな手順は、どのような動作の EJB を作成するかによって異なります。

以降の節で使用するサンプル コードについては、「エンタープライズ JavaBeans 3.0 の単純なサンプル」を参照してください。

  1. Bean ファイルで使用する EJB 3.0 アノテーションおよびその他の共通アノテーションをインポートします。一般的な EJB アノテーションは javax.ejb パッケージに含まれています。また、インターセプタ アノテーションは javax.interceptor パッケージ、3.0 エンティティを呼び出すためのアノテーションは javax.persistence パッケージ、共通アノテーションは javax.common または javax.common.security パッケージに含まれています。次に例を示します。
  2. import javax.ejb.Stateless;
    import javax.ejb.TransactionAttribute;
    import javax.interceptor.ExcludeDefaultInterceptors;
  3. EJB に実装するビジネス インタフェースと、その他の標準インタフェースを指定します。インタフェースは、明示的に実装しても、アノテーションを使用して指定しても構いません。
  4. ビジネス インタフェースとその他のインタフェースを指定する」を参照してください。

  5. 必須のアノテーションを使用して、プログラミングする Bean のタイプ (セッションまたはメッセージ駆動型) を指定します。
  6. Bean タイプ (ステートレス、ステートフル、メッセージ駆動型) を指定する」を参照してください。

  7. 必要に応じて依存性注入を設定し、外部リソース (別の EJB、他の Java Platform, Enterprise Edition (Java EE) バージョン 5 オブジェクトなど) を使用できるようにします。
  8. 変数またはセッター メソッドにリソース依存性を注入する」を参照してください。

  9. 必要に応じて EntityManager オブジェクトを作成し、エンティティ アノテーションを使用してエンティティ情報を注入します。
  10. 3.0 エンティティを呼び出す」を参照してください。

  11. 必要に応じて、ビジネス メソッドまたはライフサイクル コールバック メソッドのインターセプタ メソッドをプログラミングおよびコンフィグレーションします。インターセプタ メソッドは、Bean ファイル自体の中でも、別の Java ファイル内でもプログラミングできます。
  12. ビジネス メソッドまたはライフサイクル コールバック イベントのインターセプタを指定する」を参照してください。

  13. ビジネス インタフェースにアプリケーション例外を送出するビジネス メソッドを指定した場合は、例外クラスをプログラミングする必要があります。この点は、EJB 2.X でも同様です。
  14. EJB 3.0 固有の情報については、「アプリケーション例外をプログラミングする」を参照してください。

  15. 必要に応じ、セキュリティ関連のメタデータ アノテーションを使用して、EJB メソッドを呼び出すことができるセキュリティ ロールを指定します。
  16. EJB へのアクセスにセキュリティを設定する」を参照してください。

  17. 必要に応じて、EJB で実行するデフォルトのトランザクション コンフィグレーションを変更します。
  18. トランザクション管理とトランザクション属性を指定する」を参照してください。

ビジネス インタフェースとその他のインタフェースを指定する

EJB 3.0 プログラミング モデルを使用して Bean をプログラミングする場合は、ビジネス インタフェースを指定する必要があります。

EJB Bean クラスのビジネス インタフェースを指定する方法は 2 つあります。

通常、EJB Bean クラスに実装したインタフェースは、その EJB のビジネス インタフェースと見なされます。また、リモート インタフェースであることを明示しない限り、ビジネス インタフェースはローカル インタフェースと見なされます。ビジネス インタフェースをリモート インタフェースとして明示するには、javax.ejb.Remote アノテーションを使用するか、適切な EJB デプロイメント記述子を更新します。javax.ejb.Remote および javax.ejb.Local アノテーションは、ビジネス インタフェース自体で指定することも、そのインタフェースを実装する Bean クラスで指定することもできます。

Bean クラスには、複数のインタフェースを実装できます。その場合 (ただし、下に示すインタフェースは対象外) は、EJB のビジネス インタフェースを javax.ejb.Local または javax.ejb.Remote アノテーションを使用して明示的に指定する必要があります。指定する場所は、ビジネス インタフェース自体でも、そのビジネス インタフェースを実装する Bean クラスでも、適切なデプロイメント記述子でも構いません。

Bean クラスに複数のインタフェースが実装されているかどうかを判断する際、以下のインタフェースは対象外となります。

次のコードの抜粋に、Bean クラスのビジネス インタフェースを明示的に実装して指定する方法を示します。

public class ServiceBean
  implements Service

サンプル全体を見るには、「単純なステートレス EJB のサンプル」を参照してください。

Bean タイプ (ステートレス、ステートフル、メッセージ駆動型) を指定する

3.0 Bean クラスで必須となるメタデータ アノテーションは、プログラミングする Bean のタイプを指定するアノテーション 1 つのみです。以下のアノテーションのうち、いずれか 1 つのみを指定する必要があります。

必須ではありませんが、アノテーションの属性を指定すると、Bean タイプをより詳しく記述できます。たとえば、以下の属性はすべての Bean タイプに設定できます。

メッセージ駆動型 Bean をプログラミングする場合は、以下の属性を指定することもできます。

次のコードの抜粋に、Bean がステートレス セッション Bean であることを指定する方法を示します。

@Stateless
public class ServiceBean
implements Service

サンプル全体を見るには、「単純なステートレス EJB のサンプル」を参照してください。

変数またはセッター メソッドにリソース依存性を注入する

「依存性注入」では、Bean コンテキスト内のリソースや他の環境エントリへの参照が、EJB コンテナによって Bean の変数またはセッター メソッドに自動的に提供 (「注入」) されます。依存性注入は、javax.ejb.EJBContext インタフェースまたは JNDI API を使用したリソースのルックアップを、より簡単にプログラミングするための方法にすぎません。

依存性注入を指定するには、注入するリソースのタイプに応じて、以下のアノテーションのいずれかを変数またはセッター メソッドに追加します。

これらのアノテーションには、複数のリソースへの依存性を指定するため、それぞれに相当するグループ化アノテーション (@javax.ejb.EJBs および @javax.annotation.Resources) があります。

必須ではありませんが、これらの依存性アノテーションに属性を指定すると、依存するリソースを明示的に記述できます。指定する必要のある情報の量は、その使用コンテキストと、EJB コンテナがそのコンテキストからどの程度の情報を推測できるかによって異なります。これらの属性の詳細と、どのような場合に使用すべきかについては、「javax.ejb.EJB」および「javax.annotation.Resource」を参照してください。

次のコードの抜粋では、@javax.ejb.EJB アノテーションを使用して、EJB への依存性を変数に注入する方法を示します。ここでは、Bean ファイル内の関連する部分のみを示します。

package examples;
import javax.ejb.EJB;
...
@Stateful
public class AccountBean
implements Account
{
  @EJB(beanName="ServiceBean")
private Service service;
...
  public void sayHelloFromAccountBean() {
    service.sayHelloFromServiceBean();
  }

この例では、プライベート属性 service@javax.ejb.EJB アノテーションを付けて、Bean 名 ServiceBean で EJB への参照を作成しています。サービス変数のデータ型は Service です。これは、ServiceBean Bean クラスが実装するビジネス インタフェースです。EJB コンテナは、AccountBean EJB を作成し、即座に ServiceBean への参照を service 変数に注入します。これにより、この変数から、SessionBean のすべてのビジネス メソッドに直接アクセスできるようになります。その結果、例に示されているように、sayHelloFromAccountBean メソッド実装で sayHelloFromServiceBean メソッドを呼び出すことが可能になります。

3.0 エンティティを呼び出す

この節では、セッション Bean 内から 3.0 エンティティを呼び出して更新する方法について説明します。

注意 : この節では、すでにエンティティのプログラミングが完了しており、そのエンティティをサポートするデータベース リソースがコンフィグレーションされていることを前提としています。これらの手順については、『BEA Kodo documentation』の「Enterprise JavaBeans 3 Persistence」を参照してください。

「エンティティ」とは、データストア レコードを表す永続オブジェクトです。通常、エンティティのインスタンスは、データベース テーブルの単一の行を表します。エンティティを使用すると、永続ストア内の情報のクエリや更新を、Java EE コンポーネント内 (セッション Bean など) から簡単に行えます。たとえば、Person エンティティであれば、nameaddressage などのフィールドを含み、それぞれのフィールドがデータベース内のテーブルの列に対応します。javax.persistence.EntityManager オブジェクトを使用してエンティティにアクセスして管理する場合、ユニークな ID または SQL クエリを使用して Person レコードを簡単に取得でき、情報を変更した場合はその情報が基底のデータストアに自動的に送信されます。

以下の節では、セッション Bean をエンティティと対話させるために必要な一般的なプログラミング タスクについて説明します。

メタデータ アノテーションを使用して永続性コンテキストを注入する

セッション Bean では、以下のメタデータ アノテーションを使用して、変数にエンティティ情報を注入できます。

@PersistenceContext アノテーションと @PersistenceUnit アノテーションは、ほとんど同じ機能 (変数に永続性コンテキスト情報を注入する) を果たします。大きな違いは、情報の注入先となるインスタンスのデータ型です。セッション Bean 内の EntityManager のライフサイクルを完全に制御したい場合は、@PersistenceUnit を使用して EntityManagerFactory インスタンスに注入し、EntityManager を手動で作成するためのコードを記述します。処理が完了したら、リソースを解放するために破棄します。EntityManager のライフサイクルを EJB コンテナで管理したい場合は、@PersistenceContext アノテーションを使用して EntityManager に直接注入します。

次の例では、永続性コンテキストを EntityManager データ型の変数 em に注入する方法を示します。該当するコードは太字で示してあります。

package examples;
import javax.ejb.Stateless;
import javax.persistence.PersistenceContext;
import javax.persistence.EntityManager;
@Stateless
public class ServiceBean
implements Service
{
  @PersistenceContext private EntityManager em;
...

EntityManager API を使用してエンティティを検索する

EntityManager オブジェクトをいったんインスタンス化したら、そのメソッドを使用して永続性コンテキスト内のエンティティと対話できます。この節では、エンティティのライフサイクルを特定および管理するメソッドについて説明します。EntityManager のその他の用途 (トランザクション管理、キャッシュ処理など) については、『BEA Kodo documentation』の「EntityManager」を参照してください。

注意 : この節では、理解しやすいように、エンティティがデータベース テーブルの実際の行を表すようにコンフィグレーションされているものとします。

EntityManager.find() メソッドを使用すると、テーブル内の行をその主キーに基づいて検索できます。find メソッドは 2 つのパラメータをとります。1 つはクエリするエンティティ クラス (たとえば Person.class)、もう 1 つは取得する特定の行の主キーの値です。行を取得したら、標準の getXXX メソッドを使用して、エンティティの特定のプロパティを取得できます。次のコードの抜粋に、主キーの値が 10Person を検索してその住所を取得する方法を示します。

public List<Person> findPerson () {
   Person p = em.find(Person.class, 10);
Address a = p.getAddress();
    Query q = em.createQuery("select p from Person p where p.name = :name");
q.setParameter("name", "Patrick");
List<Person> l = (List<Person>) q.getResultList();
   return l;
  }

この例には、EntityManager.createQuery() メソッドを使用して、カスタム SQL クエリを含む Query オブジェクトを作成する方法も示されています。この方法は、テーブルの主キーだけでクエリできる EntityManager.find() メソッドとは対照的です。この例では、テーブル内の Patrick という名前の Person をすべてクエリし、行の結果セットを List<Person> オブジェクトに設定して呼び出し側のメソッド findPerson() に返しています。

EntityManager を使用してエンティティを作成および更新する

新しいエンティティ インスタンスを作成する (つまり、データベースに新しい行を追加する) には、EntityManager.persist メソッドを使用します。次にコードの抜粋を示します。

  @TransactionAttribute(REQUIRED)
  public Person createNewPerson(String name, int age) {
    Person p = new Person(name, age);
    em.persist(p); // 新しいオブジェクトをデータベースに登録する
    Address a = new Address();
    p.setAddress(a);
    em.persist(a); // この部分は、コンフィグレーションによっては不要
    return p;
  }
注意 : エンティティの作成および更新は、常にトランザクション内から行う必要があります。この例で、@TransactionAttribute アノテーションが REQUIRED に設定されているのはそのためです。

上の例では、createNewPerson に渡されたパラメータに基づいて新しい Person を作成する方法を示しています。その後、EntityManager.persist メソッドを呼び出すことで、行がデータベース テーブルに自動的に追加されます。

例では、新しく作成した Person エンティティ (つまり、新しいテーブル行) の Address を、setAddress() エンティティ メソッドを使用して更新する方法も示されています。Person エンティティのカスケード コンフィグレーションによっては、2 番目の persist() 呼び出しが不要な場合もあります。これは、データベースへの更新が、setAddress() メソッドによって自動的にトリガされる場合があるためです。カスケード処理の詳細については、『BEA Kodo documentation』の「Cascade Type」を参照してください。

EntityManager.find() メソッドを使用してエンティティ インスタンスを検索し、setXXX メソッドを使用してエンティティのプロパティを変更する場合は、データベースが自動的に更新されるため、EntityManager.persist() メソッドを明示的に呼び出す必要はありません。次のコードの抜粋を参照してください。

  @TransactionAttribute(REQUIRED)
  public Person changePerson(int id, int newAge) {   
    Person p = em.find(Person.class, id);
    p.setAge(newAge);
    return p;
  }

この例では、Person.setAge() メソッドの呼び出しによって、データベース テーブル内の適切な行への更新が自動的にトリガされています。

EntityManager.merge() メソッドを使用すると、クライアントによるエンティティの更新に基づいて、データベース テーブル内の行をすばやく簡単に更新できます。次に例を示します。

  @TransactionAttribute(REQUIRED)
  public Person applyOfflineChanges(Person pDTO) {
    return em.merge(pDTO);
  }

この例の applyOfflineChanges() メソッドはセッション Bean のビジネス メソッドで、パラメータとしてセッション Bean クライアントによって作成済みの Person を取ります。この PersonEntityManager.merge() メソッドに渡すと、EJB コンテナが自動的にデータベース テーブルの既存の行を検索し、その行を新しいデータで更新します。更新後には、merge() メソッドによってその行のコピーが返されます。

ビジネス メソッドまたはライフサイクル コールバック イベントのインターセプタを指定する

インターセプタは、ビジネス メソッドの呼び出しやライフサイクル コールバック イベントをインターセプトするメソッドです。インターセプタ メソッドには、ビジネス メソッドをインターセプトするメソッドと、ライフサイクル コールバック メソッドをインターセプトするメソッドの 2 種類があります。

インターセプタは、セッション Bean およびメッセージ駆動型 Bean に指定できます。

インターセプタ メソッドは、Bean クラス自体の中でプログラミングできますが、Bean クラスとは別にインターセプタ クラスをプログラミングして @javax.interceptor.Interceptors アノテーションで Bean クラスに関連付けることもできます。特定の順序でチェーンとして実行する複数のインターセプタ メソッドを作成できます。

インターセプタ インスタンスには状態を保持できます。インターセプタ インスタンスのライフサイクルは、それが関連付けられている Bean インスタンスのライフサイクルと同じです。インターセプタからは、JNDI、JDBC、JMS、他のエンタープライズ Bean、および EntityManager を呼び出すことができます。インターセプタ メソッドでは、その呼び出しの対象となった Bean の JNDI ネーム スペースが共有されます。エンタープライズ Bean のコンポーネントに適用する制約をプログラミングすると、それがインターセプタにも適用されます。

インターセプタは、javax.interceptor パッケージのメタデータ アノテーションを使用してコンフィグレーションします。コンフィグレーション方法については後ほど説明します。

以下の節では、Bean クラスのインターセプタを実際にプログラミングする方法について説明します。

ビジネス インターセプタまたはライフサイクル インターセプタを指定する : 一般的な手順

次に示す手順は、Bean クラスのインターセプタを指定してプログラミングする一般的な手順です。

インターセプタを指定しているサンプルについては「単純なステートフル EJB のサンプル」を、インターセプタ クラスのプログラミングのサンプルについては「インターセプタ クラスのサンプル」を参照してください。

  1. インターセプタ メソッドを、Bean クラス内でプログラミングするか、別のインターセプタ クラス内でプログラミングするかを決めます。
  2. インターセプタ メソッドを別のインターセプタ クラス内でプログラミングする場合は、次の手順に従います。
    1. インターセプタ クラスをプログラミングする」の説明に従ってクラスをプログラミングします。
    2. Bean クラスでは、@javax.interceptor.Interceptors アノテーションを使用して、インターセプタ クラスを Bean クラスに関連付けます。インターセプタ クラス内のメソッドには、@javax.interceptor.AroundInvoke アノテーションを付けます。これで、その Bean クラスのビジネス メソッド インターセプタ メソッドになります。同様に、ライフサイクル コールバック アノテーションを付けたメソッドは、その Bean クラスのライフサイクル コールバック インターセプタ メソッドになります。
    3. 1 つの Bean クラスに指定できるインターセプタ クラスの数に制限はありません。複数のインターセプタ クラスを指定した場合は、アノテーションに記述されている順序で実行されます。インターセプタ クラスをクラス レベルで指定した場合、インターセプタ メソッドは適切なすべての Bean クラス メソッドに適用されます。インターセプタ クラスをメソッド レベルで指定した場合は、アノテーションを付けたメソッドにのみ適用されます。

  3. インターセプタ メソッドをプログラミングしたクラス (Bean クラスまたはインターセプタ クラス) で、「ビジネス メソッド インターセプタ メソッドをプログラミングする」の説明に従ってビジネス メソッド インターセプタ メソッドをプログラミングします。
  4. インターセプタ メソッドをプログラミングしたクラス (Bean クラスまたはインターセプタ クラス) で、「ライフサイクル コールバック インターセプタ メソッドをプログラミングする」の説明に従ってライフサイクル コールバック インターセプタ メソッドをプログラミングします。
  5. 必要に応じ、Bean クラス内でメソッドに @javax.interceptor.ExcludeClassInterceptors アノテーションを付けて、クラス レベルで定義したインターセプタを除外します。
  6. 必要に応じ、Bean クラス内でクラスまたはメソッドに @javax.interceptor.ExcludeDefaultInterceptors アノテーションを付けて、後で定義する可能性のあるデフォルト インターセプタを除外します。デフォルト インターセプタは、ejb-jar.xml デプロイメント記述子でコンフィグレーションします。アノテーションを使用して明示的に除外しない限り、JAR ファイル内のすべての EJB に適用されます。
  7. 必要に応じ、「デフォルト インターセプタ メソッドを指定する」の説明に従って、EJB JAR ファイル全体に適用されるデフォルト インターセプタを指定します。

インターセプタ クラスをプログラミングする

インターセプタ クラスは、インターセプタ アノテーションを含むプレーン Java クラスです。インターセプタ アノテーションによって、どのメソッドでビジネス メソッドやライフサイクル コールバック メソッドをインターセプトするかを指定します。

インターセプタ クラスでは、依存性注入がサポートされます。依存性注入は、インターセプタ クラス インスタンスの作成時に、関連付けられているエンタープライズ Bean のネーミング コンテキストを使用して実行されます。

インターセプタ クラスには、引数を取らないパブリック コンストラクタを含める必要があります。

インターセプタ クラスに含めるメソッドの数に制限はありませんが、インターセプタ アノテーションを付けることのできるメソッドの数に上限があるためその制約を受けます。この点については、以降の節で説明します。

サンプルについては、「インターセプタ クラスのサンプル」を参照してください。

ビジネス メソッド インターセプタ メソッドをプログラミングする

ビジネス メソッド インターセプタ メソッドを指定するには、メソッドに @AroundInvoke アノテーションを付けます。

@AroundInvoke アノテーションを付けたメソッドは、インターセプタ クラスまたは Bean クラスごとに 1 つしか指定できません。1 つのビジネス メソッドに対して複数のインターセプタ メソッドを指定するには、Bean ファイル自体の中にインターセプタ メソッドを指定した上で (この指定は省略可能)、複数のインターセプタ クラスを Bean ファイルに関連付ける必要があります。インターセプタ メソッドが実行される順序は、関連付けられたインターセプタ クラスを @Interceptor アノテーション内で指定する順序によって決まります。Bean ファイル自体の中に指定したインターセプタ メソッドは、インターセプタ クラス内に定義されたメソッドの後に実行されます。

ビジネス メソッド自体に @AroundInvoke アノテーションを付けることはできません。

@AroundInvoke メソッドのシグネチャは次のようになっている必要があります。

 Object <METHOD>(InvocationContext) throws Exception

@AroundInvoke アノテーションを付けたメソッドは、常に InvocationContext.proceed() を呼び出すようにするか、ビジネス メソッドや後続の @AroundInvoke メソッドが呼び出されないようにする必要があります。InvocationContext API の詳細については、「InvocationContext API を使用してインターセプタ間で状態を保存する」を参照してください。

ビジネス メソッド インターセプタ メソッドの呼び出しは、対象となるビジネス メソッドと同じトランザクションおよびセキュリティ コンテキストの中で発生します。ビジネス メソッド インターセプタ メソッドからは、ビジネス メソッドの throws 句で許可されている実行時例外やアプリケーション例外が送出されることがあります。

サンプルについては、「インターセプタ クラスのサンプル」を参照してください。

ライフサイクル コールバック インターセプタ メソッドをプログラミングする

ライフサイクル コールバック インターセプタ メソッドとして指定したメソッドは、EJB コンテナからライフサイクル イベントの通知を受信できます。ライフサイクル イベントには、Bean インスタンスの作成、パッシベーション、破棄などがあります。

ライフサイクル コールバック インターセプタ メソッドには任意の名前を付けることができます。この点は、メソッドの名前を ejbCreate()ejbPassivate() などにしなければならなかった EJB 2.X プログラミング モデルとは異なります。

メソッドをライフサイクル コールバック インターセプタ メソッドとして指定するには、以下のライフサイクル インターセプタ アノテーションを使用します。

上に挙げたアノテーションは、メソッドが Bean クラス内にあるか別のインターセプタ クラス内にあるかに関係なく同じ方法で使用します。1 つのメソッドに複数のアノテーションを付けることもできます。

また、Bean クラス内または関連付けられたインターセプタ クラス内に、ライフサイクル コールバック アノテーションのサブセットや組み合わせを指定することも可能です。ただし、1 つのクラス内に、同じコールバック アノテーションを複数回指定することはできません。1 つのクラス内に複数のコールバック アノテーションを指定した場合、その EJB はデプロイされません。

1 つのライフサイクル コールバック イベントに対して複数のインターセプタ メソッドを指定するには、Bean ファイル自体の中にライフサイクル コールバック インターセプタ メソッドを指定した上で (この指定は省略可能)、複数のインターセプタ クラスを Bean ファイルに関連付ける必要があります。インターセプタ メソッドが実行される順序は、関連付けられたインターセプタ クラスを @Interceptor アノテーション内で指定する順序によって決まります。Bean ファイル自体の中に指定したインターセプタ メソッドは、インターセプタ クラス内に定義されたメソッドの後に実行されます。

アノテーションを付けたメソッドのシグネチャは、メソッドをどこで定義したかによって異なります。

InvocationContext API の詳細については、「InvocationContext API を使用してインターセプタ間で状態を保存する」を参照してください。

ライフサイクル インターセプタ クラスをプログラミングする際のその他の要件については、「javax.ejb.PostActivate」、「javax.ejb.PrePassivate」、「javax.annotation.PostConstruct」、および「javax.annotation.PreDestroy」を参照してください。

サンプルについては、「インターセプタ クラスのサンプル」を参照してください。

デフォルト インターセプタ メソッドを指定する

デフォルト インターセプタ メソッドは、特定の EJB JAR ファイル内または展開されたディレクトリ内のすべてのコンポーネントに適用されます。したがって、必ず ejb-jar.xml デプロイメント記述子でコンフィグレーションする必要があり、メタデータ アノテーションは特定の EJB にしか適用されないため使用できません。

デフォルト インターセプタ メソッドが設定されている場合、EJB コンテナは、EJB に対して定義されている他のすべてのインターセプタ (ビジネスおよびライフサイクルの両方) を呼び出す前に、このデフォルト インターセプタ メソッドを呼び出します。特定の EJB でデフォルト インターセプタが呼び出されないようにするには、Bean ファイルでクラス レベルの @javax.interceptor.ExcludeDefaultInterceptors アノテーションを指定します。

ejb-jar.xml ファイルでは、<assembly-descriptor><interceptor-binding> 子要素を使用してデフォルト インターセプタを指定します。具体的には、<ejb-name> 子要素を * に設定してそのクラスがすべての EJB に適用されるようにしてから、<interceptor-class> 子要素をインターセプタ クラスの名前に設定します。

次の ejb-jar.xml からの抜粋に、デフォルト インターセプタ クラス org.mycompany.DefaultIC を指定する方法を示します。

<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar version="3.0"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd">
...
   <assembly-descriptor>
...
      <interceptor-binding>
<ejb-name>*</ejb-name>
<interceptor-class>org.mycompany.DefaultIC</interceptor-class>
</interceptors>
   </assembly-descriptor>
</ejb-jar>

InvocationContext API を使用してインターセプタ間で状態を保存する

javax.interceptor.InvocationContext API を使用すると、特定のビジネス メソッドまたはライフサイクル コールバックに対して実行するインターセプタ間で状態情報をやり取りできます。EJB コンテナは、同じ InvocationContext インスタンスを各インターセプタ メソッドに渡します。したがって、たとえばビジネス メソッド インターセプタ メソッドを初めて実行したときの情報を保存しておき、このビジネス メソッドに対して実行する後続のインターセプタ メソッドにこの情報を渡すことができます。InvocationContext インスタンスは、ビジネス メソッド呼び出しやライフサイクル コールバック呼び出しの間では共有されません。

すべてのインターセプタ メソッドは、InvocationContext パラメータを取る必要があります。これにより、InvocationContext インタフェースのメソッドを使用して、コンテキスト情報を取得したり設定したりすることが可能になります。次に、InvocationContext インタフェースを示します。

public interface InvocationContext {
public Object getBean();
public Method getMethod();
public Object[] getParameters();
public void setParameters(Object[]);
public java.util.Map getContextData();
public Object proceed() throws Exception;
}

getBean メソッドは、Bean インスタンスを返します。getMethod メソッドは、呼び出されたインターセプタ メソッドが対象とするビジネス メソッドの名前を返します。ライフサイクル コールバック インターセプタ メソッドの場合は null を返します。

proceed メソッドは、チェーン内の次のインターセプタ メソッドの呼び出しを発生させます。チェーン内の最後の @AroundInvoke インターセプタ メソッドから呼び出された場合は、ビジネス メソッド自体の呼び出しを発生させます。

InvocationContext を使用しているサンプルについては、「インターセプタ クラスのサンプル」を参照してください。

アプリケーション例外をプログラミングする

ビジネス インタフェースにアプリケーション例外を送出するメソッドを指定した場合は、その例外を Bean クラスとは別のクラスとしてプログラミングする必要があります。

@javax.ejb.ApplicationException アノテーションを使用すると、例外クラスが EJB のビジネス メソッドによって送出されるアプリケーション例外であることを指定できます。アプリケーション エラーが発生すると、EJB コンテナからクライアントに直接例外が報告されます。

アプリケーション エラーが発生したときに現在のトランザクションをロールバックするかどうかを指定するには、@ApplicationExceptionrollback ブール属性を使用します。デフォルトでは、エラーが発生しても現在のトランザクションはロールバックされません。

このアノテーションでは、検査済みの例外も未検査の例外も指定できます。

次に示す ProcessingException.java ファイルでは、@ApplicationException アノテーションを使用して、例外クラスが EJB のビジネス メソッドによって送出されるアプリケーション例外であることを指定する方法を示します。

package examples;
import javax.ejb.ApplicationException;
/**
 * EJB のビジネス メソッドで処理エラーが発生したときに送出される
* アプリケーション例外クラス。@ApplicationException
* アノテーションが追加されている。
*/
@ApplicationException()
public class ProcessingException extends Exception {
  /**
   * 文字列を指定せずに例外をキャッシュする
   *
   */
public ProcessingException() {}
  /**
   * 指定された文字列で適切な例外を生成する
   *
   * @param message 例外メッセージ
   */
public ProcessingException(String message) {super(message);}
}

EJB へのアクセスにセキュリティを設定する

デフォルトでは、EJB のパブリック メソッドはどのユーザでも呼び出すことができます。EJB へのアクセスを制限したい場合は、以下のセキュリティ関連アノテーションを使用して、すべてのメソッド (またはメソッドのサブセット) を呼び出すことができるロールを指定します。

上に挙げたアノテーションは、EJB 3.0 だけでなく、メタデータ アノテーションをサポートするさまざまな Java EE コンポーネントで使用できます。

セキュリティ ロールを作成し、ロールにユーザをマッピングするには、WebLogic Server Administration Console でセキュリティ レルムを更新します。詳細については、「セキュリティ ロールの管理」を参照してください。

次に、すべてのセキュリティ関連アノテーションを使用した単純なステートレス セッション EJB のサンプルを示します。太字で示した部分については後ほど解説します。

package examples;
import javax.ejb.Stateless;
import javax.annotation.security.DeclareRoles;
import javax.annotation.security.PermitAll;
import javax.annotation.security.DenyAll;
import javax.annotation.security.RolesAllowed;
import javax.annotation.security.RunAs;
/**
* Service ビジネス インタフェースを実装する Bean ファイル。
*/
@Stateless
@DeclareRoles( { "admin", "hr" } )
@RunAs ("admin")
public class ServiceBean
implements Service
{
  @RolesAllowed ( {"admin", "hr"} )
public void sayHelloRestricted() {
System.out.println("Only some roles can invoke this method.");
}
  @DenyAll
public void sayHelloSecret() {
System.out.println("No one can invoke this method.");
}
  @PermitAll
public void sayHelloPublic() {
System.out.println("Everyone can invoke this method.");
}
}

このサンプル コードで注目すべき主な点は以下のとおりです。

トランザクション管理とトランザクション属性を指定する

デフォルトでは、EJB コンテナはビジネス メソッドをトランザクション コンテキスト内で呼び出します。また、トランザクションをコミットまたはロールバックするかどうかは EJB コンテナ自体が決定します。これを、コンテナ管理によるトランザクションの境界設定といいます。

このデフォルト動作は、Bean ファイルで以下のアノテーションを使用して変更できます。

javax.ejb.TransactionAttribute アノテーションを使用しているサンプルについては、「単純なステートフル EJB のサンプル」を参照してください。

 


メタデータ アノテーションの機能別一覧

ここに示す EJB 3.0 メタデータ アノテーションについては、完全なリファレンス情報を「EJB 3.0 メタデータ アノテーション リファレンス」にアルファベット順でまとめてあります。この節の表では、アノテーションを機能別にグループ化しています。

Bean タイプを指定するためのアノテーション

表 5-1 Bean タイプを指定するためのアノテーション
アノテーション
説明
Bean クラスがステートレス セッション Bean であることを指定する。
Bean クラスがステートフル セッション Bean であることを指定する。
ステートフル セッション Bean メソッドと、適合する EJB 2.1 EJBHome または EJBLocalHome クライアント ビューの create<METHOD> メソッドとの対応関係を指定する。
ステートフル セッション Bean の remove メソッドを指定する。
Bean クラスがメッセージ駆動型 Bean であることを指定する。
操作環境でメッセージ駆動型 Bean をコンフィグレーションするために使用するプロパティを指定します。

ローカル インタフェースまたはリモート インタフェースを指定するためのアノテーション

表 5-2 ローカル インタフェースまたはリモート インタフェースを指定するためのアノテーション
アノテーション
説明
Bean のローカル インタフェースを指定する。
Bean のリモート インタフェースを指定する。

EJB 2.X クライアント ビューをサポートするためのアノテーション

表 5-3 EJB 2.X クライアント ビューをサポートするためのアノテーション
アノテーション
説明
Bean のローカル ホーム インタフェースを指定する。
Bean のリモート ホーム インタフェースを指定する。

3.0 エンティティ Bean を呼び出すためのアノテーション

表 5-4 3.0 エンティティ Bean を呼び出すためのアノテーション
アノテーション
説明
EntityManager 永続性コンテキストへの依存性を指定する。
1 つまたは複数の PersistenceContext アノテーションを指定する。
EntityManagerFactory への依存性を指定する。
1 つまたは複数の PersistenceUnit アノテーションを指定する。

トランザクション関連のアノテーション

表 5-5 トランザクション関連のアノテーション
アノテーション
説明
トランザクションの境界設定管理の種類 (コンテナ管理または Bean 管理) を指定する。
ビジネス メソッドをトランザクションのコンテキスト内で呼び出すかどうかを指定する。

インターセプタを指定するためのアノテーション

表 5-6 インターセプタを指定するためのアノテーション
アノテーション
説明
Bean クラスまたはメソッドに関連付けるインターセプタ クラスのリストを指定する。
インターセプタ メソッドを指定する。
アノテーションを付けたメソッドが呼び出されたときに、クラス レベルのインターセプタを呼び出さないことを指定する。
アノテーションを付けたメソッドが呼び出されたときに、デフォルト インターセプタを呼び出さないことを指定する。

ライフサイクル コールバックを指定するためのアノテーション

表 5-7 ライフサイクル コールバックを指定するためのアノテーション
アノテーション
説明
ステートフル セッション Bean がアクティブ化された後にコールバックを受信するメソッドを指定する。
ステートフル セッション Bean がパッシベーションされる前にコールバックを受信するメソッドを指定する。
依存性注入が完了した後に、初期化を実行するために呼び出す必要のあるメソッドを指定する。
コンテナがインスタンスを削除しようとしていることを知らせるコールバック通知を受信するメソッドを指定する。

セキュリティ関連のアノテーション

以下のメタデータ アノテーションは、EJB 3.0 固有のアノテーションではなく、javax.annotation.security パッケージに含まれる一般的なセキュリティ関連アノテーションです。

表 5-8 セキュリティ関連のアノテーション
アノテーション
説明
Bean クラス内のセキュリティ ロールへの参照を指定する。
Bean のビジネス メソッドを呼び出すことができるセキュリティ ロールのリストを指定する。
そのメソッドがすべてのセキュリティ ロールで呼び出せることを指定する。
そのメソッドがどのセキュリティ ロールでも呼び出せないことを指定する。
そのメソッドをどのセキュリティ ロールとして実行するかを指定する。

コンテキスト依存性アノテーション

表 5-9 コンテキスト依存性アノテーション
アノテーション
説明
EJB ビジネス インタフェースまたはホーム インタフェースへの依存性を指定する。
1 つまたは複数の @EJB アノテーションを指定する。
Bean の環境内の外部リソースへの依存性を指定する。
1 つまたは複数の @Resource アノテーションを指定する。

タイムアウトと例外のアノテーション

表 5-10 タイムアウトと例外のアノテーション
アノテーション
説明
Bean クラスのタイムアウト メソッドを指定します。
例外がアプリケーション例外で、クライアントに直接報告することを指定する。


ページの先頭       前  次