JMS メッセージの処理

JMS メッセージがトピックまたはキューに送信されると、メッセージ駆動型 Bean インスタンスが、onMessage メソッドでの指定に従ってそのメッセージを解釈および処理します。JMS メッセージがトピックに送信されると、パブリッシュ/サブスクライブ システム、すなわちこのトピックをリスンしているすべてのメッセージ駆動型 Bean クラスのインスタンスが、原則としてこのメッセージを受信および処理します。ただし、メッセージにメッセージ セレクタが含まれている場合は、そのメッセージ セレクタに一致するメッセージ駆動型 Bean のみが、メッセージを処理します。JMS メッセージがキューに送信されると、ポイント ツー ポイント システム、つまりただ 1 つのメッセージ駆動型 Bean が、複数の Bean クラスがキューをリスンしている場合でもメッセージを処理します。この場合も、メッセージ セレクタが使用されていると、Bean によるメッセージ処理が制限されることがあります。

JMS メッセージの処理内容は、モデリングされているビジネス タスクに完全に依存します。これは、単にメッセージのログを記録することから、セッションおよびエンティティ Bean に対するメソッド呼び出しをはじめとする一連のタスクを実行することまで、多岐にわたります。以下のコード サンプルは、メッセージ駆動型 Bean の使い方の一例を示します。この Bean は、jms/SamplesAppMDBQ キューを経由して配信された JMS メッセージのみに応答し、メッセージ セレクタ Command= 'Delete' を含んでいます。JMS メッセージの処理時に、この Bean のインスタンスがエンティティ Bean SimpleToken_M のクエリ メソッド findAll を呼び出し、その後、基底のデータベースから SimpleToken_M に対応するすべてのレコードを削除します。

@EjbLocalRefs( { 
    @EjbLocalRef(link = "SimpleToken_M") })
@MessageDriven(defaultTransaction = MessageDriven.DefaultTransaction.NOT_SUPPORTED, 
        messageSelector = "Command = 'Delete'", 
        ejbName = "DeleteViaQMD", 
        destinationJndiName = "jms/SamplesAppMDBQ", 
        destinationType = "javax.jms.Queue")
public class DeleteViaQMDBean 
    extends GenericMessageDrivenBean 
    implements MessageDrivenBean, MessageListener {

    private static final long serialVersionUID = 1L;

    private SimpleTokenHome_M tokenHome;

    public void ejbCreate() {
        try {
            javax.naming.Context ic = new InitialContext();
            tokenHome = (SimpleTokenHome_M) ic
                    .lookup("java:/comp/env/ejb/SimpleToken_M");
        } catch (NamingException ne) {
            System.out.println("Encountered the following naming exception: "
                    + ne.getMessage());
        }
    }

    public void onMessage(Message msg) {
        try {
            Iterator allIter = tokenHome.findAll().iterator();
            while (allIter.hasNext()) {
                ((SimpleToken_M) allIter.next()).remove();
            }
        } catch (Exception e) {
            System.out.println("Encountered the following exception: "
                    + e.getMessage());
        }
    }
}

確認応答およびトランザクション

メッセージ駆動型 Bean インスタンスは、メッセージを受信し、かつそれがコンテナ管理によるトランザクションの一部ではない場合は、デフォルトでは即座に、メッセージが受信されたということを通知する確認応答を、JMS プロバイダに送信します。これにより、JMS プロバイダがこのメッセージを再配信しようとすることが回避されます。しかし、この確認応答は、メッセージの受信が正常に行われたことを示すだけであって、メッセージの処理が正常に行われるという保証はありません。たとえば、エンティティ Bean を見つけようとしたり、レコードを更新しようとしたりしているときに、システム例外が起こって、処理が失敗する可能性もあります。

処理が失敗したときに、確実にメッセージが再配信されるようにするには、メッセージ駆動型 Bean をトランザクションの一部とします。一番簡単な方法は、コンテナ管理によるトランザクションを使用することです。この場合、トランザクション管理は、EJB コンテナが行います。メッセージ駆動型 Bean のコンテナ管理によるトランザクションを有効にするには、カーソルを @MessageDriven アノテーションの内部に移動し、[プロパティ] ビューを使用して transactionType 属性を CONTAINER に、defaultTransaction 属性を REQUIRED にそれぞれ設定します。JMS メッセージ処理の実行が正常に完了すると、エンティティ Bean レコードの更新など、このビジネス タスクの途中で行われた変更がすべてコミットされ、確認応答が JMS プロバイダに送信されます。しかし、JMS メッセージ処理が、システム例外によって失敗すると、すべての変更はロールバックされて、受信は確認されません。つまり、処理の失敗後は、処理が正常に完了するか、このトピックまたはキューに関して指定された再配信の試行回数が上限に達するまで、JMS プロバイダは JMS メッセージの再送信を試行し続けます。

注意 : メッセージ駆動型 Bean がトランザクションの一部である場合は、自身のトランザクションの一部として実行されます。つまり、トランザクションが失敗すると、onMessage メソッドの一部として行われた変更はロールバックされますが、送信者とメッセージ駆動型 Bean は切り離されているので、例外の発生は JMS メッセージを送信する EJB にもクライアント アプリケーションにも直接影響しません。

関連トピック

weblogic.ejbgen.MessageDriven


さらにヘルプが必要ですか。質問は Workshop ニュース グループまでお寄せください。