EJB再試行機能は、セションBeanがアプリケーション例外を発生した場合に、再度自動的にセションBeanを呼び出す機能です。セションBeanを呼び出すアプリケーションで使用します。 ロック中のデータベースにアクセスできなかったなどの原因で、セションBeanを再度呼び出すことで正常終了する可能性があるエラーが発生した場合に、その処理を再実行する目的で本機能を使用します。
EJB再試行機能を使って呼び出せるのはApcoordinatorで作成したセションBeanです。 また、EJBの呼び出しにはリモート共通インターフェイスを使用します。EJB再試行機能を使用しないでセションBeanを呼び出す場合と呼び出し方法が共通です。
Apcoordinatorを使用したセションBeanの作成方法は“20.2 EJBアプリケーション”を参照してください。また、EJB再試行機能で呼び出すセションBeanを作成する際の注意点については、“20.4.6.3 セションBean作成時の注意事項”を参照してください。
再試行が実施される契機
アプリケーションがCallインターフェイスのinvokeメソッドによってセションBeanを呼び出し、セションBeanがある特定のアプリケーション例外を発生した場合に、ApcoordinatorがセションBeanの呼び出しを再試行します。再試行を起こすアプリケーション例外を再試行例外と呼びます。再試行例外として使用する例外クラスはリモートマップで指定します。
セションBeanがシステム例外を発生した場合は、再試行されません。また、セションBeanオブジェクトの作成時は例外が発生しても再試行されません。
アプリケーション例外とシステム例外については“EJBアプリケーションの開発”の“20.2.2.1 例外処理”を参照してください。
EJB再試行機能を使用してEJBを呼び出すには、リモート共通インターフェイスを使用し、EJBを呼び出すアプリケーションを以下のように作成します。
リモートマップの作成
リモートマップを作成して、呼び出すセションBeanの名前と再試行のパラメータを定義します。リモートマップは、リモート共通インターフェイスにおいて、呼び出されるアプリケーションを定義するXMLファイルです。リモートマップの詳細は“20.3.2 リモートマップ”を参照してください。ここでは、EJB再試行機能を使用する場合のリモートマップの記述方法を説明します。
以下は、EJB再試行機能を使う場合のリモートマップの記述例です。
<?xml version="1.0" encoding="Shift_JIS"?> <remoteMap xmlns=http://interstage.fujitsu.com/schemas/uji/remoteMap xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance xsi:schemaLocation="http://interstage.fujitsu.com/schemas/uji/remoteMap http://interstage.fujitsu.com/schemas/uji/remotemap.xsd"> <config> <version>5.0</version> </config> <!-- EJB再試行機能を使って呼び出すセションBeanを定義します。--> <ejbExt name="MySessionBean" retryCount="3" retryInterval="150" > <application name="java:comp/env/ejb/MySessionBean" /> <retriableException class="some.pkg.BusyException" /> <retriableException class="some.pkg.NotReadyException" /> </ejbExt> </remoteMap>
呼び出すセションBeanをejbExtタグを使って記述します。セションBeanに与える名前をejbExtタグのnameアトリビュートに指定します。ejbExtタグのコンテントにはapplicationタグを書き、applicationタグのnameアトリビュートにはJNDIで検索するセションBeanの名前を指定します。
さらに、ejbExtタグのアトリビュートとコンテントには、再試行に関する以下のパラメータを指定します。
再試行最大回数
ejbExtタグのretryCountアトリビュートに指定します。例えば2を指定すると、初回の呼び出しを含めて最大で合計3回呼び出されます。デフォルトは2です。
再試行間隔
再試行するまでの時間をミリ秒単位で指定します。ejbExtタグのretryIntervalアトリビュートに指定します。デフォルトは100ミリ秒です。
再試行例外
再試行例外として使用するアプリケーション例外のクラスをretriableExceptionタグで指定します。retriableExceptionタグはejbExtタグのコンテントに記述します。retriableExceptionタグのclassアトリビュートに例外クラスを指定します。セションBeanを呼び出した結果、アプリケーション例外が発生し、その例外のクラスがclassアトリビュートに指定したクラスと同じか、そのサブクラスであった場合に、再試行します。なお、以下のクラスを再試行例外に指定することはできません。
java.lang.RuntimeExceptionとそのサブクラス
java.rmi.RemoteExceptionとそのサブクラス
java.lang.Exception
java.lang.Errorとそのサブクラス
注意
再試行間隔の精度はご使用になるシステムに依存します。 10ミリ秒より高い精度による指定はシステムによっては有効にならない場合があります。
CallFactoryインターフェイスとCallインターフェイスによるセションBeanの呼び出し
com.fujitsu.uji.ext.CallFactoryとcom.fujitsu.uji.ext.Callの2つのインターフェイスを使用してセションBeanを呼び出します。これらのインターフェイスは、リモート共通インターフェイスにおいてアプリケーションを呼び出すためのインターフェイスです。詳細は“20.3.3 CallFactoryインターフェイスとCallインターフェイスによる呼び出し”を参照してください。ここでは、これらのインターフェイスの使用方法をEJB再試行機能の場合について説明します。
CallFactoryインターフェイスとCallインターフェイスを使った呼び出しの手順は以下のとおりです。
com.fujitsu.uji.DispatchContextクラスからCallFactoryインターフェイスを取得します。
セションBeanの名前(ejbExtタグのnameアトリビュートに指定したもの)を指定してCallFactoryインターフェイスからCallインターフェイスを取得します。この処理によって、セションBeanオブジェクトが作成されます。
データBeanとコマンド名を引数としてCallインターフェイスのinvokeメソッドを呼び出すと、セションBeanが呼び出されます。セションBeanが再試行例外を発生した場合は、セションBeanが再度呼び出されます。
以下はビジネスクラスからセションBeanを呼び出す例です。
import com.fujitsu.uji.DispatchContext; import com.fujitsu.uji.ext.CallFactory; import com.fujitsu.uji.ext.Call; import com.fujitsu.uji.ext.UjiCreateException; import com.fujitsu.uji.ext.UjiRemoteException; import com.fujitsu.uji.ext.UjiTargetException; ... public Object doSomething(DispatchContext context, SomeBean dataBean) { // CallFactoryインターフェイスを取得します。 CallFactory factory = context.getCallFactory(); try { // セションBeanの名前を指定してCallインターフェイスを取得します。 Call call = factory.createCall("MySessionBean"); // 送信するデータとコマンド名を指定してセションBeanを呼び出します。 ResBean response = (ResBean)call.invoke(dataBean,"update"); } catch (UjiCreateException e) { ... } catch (UjiRemoteException e) { ... } catch (UjiTargetException e) { ... } ... }
再試行最大回数だけ再試行を繰り返してもセションBeanが例外を発生する場合、invokeメソッドはcom.fujitsu.uji.ejb.EJBApplicationExceptionを発生します。セションBeanで発生した例外は、EJBApplicationExceptionのgetRootCauseメソッドにより取得できます。
セションBeanがシステム例外を発生した場合は、invokeメソッドがcom.fujitsu.uji.ext.UjiRemoteExceptionを発生します。再試行は行われません。
EJB複数指定機能との併用
EJB再試行機能はEJB複数指定機能と併用できます。
EJB再試行機能とEJB複数指定機能を併用するには、リモートマップにejbExtタグを以下のように記述します。
<?xml version="1.0" encoding="Shift_JIS"?> <remoteMap xmlns=http://interstage.fujitsu.com/schemas/uji/remoteMap xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance xsi:schemaLocation="http://interstage.fujitsu.com/schemas/uji/remoteMap http://interstage.fujitsu.com/schemas/uji/remotemap.xsd"> <config> <version>5.0</version> </config> <!-- EJB複数指定機能を使用して呼び出すセションBeanのグループを定義します。 --> <!-- また、再試行例外を定義します。 --> <ejbExt name="MySessionBeans" type="proxy" > <application name="java:comp/env/ejb/MySessionBean1" /> <application name="java:comp/env/ejb/MySessionBean2" /> <application name="java:comp/env/ejb/MySessionBean3" /> <retriableException class="some.pkg.BusyException" /> <retriableException class="some.pkg.NotReadyException" /> </ejbExt> </remoteMap>
EJB複数指定機能を使用して呼び出すセションBeanのグループをejbExtタグで定義します。さらに、ejbExtタグのコンテントにretriableExceptionタグを記述して再試行例外を定義します。必要に応じて、ejbExtタグにretryCountアトリビュート(再試行最大回数)やretryIntervalアトリビュート(再試行間隔)を追加します。
EJB再試行機能とEJB複数指定機能を併用した場合、Callインターフェイスのinvokeメソッド呼び出し時に、セションBeanオブジェクトの作成と呼び出しが以下の順に実行されます。
Callインターフェイス取得後で最初にinvokeが呼び出された場合は、セションBeanオブジェクトを作成します。EJB複数指定機能はこのタイミングで動作します。EJBコンテナがダウンしていると判定した場合は、別のEJBコンテナを選択して、再度セションBeanオブジェクトの作成を実行します。セションBeanオブジェクトの作成に成功すると、2の処理に進みます。
セションBeanオブジェクトを呼び出します。EJB再試行機能はこのタイミングで動作します。セションBeanが再試行例外を発生した場合は、同一のセションBeanを再度呼び出します。この段階でEJBコンテナがダウンしていた場合、セションBeanオブジェクトは再作成せず、例外UjiRemoteExceptionを発生します。
リモートマップでejbExtタグのcreateOnInvokeアトリビュートにtrueを指定した場合は、Callオブジェクトのinvokeメソッドを呼び出すたびに新しくセションBeanオブジェクトが作成されます。この場合、上記の1の処理はinvokeが呼び出された時に常に実行されます。
セションBeanが再試行例外を発生して再試行される場合でも、再試行例外を発生する前にセションBeanが実行した処理は取り消されません。このため、EJB再試行機能で呼び出されるセションBeanは、以下の点に注意して作成してください。
トランザクションを使用する場合の注意事項
セションBeanの処理でトランザクションを必要とする場合は、再試行例外を発生させる前にトランザクションをロールバックしてください。セションBeanで開始したトランザクションや、セションBeanから呼び出された処理で開始されたトランザクションがすでにコミットされている場合、その処理は取り消せないため、再試行例外を発生させないでください。
また、上記のようにコミット、ロールバックをセションBeanで実行する場合は、セションBeanの呼び出し元が開始したトランザクションにセションBeanが参加することはできません。
引数の参照渡しを使用する場合の注意事項
通常は、EJBの呼び出しにおいては引数は値渡しで呼び出されます。このため、Callインターフェイスを使ってセションBeanを呼び出すと、invokeメソッドの引数に与えたデータBeanのコピーがセションBeanに渡されます。
ただし、アプリケーションサーバーによっては、クライアントとEJBが同一のJVM上に存在する場合に、 EJB呼び出しの性能を向上させる目的で、引数の参照渡しを可能にしている場合があります。引数の参照渡しを有効にした場合、Callインターフェイスのinvokeに与えたデータBeanのインスタンスそのものがセションBeanに渡されます。データBeanはコピーされません。
引数の参照渡しを有効にする場合は、ビジネスクラスの引数に与えられたデータBeanをビジネスクラスの処理で変更しないでください。データBeanに変更を加えると、再試行によって呼び出された時に、変更後のデータBeanがビジネスクラスの引数に与えられます。
ビジネスクラス、セションクラス、アプリケーションクラスのデータを変更する場合の注意事項
以下のクラスのオブジェクトは、セションBeanの呼び出しが終了したあとも生存しています。これらのオブジェクトが持つデータを変更したあとで再試行例外を発生させた場合、再試行によってセションBeanが呼び出された時点で、オブジェクトが持つデータは変更後の状態のままになっています。
ビジネスクラス (initメソッドがtrueを返す場合)
セションクラス
アプリケーションクラス
再試行前のデータ変更が再試行後に残っていることが問題となる場合は、再試行例外が発生する処理が完了したあとでビジネスクラス、セションクラス、アプリケーションクラスのデータを変更する処理を実行してください。