MDB (Message-driven bean:メッセージ駆動型 bean) は、JMS メッセージを使用するためにデザインされる EJB です。これは、直接呼び出すことがないため、リモート、ローカル、リモートホーム、またはローカルホームのインターフェイスがありません。ただし、ejb-jar.xml および jrun-ejb-jar.xml ファイルに MDB を定義する必要があります。また、デプロイメントディスクリプタで指定したキューおよびトピックが存在することを確認する必要もあります。
MDB 実装クラスは、MessageDrivenBean
と MessageListener
の両方を実装します。MessageListener
インターフェイスには、onMessage
というコールバックメソッドが含まれます。これは、メッセージが受信されるとコンテナから呼び出されます。
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-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-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 管理者ガイド』を参照してください。
次のコードは、サンプルの 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()); } ...