ORACLE JAPAN Server Release 6.1

 

  |  

  WebLogic Server ホーム   |     WebLogic J2EE コネクタ アーキテクチャ   |   前へ   |   次へ   |   目次   |   索引   |   PDF 版

一般的な BEA J2EE コネクタ アーキテクチャ例外の回避策

 

ここでは、2 つの一般的な BEA J2EE コネクタ アーキテクチャ例外の原因とその回避策について説明します。

 


例外 1 : Problem Granting Connection Request to a ManagedConnectionFactory That Does Not Exist in Connection Pool. Check Your MFC's HashCode()

この例外は、指定した ManagedConnectionFactory に関連付けられた ConnectionPool が見つからない場合に、ConnectionPoolManager の getConnection(ManagedConnectionFactory mcf, ConnectionRequestInfo cxInfo) メソッドによって WebLogic Server の内部に送出されます。

この例外の原因と回避策

この例外には 2 つの原因があり、関連する動作も 1 つあるため少々複雑です。

原因 1 : クライアントが変更した ManagedConnectionFactory が、その後のルックアップでも見つかるようにサーバ上でハッシュ化されていない

この問題は、Java での Hashtable の基本動作と、JNDI での Serializable オブジェクトの動作方法の組み合わせにより発生します。

Hashtable を使用すると、キーと値の任意のペアをメモリに格納でき、後からキーを使ってすばやくキーと値のペアを見つけることができます。キーとそれに関連付けられたオブジェクトは Java Hashtable に書き込まれ、そのキーの hashCode() メソッドを呼び出すことで整数値が取得できます。この整数値はユニークとは限りませんが、すべての Hashtable キーに配布されることは保証されています。

このハッシュ化は、オブジェクトが Hashtable に書き込まれたときに 1 度だけ発生します。サーバでは、このオブジェクトがデータ構造に書き込まれます。これは、それと同じ派生整数値を、一致するキーの候補セットをすばやく見つけるためのメソッドとして繰り返し使用できるようにするためです。

その後サーバが Hashtable へのルックアップを実行すると、オーバーライドされた(または java.lang.Object で見つかった) hashCode() メソッドによって、要求されたキーがハッシュ化されます。デフォルトの hashCode() メソッドは単純に、hashCode() メソッドが呼び出されたオブジェクトのメモリ アドレスを返します。次に、ルックアップ キーのハッシュ化されたキー値と一致するハッシュ値を持つバッキング データ構造内のキーのセットが取得されます。つづいて、次のコードを実行することによって、実装ではこの候補リストを繰り返し、適切な一致があるかどうかが識別されます。

for (Entry e = tab[index] ; e != null ; e = e.next) {

if ((e.hash == hash) && e.key.equals(key)) {

return e.value;

}

}

return null;

このコードでは、各候補キーで equals() メソッドを呼び出して、ルックアップ キーを各候補リストと比較しています。一致したものが見つかると値が返されます。一致したものが見つからなかった場合は null 値が返されます。

アプリケーション サーバで Serializable JNDI エントリのみがサポートされている(Referenceable エントリはサポートされていない)場合は、リソース アダプタのデプロイメントでのオブジェクトの対話と、リソース アダプタの ConnectionFactory 実装の JNDI ルックアップを考慮してください。リソース アダプタのデプロイメントにおいては、そのリソース アダプタに関連付けられた ManagedConnectionFactory のインスタンスがアプリケーション サーバによって作成されます。さらに、その ConnectionManager 実装が、作成したばかりの ManagedConnectionFactory に関連付けられます。

次に、ManagedConnectionFactory によって ConnectionFactory のインスタンスが作成され、この ConnectionFactory がその ManagedConnectionFactory(MCF)に関連付けられます。この時点で、不可欠な 3 つのリソースが設定できました。内部的には、このリンクが Hashtable のペアとして表現されます。ペアの 1 つは JNDI 名を MCF(jndiToMCFMap)にマップするもの、もう 1 つは MCF を接続プール(poolTable)の内部表現にマップするものです。ConnectionManager はアプリケーション サーバに対して暗黙的であるため、明示的なマッピングは必要ありません。

