JCAによる接続の仕組み

今回はJCAを用いてJavaアプリケーションからエンタープライズシステムに接続する際に、アプリケーションサーバやリソースアダプタの内部で何が起こっているかを説明する。とくにリソースアダプタの中身を理解することは、独自のリソースアダプタを作成する上で必要不可欠である。実際に実用的なリソースアダプタを作成する際には、このほかにトランザクション管理やセキュリティ、インバウンドコミュニケーションなどに対する理解が必要となるが、誌面の都合もあるため、今回は接続管理の部分のみに的を絞って紹介したい。

JCA 1.5のコネクション管理のアーキテクチャは図1のようになっている。この図はJCA 1.5の仕様書より引用したものである。このうち、灰色で囲まれたPoolManagerやTransactionManagerなどはアプリケーションサーバの持つ機能であり、その他がJCAで定義されたインタフェースだ。各インタフェースどうしの関係は、太い線が仕様で定められたコントラクトであり、細い線が実装依存であることを示している。

図1 コネクション管理のアーキテクチャ(JCA 1.5のSpecificationより引用)

図に示されたインタフェースは、それぞれ次のような機能を定義している。より詳細な説明はJava EE 5のAPIドキュメントを参照していただきたい。

javax.resource.spi.ConnectionManager アプリケーションサーバとリソースアダプタとの接続を管理する
javax.resource.spi.ManagedConnectionFactor ManagedConnectionおよびEIS固有のConnectionのファクトリインタフェース
javax.resource.spi.ManagedConnection EISとの物理的な接続を仲介する
javax.resource.spi.ConnectionEventListener ManagedConnectionによってアプリケーションサーバとの接続中に発生したイベントを受け取るリスナ
javax.resource.spi.LocalTransaction EISトランザクションマネージャに管理されたトランザクションをサポートする
javax.transaction.xa.XAResource リソースマネージャとトランザクションマネージャ間の標準的なコントラクトを定義する
javax.resource.cci.ConnectionFactory Connectionのためファクトリインタフェース
javax.resource.cci.Connection EISとの接続を仲介するアプリケーションレベルのインタフェース

これを見てわかるように、アプリケーションから接続に利用するインタフェースはConnectionFactoryやConnectionだが、実際にEISとの接続を確立するのはManagedConnectionFactoryやManagedConnectionが行うことになる。ConnectionEventListenerはManagedConnectionに対して登録する。また、トランザクションをサポートする場合にはXAResourceやLocalTransactionを実装しておく必要がある。

リソースアダプタを自前で作成する場合には、これらインタフェースん実装クラスを用意に、デプロイメントデスクリプタと共にRARとしてパッケージングすればよい。

リソースアダプタによるコネクション確立までの流れ

では、実際にリソースアダプタがデプロイされてからそれがアプリケーションから利用されるまでの一連の動作を追ってみよう。

まずリソースアダプタがデプロイされた段階で、ManagedConnectionFactoryのインスタンスが生成され、さらにそこからcreateManagedConnection()メソッドでManagedConnectionインスタンスが生成される。

アプリケーションからJNDI経由でConnectionFactoryをLookupされた場合には、まずManagedConnectionFactoryのcreateConnectionFactory()メソッドが呼ばれる。このメソッドはConnectionFactoryインスタンスを生成してを返す。

アプリケーション側では、前回示したようにConnectionFactoryのcreateConnection()メソッドを用いてConnectionインスタンスの生成を試みる。実際にはConnectionManagerのallocateConnection()メソッドを呼び出す。このメソッドにはManagedConnectionFactoryとコネクションリソースの情報を持ったConnectionRequestInfoの両インスタンスが渡される。ここで2つのパターンが考えられる。ひとつはリソースアダプタがアプリケーションサーバのコネクションプールを利用しているケースで、この場合はプールに既存のManagedConnectionがあるかどうかを調べ (ManagedConnectionFactory.matchManagedConnection()メソッド)、あればそれを返す。

プールにManagedConnectionが存在しない場合や、プールを利用しておらずConnactionManagerがリソースアダプタによって独自に提供されている場合には、まずManagedConnectionFactoryのcreateManagedConnection()メソッドにより渡されたConnectionRequestInfoの情報を持つManagedConnectionインスタンスを生成し、そこからgetConnection()メソッドでConnectionインスタンスを取得して返すといった手順になっている。

上記の手順を図で示すと図2のようになる。

図2 コネクションが確立するまでの流れ (JCA 1.5のSpecificationより引用)

各メソッドの具体的な実装方法については、前回使用した「Generic Resource Adapter for JMS」のソースコードが参考になるだろう。Generic Resource Adapter for JMSのソースコードはプロジェクトサイトのCVSリポジトリより取得することができる。今回取り扱わなかったインバウンドコミュニケーション部分も実装されているので、興味のある人は目を通してみるといいだろう。