S2JMS開発記 MessageEndpoint を読む
id:koichikさんがMessageEndpointまで動作したバージョンをコミットしてくれたので、さっそく動かしてみました。
S2JCA-ActiveMQ の activemq/bin/activemq.bat を実行しておいて, org.seasar.jca.mi.jms.ActiveMQTest で動作確認ができます.
まったく簡単ですね。おぉ、すごい勢いでログが流れていきます。
大きな流れは、
- ActiveMQTest の test() メソッドで1〜100までのtextMessageを順次送信。
- ActiveMQTest内で宣言されている MessageListenerImpl(implements MessageListener)クラスの onMessage() が受信。
という感じですね。
ここから先はS2JMS-Containerの仕事となります。私の理解を整理するためにも流れを書いてみましょう。
まず、S2JMS-Containerが MessageListener の実装クラスを提供し、さらにS2JMS-Containerに登録されたクラスに対してメッセージを送信します。
S2JMS-Containerを経由することで、MessageListenerを実装しないPOJOがJMSのメッセージを受信できるようになるのです。
さらに、S2JMS-Containerが受信したメッセージのヘッダやペイロードをPOJOに対してインジェクションしてくれるので、POJO側はJMSのメッセージすらも意識する必要がない、というのが今回の売りです。(よね?id:koichikさん)
で、問題はこのマッピングをどうするかですが、これはあとで考えましょう。
id:koichikさんのサンプルに戻って、どのような流れでMessageListenerImplが呼び出されているのかを少し追ってみましょう。
jms-activemq-inbound.dicon をちょっと覗いてみましょう。MessageListenerはMessageEndpointから呼び出されますが、ソースを見るかぎり、MessageEndpoint(この場合はJmsMessageEndpointImpl)を生成しているMessageEndpointFactoryImplがMessageEndpointのコンストラクタに引数として渡しているようです。
<component class="org.seasar.jca.mi.MessageEndpointFactoryImpl"> <property name="endpointClass">@org.seasar.jca.mi.JmsMessageEndpointImpl@class</property> </component> <component class="org.seasar.jca.mi.jms.ActiveMQTest$MessageListenerImpl"/>
で、MessageEndpointFactoryはどうやってMessageListenerを探しているかというと、コンテナに登録されたクラスの中から、MessageListenerインターフェースの実装クラスを引っ張ってきているようですね。デフォルトではJMSのMessageListenerを探しますが、listenerTypeプロパティに任意のClassを設定すれば、その実装クラスを探してきてくれるようです。さらに、listenerName プロパティで明示的にコンポーネント名を指定することもできますね。
とにかく、これでS2JMS-ContainerとしてはMessageListenerの実装クラスを用意してコンテナに放りこめば良いというのがわかりました。
このあたりの依存関係をあまり気にしなくて良いというのがDIコンテナのいいところですが、実行時にどのようにオブジェクトが結びつくのか調べようとすると、結構大変ですね。これをビジュアル化するツールがあると、とっても嬉しいのですが。