第一個 Message-Driven Bean


Message-Driven Bean(MDB)是EJB當中用以處理JMS的Bean,它是受EJB容器所管理的MessageListener,MDB基本上設計為無狀態(Stateless),並可以使用EJB容器的各種資源,例如交易。

第 一個 Session Bean(單機客戶端) 為例,來為其加入MDB,在EJB伺服端,您可以新增一個MDB如下:
  • HelloMessageBean.java
package onlyfun.caterpillar;

import java.util.logging.Level;
import java.util.logging.Logger;
import javax.ejb.ActivationConfigProperty;
import javax.ejb.MessageDriven;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;

@MessageDriven(mappedName = "jms/HelloQueue",
activationConfig = {
@ActivationConfigProperty(propertyName = "acknowledgeMode",
propertyValue = "Auto-acknowledge"),
@ActivationConfigProperty(propertyName = "destinationType",
propertyValue = "javax.jms.Queue")
})
public class HelloMessageBean implements MessageListener {

public void onMessage(Message message) {
try {
TextMessage txtMessage = (TextMessage) message;
System.out.println(txtMessage.getText() + " processed....Orz");
} catch (JMSException ex) {
Logger.getLogger(HelloMessageBean.class.getName())
.log(Level.SEVERE, null, ex);
}
}
}

MDB為受EJB容器所管理的MessageListener,所以實作了 MessageListener介面,在EJB3中,使用@MessageDriven標示它為MDB,而它的JNDI查找名稱為 "jms/HelloQueue",若您使用NetBeans+Glassfish,將這個MDB部署上去後,會自動在Glassfish的資源當中為您 建立ConnectionFactory,JNDI名稱為"jms/HelloQueueFactory",以及建立Destination,JNDI名 稱為"jms/HelloQueue"。

您可以使用@MessageDriven的屬性messageListenerInterface來指定要實作哪個 MessageListener,如此可不用implements來實作MessageListener介面,實作時有個onMessage方法即可,另一個方式是用部署描述檔來指定實作介面,例如:
....
    <message-driven>

             <ejb-name>HelloMessageBean</ejb-name>
             <ejb-class>onlyfun.caterpillar.HelloMessageBean </ejb-class>
             <messaging-type>javax.jms.MessageListener</messaging-type>
            ....
    </message-driven>
...

要讓其它的元件或Bean取得MDB,首先要讓它們取得ConnectionFactory以及Destination,在DJB3上,這是由容器所管理,您可以將之注入其它元件或Bean中,例如:
  • HelloBeanImpl.java
package onlyfun.caterpillar;

import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.Resource;
import javax.ejb.Stateless;
import javax.jms.*;

@Stateless(name="ejb/HelloFacade",
mappedName="ejb/HelloFacade")
public class HelloBeanImpl implements HelloBean {
@Resource(name="jms/HelloQueueFactory")
private ConnectionFactory connectionFactory;

@Resource(name="jms/HelloQueue")
private Destination queue;

public String doHello(String message) {
String result = null;
try {
result = message + "processed....";

Connection connection = connectionFactory.createConnection();
Session session = connection.createSession(
false, Session.AUTO_ACKNOWLEDGE);
MessageProducer producer = session.createProducer(queue);
TextMessage textMessage = session.createTextMessage();
textMessage.setText(result);
producer.send(textMessage);

producer.close();
session.close();
connection.close();
} catch (JMSException ex) {
Logger.getLogger(
HelloBeanImpl.class.getName()).log(Level.SEVERE, null, ex);
}
return result;
}
}

您使用@Resource標注要注入的資源之JNDI名稱,容器會自動將ConnectionFactory以及Destination注入,接下來就是JMS的處理流程了(參考 簡介 Java Message Service)。

接下來,當您執行 第 一個 Session Bean(單機客戶端) 中的客戶端程式,除了客戶端程式會出現"XD...processed...."的訊息之外,依伺服端的MDB設計,在伺服端的主控台下也會出現"XD processed....Orz"的訊息。