S2JMS 開発記 S2JMS-Container

S2JMS-Container をこもりさんにお願いするべく,簡単なイメージを書いておくテスト.


まずは基本的な位置づけを.
JMS と JCA を含めた J2EE アーキテクチャでは,非同期メッセージの受信はリソースアダプタが行います.
リソースアダプタは通常 JMS プロバイダが提供します.ActiveMQ だと lib/optional の下にある activemq-ra-v.r.z.rar がそれです.
リソースアダプタはメッセージを受信するとアプリケーションサーバに渡します.そのための「端点」を表すのが javax.resource.spi.endpoint.MessageEndpoing です.
アプリケーションサーバMessageEndpoint の実装クラスでトランザクション制御など諸々のシステム的なサービスを付加します.
そして MessageEndpoint はアプリケーションを呼び出します.
JMS の場合はアプリケーションは javax.jms.MessageListener を実装します.


そんなわけで (どんなわけで?),

  • リソースアダプタ → MessageEndpointMessageListener

という流れが見えてきます.
んで,この MessageEndpointS2JCA で実装します.
そして MessageListener を実装するのが S2JMS-Container になります.


S2JMS-Container は MessageEndpoint から受け取った javax.jms.Message を本当のアプリケーションコンポーネントバインディングして,本当のリスナーメソッドを呼び出します.
中核の機能はこれだけ.たぶん.
まずは簡単な実装から始めるとすると,メッセージをバインディングするコンポーネントとリスナーメソッドを持つコンポーネントは同じだとして,

<component class="org.seasar.jms.container.JmsContainerImpl">
	<property name="componentName">hogeAction</componentName>
</component>

みたいにコンポーネントのキーをプロパティで受け取って,MessageListener#onMessage(Message) が呼び出されたらその都度 S2 コンテナからコンポーネント (たぶん instance="request") を取得して,アノテーションの付けられたプロパティに受信したメッセージのヘッダやプロパティ,ボディを設定し,同じくアノテーションで示されたリスナーメソッドを呼び出します.


S2JMS-Container は Web コンテナの外で動くので,そのままだと instance="request" なスコープは使えません.
そこで,独自の HttpServletRequest の実装を用意します.
最初は S2 に含まれているモックでもいいかも.いずれは HttpServletRequestgetHeader(String)Message のヘッダ (もしかしたらプロパティ) にアクセスできたら便利かも.
あ,受信した Message 自身も request スコープのコンポーネントとして登録して欲しいです.
最悪 Message を参照しないとできないケースはあると思うので.
他にも Message#getJMSReplyTo() の宛先に返信メッセージを送信したりとか.


といった感じです.
他にもアプリに便利なこととか思いついたらどんどん追加しちゃってください.
先の話としては,アプリケーションの処理が失敗 (例外がスローされた) した場合に更新した DB はロールバックするけど,メッセージは受信したことにする (つまり破棄する) 機能をサポートしたいと考えています.
ただしこれ,悩ましい課題が多いので,基本的なところができてからでいいかな,と.たぶん MethodInterceptor で実装できると思うので.


そんなわけで (どんなわけで?),よろしくお願いします.