EJBにおけるメッセージ駆動型Beanの手引き

EJBのメッセージ駆動型Beanのガイド

1. 前書き

簡単に言えば、エンタープライズJavaBean(EJB)は、アプリケーションサーバーで実行されるJEEコンポーネントです。

このチュートリアルでは、非同期コンテキストでのメッセージ処理の処理を担当するメッセージ駆動型Bean(MDB)について説明します。

MDBは、EJB2.0仕様以降のJEEの一部です。 EJB 3.0 introduced the use of annotations、これらのオブジェクトの作成を容易にします。 ここでは、注釈に焦点を当てます。

2. いくつかの背景

メッセージ駆動型Beanの詳細に入る前に、メッセージングに関連するいくつかの概念を確認しましょう。

2.1. メッセージング

メッセージングは​​通信メカニズムです。 By using messaging, programs can exchange data even if they’re written in different program languages or reside in different operational systems.

疎結合ソリューションを提供します。 neither the producer or the consumer of the information need to know details about each other

したがって、メッセージングシステムに同時に接続する必要もありません(非同期通信)。

2.2. 同期および非同期通信

同期通信中、リクエスターは応答が戻るまで待機します。 その間、リクエスタープロセスはブロックされたままになります。

一方、非同期通信では、リクエスターは操作を開始しますが、操作によってブロックされることはありません。リクエスターは他のタスクに進み、後で応答を受け取ることができます。

2.3. JMS

Java Message Services(「JMS」)は、メッセージングをサポートするJava APIです。

JMSは、ピアツーピアおよびパブリッシュ/サブスクライブのメッセージングモデルを提供します。

3. メッセージ駆動型Bean

An MDB is a component invoked by the container every time a message arrives on the messaging system.結果として、このイベントはこのBean内のコードをトリガーします。

受信したデータをブラウザに表示したり、解析してデータベースに保存したりするため、MDBonMessage()メソッド内で多くのタスクを実行できます。

別の例は、何らかの処理後にデータを別のキューに送信することです。 それはすべて、ビジネスルールに基づいています。

3.1. メッセージ駆動型Beanのライフサイクル

MDBには2つの状態しかありません。

  1. コンテナには存在しません

  2. 作成され、メッセージを受信する準備ができました

依存関係が存在する場合、MDBの作成直後に注入されます。

メッセージを受信する前に命令を実行するには、メソッドに@javax.ejb.PostConstructアノテーションを付ける必要があります。

依存性注入と@javax.ejb.PostConstructの実行はどちらも1回だけ発生します。

その後、MDBはメッセージを受信する準備が整います。

3.2. トランザクション

メッセージは、トランザクションコンテキスト内でMDBに配信できます。

onMessage()メソッド内のすべての操作が単一のトランザクションの一部であることを意味します。

したがって、ロールバックが発生した場合、メッセージシステムはデータを再配信します。

4. メッセージ駆動型Beanの操作

4.1. 消費者の作成

メッセージ駆動型Beanを作成するには、クラス名宣言の前に@javax.ejb.MessageDrivenアノテーションを使用します。

着信メッセージを処理するには、MessageListenerインターフェイスのonMessage()メソッドを実装する必要があります。

@MessageDriven(activationConfig = {
    @ActivationConfigProperty(
      propertyName = "destination",
      propertyValue = "tutorialQueue"),
    @ActivationConfigProperty(
      propertyName = "destinationType",
      propertyValue = "javax.jms.Queue")
})
public class ReadMessageMDB implements MessageListener {

    public void onMessage(Message message) {
        TextMessage textMessage = (TextMessage) message;
        try {
            System.out.println("Message received: " + textMessage.getText());
        } catch (JMSException e) {
            System.out.println(
              "Error while trying to consume messages: " + e.getMessage());
        }
    }
}

この記事では.xml記述子ではなくアノテーションに焦点を当てているため、.ではなく@ActivationConfigPropertyを使用します

@ActivationConfigPropertyは、その構成を表すKey-Valueプロパティです。 activationConfig内で2つのプロパティを使用して、キューとMDBが消費するオブジェクトのタイプを設定します。

onMessage()メソッド内で、メッセージパラメータをTextMessage, BytesMessage, MapMessage StreamMessageまたはObjectMessageにキャストできます。

ただし、この記事では、標準出力のメッセージコンテンツのみを見ていきます。

4.2. プロデューサーの作成

セクション2.1で説明したように、producer and consumer services are completely independent and can even be written in different programming languages

Javaサーブレットを使用してメッセージを生成します。

@Override
protected void doGet(
  HttpServletRequest req,
  HttpServletResponse res)
  throws ServletException, IOException {

    String text = req.getParameter("text") != null ? req.getParameter("text") : "Hello World";

    try (
        Context ic = new InitialContext();

        ConnectionFactory cf = (ConnectionFactory) ic.lookup("/ConnectionFactory");
        Queue queue = (Queue) ic.lookup("queue/tutorialQueue");

        Connection connection = cf.createConnection();
    ) {
        Session session = connection.createSession(
          false, Session.AUTO_ACKNOWLEDGE);
        MessageProducer publisher = session
          .createProducer(queue);

        connection.start();

        TextMessage message = session.createTextMessage(text);
        publisher.send(message);

    } catch (NamingException | JMSException e) {
        res.getWriter()
          .println("Error while trying to send <" + text + "> message: " + e.getMessage());
    }

    res.getWriter()
      .println("Message sent: " + text);
}

ConnectionFactoryおよびQueueインスタンスを取得した後、ConnectionおよびSessionを作成する必要があります。

セッションを作成するには、createSessionメソッドを呼び出します。

createSessionの最初のパラメーターは、セッションがトランザクションの一部であるかどうかを定義するbooleanです。

2番目のパラメーターは、最初のパラメーターがfalseの場合にのみ使用されます。 これにより、着信メッセージに適用され、Session.AUTO_ACKNOWLEDGE, Session.CLIENT_ACKNOWLEDGEおよびSession.DUPS_OK_ACKNOWLEDGEの値をとる確認応答方法を説明できます。

接続を開始し、セッションオブジェクトでテキストメッセージを作成して、メッセージを送信できます。

同じキューにバインドされたコンシューマーは、メッセージを受信し、非同期タスクを実行します。

また、JNDIオブジェクトの検索とは別に、try-with-resourcesブロック内のすべてのアクションは、JMSExceptionが存在しないキューに接続しようとするなどのエラーに遭遇した場合に、接続が閉じていることを確認します。または、接続するポート番号を間違って指定しました。

5. メッセージ駆動型Beanのテスト

次のように、SendMessageServletGETメソッドを介してメッセージを送信します。

また、http://127.0.0.1:8080/producer/SendMessageServlet.のようにパラメータを送信しない場合、サーブレットは“Hello World”をキューに送信します

6. 結論

メッセージ駆動型Beanを使用すると、キューベースのアプリケーションを簡単に作成できます。

したがって、MDBs allow us to decouple our applications into smaller services with localized responsibilitiesにより、システム障害から回復できる、はるかにモジュール化された増分システムが可能になります。

いつものように、コードはover on GitHubです。