ConnectionFactory(リソース アダプタのクライアントが見るもの)は MCF を持ち、MCF は、上記の暗黙的なマッピングによってアプリケーション サーバから提供される ConnectionManager 実装を持ちます。最後に、ConnectionFactory(クライアントが見るオブジェクト)が JNDI にバインドされます。ここが、問題の発生する可能性がある部分です。

現在の WebLogic Server JNDI 実装では、java.io.Serializable オブジェクトはサポートされていますが、javax.naming.Referenceable オブジェクトはサポートされていません。Referenceable オブジェクトが JNDI にバインドされると、実際のオブジェクトへの参照(エンドポイントを含む)が実際に JNDI にバインドされます。このバインドでは、オブジェクトはネーミング ツリーには転送されません。サーバによって Serializable オブジェクトが JNDI ツリーにバインドされると、実質的にはオブジェクト(および参照されるすべての Serializable オブジェクト)がツリーにシリアライズされます。

クライアントが ConnectionFactory のネーミング コンテキストで lookup() を実行すると、同じシリアライズのプロセスが逆方向に発生します。ConnectionFactory 実装は、クライアントのアドレス空間にシリアライズされます。このシリアライゼーションは、クライアントが JNDI 実装(サーバ)と同じアドレス空間で実行されている場合でも行われます。これでアプリケーション コンポーネント(クライアント)は、JNDI ツリー内の実際のオブジェクト グラフのコピーを持つことになります。

MCF は、オブジェクト グラフの一部としてクライアントにシリアライズされます。リソース アダプタの MCF には、MCF のステートの管理に使用するフィールドが含まれているものとみなします。さらに、これらのフィールドは、MCF のオーバーライドされた hashCode() メソッドおよび equals() メソッドによって考慮されるものとみなします。たとえば、デバッグ フラグを考えてみます。

リソース アダプタがデプロイされると、エントリは jndiToMCFMap Hashtable になります。Hashtable が Java でどのように機能するかを思い出してください。ハッシュは、デバッグ フラグを含め、すべてのフィールドを使用して計算されます。これらのフィールドは hashCode() メソッドで使用されているためです。クライアントは、JNDI lookup() を実行すると、CF(およびその MCF)のコピーを取得できます。

次に、クライアントはデバッグ フラグを true に設定して CF の getConnection() を呼び出します。つづいて CF は、その MCF と ConnectionRequestInfo オブジェクトをパラメータにして CM の allocateConnection() を呼び出します。CM は、MCF をキーとして、その poolTable Hashtable 内の MCF をルックアップします。Java Hashtable 実装は、MCF(デバッグ フラグを含む)をハッシュ化し、poolTable Hashtable 内で一致するものの候補リストを取得します。MCF の内部ステートが、元々のデプロイ時の Hashtable への put からその次のルックアップまでの間に変更されたため、MCF が見つからず次のような例外がロギングされます。

Problem granting connection request to a ManagedConnectionFactory which does not exist in connection pool. Check your MCF's hashcode().

この例外の防止策

この例外を防止するもっとも簡単な方法は、WebLogic Server で、javax.naming.Referenceable インタフェースを実装する JNDI オブジェクトがサポートされるようにすることです。この場合、リソース アダプタ開発者としては何もする必要はありません。上記のサポートは、次期のメジャー リリースで計画されています。

それまでは、いくつかの手順を踏むことによってこの例外を回避できます。手順は、リソース アダプタの MCF ステートの要件によって異なります。もっとも簡単な解決策は、リソース アダプタの MCF 用に hashCode() メソッドおよび equals() メソッドを実装することです。もちろん、このマニュアルの記述に基づいて、リソース アダプタ固有の別の方法で問題を解決しても構いません。

hashCode() および equals() を実装する際のガイドラインとしては、これらのメソッドで考慮されるのが、サーバ内で稼動する各リソース アダプタ インスタンスを一意に識別できることが絶対に必要な内部ステートのみという点です。たとえば、リソース アダプタをメインフレーム TP インスタンスと対話するように構築した場合、その hashCode() メソッドおよび equals() メソッドにおけるホスト IP アドレス、ポート、および領域が考慮されます。また、同じコンフィグレーション データを使用することになった 2 種類のリソース アダプタを区別できるような何かをメソッドにもたせることも必要です。たとえば、名前、クラス タイプなどが考えられます。

