譯者前言
有關本章中相應源代碼的下載,請參看一個Session Bean的示例。
正文
因為message-driven bean是基於Java消息服務(JMS)技術的,要理解以下示例,你必須已經熟悉基本的JMS概念,例如隊列和消息。學習有關這些概念的最好的地方是Java消息服務指南:
http://java.sun.com/prodUCts/jms/tutorial/index.Html
這一章講述了一個message-driven bean示例的源代碼。在開始學習前,你必須首先閱讀Message-Driven Bean是什麼中的基本概念。
示例應用程序概覽
這個應用程序包括下列組件:
1、SimpleMessageClient:一個發送幾個消息到一個隊列中的J2EE應用程序客戶端。
2、SimpleMessageEJB:一個異步接收和處理發送到隊列中的消息的message-driven bean。
圖7-1說明了這個應用程序的結構。應用程序客戶端發送消息到隊列中,這個隊列是用j2eeadmin命令創建的。JMS供應者(在這裡也就是J2EE服務器)將消息遞交給一個message-driven bean的實例,這個實例將處理這個消息。
圖7-1 SimpleMessageApp應用程序
在j2eetutorial/examples/src/ejb/simplemessage目錄下有這個應用程序的源代碼。要編譯這個代碼,到j2eetutorial/examples目錄下。輸入ant simplemessage。在j2eetutorial/examples/ears目錄下有SimpleMessageApp.ear文件的示例。
J2EE應用程序客戶端
SimpleMessageClient發送消息到隊列中,SimpleMessageBean將對這個隊列進行監聽。客戶端首先將定位連接factory和隊列:
queueConnectionFactory = (QueueConnectionFactory)
jndiContext.lookup
("java:comp/env/jms/MyQueueConnectionFactory");
queue = (Queue)
jndiContext.lookup("java:comp/env/jms/QueueName");
然後,客戶端創建隊列連接、會話和發送端:
queueConnection =
queueConnectionFactory.createQueueConnection();
queueSession =
queueConnection.createQueueSession(false,
Session.AUTO_ACKNOWLEDGE);
queueSender = queueSession.createSender(queue);
最後,客戶端向隊列中發送幾條消息:
message = queueSession.createTextMessage();
for (int i = 0; i < NUM_MSGS; i++) {
message.setText("This is message " + (i + 1));
System.out.println("Sending message: " +
message.getText());
queueSender.send(message);
}
Message-Driven Bean類
SimpleMessageEJB類的代碼闡明了一個message-driven bean類所需滿足的基本條件:
1、它實現了MessageDrivenBean接口和MessageListener接口。
2、類被定義為public。
3、類不能定義為abstract或final。
4、它實現了一個onMessage方法。
5、它實現了一個ejbCreate方法和一個ejbRemove方法。
6、它包含了一個公用的無參數的構造函數。
7、它不能定義finalize方法。
與session bean或entity bean不同,message-driven bean不具有定義客戶端訪問的remote接口或local接口。客戶端組件不能定位message-driven bean並調用其中的方法。盡管message-driven bean不包含商業方法,但是它可能包含由onMessage方法調用的輔助方法。
onMessage方法
當隊列接受到一個消息時,EJB容器調用message-driven bean中的onMessage方法。在SimpleMessageBean類中,onMessage方法將消息引入TextMessage並顯示其內容:
public void onMessage(Message inMessage) {
TextMessage msg = null;
try {
if (inMessage instanceof TextMessage) {
msg = (TextMessage) inMessage;
System.out.println
("MESSAGE BEAN: Message received: "
+ msg.getText());
} else {
System.out.println
("Message of wrong type: "
+ inMessage.getClass().getName());
}
} catch (JMSException e) {
e.printStackTrace();
mdc.setRollbackOnly();
} catch (Throwable te) {
te.printStackTrace();
}
}
ejbCreate方法和ejbRemove方法
這些方法必須滿足以下條件:
1、訪問控制修飾必須是public。
2、返回類型必須是void。
3、修飾不能是static或final。
4、throws子句不能定義任何應用程序例外。
5、這個方法沒有參數。
在SimpleMessageBean類中,ejbCreate方法和ejbRemove方法為空。
運行SimpleMessageEJB示例
啟動J2EE服務
要顯示message-driven bean的輸出,你必須使用verbose模式啟動服務:
j2ee -verbose
創建隊列
1、使用j2eeadmin命令創建隊列:
j2eeadmin -addJmsDestination jms/MyQueue queue
2、檢查隊列是否已被建立:
j2eeadmin -listJmsDestination
部署應用程序
1、在deploytool中打開j2eetutorial/examples/ears/SimpleMessageApp.ear文件(FileOpen)。
2、部署SimpleMessageApp應用程序(ToolsDeploy)。在Introduction對話框中,檢查是否選中Return Client JAR檢驗欄。詳細信息請參看部署J2EE應用程序.
運行客戶端
1、在一個終端窗口時,到j2eetutorial/examples/ears目錄下。
2、設置APPCPATH環境變量為SimpleMessageAppClient.jar。
3、在一行中輸入以下命令:
runclient -client SimpleMessageApp.ear -name
SimpleMessageClient -textauth
4、在提示登錄時,輸入j2ee作為用戶名和口令。
5、客戶端會顯示以下內容:
Sending message: This is message 1
Sending message: This is message 2
Sending message: This is message 3
6、在你啟動J2EE服務(用verbose模式)的終端窗口下,會顯示以下內容:
MESSAGE BEAN: Message received: This is message 1
MESSAGE BEAN: Message received: This is message 2
MESSAGE BEAN: Message received: This is message 3
Message-Driven Bean的Deploytool提示
第二章概括了創建和封裝enterprise bean的基本步驟。這一章我們將介紹對於message-driven bean在deploytool中必須執行的任務。要在deploytool中顯示這個示例,打開j2eetutorial/examples/ears/SimpleMessageApp.ear文件並選中SimpleMessageEJB。
指定Bean的類型和事務管理
你可經在使用New Enterprise Bean向導創建bean時指定其類型。
1、要啟動這個向導,選擇FileNewEnterprise Bean。
2、在向導的General對話框中,選擇Message-Driven按鈕。
3、在Transaction Management對話框中,你可以選擇Bean-Managed,也可以選擇Container-Managed。如果你選擇的是Bean-Managed,那麼在下面一段的第4步中,你必須選擇確認類型。
設定Message-Driven Bean的特征
你可以在兩個地方作這個設定:
1、在New Enterprise Bean向導中的Message-Driven Bean Settings對話框
2、bean的Message標簽(參見圖7-2)
這些設定包括以下內容:
1、對於Destination類型,可以選擇Queue也可以選擇Topic。一個隊列使用點對點的消息域,至多只能有一個使用者。而一個主題使用發布-訂閱的消息域,它可以有零個、一個或多個使用者。
2、在Destination組合框中,選擇你創建的目的地的JNDI命名。作為一個示例,你可以參看創建隊列。目的地可以是一個Queue對象,也可以是一個Topic對象;它是引入消息的發起者和發出消息的目標。
3、在Connection Factory組合框中,選擇適當的對象,這可以是一個QueueConnectionFactory,也可以是一個TopicConnectionFactory。這個對象出示了J2EE組件訪問消息服務的連接。
4、如果你選擇了bean管理事務,那麼你可能需要在Acknowledgement組合框中選擇確認類型--這可能是Auto-Acknowledge(自動確認)或Duplicates-OK(OK重復)。Auto-Acknowledge類型要求會話自動確認bean在使用這個消息。而Duplicates-OK類型對消息提交的確認會遲鈍一些;這個類型可能會導致一個消息的復制,但是它會減少會話的開銷。
5、在JMS Message Selector區域,你可以輸入一個過濾bean接收到的消息的語句。
圖7-2 SimpleMessageEJB的Message標簽
JMS客戶端的deploytool提示
有關JMS客戶端的更多的信息,請參看Java消息服務指南:
http://java.sun.com/products/jms/tutorial/index.html
設定資源索引
1、選中客戶端的節點。
2、選中Resource Refs標簽。
3、單擊Add。
4、在Coded Name中,輸入與客戶端的代碼中的lookup方法的參數相匹配的命名。例如,如果lookup方法的參數是java:comp/env/jms/MyQueueConnectionFactory,Coded Name就應該是jms/QueueConnectionFactory。
5、在Type中,選擇與目的類型相匹配的連接factory類。
6、在Authentication中,絕大多數情況下你的選擇應該是Container。如果你的代碼明確地登錄到消息服務器,這裡你可以選擇Application。
7、在Sharable中,確保檢驗欄被選中。這個選擇使得容
4、如果你選擇了bean管理事務,那麼你可能需要在Acknowledgement組合框中選擇確認類型--這可能是Auto-Acknowledge(自動確認)或Duplicates-OK(OK重復)。Auto-Acknowledge類型要求會話自動確認bean在使用這個消息。而Duplicates-OK類型對消息提交的確認會遲鈍一些;這個類型可能會導致一個消息的復制,但是它會減少會話的開銷。
5、在JMS Message Selector區域,你可以輸入一個過濾bean接收到的消息的語句。
圖7-2 SimpleMessageEJB的Message標簽
JMS客戶端的deploytool提示
有關JMS客戶端的更多的信息,請參看Java消息服務指南:
http://java.sun.com/products/jms/tutorial/index.html
設定資源索引
1、選中客戶端的節點。
2、選中Resource Refs標簽。
3、單擊Add。
4、在Coded Name中,輸入與客戶端的代碼中的lookup方法的參數相匹配的命名。例如,如果lookup方法的參數是java:comp/env/jms/MyQueueConnectionFactory,Coded Name就應該是jms/QueueConnectionFactory。
5、在Type中,選擇與目的類型相匹配的連接factory類。
6、在Authentication中,絕大多數情況下你的選擇應該是Container。如果你的代碼明確地登錄到消息服務器,這裡你可以選擇Application。
7、在Sharable中,確保檢驗欄被選中。這個選擇使得容