ヘッダーをスキップ
Oracle® Fusion Middleware Oracle WebLogic Server Enterprise JavaBeansのプログラミング
12c リリース1(12.1.1)
B65950-02
  ドキュメント・ライブラリへ移動
ライブラリ
製品リストへ移動
製品
目次へ移動
目次

前
 
次
 

4 Enterprise JavaBeansの反復的な開発

次の項では、EJB 3.1の一般的な実装プロセスを説明し、EJBをWebLogic Serverで実行する方法について説明します。

EJB開発プロセスの概要

この節では、EJB 3.1の開発プロセスを簡単に説明します。主な実装タスクと関連する結果について説明します。

次の項の大部分では、EJB 3.1プログラミング・モデルについて説明しています。3.1と2.xでのプログラミング・モデルの相違点については、一部で簡単に触れているのみです。EJB 2.xに精通しており、2つのモデルの相違点について詳しく知りたい場合は、「EJBの新機能および変更点」を参照してください。

表4-1 EJB開発タスクと結果

#
手順 説明 結果

1

ソース・ディレクトリを作成する


Javaソース・ファイルのディレクトリ構造を作成し、必要に応じてデプロイメント記述子を作成します。

ローカル・ドライブ上のディレクトリ構造

2

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


インタフェースを実装するJavaファイルを作成し、EJBの動作を記述するEJB 3.1メタデータ・アノテーションを含めます。

.javaファイル

3

EJBインタフェースのプログラミング


EJBを記述するインタフェースなしのビューまたはビジネス・インタフェースを作成します。

各インタフェースの.javaファイル

4

インターセプタのプログラミング(省略可能)


必要に応じて、ビジネス・メソッド呼出しやライフサイクル・コールバック・イベントをインターセプトするインターセプタを記述したインターセプタ・クラスを作成します。

各インターセプタ・クラスの.javaファイル

5

EJBタイマー・サービスのプログラミング(省略可能)


必要に応じて、タイマー・オブジェクトが時限イベントの時刻を過ぎたときに発生するコールバックをスケジューリングするタイマーを作成します。

メタデータの変更(自動タイマーの場合)またはクラスの変更(プログラムによるタイマーの場合)。

6

EJBクライアントへのアクセスのプログラミング


依存関係インジェクションまたはJNDIルックアップを使用してEJBの参照を取得します。

メタデータの変更(アノテーションの設定やデプロイメント記述子の設定)またはクライアントに対するコード変更。

7

トランザクションのプログラミングと構成


コンテナ管理のトランザクションまたはBean管理のトランザクションをプログラミングします。

メタデータおよび場合によっては例外を処理するためのロジック(再試行ロジックまたはsetRollbackOnlyの呼出し)。

8

Javaソースをコンパイルする


ソース・コードをコンパイルします。

各クラスおよびインタフェースの.classファイル

9

デプロイメント記述子の作成と編集(省略可能)


必要に応じて、EJB固有のデプロイメント記述子を作成します。この手順は、EJB 3.1プログラミング・モデルを使用する場合は不要です。

  • ejb-jar.xml

  • weblogic-ejb-jar.xml (WebLogic Server固有の機能を制御する要素が格納されます)。

10

EJBのパッケージ化


コンパイル済みのクラス(および、必要に応じてデプロイメント記述子)をデプロイメント用にパッケージ化します。

状況によっては、ファイルをアーカイブせずにディレクトリ形式で展開しておくことも可能です。

アーカイブ・ファイル(EJB JARまたはエンタープライズ・アプリケーションEAR)、または対応する展開済みディレクトリ

11

EJBのデプロイメント


選択したステージング・モードに従って、アーカイブまたはアプリケーション・ディレクトリのターゲットとして目的の管理対象サーバーまたはWebLogic Serverクラスタを設定します。

デプロイしたEJBでサービスを呼び出せます。


ソース・ディレクトリを作成する

EJB 3.1モジュールをアセンブルするソース・ディレクトリを作成します。

ソース・ファイルと出力ファイルを並列ディレクトリ構造に分離する分割開発ディレクトリ構造をお薦めします。分割ディレクトリ構造を準備し、EJB 3.1をエンタープライズ・アプリケーション・アーカイブ(EAR)としてパッケージ化する方法については、『Oracle WebLogic Serverアプリケーションの開発』の分割開発ディレクトリ環境の概要に関する項を参照してください。

JARをパッケージ化するためのディレクトリ構造

EJBをJARファイルにパッケージ化してデプロイする場合は、クラス・ファイル用のディレクトリを作成します。EJBデプロイメント記述子(EJB 3.1プログラミング・モデルでは、オプションですがサポートはされています)も使用する場合は、それをMETA-INF/ejb-jar.xmlとしてパッケージ化できます。

例4-1 JARをパッケージ化するためのディレクトリ構造

myEJBjar/
     META-INF/
          ejb-jar.xml
          weblogic-ejb-jar.xml
          weblogic-cmp-jar.xml
     foo.class
     fooBean.class

詳細は、「JARでのEJBのパッケージ化」を参照してください。

WARをパッケージ化するためのディレクトリ構造

EJBは、EJBクラスをWEB-INF/classesという名前のサブディレクトリに入れるか、WEB-INF/libディレクトリ内のJARファイルに入れることで、Webアプリケーション・モジュール(WAR)に直接パッケージ化することもできます。必要に応じて、EJBデプロイメント記述子も使用する場合は、それをWEB-INF/ejb-jar.xmlとしてパッケージ化できます。

例4-2 WARをパッケージ化するためのディレクトリ構造

myEJBwar/
     WEB-INF/
          ejb-jar.xml
          weblogic.xml
          weblogic-ejb-jar.xml
          /classes
               foo.class
               fooServlet.class
               fooBean.class

注意:

EJB 2.1エンティティBeanおよびEJB 1.1エンティティBeanは、WARファイル内ではサポートされません。これらのコンポーネント・タイプは、スタンドアロンのejb-jarファイルまたはEARファイル内でパッケージ化されたejb-jarファイル内でのみパッケージ化する必要があります。


詳細は、「WARでのEJBのパッケージ化」を参照してください。

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

EJB Beanクラスは、EJBプログラミングの主要なアーティファクトで、EJBビジネス・インタフェースを実装し、EJBメタデータ・アノテーションを含みます。EJBメタデータ・アノテーションの用途としては、EJBコンテナへのセマンティクスおよび要件の指定、コンテナ・サービスの要求、アプリケーション・デプロイヤやコンテナ・ランタイムへの構造情報および構成情報の提供などがあります。

EJB 3.1プログラミング・モデルで必須なアノテーションは、EJBのタイプを指定する@javax.ejb.Stateful@javax.ejb.Stateless、または@javax.ejb.MessageDrivenのいずれか1つのみです。他にもさまざまなアノテーションを使用してEJBを細かく構成できますが、それらのアノテーションには一般的なデフォルト値が設定されているため、デフォルト以外の動作を設定したい場合を除けば、Beanクラス内で明示的にそれらのアノテーションを使用する必要はありません。このようなプログラミング・モデルにより、一般的な動作を実行するEJBのプログラミングが非常に簡単になっています。

Beanクラスのプログラミングの詳細やサンプルについては、第5章「アノテーション付きEJBクラスのプログラミング」を参照してください。

EJBインタフェースのプログラミング

クライアントは、インタフェースなしのビューまたはビジネス・インタフェースを介してエンタープライズBeanにアクセスします。

インタフェースなしのクライアント・ビューを使用したEJBへのアクセス

EJB 3.1のインタフェースなしのローカル・クライアント・ビュー・タイプでは、個別のローカル・ビジネス・インタフェースを必要とすることなく、ローカル・セッションBeanへのアクセスを提供して、コンポーネントでEJB Beanクラス・インスタンスを直接注入させることで、EJBの開発を単純化しています。

