メッセージ駆動型 bean

MDB (Message-driven bean:メッセージ駆動型 bean) は、JMS メッセージを使用するためにデザインされる EJB です。これは、直接呼び出すことがないため、リモート、ローカル、リモートホーム、またはローカルホームのインターフェイスがありません。ただし、ejb-jar.xml および jrun-ejb-jar.xml ファイルに MDB を定義する必要があります。また、デプロイメントディスクリプタで指定したキューおよびトピックが存在することを確認する必要もあります。

MDB 実装

MDB 実装クラスは、MessageDrivenBeanMessageListener の両方を実装します。MessageListener インターフェイスには、onMessage というコールバックメソッドが含まれます。これは、メッセージが受信されるとコンテナから呼び出されます。

次のコードは、MDB 実装を示しています。

import javax.ejb.*;
import javax.jms.MessageListener;
import javax.jms.Message;
import javax.jms.TextMessage;
import javax.jms.JMSException;

public class SimpleMDBBean implements MessageDrivenBean, 
MessageListener {
    MessageDrivenContext ctx;

    /* NO-ARGS CONSTRUCTOR */
    public SimpleMDBBean() {
    System.out.println("In MDBTest:constructor");
    }

    /* onMessage callback method; part of MessageListener interface */
    public void onMessage(Message message) {
    try {
    TextMessage tMessage = (TextMessage)message;
      //実際の環境では、ここで do more を実行します。
     System.out.println("In MDBTest.onMessage(), message = " +
 tMessage.getText() );
    }
    catch(JMSException e) {
      System.out.println("JMS Exception:" + e.getMessage());
    }
    } // onMessage を終了
    /* Required EJB callback methods */
    public void setMessageDrivenContext(MessageDrivenContext ctx)
                                     throws EJBException {
    System.out.println("In MDBTest.setMessageDrivenContext()");
    this.ctx = ctx;
    }
   public void ejbCreate() {  }
   public void ejbRemove() {  }
}

EJB デプロイメントディスクリプタ

ejb-jar.xml ファイルでは、MDB で使用するキューまたはトピックを定義します。また、EJB コンテナで使用するその他情報も指定します。

次のサンプルは、MDB のデプロイメントディスクリプタの基本的要素を示しています。

...
  <message-driven>
      <ejb-name>RKN Test Message-Driven Bean</ejb-name>
      <ejb-class>SimpleMDBBean</ejb-class>
      <transaction-type>Container</transaction-type>
      <acknowledge-mode>Auto-acknowledge</acknowledge-mode>
      <security-identity>
        <description></description>
        <run-as>
          <role-name>everyone</role-name>
        </run-as>
      </security-identity>
      <resource-ref>
        <res-ref-name>MDBQCF</res-ref-name>
        <res-type>javax.jms.QueueConnectionFactory</res-type>
        <res-auth>Container</res-auth>
        <res-sharing-scope>Unshareable</res-sharing-scope>
      </resource-ref>
      <resource-env-ref>
        <resource-env-ref-name>jms/queue/queue1</
resource-env-ref-name>
        <resource-env-ref-type>javax.jms.Queue</resource-env-ref-type>
      </resource-env-ref>
      <message-driven-destination>
        <destination-type>javax.jms.Queue</destination-type>
        <subscription-durability>Durable</subscription-durability>
      </message-driven-destination>
  </message-driven>
...

JRun EJB デプロイメントディスクリプタ

jrun-ejb-jar.xml ファイルには、MDB の JNDI キューの接続ファクトリ情報など、JRun 特有のデプロイ設定が含まれます。

次のサンプルは、MDB の JRun EJB デプロイメントディスクリプタを示しています。

...
<message-driven>
      <ejb-name>RKN Test Message-Driven Bean</ejb-name>
      <jndi-name>RKN Test Message-Driven Bean</jndi-name>
      <resource-ref>
        <res-ref-name>MDBQCF</res-ref-name>
        <jndi-name>jms/QueueConnectionFactory</jndi-name>
        <user>admin</user>
        <password>admin</password>
      </resource-ref>
      <resource-env-ref>
        <resource-env-ref-name>jms/queue/queue1</
resource-env-ref-name>
        <jndi-name>jms/queue/queue1</jndi-name>
      </resource-env-ref>
      <message-driven-subscription>
        <client-id>MDBSubscriber</client-id>
      </message-driven-subscription>
    </message-driven>
...

その他のファイルと設定

