メッセージ タイプ

EJB エンジンではポイントツーポイント メッセージング メカニズムと、パブリッシュ/サブスクライブ メッセージング メカニズムの両方がサポートされています。

ポイントツーポイント

ポイントツーポイントは、キューベースのメッセージング メカニズムです。メッセージは特定のキューに送られます。送信者はメッセージをキューに追加し、受信者はキューからメッセージを抽出します。

ポイントツーポイント メッセージング ソリューションを実装する場合は、次のコードを記述します。

キューの定義

local.properties ファイルの次のプロパティを使用してキューを定義します。

jms.queue.queue-name.description=queue description
jms.queue.queue-name.display-name=queue display name

JRun の起動時に、JNDI にキューを保存します。JNDI 検索を使用してキューにアクセスするコードは次のようになります。

_sender =
  _session.createSender((Queue)_context.lookup
    ("java:comp/env/jms/queue-name"));

詳細については、次の説明で送信者および受信者の例を参照してください。

EJB エンジンをスタンドアロン モードで実行している場合は、deploy.properties ファイルにこれらのプロパティを指定します。

送信者のコーディング

送信者により、メッセージがキューに追加される場合、次のオブジェクトが使用されます。

送信者クラスは、javax.jms クラスのいずれからも拡張されません。このクラスでは、明示的にほかのクラスを拡張したり、暗黙的に java.lang.Object を拡張できます。


メモ

次のコードをコンパイルおよび実行する場合は、必ずサーバーの local.properties ファイルでキューをキュー 1 と定義します。既定では、default JRun サーバーには キュー 1 が含まれます。ただし、別のサーバーで実行している場合は、キュー 1 を 定義しなければなりません。


送信者のコードを記述するには

  1. 次のパッケージをインポートします。
    import java.util.*;
    import javax.ejb.*;
    import javax.jms.*;
    import javax.naming.*;
    import java.rmi.*;
    
  2. 次のように、JMS により使用されるオブジェクトのオブジェクトスコープ変数を宣言します。
    private Context _context = null;
    private QueueConnection _connection = null;
    private QueueSession _session = null;
    private TextMessage _message = null; // TextMessage を使用する例
    private QueueSender _sender = null;
    
  3. RMISecurityManager を使用してシステム セキュリティを確立します。
    static {
      System.setSecurityManager(new RMISecurityManager());
    }
    
  4. メッセージを送信する前に、JMS 変数を作成して、値を代入します。
    try {
      // JNDI で設定を行います。
      _context = new InitialContext();
    
      / JNDI から QueueConnectionFactory を取得します。
      final QueueConnectionFactory factory = 
        (QueueConnectionFactory)_context.lookup
          ("java:comp/env/jms/QueueConnectionFactory");
      // ファクトリを使用して、QueueConnection (匿名) を作成します。
      _connection = factory.createQueueConnection();
      // QueueConnection を使用して、QueueSession を作成します。
      _session = _connection.createQueueSession(false,
        Session.AUTO_ACKNOWLEDGE);
      // QueueSession を使用して QueueSender を作成します。
      // この例では、local.properties で指定されたキュー 1 を探します。
      // via jms.queue.queue1.description/display-name
      _sender = _session.createSender((Queue)_context.lookup
        ("java:comp/env/jms/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());
    }
    
  5. メッセージを送信します。このサーブレット例では、フォーム フィールドからメッセージが取得されています。
    ...
    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 {
      _message.setText(text);
      // キューに送信します。メッセージは 5 分間存続します。
      _sender.send(_message, delivery, priority, 5 * 60 * 1000); 
    }
    catch(JMSException e) {
      System.out.println("JMS Exception:" + e.getMessage());
    }
    ...
    
  6. 完了したら、JMS オブジェクトを閉じます。
    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());
    }
    

次のサーブレット例には、ポイントツーポイント メッセージを送信するためのコード全体が含まれています。

import java.io.*; 
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.*;
import javax.ejb.*;
import javax.jms.*;
import javax.naming.*;
import java.rmi.*;

