概要
S2JMS-Containerは、POJOがJMSのAPIを意識することなく、 非同期通信によるメッセージを受信できるようにするためのコンポーネントです。
通常、JMSによるインバウンドメッセージ受信アプリケーション (EJBのMessage-Driven Beanなど) を作成するには、以下の手順を踏みます。
javax.jms.MessageListener
インターフェースを実装したクラスを作成する。onMessage(javax.jms.Message)
メソッドを作成する。onMessage(javax.jms.Message)
メソッドの中で、受信したjavax.jms.Message
を処理する。
しかし、この場合作成したクラスはJMSのAPIに依存することになってしまいます。
S2JMS-Containerを利用することで、JMSのAPIに依存しない受信アプリケーション (Message-Driven POJOs) を作ることができ、特に既存の資産をJMS受信アプリケーションに変換する際に威力を発揮します。
S2JMS-Containerの提供する機能
S2JMS-Containerは、以下の機能を提供します。
- メッセージリスナ・コンポーネントへJMSメッセージのバインド
- メッセージリスナ・コンポーネントの呼び出し
- 非Webコンテナ環境でSeasar2におけるrequestスコープの提供
JMSメッセージヘッダのバインド
メッセージリスナ・コンポーネントに対して、受信したJMSメッセージのヘッダをバインドします。
バインドしたいフィールドまたはsetterメソッドに @JMSHeader
アノテーションを記述することで、
該当するメッセージヘッダがバインドされます。
以下のように、@JMSHeader
アノテーションのみを記述した場合、
フィールド名に一致するメッセージヘッダがバインドされます。
この場合、フィールド名は「correlationID
」 (「JMS」というプレフィックスをつけない)
または「JMSCorrelationID
」 (「JMS」というプレフィックスをつける) のどちらでも有効です。
@JMSHeader String correlationID;
以下のように、name
メンバを利用してヘッダ名称を記述することもできます。
この場合、フィールド名には関係なくname
メンバで指定されたヘッダ名が使用されます。
この場合もヘッダ名称には「JMS」プレフィックスをつけてもつけなくても構いません。
@JMSHeader(name = "deliveryMode") int mode;
@JMSHeader
アノテーションには、
S2ContainerのbindingType
メンバも指定することができます。
@JMSHeader(bindingType = BindingType.MUST) String JMSMessageID;
bindingType
については、以下の表を参照してください。
bindingType | 説明 |
---|---|
MUST |
バインドに失敗した場合、例外が発生します。 |
SHOULD (デフォルト) |
バインドに失敗した場合、警告を通知します。 |
MAY |
バインドに失敗した場合、何もおきません。 |
NONE |
バインドを行いません。 |
setterメソッドに対しても@JMSHeader
アノテーションを記述することができます。
name
メンバを省略した場合、メソッド名から「set
」を除いた部分がヘッダ名称として扱われます。
int priority; @JMSHeader(name = "JMSPriority", bindingType = BindingType.MUST) public void setPriority(int priority) { this.priority = priority; }
JMSメッセージプロパティのバインド
ヘッダと同様にメッセージのプロパティもバインドすることができます。
以下のように、フィールドやsetterに@JMSProperty
アノテーションのみを記述した場合、
フィールド名に一致するメッセージプロパティがバインドされます。
この場合、「foo」という名前のプロパティがバインドされます。
@JMSProperty int foo;
@JMSProperty public void setFoo(int foo){ this.foo = foo; }
また、以下のようにname
メンバを利用してプロパティ名を明示することもできます。
@JMSProperty(name = "baz") public void setBar(String bar) { this.bar = bar; }
@JMSProperty
アノテーションにも、@JMSHeader
アノテーションと同様に、
bindingType
メンバによるバインディングの制御を指定することができます。
JMSメッセージペイロードデータのバインド
ヘッダと同様にメッセージの本体 (ペイロードデータ) もバインドすることができます。
MapMessage
を除いて、
以下のようにフィールドやsetterに@JMSPayload
アノテーションのみを記述した場合、
フィールド名に一致するメッセージプロパティがバインドされます。
この場合、TextMessage
のペイロードデータがバインドされます。
@JMSPayload String text;
@JMSPayload public void setText(String text){ this.text = text; }
MapMessage
の場合、
以下のようにフィールドやsetterに@JMSPayload
アノテーションのみを記述した場合、
ペイロードデータからフィールド名に一致するマッピングの値がバインドされます。
この場合、MapMessage
のペイロードデータから、
foo
というキーにマッピングされている値がバインドされます。
@JMSPayload int foo;
@JMSPayload public void setFoo(int foo){ this.foo = foo; }
また、以下のようにname
メンバを利用してキーを明示することもできます。
@JMSPayload(name = "baz") public void setBar(String bar) { this.bar = bar; }
ただし、フィールドまたはプロパティの型がMap
の場合は、
MapMessage
のペイロードが持つ全てのマッピングを含んだMap
がバインドされます。
@JMSPayload public void setBaz(Map baz) { this.baz = baz; }
@JMSPayload
アノテーションにも、@JMSHeader
アノテーションと同様に、
bindingType
メンバによるバインディングの制御を指定することができます。
リスナメソッド
受信したメッセージがバインドされた後に呼び出されるのがリスナメソッドです。
リスナメソッドは、デフォルトではメソッド名がonMessage
のメソッドです。
void onMessage() { ... }
引数を一つ持つこともできます。
引数の型はメッセージのペイロードデータ型か、javax.jms.Message
です。
void onMessage(String text) { ... }
void onMessage(Message message) { ... }
また、以下のように@OnMessage
アノテーションで任意の名前のメソッドをリスナメソッドにすることができます。
@OnMessage void some() { ... }
@OnMessage void some(Map payload) { ... }
いずれも、戻り値の型は任意です。 S2JMS-Containerが戻り値を利用することはありません。