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
を実装します.
そんなわけで (どんなわけで?),
- リソースアダプタ →
MessageEndpoint
→MessageListener
という流れが見えてきます.
んで,この MessageEndpoint
は S2JCA で実装します.
そして 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 に含まれているモックでもいいかも.いずれは HttpServletRequest
の getHeader(String)
で Message
のヘッダ (もしかしたらプロパティ) にアクセスできたら便利かも.
あ,受信した Message
自身も request
スコープのコンポーネントとして登録して欲しいです.
最悪 Message
を参照しないとできないケースはあると思うので.
他にも Message#getJMSReplyTo()
の宛先に返信メッセージを送信したりとか.
といった感じです.
他にもアプリに便利なこととか思いついたらどんどん追加しちゃってください.
先の話としては,アプリケーションの処理が失敗 (例外がスローされた) した場合に更新した DB はロールバックするけど,メッセージは受信したことにする (つまり破棄する) 機能をサポートしたいと考えています.
ただしこれ,悩ましい課題が多いので,基本的なところができてからでいいかな,と.たぶん MethodInterceptor
で実装できると思うので.
そんなわけで (どんなわけで?),よろしくお願いします.