public class MySender extends HttpServlet {
  // キュー属性を設定します。
  // init パラメータを介して渡されない限り、既定値を使用します。
  private final String _mode = new String("manual");   
  private final String _name = new String("defaultUser");   
  // Matches jms.queue.queue1.* properties in local.properties
  private final String _queue = new String("queue1");
  private final String _host = new String("rnielsen");

  // JMS で使用するオブジェクトを設定します。
  private Context _context = null;
  private QueueConnection _connection = null;
  private QueueSession _session = null;
  private TextMessage _message = null;
  private QueueSender _sender = null;

  static {
    System.setSecurityManager(new RMISecurityManager());
  }

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

  // JNDI で設定を行います。
  try {
    _context = new InitialContext();

    // JNDI から QueueConnectionFactory を取得します。
    final QueueConnectionFactory factory = 
      (QueueConnectionFactory)_context.lookup
        ("java:comp/env/jms/QueueConnectionFactory");
    // ファクトリを使用して QueueConnection (匿名) を作成します。
    _connection = factory.createQueueConnection();
    // QueueConnection を使用して QueueSession を作成します。
    _session = _connection.createQueueSession(false,
      Session.AUTO_ACKNOWLEDGE);
    // QueueSession を使用して QueueSender を作成します。
    // local.properties で指定されたキューを参照します。
    // via jms.queue.queue1.description/display-name
    _sender = _session.createSender((Queue)_context.lookup
      ("java:comp/env/jms/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());
  }
}

// 送信するメッセージを受け取るフォームを表示します。
public void doGet(HttpServletRequest req, 
  HttpServletResponse res) throws IOException, ServletException { 
  res.setContentType("text/html");
  PrintWriter out = res.getWriter();

  out.println
    ("<html><head><title>Message Sender</title></head><body>");
  out.println("<h1>Message Sender</h1>");
  out.println("<p>Type your message and press Submit</p><hr>");
  out.println("<form action=¥"/servlet/MySender\" method=\"post\">");

  // メッセージを含んでいる Textarea
  out.println("<p>Message:<p>");
  out.println("<TextArea name=\"thisMessage\"></textarea>");
  out.println("<p>");
  out.println("<input type=\"Submit\" value=\"Submit Message\">"); 
  out.println("</form>");
  out.println("</body></html>");
} 

// フォームを読み込んで、メッセージを送信します。
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 {
    _message.setText(text);
    // キューに送信します。メッセージは 5 分間存続します。
    _sender.send(_message, delivery, priority, 5 * 60 * 1000);
  }
  catch(JMSException e) {
    System.out.println("JMS Exception:" + e.getMessage());
  }

  // 送信確認を表示します。
  out.println("<html><head><title>Message Sent</title></head><body>");
  out.println("<h1>Message Sent</h1>");
  out.println("<p>The following message was sent</p><hr>");
  out.println("<p>" + text);
  out.println("<form action=\"/servlet/MySender\" method=\"get\">");
  out.println("<p>");
  out.println("<input type=\"Submit\" value=\"Return\">"); 
  out.println("</form>");
  out.println("</body></html>");
}

public String getServletInfo() {
  return "Message Sender";
}

public void destroy() {
  // ヌル メッセージ チェックでない場合はラップします。
  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());
  }
} // メソッドを終了します。
} // サーブレットを終了します。

受信者のコーディング

受信者により、メッセージがキューから取得される場合、次のオブジェクトが使用されます。

受信者で非同期メッセージを使用する場合は、MessageListener インターフェイスを実装しなければなりません (この例では非同期メッセージは使用しません)。受信者クラスは、javax.jms クラスのいずれからも拡張されませんが、このクラスは明示的にほかのクラスを拡張したり、暗黙的に java.lang.Object を拡張できます。