インタフェースなしのビューは、EJB 3.0ローカル・ビューと同様に動作します。たとえば、参照渡しのコールのセマンティクスおよびトランザクションやセキュリティ伝播などの機能をサポートします。ただし、インタフェースなしのビューでは、個別のインタフェースは必要ありません。つまり、Beanクラスのすべてのパブリック・メソッドは、コール元に自動的に公開されます。デフォルトでは、空のimplements句を持ち、他のローカルまたはリモート・クライアント・ビューを定義しないセッションBeanは、インタフェースなしのクライアント・ビューを公開します。

「インタフェースなしの単純なステートレスEJBの例」には、インタフェースなしのクライアント・ビューのコード・サンプルがあります。また、WebLogic Server配布キットには、インタフェースなしのクライアント・ビューの使用サンプルがバンドルされています。「EJB 3.1: 単純化されたインタフェースなしのプログラミングおよびWARファイルでのパッケージ化」を参照してください。

インタフェースなしのクライアント・ビューの実装の詳細は、Java EE 6チュートリアル(http://download.oracle.com/javaee/6/tutorial/doc/gipjf.html)の「エンタープライズBean」の章のインタフェースなしのビューを使用したローカル・エンタープライズBeanへのアクセスに関する項を参照してください。

ビジネス・インタフェースを使用したEJBへのアクセス

EJB 3.1ビジネス・インタフェースは、EJBのすべてのビジネス・メソッドの完全なシグネチャを記述するプレーンJavaインタフェースです。たとえば、Account EJBが顧客の当座預金口座を表す場合であれば、そのビジネス・インタフェースには顧客がその口座を管理するためのメソッド(withdrawdepositbalanceなど)を含めます。

ビジネス・インタフェースは、他のインタフェースを拡張できます。メッセージドリブンBeanの場合であれば、ビジネス・インタフェースはメッセージ・リスナー・インタフェースにするのが一般的です。どのメッセージング・リスナー・インタフェースにするかは、そのBeanで使用するメッセージングの種類によって決まります。たとえば、JMSの場合はjavax.jms.MessageListenerになります。セッションBeanのインタフェースには、このような明確な種類はありません。ビジネス・ニーズに合わせて、どのようなインタフェースでも使用できます。


注意:

EJB 3.1ビジネス・インタフェースの唯一の要件は、EJB 2.xと同様に、javax.ejb.EJBObjectまたはjavax.ejb.EJBLocalObjectを拡張してはいけないことです。


ステートレスおよびステートフル・セッションBeanによって実装されたビジネス・インタフェースのサンプルについては、「単純なビジネス・インタフェースを使用するステートレスEJBのサンプル」および「単純なステートフルEJBのサンプル」を参照してください。

ビジネス・インタフェースの指定に関する詳細やサンプルは、第5章「ビジネス・インタフェースとその他のインタフェースを指定する」を参照してください。

ビジネス・インタフェース・アプリケーション例外

EJBのビジネス・メソッドを設計する場合は、EJBのビジネス・インタフェースのメソッドのthrows句にアプリケーション例外を定義できます。「アプリケーション例外」とは、Beanクラス内に作成したプログラムからクライアントに、アプリケーション・レベルの異常な状態を警告するための例外です。たとえば、顧客が当座預金口座の引出し可能額を超える金額を引き出そうとしたときに、その口座を表すAccount EJBのwithdraw()メソッドからアプリケーション例外を送出できます。

アプリケーション例外は、システム例外とは異なります。システム例外は、データベース管理システムが利用できないなど、システム・レベルの例外をクライアントに警告するためにEJBコンテナからスローされる例外です。システム・レベルのエラーが、アプリケーション例外として報告されないようにしてください。

また、インタフェースがリモート・ビジネス・インタフェースである場合や、Beanクラスに@WebService JWSアノテーションが含まれている場合、およびメソッドに@WebMethodアノテーションが含まれている場合でも、ビジネス・メソッドがjava.rmi.RemoteException例外を送出しないようにする必要があります。唯一の例外は、ビジネス・インタフェースがjava.rmi.Remoteを拡張している場合です。EJBコンテナでプロトコル・レベルの問題が発生すると、基底のRemoteExceptionをラップしたEJBExceptionが送出されます。


注意:

@WebServiceおよび@WebMethodアノテーションは、javax.jwsパッケージに含まれています。これらのアノテーションは、EJBにWebサービスを実装すること、およびEJBビジネスをパブリックなWebサービス操作として公開することを指定するために使用します。これらのアノテーションの詳細、およびWebサービスのプログラミング全般については、『Oracle WebLogic Server JAX-WS Webサービス・スタート・ガイド』を参照してください。


EJBでのジェネリックスの使用

EJB 3.1プログラミング・モデルでは、ビジネス・インタフェースにおいてクラス・レベルでジェネリックスを使用できます。

ジェネリックスを使用する場合のベスト・プラクティスとしては、まずジェネリックスを使用するスーパーインタフェースを定義し、実際のビジネス・インタフェースでは特定のデータ型を使用してこのスーパーインタフェースを拡張することをお薦めします。

次に、この方法のサンプルを示します。まず、ジェネリックスを使用するスーパーインタフェースをプログラミングします。

  public interface RootI<T> {
    public T getObject();
    public void updateObject(T object);
  }

次に、実際のビジネス・インタフェースをプログラミングし、特定のデータ型でRootI<T>を拡張します。

  @Remote
  public interface StatelessI extends RootI<String> { }

最後に、実際のステートレス・セッションBeanをプログラミングしてビジネス・インタフェースを実装します。メソッドの実装では、指定したデータ型(この場合はString)を使用します。

  @Stateless
  public class StatelessSample implements StatelessI {
    public String getObject() {
      return null;
    }
    public void updateObject(String object) {
    }
  }

ビジネス・インタフェースまたはクラスで型変数を定義しても削除されます。この場合、ビジネス・インタフェースがBeanクラスによって他のジェネリック情報ではなくその型パラメータの上限値でパラメータ化されている場合のみ、EJBアプリケーションを正常にデプロイすることができます。たとえば、次の例の上限値はObjectです。

public class StatelessSample implements StatelessI<Object> { 
   public Object getObject() { 
      return null;
   } 
   public void updateObject(Object object) { 
   } 
} 

ビジネス・オブジェクトのシリアライズとデシリアライズ

ビジネス・オブジェクトのシリアライズとデシリアライズは、以下のインタフェースでサポートされます。これらのインタフェースは、すべてのビジネス・オブジェクトで実装されます。

  • weblogic.ejb.spi.BusinessObject

  • weblogic.ejb.spi.BusinessHandle

BusinessObject._WL_getBusinessObjectHandle()メソッドを使用して、ビジネス・ハンドル・オブジェクトを取得し、シリアライズします。

ビジネス・オブジェクトをデシリアライズするには、ビジネス・ハンドル・オブジェクトをデシリアライズし、BusinessHandle.getBusinessObject()メソッドを使用してビジネス・オブジェクトを取得します。

インターセプタのプログラミング(省略可能)

インターセプタは、ビジネス・メソッドの呼出しやライフサイクル・コールバック・イベントをインターセプトするメソッドです。

インターセプタ・メソッドは、実際のBeanクラス内に定義できますが、Beanクラスとは別にインターセプタ・クラスをプログラミングして@javax.ejb.InterceptorアノテーションでBeanクラスに関連付けることもできます。

インターセプタを使用するBeanクラスのプログラミングについては、「ビジネス・メソッドまたはライフサイクル・コールバック・イベントのインターセプタを指定する」を参照してください。

EJBタイマー・サービスのプログラミング(省略可能)

WebLogic Serverは、EJB 3.1仕様で定義されているEJBタイマー・サービスをサポートしています。EJBタイマー・サービスは、EJB 3.1仕様のとおり、時間ベースのイベントに対してコールバックをスケジュールできるコンテナ管理によるサービスです。コンテナは、時限イベントに関する信頼性の高いトランザクション通知サービスを提供します。タイマー通知は、カレンダベースのスケジュールに応じて、特定の時刻、特定の経過時間後、または特定の反復間隔で発生するようにスケジュールできます。

タイマー・サービスは、EJBコンテナで実装されます。エンタープライズBeanは、EJBContextインタフェースを介して、またはJNDIネームスペースのルックアップを介して、依存関係インジェクションによってこのサービスにアクセスします。

タイマー・サービスは、大まかなタイマー・サービスとして使用するように設計されています。大量のタイマー・オブジェクトを使用してデータ・セットに対して同じタスクを実行するより、少数のタイマーを使用して大量のタスクを実行することをお薦めします。たとえば、従業員の経費レポートを表すEJBがあるとします。各経費レポートは、マネージャの承認を受けてから処理されなければなりません。この場合、1つのEJBタイマーを使用してすべての未決の経費レポートを定期的に検査し、担当のマネージャに対して、承認待ちのレポートを決裁するように促す電子メールを送信できます。

タイマー・サービスの概要

タイマー・サービスは、タイマーのプログラムによる作成およびキャンセルのほか、Beanに関連付けられているタイマーの検索のためのメソッドを提供します。タイマーは、Beanクラスまたはデプロイメント記述子のメタデータに基づいて、デプロイメント時にコンテナにより自動的に作成することもできます。タイマー・オブジェクトは、ステートレス・セッションBean、シングルトン・セッションBean、メッセージドリブンBean、および2.1エンティティBean用に作成できます。タイマーは、ステートフル・セッションBeanでは作成できません。


注意:

2.1エンティティBeanでは、カレンダベースのタイマー、自動で作成されるタイマー、および非永続タイマー機能はサポートされません。


タイマーは、時限コールバックをスケジューリングするために作成されます。タイマー・サービスを使用するエンタープライズBeanのBeanクラスでは、次のようなタイムアウト・コールバック・メソッドを1つ以上を提供する必要があります。

  • プログラムによるタイマー - プログラムで作成されたタイマーの場合、このメソッドはTimeoutアノテーションの付いたメソッドになります。Beanでjavax.ejb.TimedObjectインタフェースを実装することもできます。javax.ejb.TimedObjectインタフェースは、単一のメソッド、タイマー・コールバック・メソッドejbTimeoutを備えています。

  • 自動タイマー - 自動で作成されるタイマーの場合、タイムアウト・メソッドは、Scheduleアノテーションの付いたメソッドになります。

  • 2.1エンティティBeanタイマー - 2.1エンティティBean用に作成されるタイマーは、エンティティBeanのIDと関連付けられます。ステートレス・セッションBeanまたはメッセージドリブンBean用に作成されるタイマーのタイムアウト・コールバック・メソッド呼出しは、プールされた状態で任意のBeanインスタンスで呼び出すことができます。

カレンダベースのEJBタイマー

EJB 31。タイマー・サービスでは、カレンダベースのEJBタイマー式をサポートします。このスケジューリング機能では、CRONスタイルのスケジュール定義という形式をとっています。これは、EJBメソッドに配置され、定義されたスケジュールに応じてメソッドを自動的に呼び出せます。


注意:

EJB 2.xエンティティBeanでは、カレンダベースのタイマーはサポートされません。


カレンダベースのタイマーは、javax.ejb.TimerServiceの2つのメソッドを使用してプログラム的に作成できます。これらは、引数としてjavax.ejb.ScheduleExpressionを受け取ります。タイマーを作成する前に、ScheduleExpressionを作成してデータを入力します。自動カレンダベース・タイマーを作成する場合、javax.ejb.Scheduleアノテーション(および対応するejb-jar.xml要素)には、カレンダベースのタイマー式を構成できる多数の属性が含まれます。

カレンダベースの時間式の7つの属性の詳細は、Enterprise JavaBeans 3.1仕様(JSR-318)(http://jcp.org/en/jsr/summary?id=318)のカレンダベースのタイマー式に関する第18.2.1項を参照してください。

自動作成されるEJBタイマー

EJB 3.1タイマー・サービスでは、Beanクラスまたはデプロイメント記述子のメタデータに基づくタイマーの自動作成をサポートします。これによりBean開発者は、Bean呼出しに依存せずにタイマーをスケジューリングし、プログラムでいずれかのTimer Serviceタイマー作成メソッドを呼び出すことができます。自動作成されるタイマーは、アプリケーション・デプロイメントの結果としてコンテナで作成されます。

javax.ejb.Scheduleアノテーションを使用して、特定のタイムアウト・スケジュールを持つタイマーを自動的に作成できます。このアノテーションは、そのスケジュールに関連付けられるタイマー・コールバックを受け取るBeanクラス(またはスーパークラス)のメソッドに適用されます。javax.ejb.Schedulesアノテーションを使用して、複数の自動タイマーを単一のタイムアウト・コールバック・メソッドに適用できます。

クラスタ化EJBタイマー実装を使用する場合、EJBがデプロイされているサーバー数にかかわらず、それぞれのScheduleアノテーションは単一の永続タイマーに対応します。

非永続タイマー

デフォルトでは、EJBタイマーは永続します。非永続タイマーは、その存続時間が、タイマーが作成されたJVMに関係するタイマーです。非永続タイマーは、アプリケーションの停止、コンテナのクラッシュ、タイマーが起動されたJVMの失敗/停止のイベントが発生すると、キャンセルと見なされます。


注意:

EJB 2.xエンティティBeanでは、非永続タイマーはサポートされません。


非永続タイマーは、プログラムで作成することも自動的に作成することもできます(@Scheduleまたはデプロイメント記述子を使用します)。

自動の非永続タイマーを指定するには、@Scheduleアノテーションの永続属性をfalseに設定します。自動の非永続タイマーでは、コンテナが配信される各JVMのアプリケーションの初期化時に、コンテナで新しい非永続タイマーを作成します。

クラスタ化EJBタイマー・サービスとローカルEJBタイマー・サービス

EJBタイマー・サービスは、2つのタイプ(クラスタまたはローカル)を構成することができます。

クラスタ化EJBタイマー・サービス

クラスタ化EJBタイマー・サービスには、次の利点があります。

  • 可視性に優れています。

    クラスタ内のすべてのノードからタイマーにアクセスできます。たとえば、javax.ejb.TimerService.getTimers()メソッドを使用すると、EJBに対して作成されたクラスタに含まれるすべてのステートレス・セッションBeanタイマーまたはメッセージドリブンBeanタイマーの完全なリストが返されます。エンティティBeanの主キーをgetTimers()メソッドに渡すと、そのエンティティBeanのタイマーのリストが返されます。

  • 自動ロード・バランシングおよびフェイルオーバー

    クラスタ化EJBタイマー・サービスは、ジョブ・スケジューラのロード・バランシング機能とフェイルオーバー機能を利用できます。

クラスタ化EJBタイマー・サービスの構成については、「クラスタ化EJBタイマーの構成」を参照してください。

ローカルEJBタイマー・サービス

ローカルEJBタイマー・サービスは、ローカルEJBタイマー・サービスが作成されたサーバー上でのみ実行され、そのサーバー上のBeanにしか認識されません。ローカルEJBタイマー・サービスを使用する場合、クラスタ化EJBタイマー・サービスとは異なり、クラスタ、データベース、JDBCデータ・ソース、またはリース・サービスを構成する必要はありません。

ローカルEJBタイマー・オブジェクトは、別のサーバーに移行できません。タイマー・オブジェクトは、サーバー全体の一部としてのみ移行できます。EJBタイマーが存在するサーバーが何らかの理由でダウンした場合、サーバーを再起動するか、またはサーバー全体を移行しなければタイマーを実行できません。


注意:

クラスタ化された環境では、ローカル・タイマー実装に厳密な制限があるため、ローカル・タイマーを使用しないことをお薦めします。そのかわりに、クラスタ化されたタイマー実装を使用します。クラスタ化された環境でローカル・タイマー実装が使用されるように構成されている場合、デプロイメント時に警告がスローされます。


クラスタ化EJBタイマーの構成


注意:

クラスタ化EJBタイマーの利点については、「クラスタ化EJBタイマー・サービスとローカルEJBタイマー・サービス」を参照してください。


EJBタイマーのクラスタリングを構成するには、次のステップを実行します:

  1. 以下について構成したかどうかを確認します。

    • クラスタ化ドメイン。詳細は、『Oracle WebLogic Serverクラスタの使用』のWebLogicクラスタの設定に関する項を参照してください。

    • ジョブ・スケジューラの以下の機能。

      • HAデータベース(Oracle、DB2、Informix、MySQL、Sybase、MSSQLなど)。

      • config.xmlファイルの<data-source-for-job-scheduler>要素を使用してHAデータベースにマップされているJDBCデータ・ソース。

      • リース・サービス。デフォルトでは、データベース・リースが使用され、config.xmlファイルの<data-source-for-job-scheduler>要素によって定義されたJDBCデータ・ソースが使用されます。

    ジョブ・スケジューラの構成については、『Oracle WebLogic Server Timer and Work Manager API (CommonJ)プログラマーズ・ガイド』を参照してください。

  2. クラスタ化EJBタイマー・サービスを有効にするために、weblogic-ejb-jar.xmlデプロイメント記述子のtimer-implementation要素をClusteredに設定します。

    <timer-implementation>Clustered</timer-implementation>
    

    詳細は、『Oracle WebLogic Server Enterprise JavaBeansバージョン2.1のプログラミング』のweblogic-ejb-jar.xmlデプロイメント記述子のリファレンスに関する項のtimer-implementation要素を参照してください。

クラスタ化EJBタイマー・サービスでは、以下のように動作が変更されることに注意してください。

  • weblogic.ejb.WLTimer*インタフェースは、クラスタ化EJBタイマー・サービスではサポートされません。

  • createTimer()メソッドを使用してクラスタ化EJBタイマーを新しく作成する場合、タイマーの初期セット・アップ時にタイムアウトの実行が遅延する場合があります。

  • ジョブ・スケジューラでは、「少なくとも1回」の実行が保証されます。クラスタ化EJBタイマーが期限切れになった場合、データベースはリスナー・コールバック・メソッドが完了するまで更新されません。データベースが更新される前にサーバーがクラッシュした場合、タイマーはもう一度実行されます。

  • クラスタ化EJBタイマー・サービスでは、障害が発生した場合に実行するアクションに関するタイマーの構成オプションは使用できません。これらの構成オプションには、再試行の遅延、再試行の最大数、タイムアウトの最大数、およびタイムアウト・エラー・アクションがあります。

  • ジョブ・スケジューラは、期限切れになるタイマーを識別するために30秒ごとにデータベースに対して問合せを実行します。30秒未満の間隔でタイマーの実行が遅延する場合があります。

  • 障害が発生した場合、トランザクション対応のタイマーのみ再試行されます。

  • タイマー実行の固定間隔スケジューリングはサポートされません。

Javaプログラミング・インタフェースを使用してタイマー・オブジェクトをプログラミングする

この節では、EJB 3.1仕様に定義されている、タイマーのプログラミングに使用できるJavaプログラミング・インタフェースについて説明します。これらのインタフェースの詳細は、EJB 3.1仕様を参照してください。また、この節では、WebLogic Server固有のタイマー関連インタフェースについて詳しく説明します。

EJB 3.1タイマー関連プログラミング・インタフェース

次の表に、タイマーのプログラミングに使用できるEJB 3.1インタフェースを示します。

表4-2 EJB 3.1タイマー関連プログラミング・インタフェース

プログラミング・インタフェース 説明

javax.ejb.ScheduleExpression

カレンダベースEJBタイマー式の作成

javax.ejb.Schedule

特定のタイムアウト・スケジュールを持つタイマーを自動的に作成します。

javax.ejb.Schedulesアノテーションを使用して、複数の自動タイマーを単一のタイムアウト・コールバック・メソッドに適用できます。

javax.ejb.TimedObject

タイマー・コールバックのためにタイマー・サービスに登録されるBeanのエンタープライズBeanクラスによって実装されます。このインタフェースは、単一のメソッド、ejbTimeoutを備えています。

EJBContext

getTimerServiceメソッドを使用してタイマー・サービスにアクセスします。

javax.ejb.TimerService

EJBの新しいEJBタイマーを作成するか、既存のEJBタイマーにアクセスします。

javax.ejb.Timer

特定のEJBタイマーに関する情報にアクセスします。

javax.ejb.TimerHandle

永続化できるシリアライズ可能なタイマー・ハンドルを定義します。タイマーはローカル・オブジェクトなので、TimerHandleはBeanのリモート・インタフェースまたはWebサービス・インタフェースを介して渡してはいけません。


EJB 2.1のタイマー関連プログラミング・インタフェースの詳細は、EJB 2.1仕様を参照してください。

WebLogic Server固有のタイマー関連インタフェース

タイマーのプログラミングに使用できるWebLogic Server固有のインタフェースは以下のとおりです。

  • weblogic.management.runtime.EJBTimerRuntimeMBean。特定のEJBHomeのタイマーの実行時情報と管理機能を提供します。例4-3weblogic.management.runtime.EJBTimerRuntimeMBeanインタフェースを示します。

例4-3 weblogic.management.runtime.EJBTimerRuntimeMBeanインタフェース

public interface weblogic.management.runtime.EJBTimerRuntimeMBean {
  public int getTimeoutCount(); // get the number of successful timeout notifications that have been made
  public int getActiveTimerCount(); // get the number of active timers for this EJBHome
  public int getCancelledTimerCount(); // get the number of timers that have been cancelled for this EJBHome
  public int getDisabledTimerCount(); // get the number of timers temporarily disabled for this EJBHome
  public void activateDisabledTimers(); // activate any temporarily disabled timers
}
  • weblogic.ejb.WLTimerServiceインタフェース。javax.ejb.TimerServiceインタフェースの拡張です。このインタフェースを使用すると、タイマーに関するWebLogic Server固有の構成情報を指定できます。例4-4weblogic.ejb.WLTimerServiceインタフェースを示します。javax.ejb.TimerServiceの詳細は、EJB 2.1仕様を参照してください。


    注意:

    weblogic.ejb.WLTimerServiceインタフェースは、クラスタ化EJBタイマー・サービスではサポートされません(「クラスタ化EJBタイマーの構成」を参照)。


例4-4 weblogic.ejb.WLTimerServiceインタフェース

public interface WLTimerService extends TimerService {
  public Timer createTimer(Date initial, long duration, Serializable info,
    WLTimerInfo wlTimerInfo)
    throws IllegalArgumentException, IllegalStateException, EJBException;
  public Timer createTimer(Date expiration, Serializable info,
    WLTimerInfo wlTimerInfo)
    throws IllegalArgumentException, IllegalStateException, EJBException;
  public Timer createTimer(long initial, long duration, Serializable info
    WLTimerInfo wlTimerInfo)
    throws IllegalArgumentException, IllegalStateException, EJBException;
  public Timer createTimer(long duration, Serializable info,
    WLTimerInfo wlTimerInfo)
    throws IllegalArgumentException, IllegalStateException, EJBException;
}
  • weblogic.ejb.WLTimerInfoインタフェース。weblogic.ejb.WLTimerServiceインタフェースで使用され、タイマーに関するWebLogic Server固有の構成情報を渡します。例4-5weblogic.ejb.WLTimerInfoインタフェースを示します。


    注意:

    weblogic.ejb.WLTimerServiceインタフェースは、クラスタ化EJBタイマー・サービスではサポートされません(「クラスタ化EJBタイマーの構成」を参照)。


例4-5 weblogic.ejb.WLTimerInfoインタフェース

public final interface WLTimerInfo {
  public static int REMOVE_TIMER_ACTION  = 1;
  public static int DISABLE_TIMER_ACTION = 2;
  public static int SKIP_TIMEOUT_ACTION  = 3;
  /**
   * Sets the maximum number of retry attempts that will be
   * performed for this timer.  If all retry attempts
   * are unsuccesful, the timeout failure action will
   * be executed.
   */
  public void setMaxRetryAttempts(int retries);
  public int getMaxRetryAttempts();
  /**
   * Sets the number of milliseconds that should elapse
   * before any retry attempts are made.
   */
  public void setRetryDelay(long millis);
  public long getRetryDelay();
  /**
   * Sets the maximum number of timeouts that can occur
   * for this timer.  After the specified number of
   * timeouts have occurred successfully, the timer
   * will be removed.
   */
  public void setMaxTimeouts(int max);
  public int getMaxTimeouts();
/**
   * Sets the action the container will take when ejbTimeout
   * and all retry attempts fail.  The REMOVE_TIMER_ACTION,
   * DISABLE_TIMER_ACTION, and SKIP_TIMEOUT_ACTION fields
   * of this interface define the possible values.
   */
  public void setTimeoutFailureAction(int action);
  public int getTimeoutFailureAction();
}
  • weblogic.ejb.WLTimerインタフェース。javax.ejb.Timerインタフェースの拡張であり、タイマーの現在の状態に関する追加情報を提供します。例4-6weblogic.ejb.WLTimerインタフェースを示します。


    注意:

    weblogic.ejb.WLTimerServiceインタフェースは、クラスタ化EJBタイマー・サービスではサポートされません(「クラスタ化EJBタイマーの構成」を参照)。


例4-6 weblogic.ejb.WLTimerインタフェース

public interface WLTimer extends Timer {
  public int getRetryAttemptCount();
  public int getMaximumRetryAttempts();
  public int getCompletedTimeoutCount();
}

EJBクライアントへのアクセスのプログラミング

この項では、エンタープライズBeanへのアクセスを提供するクライアント・ビューを決定する際のガイドラインを示します。

リモート・クライアント

EJB 3.1仕様に示されているように、リモート・クライアントは、Beanのリモート・ビジネス・インタフェースを介してセッションBeanにアクセスします。EJB 2.1以前のAPIに記述されたセッションBeanクライアントおよびコンポーネントでは、リモート・クライアントは、セッションBeanのリモート・ホームおよびリモート・コンポーネント・インタフェースを介してセッションBeanにアクセスします。


注意:

EJB 2.1以前のAPIでは、リモート・クライアントが、セッションBeanのリモート・ホームおよびリモート・コンポーネント・インタフェースによって、ステートフルまたはステートレスのセッションBeanにアクセス必要がありました。これらのインタフェースは、EJB 3.xでも使用できます。詳細は、『Oracle WebLogic Server Enterprise JavaBeansバージョン2.1のプログラミング』のEJBクラスおよびインタフェースの作成に関する項を参照してください。


エンタープライズBeanのリモート・クライアント・ビューは、場所に関係なく動作します。Beanインスタンスと同じJVMで稼働しているクライアントは、同じAPIを使用して、同じマシンまたは別のマシン上の異なるJVMで稼働するクライアントとしてBeanにアクセスします。

ローカル・クライアント

EJB 3.1仕様で示されているように、ローカル・クライアントは、Beanのローカル・ビジネス・インタフェース、またはBeanクラスのすべてのパブリック・メソッドを示すインタフェースなしのクライアント・ビューを介してセッションBeanにアクセスします。EJB 2.1以前のAPIに記述されたセッションBeanまたはエンティティBeanクライアントおよびコンポーネントでは、ローカル・クライアントは、Beanのローカル・ホームおよびローカル・コンポーネント・インタフェースを介してエンタープライズBeanにアクセスします。ローカル・ビジネス・インタフェースまたはインタフェースなしのローカル・ビューを実装するコンテナ・オブジェクトは、ローカルJavaオブジェクトです。

ローカル・クライアントは、ローカル・クライアント・ビューを提供するセッションBeanが同じアプリケーション内に存在し、そのBeanと密結合できるクライアントです。セッションBeanのローカル・クライアントは、別のエンタープライズBeanまたはWebコンポーネントにすることもできます。ローカル・クライアント・ビューを介してエンタープライズBeanにアクセスするには、ローカル・クライアント・ビューを提供するエンタープライズBeanとローカル・クライアントが同じアプリケーション内に配置される必要があります。そのため、ローカル・クライアント・ビューでは、リモート・クライアント・ビューに備わる位置の透過性は提供されません。

クライアントからのEJBのルックアップ

エンタープライズBeanのクライアントは、エンタープライズBeanのインスタンスへの参照を取得します。そのためには、Javaプログラミング言語のアノテーションで依存関係インジェクションを使用するか、エンタープライズBeanインスタンスを検索するJNDI構文を使用してJNDIルックアップを実行します。


注意:

クライアントでEJBリンクを使用して2.x以前のエンタープライズBeanをルックアップする方法の詳細は、『Oracle WebLogic Server Enterprise JavaBeansバージョン2.1のプログラミング』のEJBリンクの使用に関する項を参照してください。


依存関係インジェクションの使用

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

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

  • @javax.ejb.EJB - 別のEJBへの依存性を指定します。

  • @javax.annotation.Resource - 外部リソース(JDBCデータ・ソース、JMS宛先、接続ファクトリなど)への依存性を指定します。

詳細は、「変数またはセッター・メソッドにリソース依存性を注入する」を参照してください。

JNDIポータブル構文の使用

EJB 3.1のポータブルなグローバルJNDIネーミング・オプションは、多数の一般的なネームスペースを提供します。ここにEJBコンポーネントを登録し、この節に記載されているパターンを使用して検索できます。これにより、EJBコンポーネントをJNDIに登録する方法および場所、およびそれらをアプリケーションでルックアップおよび使用する方法を標準化します。

ポータブルJNDIルックアップでは、java:globaljava:modulejava:appという3つのJNDIネームスペースが使用されます。

  • java:global JNDIネームスペースは、JNDIルックアップを使用してリモート・エンタープライズBeanを検索するポータブルな方法です。JNDIアドレスは、次のような形式です。

    java:global[/アプリケーション名]/モジュール名/エンタープライズBean名[/インタフェース名]

    アプリケーション名およびモジュール名のデフォルトは、アプリケーションおよびモジュールからファイル拡張子を除いた名前になります。アプリケーション名は、アプリケーションがEAR内にパッケージ化される場合にのみ必要になります。インタフェース名は、エンタープライズBeanが複数のビジネス・インタフェースを実装する場合にのみ必要になります。

  • java:moduleネームスペースは、同じモジュール内でローカル・エンタープライズBeanをルックアップする際に使用されます。java:moduleネームスペースを使用するJNDIアドレスは、次の形式になります。

    java:module/エンタープライズBean名/[インタフェース名]

    インタフェース名は、エンタープライズBeanが複数のビジネス・インタフェースを実装する場合にのみ必要になります。

  • java:appネームスペースは、同じアプリケーション内でパッケージ化されたローカル・エンタープライズBeanをルックアップする際に使用されます。つまり、エンタープライズBeanは、複数のJava EEモジュールを含むEARファイル内でパッケージ化されます。ava:appネームスペースを使用するJNDIアドレスは、次の形式になります。

    java:app[/モジュール名]/エンタープライズBean名[/インタフェース名]

    モジュール名は必要に応じて指定します。インタフェース名は、エンタープライズBeanが複数のビジネス・インタフェースを実装する場合にのみ必要になります。

たとえば、エンタープライズBeanのMyBeanがWebアプリケーション・アーカイブmyApp.warの中にパッケージ化される場合、デフォルトのモジュール名はmyAppになります。(この場合、web.xmlファイルでモジュール名を明示的に構成できます。)ポータブルJNDI名は、java:module/MyBeanです。java:globalネームスペースを使用して同じJNDI名を表すと、java:global/myApp/MyBeanとなります。

JNDI名のカスタマイズ

グローバルJNDIバインディングはデフォルトで登録されますが、weblogic.javaee.JNDINameおよびweblogic.javaee.JNDINamesアノテーションを使用して、EJBクライアント・ビュー・バインディングのJNDI名をカスタマイズすることもできます。詳細は、「weblogic.javaee.JNDIName」および「weblogic.javaee.JNDINames」を参照してください。

デプロイメント記述子を使用するEJBでは、weblogic-ejb-jar.xmlデプロイメント記述子のjndi-binding要素を使用して、カスタムのJNDIバインディングを指定できます。詳細は、『Oracle WebLogic Server Enterprise JavaBeansバージョン2.1のプログラミング』のEJBデプロイメント記述子に関する項を参照してください。

URLにリクエストを送信するようにEJBを構成する

EJBがjava.net.URLリソース・マネージャ接続ファクトリ・タイプを使用して外部HTTPサーバーとのHttpURLConnectionを開くようにするには、URLまたはURLに対応するJNDIツリーでバインドされたオブジェクトを、Beanクラスの@Resoruceアノテーションを使用するか、またはデプロイメント記述子を使用する場合はejb-jar.xmlresource-ref要素およびweblogic-ejb-jar.xmlres-ref-name要素を使用して指定します。

URLによるHTTPリソースの指定

EJBのリクエストが送信されるURLをアノテーションを使用して指定するには:

  1. BeanクラスのURLフィールドに@Resourceで注釈付けします。

  2. @Resourceのlook-up要素を使用してURLの値を指定します。

EJBのリクエストが送信されるURLを、デプロイメント記述子を使用して指定するには:

  1. ejb-jar.xmlresource-ref要素の<jndi-name>要素でURLを指定します。

  2. weblogic-ejb-jar.xmlresource-description要素の<jndi-name>要素でURLを指定します。

    <resource-description>
        <res-ref-name>url/MyURL</res-ref-name>
        <jndi-name>http://www.rediff.com/</jndi-name>
    </resource-description>
    

    WebLogic Serverは指定されたjndi-nameでURLオブジェクトを作成し、そのオブジェクトをjava:comp/envにバインドします。

JNDI名によるHTTPリソースの指定

JNDIでバインドされURLに対応するオブジェクトを、URLを指定するかわりにアノテーションを使用して指定するには:

  1. BeanクラスのURLフィールドに@Resourceで注釈付けします。

  2. @Resourceのlook-up要素を使用して、URLがJNDIでバインドされている名前を指定します。

JNDIでバインドされURLに対応するオブジェクトを、URLを指定するかわりにデプロイメント記述子を使用して指定するには:

  1. ejb-jar.xmlresource-ref要素の<jndi-name>要素で、URLがJNDIでバインドされている名前を指定します。

  2. 次のように、weblogic-ejb-jar.xmlresource-description要素の<jndi-name>要素で、URLがJNDIでバインドされている名前を指定します。

    <resource-description>
        <res-ref-name>url/MyURL1</res-ref-name>
        <jndi-name>firstName</jndi-name>
    </resource-description>
    

    firstNameは、URLに対応するJNDIツリーにバインドされたオブジェクトです。このバインディングは、起動クラスで行うこともできます。jndi-nameが有効なURLでない場合、WebLogic ServerはそれをURLに対応し、すでにJNDIツリーにバインドされているオブジェクトとして取り扱い、LinkRefとそのjndi-nameをバインドします。

BeanコードからのHTTPリソースへのアクセス

HTTPリソースの指定方法(URLかURLに対応するJNDI名か)に関係なく、次のようにしてEJBのコードからそのHTTPリソースにアクセスできます。

URL url = (URL) context.lookup("java:comp/env/url/MyURL");
connection = (HttpURLConnection)url.openConnection();

EJBのネットワーク通信の構成

EJBが通信に使用するネットワーク接続の属性は、カスタム・ネットワーク・チャネルを構成してEJBに割り当てることによって設定できます。WebLogic Serverのネットワーク・チャネルとそれに関連する構成手順については、『Oracle WebLogic Serverサーバー環境の構成』のネットワーク・リソースの構成に関する項を参照してください。カスタム・チャネルを構成したら、weblogic-ejb-jar.xmlnetwork-access-point要素を使用してEJBに割り当てます。

トランザクションのプログラミングと構成

以降の節では、トランザクション・プログラミングのガイドラインを示します。

コンテナ管理によるトランザクションのプログラミング

コンテナ管理によるトランザクションは、Bean管理によるトランザクションよりもプログラミングが簡単です。その理由は、境界設定(トランザクションの開始と停止)がEJBコンテナで行われるからです。目的のトランザクション動作を構成するには、EJBアノテーションjavax.ejb.TransactionAttributeを使用するか、EJBデプロイメント記述子ejb-jar.xmlおよびweblogic-ejb-jar.xmlを使用します。

  • EJBアノテーションを使用して、Beanファイルでコンテナ管理によるトランザクションを指定する方法の詳細は、第5章「トランザクション管理とトランザクション属性を指定する」を参照してください。

  • EJBデプロイメント記述子を使用して、コンテナ管理によるトランザクションを指定する方法の詳細は、『Oracle WebLogic Server Enterprise JavaBeansバージョン2.1のプログラミング』のコンテナ管理によるトランザクション要素に関する項を参照してください。

コンテナ管理によるトランザクションの主なプログラミング・ガイドラインは以下のとおりです。

  • トランザクション境界の保持 - コンテナが設定したトランザクションの境界に干渉するメソッドは呼び出さないでください。以下のメソッドは使用しないでください。

    • java.sql.ConnectioncommitsetAutoCommit、およびrollbackメソッド

    • javax.ejb.EJBContextgetUserTransactionメソッド

    • javax.transaction.UserTransactionのすべてのメソッド

  • トランザクションの明示的なロールバック - 明示的にコンテナがコンテナ管理によるトランザクションをロールバックするようにするには、EJBContextインタフェースのsetRollbackOnlyメソッドを呼び出します。Beanから非アプリケーション例外がスローされる場合(通常はEJBException)、ロールバックは自動的に行われます。

  • シリアライゼーション問題の回避 - 多くのデータ・ストアでは、シリアライゼーションに関する問題の検出は、単一ユーザー接続の場合でさえ制限されています。そのような場合は、weblogic-ejb-jar.xmltransaction-isolationTransactionSerializableに設定されていても、同じ行でクライアント間に競合が発生した場合はEJBクライアントで例外またはロールバックが発生する場合があります。そのような例外を回避するために、以下のことができます。

    • SQL例外を捕捉して(たとえばトランザクションを再起動などして)適切に解決するコードをクライアント・アプリケーションに含める

    • Oracleデータベースでは、『Oracle WebLogic Server Enterprise JavaBeansバージョン2.1のプログラミング』の付録「weblogic-ejb-jar.xmlデプロイメント記述子のリファレンス」のisolation-levelで説明されているトランザクション分離設定を使用します。

コンテナ管理トランザクションの自動的な再試行の構成

Oracle WebLogic Serverでは、トランザクションを開始したビジネス・メソッドが、システム例外に関連のないトランザクション・ロールバックが原因で失敗した場合、EJBコンテナが新しいトランザクションを開始し、失敗したメソッドを指定された回数まで再試行するように指定できます。メソッドの失敗が指定された再試行回数に達した場合、EJBコンテナは例外をスローします。


注意:

EJBコンテナは、システム例外に基づくエラーが原因で失敗したトランザクションは再試行しません。


コンテナ管理によるトランザクションの自動的な再試行を構成するには:

  1. 使用するBeanがコンテナ管理によるセッションBeanまたはエンティティBeanであることを確認します。

    コンテナ管理によるセッションBeanおよびエンティティBeanの場合にのみ、コンテナ管理によるトランザクションの自動再試行を構成できます。メッセージドリブンBeanの場合は、コンテナ管理によるトランザクションの自動再試行を構成できません。MDBは、メッセージの受信を含むトランザクションがロールバックされたときに、そのメッセージの受信の確認応答を行わないため、メッセージは確認応答が行われるまで自動的に再試行されます。また、タイマーBeanの場合も、コンテナ管理によるトランザクションの自動再試行は構成できません。タイマーBeanのejbTimeoutメソッドが開始されてロールバックされると、タイムアウトが常に再試行されるからです。

  2. トランザクションの自動再試行を構成する場合、対象となるビジネス・メソッドは、Beanのリモートまたはローカル・インタフェースの内部か、またはホーム・インタフェースのホーム・メソッド(特定のBeanインスタンスに固有ではないローカル・ホーム・ビジネス・ロジック)として定義されている必要があります。メソッドには、以下のコンテナ管理トランザクション属性の1つが設定されていなければなりません。

    • RequiresNew。メソッドのトランザクション属性(ejb-jar.xmltrans-attribute要素)がRequiresNewの場合、メソッドの呼出し前に常に新しいトランザクションが開始され、構成されている場合、そのトランザクションが失敗すると自動再試行が行われます。

    • Required。メソッドのトランザクション属性(ejb-jar.xmltrans-attribute要素)がRequiredの場合、メソッドが新しいトランザクションで再試行されるのは、失敗したトランザクションがそのメソッドのために開始された場合のみです。

    詳細については、以下を参照してください。

    • プログラミング・インタフェースについては、「EJBクライアントへのアクセスのプログラミング」を参照してください。

    • ejb-jar.xmltrans-attribute要素については、『Oracle WebLogic Server Enterprise JavaBeansバージョン2.1のプログラミング』のコンテナ管理によるトランザクション要素に関する項を参照してください。ここには、EJBデプロイメント記述子の作成および編集に関する詳細情報が記載されています。

  3. トランザクションの自動再試行を有効にする場合、対象となるメソッドは再呼出しできなければなりません。失敗したメソッドの再試行によって得られる結果は、直前の再試行が成功した場合に得られる結果と同じでなければなりません。特に、以下の場合です。

    • メソッドの呼出しによって呼出しチェーンが開始された場合、そのメソッドを再試行するときは呼出しチェーン全体を再呼び出しするのが安全です。

    • メソッドのすべてのパラメータを再利用できなければなりません。メソッドが再試行される場合、そのメソッドは失敗したメソッドを呼び出すために使用されたパラメータで再試行されます。一般に、再利用できるパラメータは、プリミティブ、不変オブジェクト、または読取り専用オブジェクトの参照です。パラメータがメソッドによって変更されるオブジェクトの参照である場合、メソッドの再呼出しによってメソッド呼出しの結果に悪影響が生じないようにしてください。

    • 再試行されるメソッドを保持するBeanがステートフル・セッションBeanである場合、そのBeanの対話状態は再呼出し時に失われてはなりません。ステートフル・セッションBeanの状態はトランザクション対応ではなく、トランザクションのロールバック中に復元できないので、トランザクションの自動再試行の機能を使用する場合、Beanの状態がロールバック後も有効であることを確認しておく必要があります。

  4. EJBコンテナがどのメソッドのトランザクションを自動的に再試行するか、およびその回数は、weblogic-ejb-jar.xmlretry-methods-on-rollback要素で指定します。

    retry-methods-on-rollbackのretry-count下位要素は、管理コンソールからも変更できます。

Bean管理のトランザクションのプログラミング

この節では、Bean管理によるトランザクションのプログラミング上の考慮事項を示します。

  • トランザクションの境界設定 - EJBまたはクライアント・コードにトランザクション境界を定義するには、Java Transaction Service (JTS)またはJDBCデータベース接続を取得する前に、UserTransactionオブジェクトを取得してトランザクションを開始しなければなりません。UserTransactionオブジェクトを取得するには、次のコマンドを使用します。

    ctx.lookup("javax.transaction.UserTransaction");
    

    UserTransactionオブジェクトを取得した後は、tx.begin()tx.commit()tx.rollback()でトランザクションの境界を指定します。

    データベース接続を取得してからトランザクションを開始した場合、その接続は新しいトランザクションと何の関連性も持たず、以後のトランザクション・コンテキストにその接続を「入れる」ためのセマンティクスも存在しません。JTS接続がトランザクション・コンテキストに関連付けられていない場合、JTS接続はautocommittrueに設定した標準のJDBC接続と同じように動作し、更新はデータ・ストアに自動的にコミットされます。

    いったんトランザクション・コンテキスト内にデータベース接続が作成されると、その接続はトランザクションがコミットまたはロールバックされるまで確保されます。パフォーマンスとスループットを最適化するには、トランザクションを迅速に完了させることによって、データベース接続を解放し、他のクライアント・リクエストが使用できるようにする必要があります。


    注意:

    アクティブなトランザクション・コンテキストには単一のデータベース接続しか関連付けることができません。


  • トランザクション分離レベルの設定 - Bean管理によるトランザクションでは、分離レベルはBeanコードで定義します。有効な分離レベルは、java.sql.Connectionインタフェースで定義されます。分離レベルの動作の詳細は、『Oracle WebLogic Server Enterprise JavaBeansバージョン2.1のプログラミング』の付録「weblogic-ejb-jar.xmlデプロイメント記述子のリファレンス」のisolation-levelを参照してください。

    サンプル・コードについては、例4-7を参照してください。

例4-7 BMTでのトランザクション分離レベルの設定

import javax.transaction.Transaction;
import java.sql.Connection
import weblogic.transaction.TxHelper:
import weblogic.transaction.Transaction;
import weblogic.transaction.TxConstants;
User Transaction tx = (UserTransaction)
ctx.lookup("javax.transaction.UserTransaction");
//Begin user transaction
    tx.begin();
//Set transaction isolation level to TransactionReadCommitted
Transaction tx = TxHelper.getTransaction();
    tx.setProperty (TxConstants.ISOLATION_LEVEL, new Integer
    (Connection.TransactionReadCommitted));
//perform transaction work 
    tx.commit();
  • 制限されたメソッドの回避 - Bean管理によるトランザクションでは、EJBContextインタフェースのgetRollbackOnlyメソッドとsetRollbackOnlyメソッドは呼び出さないでください。これらのメソッドは、コンテナ管理によるトランザクションのみで使用します。Bean管理によるトランザクションでは、UserTransactionインタフェースのgetStatusメソッドとrollbackメソッドを呼び出します。

  • アクティブなトランザクション・コンテキストにつき1つの接続の使用 - アクティブなトランザクション・コンテキストに関連付けることができるのは、1つのデータベース接続だけです。

複数のEJBで分散されるトランザクションのプログラミング

この節では、複数のBean(複数のサーバー・インスタンスに存在する場合もある)にトランザクションを分散させる2つのアプローチを説明します。

クライアントのトランザクション・コンテキストから複数のEJBを呼び出す

次の断片的なコードは、UserTransactionオブジェクトを取得し、それを使用してトランザクションを開始およびコミットするクライアント・アプリケーションから引用したものです。クライアントは、トランザクションのコンテキストの中で2つのEJBを呼び出します。

import javax.transaction.*;
...
u = (UserTransaction) jndiContext.lookup("javax.transaction.UserTransaction");
u.begin();
account1.withdraw(100);
account2.deposit(100);
u.commit();
...

account1account2のBeanで実行される更新は、1つのUserTransactionのコンテキスト内で行われます。同じサーバー・インスタンス上にあるか、異なるサーバー・インスタンスにあるか、またはWebLogic Serverクラスタにあるのかに関係なく、EJBは1つの論理単位として一緒にコミットまたはロールバックされます。

1つのトランザクション・コンテキストから呼び出されるEJBはすべて、クライアント・トランザクションをサポートしている必要があります。つまり、ejb-jar.xmlの各Beanのtrans-attribute要素が、RequiredSupports、またはMandatoryに設定されている必要があります。

EJB「ラッパー」を使用してEJB間トランザクションをカプセル化する

トランザクションをカプセル化する「ラッパー」EJBを使用できます。クライアントはラッパーEJBを呼び出して銀行振替などのアクションを実行し、ラッパーは新しいトランザクションを開始して、トランザクションの処理を実行する1つまたは複数のEJBを呼び出します。

ラッパーEJBは、他のEJBを呼び出す前にトランザクション・コンテキストを明示的に取得できます。あるいは、ejb-jar.xmlでラッパーのtrans-attribute要素がRequiredまたはRequiresNewに設定されている場合、WebLogic Serverは新しいトランザクション・コンテキストを自動的に作成できます。

ラッパーEJBによって呼び出されるすべてのEJBは、そのラッパーEJBのトランザクション・コンテキストをサポートしている必要があります。つまり、そのtrans-attribute要素がRequiredSupports、またはMandatoryに設定されていなければなりません。

Javaソースをコンパイルする

EJB BeanクラスのJavaソース・コードの記述と、必要に応じてインターセプタ・クラスの記述が完了したら、それらをクラス・ファイルにコンパイルする必要があります(通常は標準Javaコンパイラを使用します)。生成されたクラス・ファイルは、デプロイメント用のターゲット・モジュールにパッケージ化できます。コンパイルするためのツールとしては以下が一般的です。

デプロイメント記述子の作成と編集(省略可能)

EJB 3.xプログラミング・モデルの重要な点は、メタデータ・アノテーションが導入されたことです。アノテーションを使用すると、コンテナ内でのBeanの動作、依存関係インジェクションの要求方法などをJavaクラス自体の中で指定でき、EJBの開発プロセスを簡略化できます。アノテーションは、EJBの2.x以前のバージョンで必要だったデプロイメント記述子にかわるものです。

しかしながら、デプロイメント記述子は、EJB 3.xで完全にサポートされます。ただし、Java EE 6標準のデプロイメント記述子は必須ではありません。たとえば、従来の2.xプログラミング・モデルを使用する場合や、後々の開発やデプロイメントの段階でより細かくカスタマイズできるようにする場合、メタデータ・アノテーションに加えて(またはメタデータ・アノテーションのかわりに)標準のデプロイメント記述子を作成できます。

デプロイメント記述子要素は、対応するアノテーションを常にオーバーライドします。たとえば、Beanクラス内に@javax.ejb.TransactionManagement(BEAN)アノテーションを指定した上で、そのEJB用のejb-jar.xmlデプロイメント記述子を作成し、<transaction-type>要素をcontainerに設定した場合は、デプロイメント記述子の値が優先され、このEJBではコンテナ管理によるトランザクションの境界設定が使用されます。


注意:

EJB 3.1バージョンでは、2.xでサポートされていたWebLogic固有のEJB機能がすべてサポートされます。ただし、weblogic-ejb-jar.xmlまたはweblogic-cmp-rdbms-jar.xmlデプロイメント記述子ファイルで構成する機能は、このEJB 3.1のリリースでも引続き同じ方法で構成する必要があります。これは、現時点ではそれらの機能と同等のアノテーションが存在しないためです。


『Oracle WebLogic Server Enterprise JavaBeansバージョン2.1のプログラミング』の2.xバージョンでは、Java EE標準およびWebLogic固有のEJBデプロイメント記述子の作成と編集について詳しく説明しています。特に、以下の節を参照してください。

EJBのパッケージ化

エンタープライズ・アプリケーションの一部としてEJBをパッケージ化することをお薦めします。詳細は、『Oracle WebLogic Serverアプリケーションの開発』の分割開発ディレクトリからのデプロイとパッケージ化に関する項を参照してください。

ただし、EJB 3.1ではEJBコンポーネントを直接Webアプリケーション・アーカイブ(WAR)ファイルの中に配置する機能を提供することでパッケージ化が単純化されたため、WebコンポーネントとEJBコンポーネントを格納するアーカイブを個々に作成して、それらをエンタープライズ・アーカイブ(EAR)ファイルで結合する必要がなくなりました。

JARでのEJBのパッケージ化

WebLogic Serverでは、別のアプリケーションのプログラムに基づくクライアントがEJBへのアクセスに必要とするEJBクラスをパッケージ化するためのejb-client.jarファイルの使用がサポートされています。

Beanのejb-jar.xmlファイルのejb-client-jar要素でクライアントJARの名前を指定します。appcコンパイラを実行すると、EJBにアクセスするために必要なクラスを持つJARファイルが生成されます。

クライアントJARをリモート・クライアントからアクセスできるようにします。Webアプリケーションの場合は、ejb-client.jar/libディレクトリに配置します。非Webクライアントの場合は、クライアントのクラスパスでejb-client.jarを指定します。


注意:

WebLogic Serverのクラスローディング動作は、クライアントがスタンドアロンかどうかによって異なります。ejb-client.jarにアクセスできるスタンドアロンのクライアントは、ネットワーク経由で必要なクラスをロードできます。ただし、セキュリティ上の理由から、サーバー・インスタンスで動作しているプログラムに基づくクライアントはネットワーク経由でクラスをロードすることはできません。


WARでのEJBのパッケージ化

EJB 3.1では、エンタープライズBeanクラスをejb-jarファイルの中にパッケージ化しなければならないという制限が取り除かれました。そのため、Webアプリケーション・クラスに適用される同じパッケージ化のガイドラインを使用して、EJBクラスをWebアプリケーション・アーカイブ(WAR)の中に直接パッケージ化できます。単にEJBクラスをWEB-INF/classesディレクトリかWEB-INF/libディレクトリ内のJARファイルに入れるのみです。必要に応じて、EJBデプロイメント記述子も使用する場合は、それをWEB-INF/ejb-jar.xmlとしてパッケージ化できます。appcコンパイラを実行すると、EJBコンポーネントにアクセスするために必要なクラスを持つWARファイルが生成されます。

WARファイルには、モジュールで定義されたすべてのコンポーネント(Web、エンタープライズBeanなど)間で共有される単一のコンポーネント・ネーミング環境があります。WARファイルで定義されたそれぞれのエンタープライズBeanは、この単一のコンポーネント環境ネームスペースを、WARファイルで定義されたその他すべてのエンタープライズBean、およびWARファイルで定義されたその他すべてのWebコンポーネントと共有します。

WARファイルにパッケージ化されたエンタープライズBean(および関連する任意のクラス)には、WARファイルにパッケージ化された他の非エンタープライズBeanクラスと同じクラス・ローディング要件があります。たとえば、WARファイルの中にパッケージ化されているサーブレットは、同じWARファイルの中にパッケージ化されているエンタープライズBeanコンポーネントを参照できることが保証され、逆もまた保証されます。


注意:

EJB 2.1エンティティBeanおよびEJB 1.1エンティティBeanは、WARファイル内ではサポートされません。これらのコンポーネント・タイプは、スタンドアロンのejb-jarファイルまたはEARファイル内でパッケージ化されたejb-jarファイル内でのみパッケージ化する必要があります。この制限に違反するアプリケーションは、デプロイに失敗します。


WebLogic Server配布キットにバンドルされている、単純化されたWARのパッケージ化メソッドを使用するサンプルがあります。「EJB 3.1: 単純化されたインタフェースなしのプログラミングおよびWARファイルでのパッケージ化」を参照してください。

EJBのデプロイメント

EJBをデプロイすると、WebLogic ServerはEJBのコンポーネントをクライアントに提供できるようになります。EJBは、ユーザーの環境とEJBが本番環境に置かれるかどうかに基づいて、複数の手順のうちの1つでデプロイできます。

WebLogic Serverアプリケーションおよびモジュール(EJBを含む)をデプロイする一般的な手順については、『Oracle WebLogic Serverへのアプリケーションのデプロイ』を参照してください。EJB固有のデプロイメントの問題および手順の詳細は、「エンタープライズ・アプリケーションの一部としてのスタンドアロンEJBのデプロイメント」および「Webアプリケーションの一部としてのEJBのデプロイメント」を参照してください。

2.xプログラミング・モデルで作成されたEJBのデプロイメントの詳細は、2.xプログラミング・モデルに特化した『Oracle WebLogic Server Enterprise JavaBeansバージョン2.1のプログラミング』のEnterprise JavaBeansのデプロイメント・ガイドラインに関する項を参照してください。