JRun JMS および MDB を使用するには、JMC から JMS デスティネーション (キューおよびトピック) を指定する必要があります。これらの設定は、SERVER-INF/jrun-resources.xml ファイルに保存され、テキストエディタで自由に変更できます。

JMS デスティネーションの作成の詳細については、JMC オンラインヘルプを参照してください。JMS のその他の設定については、『JRun 管理者ガイド』を参照してください。

サンプル JMS センダー

次のコードは、サンプルの MDB 実装への簡単なサーブレットセンダーを示しています。

...
import java.util.*;
import javax.ejb.*;
import javax.jms.*;
import javax.naming.*;

public class MySender extends HttpServlet {
  // キュー属性を設定します。
  // ユーザー ID とパスワード
  private String _user = new String("admin");
  private String _password = new String("admin");
  // JMC で定義したキュー名と一致させます。
  // この情報は、SERVER-INF/jrun-resources.xml ファイルでも表示できます。
  private String _queue = new String("queue1");
  // これは、リモートホスト名とJNDI ポート番号を連結したものです。
  private String _providerurl = new String("localhost:2918");
  private String _ctxtFactory = new String 
("jrun.naming.JRunContextFactory");
  // JMS で使用するオブジェクトを設定します。
  private Context _context = null;
  private QueueConnection _connection = null;
  private QueueSession _session = null;
  private TextMessage _message = null;
  private QueueSender _sender = null;

public void init(ServletConfig config) throws ServletException {
  super.init(config);

  // JNDI で設定を行います。
  try {
  Properties p = new Properties();
  p.put(Context.SECURITY_PRINCIPAL, _user);
  p.put(Context.SECURITY_CREDENTIALS, _password);
  p.put(Context.PROVIDER_URL, _providerurl );
  p.put( Context.INITIAL_CONTEXT_FACTORY, _ctxtFactory);

    // 同一サーバのコンテキストにアクセスする場合は、空のコンストラクタ
    // になることがあるので、EJB では Web アプリケーションの認証情報が
    // 使用されます。
    _context = new InitialContext(p);

    final QueueConnectionFactory factory =
      (QueueConnectionFactory)_context.lookup
        ("jms/QueueConnectionFactory");
    // ファクトリを使用して QueueConnection (anonymous) を作成します。
    _connection = factory.createQueueConnection();
    // QueueConnection を使用して QueueSession を作成します。
    _session = _connection.createQueueSession(false,
      Session.AUTO_ACKNOWLEDGE);
    // QueueSession を使用して QueueSender を作成します。
    _sender = _session.createSender((Queue)_context.lookup
      ("java:jms/queue/queue1"));
    // TextMessage オブジェクトを作成します。
    _message = _session.createTextMessage();
  }
  catch(NamingException e) {
    System.out.println("Naming Exception:" + e.getMessage());
  }
  catch(JMSException e) {
    System.out.println("JMS Exception:" + e.getMessage());
  }
}

// doGet は、送信するメッセージ (非表示) を受け取るフォームを表示します。
public void doGet(HttpServletRequest req,
  HttpServletResponse res) throws IOException, ServletException { 
...
// doPost は、フォームを読み込んでメッセージを送信します。
public void doPost(HttpServletRequest req,
  HttpServletResponse res) throws IOException, ServletException { 
  // フォームを読み込みます。
  // メッセージはすべて、ここで送信されます。
  // 設定の内容については、init メソッドを参照してください。
  res.setContentType("text/html");
  PrintWriter out = res.getWriter();

  int priority = Message.DEFAULT_PRIORITY;
  int delivery = Message.DEFAULT_DELIVERY_MODE;
  String text = new String("Blank Message");

  String[] attrArray = req.getParameterValues("thisMessage");
  // 呼び出しフォームには、thisMessage 用の値が 1 つしかないと想定します。
  if(attrArray != null) {
    text = attrArray[0];
  }
   try {
        System.out.println("just before setText");
        _message.setText(text);
        // キューに送信します。
        _sender.send(_message);
    } // try を終了
    catch(JMSException e) {
      System.out.println("JMS Exception:" + e.getMessage());
    }
...
public void destroy() {
  // これらは if != null のチェックでラップしたほうがよいでしょう。
  try {
    _sender.close();
    _session.close();
    _connection.close();
    _context.close();
  }
  catch(NamingException e) {
    System.out.println("Naming exception in destroy: " +
      e.getMessage());
  }
  catch(JMSException e) {
    System.out.println("JMS Exception:" + e.getMessage());
  }
...