受信者のコードを記述するには

  1. 次のパッケージをインポートします。
    import java.util.*;
    import javax.ejb.*;
    import javax.jms.*;
    import javax.naming.*;
    import java.rmi.*;
    
  2. 次のように、JMS により使用されるオブジェクトのオブジェクトスコープ変数を宣言します。
    private Context _context = null;
    private QueueConnection _connection = null;
    private QueueSession _session = null;
    private TextMessage _message = null; // TextMessage を使用する例
    private QueueReceiver _receiver = null;
    
  3. RMISecurityManager を使用してシステム セキュリティを確立します。
    static {
      System.setSecurityManager(new RMISecurityManager());
    }
    
  4. メッセージを受信する前に、JMS 変数を作成して、値を代入します。
    try {
      _context = new InitialContext();
    
      // JNDI から QueueConnectionFactory を取得します。
      final QueueConnectionFactory factory = 
        (QueueConnectionFactory)_context.lookup
          ("java:comp/env/jms/QueueConnectionFactory");
      // ファクトリを使用して QueueConnection を作成します。
      _connection = factory.createQueueConnection();
      // QueueConnection を使用して QueueSession を作成します。
      _session = _connection.createQueueSession(false,
        Session.AUTO_ACKNOWLEDGE);
      // QueueSession を使用して QueueReceiver を作成します。
      // local.properties で指定されたキュー1 を参照します。
      // via jms.queue.queue1.description/display-name
      _receiver =
        _session.createReceiver((Queue)_context.lookup
          ("java:comp/env/jms/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());
    }
    
  5. キューからメッセージを取得します。
    ...
    // キューからメッセージを取得します。
    try {
      // 接続を開始します。
      _connection.start();
      // メッセージ オブジェクトを取得します。
      final TextMessage message =
        (TextMessage)(_receiver.receiveNoWait());
      // メッセージ テキストを取得します。
      // ヌル メッセージをチェックします。
      String text = "";
      if (message != null) {
        text = new String(message.getText());
      }
      else {
        text = "No Message";
      }
      if(text.equals("")) {
        text = "Empty Message";
      }
      out.println(text);
      _connection.stop();
      out.println("</body></html>");
    }
    catch(JMSException e) {
      System.out.println("JMS Exception:" + e.getMessage());
    }
    ...
    
  6. 完了したら、JMS オブジェクトを閉じます。
    try {
      _receiver.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());
    }
    

次のサーブレット例には、ポイントツーポイント メッセージを受信するためのコード全体が含まれています。

import java.io.*; 
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.*;
import javax.ejb.*;
import javax.jms.*;
import javax.naming.*;
import java.rmi.*;

public class MyReceiver extends HttpServlet {
  // キュー属性を設定します。
  // init パラメータを介して渡されない限り、既定値を使用します。
  private final String _mode = new String("manual");   
  private final String _name = new String("defaultUser");   
  // Matches jms.queue.queue1.* properties in local.properties
  private final String _queue = new String("queue1");
  private final String _host = new String("rnielsen");

  // JMS で使用するオブジェクトを設定します。
  private Context _context = null;
  private QueueConnection _connection = null;
  private QueueSession _session = null;
  private TextMessage _message = null;
  private QueueReceiver _receiver = null;

  static {
    System.setSecurityManager(new RMISecurityManager());
  }

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

  // JNDI で設定を行います。
  try {
    _context = new InitialContext();

    // JNDI から QueueConnectionFactory を取得します。
    final QueueConnectionFactory factory = 
      (QueueConnectionFactory)_context.lookup
        ("java:comp/env/jms/QueueConnectionFactory");
    // ファクトリを使用して QueueConnection を作成します。
    _connection = factory.createQueueConnection();
    // QueueConnection を使用して QueueSession を作成します。
    _session = _connection.createQueueSession(false,
      Session.AUTO_ACKNOWLEDGE);
    // QueueSession を使用して QueueReceiver を作成します。
    // local.properties で指定されたキュー1 を参照します。
    // via jms.queue.queue1.description/display-name
    _receiver =
      _session.createReceiver((Queue)_context.lookup
        ("java:comp/env/jms/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());
  }
}

// 初めて実行したときだけ [メッセージの受信] ボタンを表示します。
// メッセージを受信するフォームを表示します。
public void doGet(HttpServletRequest req, 
  HttpServletResponse res) throws IOException, ServletException { 

  res.setContentType("text/html");
  PrintWriter out = res.getWriter();

  out.println
    ("<html><head><title>Message Receiver</title></head><body>");
  out.println("<h1>Message Receiver</h1>");
  out.println
    ("<p>Press Receive Message to retrieve a message:<p><hr>");
  out.println("<form action=\"/servlet/MyReceiver\" method=\"post\">");
  out.println("<p>");
  out.println("<input type=\"Submit\" value=\"Receive Message\">"); 
  out.println("</form>");
  out.println("</body></html>");
}

public void doPost(HttpServletRequest req, 
  HttpServletResponse res) throws IOException, ServletException { 

  res.setContentType("text/html");
  PrintWriter out = res.getWriter();

  out.println
    ("<html><head><title>Message Receiver</title></head><body>");
  out.println("<h1>Message Receiver</h1>");
  out.println
    ("<p>Press Receive Message to retrieve another message:</p><hr>");
  out.println("<form action=\"/servlet/MyReceiver\" method=\"post\">");
  // キューからメッセージを取得します。
  try {
    // 接続を開始します。
    _connection.start();
    // メッセージ オブジェクトを取得します。
    final TextMessage message =
      (TextMessage)(_receiver.receiveNoWait());
    // メッセージ テキストを取得します。
    // ヌル メッセージをチェックします。
    String text = "";
    if (message != null) {
      text = new String(message.getText());
    }
    else {
      text = "No Message";
    }
    if(text.equals("")) {
      text = "Empty Message";
    }
    out.println(text);
    _connection.stop();
    out.println("</body></html>");
  }
  catch(JMSException e) {
    System.out.println("JMS Exception:" + e.getMessage());
  }

  // form/html を完成させます。
  out.println("<p>");
  out.println("<input type=\"Submit\" value=\"Receive Message\">"); 
  out.println("</form>");
  out.println("</body></html>");
}

public String getServletInfo() {
  return "Message Receiver";
}

public void destroy() {
  // ヌル メッセージ チェックでない場合はラップします。
  try {
    _receiver.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());
  }
} // メソッドを終了します。
} // サーブレットを終了します。

パブリッシュ/サブスクライブ

パブリッシュ/サブスクライブはブロードキャスト メカニズムの 1 つです。パブリッシュ/サブスクライブではメッセージはトピックに発行され、自動的にトピックのサブスクライバに配布されます。トピックを階層的にしておくと、最上位レベルのサブスクライバはメッセージをすべて受信しますが、サブトピックのサブスクライバはサブトピック メッセージだけを受信します。

トピックの定義

local.properties ファイルの次のプロパティを使用してトピックを定義します。

jms.topic.topic-name.description=topic description
jms.topic.topic-name.display-name=topic display name

JRun の起動時に、JNDI にトピックを保存します。JNDI 検索を使用してトピックにアクセスするコードは次のようになります。

_publisher =
  _session.createPublisher((Topic)_context.lookup
    ("java:comp/env/jms/topic-name");

詳細については、次の説明でパブリッシャおよびサブスクライバの例を参照してください。

EJB エンジンをスタンドアロン モードで実行している場合は、deploy.properties ファイルにこれらのプロパティを指定します。

パブリッシャのコーディング

パブリッシャにより、メッセージがトピックに追加される場合は、次のオブジェクトが使用されます。

パブリッシャ クラスは、javax.jms クラスのいずれからも拡張されません。このクラスでは、明示的にほかのクラスを拡張したり、暗黙的に java.lang.Object を拡張できます。


メモ

次のコードをコンパイルおよび実行する場合は、JRun サーバーの local.properties ファイルでトピックをトピック 1 と定義することを確認します。


パブリッシャのコードを記述するには

  1. 次のパッケージをインポートします。
    import java.util.*;
    import javax.ejb.*;
    import javax.jms.*;
    import javax.naming.*;
    import java.rmi.*;
    
  2. 次のように、JMS により使用されるオブジェクトのオブジェクトスコープ変数を宣言します。
    private Context _context = null;
    private TopicConnection _connection = null;
    private TopicSession _session = null;
    private TextMessage _message = null;
    private TopicPublisher _publisher = null;
    
  3. RMISecurityManager を使用してシステム セキュリティを確立します。
    static {
      System.setSecurityManager(new RMISecurityManager());
    }
    
  4. メッセージを送信する前に、JMS 変数を作成して、値を代入します。
    try {
      _context = new InitialContext();
    
      final TopicConnectionFactory factory = 
        (TopicConnectionFactory)_context.lookup
          ("java:comp/env/jms/TopicConnectionFactory");
      // ファクトリを使用して TopicConnection を作成します。
      _connection = factory.createTopicConnection();
      // TopicConnection を使用して TopicSession を作成します。
      _session = _connection.createTopicSession(false,
        Session.AUTO_ACKNOWLEDGE);
      // TopicSession を使用して TopicPublisher を作成します。
      _publisher =
        _session.createPublisher((Topic)_context.lookup
          ("java:comp/env/jms/" + _topic)); 
      // TextMessage オブジェクトを作成します。
      _message = _session.createTextMessage();
    }
    catch(NamingException e) {
      System.out.println("Naming Exception:" + e.getMessage());
    }
    catch(JMSException e) {
      System.out.println("JMS Exception:" + e.getMessage());
    }
    
  5. メッセージを発行します。このサーブレット例では、フォーム フィールドからメッセージが取得されています。
    ...
    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 {
      _message.setText(text);
      // トピックを発行します。メッセージは 5 分間存続します。
      _publisher.publish(_message, delivery, priority, 5 * 60 * 1000);
    }
    catch(JMSException e) {
      System.out.println("JMS Exception:" + e.getMessage());
    }
    ...
    
  6. 完了したら、JMS オブジェクトを閉じます。
    try {
      _publisher.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());
    }
    

次のサーブレット例には、トピックを発行するために必要なコードがすべて含まれています。

import java.io.*; 
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.*;
import javax.ejb.*;
import javax.jms.*;
import javax.naming.*;
import java.rmi.*;

public class MyPublisher extends HttpServlet {
  // キュー属性を設定します。
  private String _topic = new String("topic1");
  private String _host = new String("rnielsen");

  // JMS で使用するオブジェクトを設定します。
  private Context _context = null;
  private TopicConnection _connection = null;
  private TopicSession _session = null;
  private TextMessage _message = null;
  private TopicPublisher _publisher = null;

  static {
    System.setSecurityManager(new RMISecurityManager());
  }

public void init(ServletConfig config) throws ServletException {
  super.init(config);
  // JNDI で設定を行います。
  try {
    _context = new InitialContext();

    final TopicConnectionFactory factory = 
      (TopicConnectionFactory)_context.lookup
        ("java:comp/env/jms/TopicConnectionFactory");
    // ファクトリを使用して TopicConnection を作成します。
    _connection = factory.createTopicConnection();
    // TopicConnection を使用して TopicSession を作成します。
    _session = _connection.createTopicSession(false,
      Session.AUTO_ACKNOWLEDGE);
    // TopicSession を使用して TopicPublisher を作成します。
    _publisher =
      _session.createPublisher((Topic)_context.lookup
        ("java:comp/env/jms/" + _topic)); 
    // TextMessage オブジェクトを作成します。
    _message = _session.createTextMessage();
  }
  catch(NamingException e) {
    System.out.println("Naming Exception:" + e.getMessage());
  }
  catch(JMSException e) {
    System.out.println("JMS Exception:" + e.getMessage());
  }
} // init を終了します。

// 発行するメッセージを受け取るフォームを表示します。
public void doGet(HttpServletRequest req, 
  HttpServletResponse res) throws IOException, ServletException { 

  res.setContentType("text/html");
  PrintWriter out = res.getWriter();

  out.println
    ("<html><head><title>Message Publisherr</title></head><body>");
  out.println("<h1>Message Publisher</h1>");
  out.println("<p>Type your message and press Submit</p><hr>");
  out.println
    ("<form action=\"/servlet/MyPublisher\" method=\"post\">");

  // メッセージを含んでいる Textarea
  out.println("<p>Message:<p>");
  out.println("<TextArea name=\"thisMessage\"></textarea>");
  out.println("<p>");
  out.println("<input type=\"Submit\" value=\"Submit Message\">"); 
  out.println("</form>");
  out.println("</body></html>");
} // doGet を終了します。

// フォームを読み込んで、メッセージを送信します。
public void doPost(HttpServletRequest req, 
  HttpServletResponse res) throws IOException, ServletException { 
  // フォームを読み込みます。
  // メッセージはすべて、ここで送信されます。
  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 {
    _message.setText(text);
    // トピックを発行します。メッセージは 5 分間存続します。
    _publisher.publish(_message, delivery, priority, 5 * 60 * 1000);
  }
  catch(JMSException e) {
    System.out.println("JMS Exception:" + e.getMessage());
  }

  // 送信確認を表示します。
  out.println
    ("<html><head><title>Message Published</title></head><body>");
  out.println("<h1>Message Published</h1>");
  out.println("<p>The following message was sent</p><hr>");
  out.println("<p>" + text);
  out.println("<form action=\"/servlet/MyPublisher\" method=\"get\">");

  out.println("<p>");
  out.println("<input type=\"Submit\" value=\"Return\">"); 
  out.println("</form>");
  out.println("</body></html>");

} // doPost を終了します。

public String getServletInfo() {
  return "Message Publisher";
}

public void destroy() {
  // ヌル メッセージ チェックでない場合はラップします。
  try {
    _publisher.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());
  }
} // destroy を終了します。
} // サーブレットを終了します。