原因 2 : クライアントがリモート JVM からリソース アダプタを使用しようとしている

この例外の 2 つめの原因はより単純な場合です。J2EE コネクタ アーキテクチャは、リモートでアクセスするためのモデルではありません。このモデルは当面は変更されません。定義されているインタフェースはいずれもリモートではなく、構築されたシステム規約でも MCF と ConnectionManager とのローカル関係が仮定されています。

それでもやはり、WebLogic Server J2EE コネクタ アーキテクチャの実装で、ConnectionFactory にリモートでアクセスしようとすると MFC の hashCode() 実装に問題があるとレポートされるのはバグであり、将来のリリースでは修正されます。エラー メッセージも改善される予定です。

関連する動作 : クライアントサイドのミューテータがうまく機能しない

Referenceable JNDI 実装の不足によるもう 1 つの副作用は、クライアントの対話の間に MCF のコピーが 2 つ作成されるために、クライアントサイドでの MCF への変更がサーバサイドに反映されないことです。

リソース アダプタのデプロイメント中は、WebLogic Server によってオブジェクト グラフが JNDI ツリーにバインドされることに注意してください。また、クライアントが Naming.lookup() を使ってこのグラフをルックアップすると、元のグラフではなく、シリアライズされたグラフのコピーが取得される点にも注意が必要です。クライアントが MCF の内部ステートを変更しても、それらの変更はサーバサイドには反映されません。デバッグ フラグを再び使用して、クライアントが setDebug(true) メソッドを実行する場合、MCF のステート(デバッグ)への変更はそのクライアントの MCF のコピーに対してローカルであり、サーバサイドのコピーはクライアントと同じステートを共有しません。

 


例外 2 : ClassCastException

現在、WebLogic J2EE コネクタ アーキテクチャ コンテナではカスタム クラスローダが使用されています。これは、クラスのロードおよび検索に関連する拡張機能をリソース アダプタで使用できるようにするためのものです。現在の実装には、Web(サーブレット/JSP)コンテナ、EJB コンテナなどの WebLogic Server コンテナからリソース アダプタ クラスを参照する動作があまり直観的ではないという問題があります。タイプの比較とキャストを実行する場合、そのクラスとクラス タイプをロードしたクラスローダが JVM によって先頭に追加されます(つまり、com.acb.ra.MyCF が内部的には RARClassloader@abcdef:com.acb.ra.MyCF として表現されます)。詳細については、Java 言語仕様を参照してください。

Web コンテナおよび EJB コンテナでは、WebLogic Server クラスローダから派生したクラスローダを使用します。したがって、他の WebLogic Server リソースとの相性も良く、ホット デプロイ などの機能も利用できます。J2EE コネクタ アーキテクチャで使用される RARClassLoader は、Java クラスローダから派生したもので、WebLogic 階層の中にはありません。この点は、できる限り早く修正される予定です。

Web コンテナまたは EJB コンテナで実行されているアプリケーション コンポーネントが JNDI 内の ConnectionFactory をルックアップしたときに返されるオブジェクトは、RARClassloader(RARClassloader@abcdef.com.acb.ra.MyCF)によって作成されたオブジェクトのインスタンスです。アプリケーション コンポーネントが実際に想定するオブジェクトは WebLogicClassloader@fedcba:com.acb.ra.MyCF です。変数またはキャストを割り当てようとすると、ClassCastException が送出されます。

この例外の防止策

このエラーを防止する方法として最も信頼性が高いのは、WebLogic Server の起動スクリプトの CLASSPATH 設定にリソース アダプタへのパスを追加することにより、リソース アダプタのクラスを WebLogic Server クラスパスに配置する方法です。これにより、WebLogic Server が提供するホット デプロイ機能および再デプロイ機能が無効になります。ただし、これも望ましい方法ではなく、早急に修正される予定です。

 

back to top previous page