JCAによる接続の仕組み
今回はJCAを用いてJavaアプリケーションからエンタープライズシステムに接続する際に、アプリケーションサーバやリソースアダプタの内部で何が起こっているかを説明する。とくにリソースアダプタの中身を理解することは、独自のリソースアダプタを作成する上で必要不可欠である。実際に実用的なリソースアダプタを作成する際には、このほかにトランザクション管理やセキュリティ、インバウンドコミュニケーションなどに対する理解が必要となるが、誌面の都合もあるため、今回は接続管理の部分のみに的を絞って紹介したい。
JCA 1.5のコネクション管理のアーキテクチャは図1のようになっている。この図はJCA 1.5の仕様書より引用したものである。このうち、灰色で囲まれたPoolManagerやTransactionManagerなどはアプリケーションサーバの持つ機能であり、その他がJCAで定義されたインタフェースだ。各インタフェースどうしの関係は、太い線が仕様で定められたコントラクトであり、細い線が実装依存であることを示している。
図に示されたインタフェースは、それぞれ次のような機能を定義している。より詳細な説明は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のようになる。
各メソッドの具体的な実装方法については、前回使用した「Generic Resource Adapter for JMS」のソースコードが参考になるだろう。Generic Resource Adapter for JMSのソースコードはプロジェクトサイトのCVSリポジトリより取得することができる。今回取り扱わなかったインバウンドコミュニケーション部分も実装されているので、興味のある人は目を通してみるといいだろう。