サブスクライバのコーディング

JMS により、関連するトピックに対してトピックが発行されたときに、これがサブスクライバに渡されます。次のオブジェクトを使用して、サブスクライバのコードを記述します。

サブスクライバ クラスには、MessageListener インターフェイスと onMessage メソッドを実装する必要があります。登録されたサブスクライバ クラスへのトピックに対してメッセージが発行されたときに、JRun により、onMessage メソッドが呼び出されます。

サブスクライバ クラスは、javax.jms クラスのいずれからも拡張されません。このクラスでは、明示的にほかのクラスを拡張したり、暗黙的に java.lang.Object を拡張できます。


メモ

次のコード例にあるサブスクライバ アーキテクチャでは、スタンドアロン メッセージ リスナ クラスを使用して、メッセージが捕捉され、保存されます。その後、このクラス は所有者クラス (この場合はサーブレット) によってインスタンス化されます。この クラスにより、必要に応じてメッセージへのアクセスが行われます。


サブスクライバ (リスナ) のコードを記述するには

  1. 次のパッケージをインポートします。
    import java.util.*;
    import javax.ejb.*;
    import javax.jms.*;
    import javax.naming.*;
    import java.rmi.*;
    
  2. MessageListener インターフェイスを実装するクラス宣言を作成します。
    public class MyTopicListener implements MessageListener {
    ...
    
  3. 次のように、JMS により使用されるオブジェクトのオブジェクトスコープ変数を宣言します。
    private Context _context = null;
    private TopicConnection _connection = null;
    private TopicSession _session = null;
    private TopicSubscriber _subscriber = null;
    
  4. メッセージを保管するためのオブジェクトを作成します。この例では、Vector を使用しています。
    // これは単なる例です。リスナは、さまざまなテクニックを使用して
    // メッセージを管理することができます。
    Vector theMessages = new Vector();
    
  5. RMISecurityManager を使用してシステム セキュリティを確立します。
    static {
      System.setSecurityManager(new RMISecurityManager());
    }
    
  6. メッセージを受信する前に、JMS 変数を作成して、値を代入します。
    try {
      _context = new InitialContext();
    
      final TopicConnectionFactory factory = 
        (TopicConnectionFactory)_context.lookup
          ("java:comp/env/jms/TopicConnectionFactory");
      // ファクトリを使用して TopicConnection を作成します。
      _connection = factory.createTopicConnection();
      // TopicConnection を使用して TopicSession を作成します。
      _session = _connection.createTopicSession(false,
        Session.AUTO_ACKNOWLEDGE);
      // TopicSession を使用して TopicSubscriber を作成します。
      // トピック 1 を使用して、local.properties で次のようなコードによって
    定義されます。
      // jms.topic.topic1.description=Topic for Doc Sample
      // jms.topic.topic1.display-name=DocSampleTopic
      _subscriber =
        _session.createSubscriber((Topic)_context.lookup
          ("java:comp/env/jms/" + _topic));
      // messageListener を設定します。
      _subscriber.setMessageListener(this);
      _connection.start();
    }
    catch(NamingException e) {
      System.out.println("Naming Exception:" + e.getMessage());
    }
    catch(JMSException e) {
      System.out.println("JMS Exception:" + e.getMessage());
    }
    
  7. onMessage メソッド、および関連するメッセージ管理メソッドのコードを記述します。
    ...
    
public void setMessage(String thisMessage) {
  // メッセージを theMessages Vector に追加します。
  theMessages.add(thisMessage);
}

public Enumeration getMessages() {
  // VectorをEnumeration に変換します。
  Enumeration returnThis = theMessages.elements();
  // Enumeration を返します。
  return returnThis;
}

public void onMessage(final Message message) { 
  String text = null; 
  try { 
    text = ((TextMessage)message).getText(); 
    setMessage(text); 
  } 
  catch(JMSException e) { 
    System.out.println("JMSException:" + e.getMessage()); 
  } 
} 
...
  • 完了したら、JMS オブジェクトを閉じます。
    // この例では、メソッドを呼び出して、オブジェクトを閉じます。
    // これにより、外部クラスで、メッセージ リスナを管理できるようになります。
    public void cleanUp() {
      try {
        _connection.stop();
        _subscriber.setMessageListener(null);
        _subscriber.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());
      }
    }
    
  • 次の例は、メッセージ リスナ クラスと onMessage メソッドを通じてトピックを取得するために必要なコードのすべてです。

    import java.util.*;
    
    import javax.ejb.*;
    import javax.jms.*;
    import javax.naming.*;
    import java.rmi.*;
    
    public class MyTopicListener implements MessageListener {
      // トピック属性を設定します。
      // init パラメータを介して渡されない限り、既定値を使用します。
      private String _topic;
      private String _host;
    
      // メッセージを保持するための変数を設定します。
      Vector theMessages = new Vector();
    
      // JMS で使用するオブジェクトを設定します。
      private Context _context = null;
      private TopicConnection _connection = null;
      private TopicSession _session = null;
      private TopicSubscriber _subscriber = null;
    
    
      static {
        System.setSecurityManager(new RMISecurityManager());
      }
    
    // 複数の引数を受け入れるコンストラクタ
    public MyTopicListener(String topic, String host) {
      // わかりやすくするために、パラメータ エラーのチェックを省略します。
      _topic = topic;
      _host = host;
      // JNDI で設定を行います。
      try {
        _context = new InitialContext();
    
        final TopicConnectionFactory factory = 
          (TopicConnectionFactory)_context.lookup
            ("java:comp/env/jms/TopicConnectionFactory");
        // ファクトリを使用して TopicConnection を作成します。
        _connection = factory.createTopicConnection();
        // TopicConnection を使用して TopicSession を作成します。
        _session = _connection.createTopicSession(false,
          Session.AUTO_ACKNOWLEDGE);
        // TopicSession を使用して TopicSubscriber を作成します。
        // トピック 1 を使用して、local.properties で次のようなコードによって
    定義されます。
        // jms.topic.topic1.description=Topic for Doc Sample
        // jms.topic.topic1.display-name=DocSampleTopic
        _subscriber =
          _session.createSubscriber((Topic)_context.lookup
            ("java:comp/env/jms/" + _topic));
        // messageListener を設定します。
        _subscriber.setMessageListener(this);
        _connection.start();
      }
      catch(NamingException e) {
        System.out.println("Naming Exception:" + e.getMessage());
    }
      catch(JMSException e) {
        System.out.println("JMS Exception:" + e.getMessage());
      }
    } // メソッドを終了します。
    
    // 既定のコンストラクタ
    public MyTopicListener() {
      // 既定のコンストラクタで使用するトピック 1 は、前述のように
      // local.properties で定義しなければなりません。
      this("topic1", "rnielsen");
    }
    
    public void setMessage(String thisMessage) {
      // メッセージを theMessages Vector に追加します。
      theMessages.add(thisMessage);
    }
    
    public Enumeration getMessages() {
      // VectorをEnumeration に変換します。
      Enumeration returnThis = theMessages.elements();
      // Enumeration を返します。
      return returnThis;
    }
    
    public void onMessage(final Message message) {
      String text = null;
      try {
        text = ((TextMessage)message).getText();
        setMessage(text);
      }
      catch(JMSException e) {
        System.out.println("JMSException:" + e.getMessage());
      }
    } // メソッドを終了します。
    
    public void cleanUp() {
      try {
        _connection.stop();
        _subscriber.setMessageListener(null);
        _subscriber.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());
      }
    } // メソッドを終了します。
    } // クラスを終了します。
    

    次のサーブレット例では、メッセージ リスナ クラスを使用して、パブリッシュ/サブスクライブ トピックからメッセージにアクセスしています。

    import java.io.*; 
    
    import javax.servlet.*;
    import javax.servlet.http.*;
    import java.util.*;
    
    public class MySubscriber extends HttpServlet {
    
      // このサーブレットは、メッセージ リスナと通信します。
      // このコンストラクタは既定のトピックを受信します。
      // トピックやホストに渡すこともできます。
      MyTopicListener thisTopicListener = new MyTopicListener(); 
    
      // 初回のみ
      // メッセージを受信するフォームを表示します。
    
    public void doGet(HttpServletRequest req, HttpServletResponse resp)
      throws IOException, ServletException { 
    
      resp.setContentType("text/html");
      PrintWriter out = resp.getWriter();
    
      out.println("<html><head><title>Message Subscriber</title>");
      out.println("</head><body>");
      out.println("<h1>Message Subscriber</h1>");
      out.println("<p>Press Get Latest Topics to retrieve messages:");
      out.println("</p><hr>");
      out.println("<form action=\"/servlet/MySubscriber\" 
    method=\"post\">");
      out.println("<p>");
      out.println("<input type=\"Submit\" value=\"Get Latest Topics\">"); 
      out.println("</form>");
      out.println("</body></html>");
    }
    
    // これは、初回を除き、すべて実行されます。
    public void doPost(HttpServletRequest req, HttpServletResponse resp)
      throws IOException, ServletException { 
      resp.setContentType("text/html");
      PrintWriter out = resp.getWriter();
    
      out.println("<html><head><title>Message Subscriber</title>");
      out.println("</head><body>");
      out.println("<h1>Message Subscriber</h1>");
      // トピックからメッセージを取得します。
      out.println("<p>");
      Enumeration enum = thisTopicListener.getMessages(); 
      if(!enum.hasMoreElements()) { 
        out.println("No messages to retrieve"); 
      } 
      while (enum.hasMoreElements()) { 
        String name = (String)enum.nextElement(); 
        out.println("<hr>" + name); 
      } 
      out.println("<p>Press Get Latest Topics to retrieve messages:<hr>");
      out.println("<form action=\"/servlet/MySubscriber\" 
    method=\"post\">");
    
      // form/html を完成させます。
      out.println("<p>");
      out.println("<input type=\"Submit\" value=\"Get Latest Topics\">"); 
      out.println("</form>");
      out.println("</body></html>");
    }
    
    public String getServletInfo() {
      return "Message Subscriber";
    }
    
    public void destroy() { 
      // myTopicListener の内容をクリーンアップします。 
      thisTopicListener.cleanUp(); 
      // myTopicListener にヌル値を設定します。 
      thisTopicListener = null; 
    } 
    }