失敗
MessageDriven アノテーションに必須属性がないため、属性を何も指定せず Bean クラスに適用しました。 このメッセージ駆動型Bean をデプロイしたところ、当然の如くデプロイエラーに…。
メッセージ駆動型Bean を動作させるためには MessageDriven アノテーションにどんな属性を設定すればいいのでしょう?
環境
このレポートは、以下の環境について記述したものです。
| JDK | JDK 6 |
| AP サーバ | JBoss Application Server 4.0.5 GA (With EJB 3.0) |
原因
JBoss 4.0 でメッセージ駆動型Bean を動作させるには、宛先のタイプ (キュー or トピック) や監視する宛先の名前を指定する必要があります。 これらをデプロイメント記述子 (ejb-jar.xml) に記述しない場合は、MessageDriven アノテーションの activationConfig 属性で指定します。
解決策
MessageDriven アノテーションの activationConfig 属性に、宛先のタイプ (destinationType) と監視する宛先の名前 (destination) を指定します。
以下に、メッセージ駆動型Bean とクライアント・クラスのサンプルを提示します。 このサンプルでは、メッセージ送受信のチャネルに JBoss MQ (JBoss AS 付属のメッセージ指向ミドルウェア) のデフォルト・キューを使用しています。
(1) メッセージの受信
まず、MessageDriven アノテーションを適用して、メッセージ駆動型Bean であることを定義します。 次に、メッセージ リスナー インターフェースを実装し、受信したメッセージを処理させます。
【注意】
メッセージの受信処理はコンテナが行ってくれるため、コンシューマに関するロジックは不要です。
import javax.ejb.ActivationConfigProperty;
import javax.ejb.MessageDriven;
import javax.jms.*;
/**
* メッセージ駆動型Beanの簡易サンプルです。
*/
@MessageDriven(
activationConfig = {
@ActivationConfigProperty(propertyName="destinationType", propertyValue="javax.jms.Queue"),
@ActivationConfigProperty(propertyName="destination", propertyValue="queue/A")
}
)
public class TestBean implements MessageListener {
/**
* 受信したメッセージを処理します。
*/
public void onMessage(Message msg) {
try {
// データ取得
ObjectMessage omsg = (ObjectMessage) msg;
TestData data = (TestData) omsg.getObject();
// データ出力
System.out.println(data.getText());
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
(2) メッセージの送信
JMS を使用して、メッセージを送信します。
【注意】
トピックを使用する場合、インターフェースの違いこそありますが、処理の流れは同じです (キューとトピックのインターフェースの違いについては 補足 を参照してください)。
import javax.jms.*;
import javax.naming.*;
/**
* メッセージを送信するクライアントです。
*/
public class TestClient {
/**
* メッセージを送信します。
*/
public void sendMessage(TestData data)
throws JMSException, NamingException {
Queue queue = null; // JMS キュー
QueueConnection conn = null; // JMS 接続
QueueSession session = null; // JMS セッション
QueueSender sender = null; // JMS プロデューサ
try {
// JNDI の初期化
InitialContext ctx = new InitialContext();
// 接続ファクトリのルックアップ
QueueConnectionFactory factory =
(QueueConnectionFactory) ctx.lookup("QueueConnectionFactory");
// 接続の生成
conn = factory.createQueueConnection();
// セッションの生成
session = conn.createQueueSession(false,
QueueSession.AUTO_ACKNOWLEDGE);
// キューのルックアップ
queue = (Queue) ctx.lookup("queue/A");
// プロデューサの生成
sender = session.createSender(queue);
// メッセージの生成
ObjectMessage msg = session.createObjectMessage(data);
// メッセージの送信
sender.send(msg);
} finally {
if (sender != null)
sender.close();
if (session != null)
session.close();
if (conn != null)
conn.close();
}
}
}
(3) メッセージのデータ
このサンプルでは任意のデータを渡すために、ObjectMessage を使用しています。 ObjectMessage に格納できるようにするため、Serializable インターフェースを適用します。
import java.io.Serializable;
/**
* メッセージに設定するデータです。
*/
public class TestData implements Serializable {
private static final long serialVersionUID = 1L;
private String text;
public String getText() {
return this.text;
}
public void setText(String text) {
this.text = text;
}
}
補足
■ キューとトピック
キューはポイント・ツー・ポイント方式 (メッセージは 1 つのコンシューマにのみ送信可能)、 トピックはパブリッシュ/サブスクライブ方式 (メッセージを複数のコンシューマに送信可能) に対応しています。
それぞれの JMS インターフェースは以下の通りです。
| ポイント・ツー・ポイント方式 | パブリッシュ/サブスクライブ方式 | |
|---|---|---|
| 宛先 | Queue | Topic |
| 接続ファクトリ | QueueConnectionFactory | TopicConnectionFactory |
| 接続 | QueueConnection | TopicConnection |
| セッション | QueueSession | TopicSession |
| プロデューサ | QueueSender | TopicPublisher |
| コンシューマ * MDB を使用する場合は不要 |
QueueReceiver QueueBrowser |
TopicSubscriber |
参考サイト
- Java EE 5 SDK API - MessageDrivenBean アノテーション
- Java EE 5 SDK API - ActivationConfigProperty アノテーション
- Java EE 5 SDK API - MessageListener インターフェース
