程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> 使您的應用程序調用我的應用程序,第1部分(下)

使您的應用程序調用我的應用程序,第1部分(下)

編輯:關於JAVA

Apache Geronimo 通信基礎 —— 開發、部署和測試(下)

消息驅動 bean()

既然您已經實現了 PurchaseOrderEJB,接下來就可以實現 PurchaseOrderMDB 了。與 EJB 不同,MDB 是 JMS 偵聽器,偵聽 JMS 主題 或隊列上的 JMS 消息。根據 EJB 2.1 規范,MDB 不僅限於 JMS 偵聽器,而是可實現任意自定義偵聽器接口。在本系列的第 3 部分中, 您將再次回顧這一點,並修改 PurchaseOrderMDB,以便使用自定義偵聽器接口,將其與 JCA 資源適配器相集成。

在本教程中,您將實現 PurchaseOrderMDB,它偵聽 JMS 主題(POTopic)接收到的帶有采購請求的 JMS 消息。接收到采購請求消息時 ,它將調用 PurchaseOrderEJB 來創建新采購訂單。

實現 PurchaseOrderMDB

不同於實體 bean,MDB 不必實現遠程接口或主接口,而是要實現 MessageDrivenBean 和 MessageListener 接口 —— 因而必須實現 onMessage() 方法。清單 9 給出了 PurchaseOrderMDB 的代碼片段。

PurchaseOrderMDB 的源文件(.java)可在 $part1.home/src/examples/po/mdb 目錄下找到。

清單 9. MDB 源代碼

public class PurchaseOrderMDB
     implements MessageDrivenBean, MessageListener {

     private MessageDrivenContext ctx = null;

     public void setMessageDrivenContext(MessageDrivenContext mdCtx)
        throws EJBException {
        ctx = mdCtx;
     }

     public void onMessage(Message msg) {

        if (msg instance of ObjectMessage) {

        Serializable bean = ((ObjectMessage) msg).getObject();
        poBean = (PurchaseOrderBean) bean;
        addPurchaseOrder(poBean);

        }

     }// end onMessage

在 PurchaseOrderMDB 的 onMessage() 方法中,您調用了 PurchaseOrderEJB 的 addPurchaseOrder() 方法在數據庫表中創建新采購 訂單行。

Geronimo 服務器的 JNDI 屬性如下:

java.naming.factory.initial=org.openejb.client.RemoteInitialContextFactory

java.naming.provider.url=localhost:4201
(4201 是默認端口)

java.naming.security.principal=system(默認用戶名)

java.naming.security.credentials=manager(默認口令)

清單 10. 查找實體 bean 並創建采購訂單

private void addPurchaseOrder (PurchaseOrderBean poBean) {

try {

//EJB JNDI Properties for Geronimo Server
Hashtable env = new Hashtable();
env.put("java.naming.factory.initial",
     "org.openejb.client.RemoteInitialContextFactory");

env.put("java.naming.provider.url", "localhost:4201");
env.put("java.naming.security.principal", "system");
env.put("java.naming.security.credentials", "manager");

// create a new InitialContext
InitialContext ctx = new InitialContext(env);

// Lookup Purchase Order Entity Bean
Object o = ctx.lookup("PurchaseOrderEJB");
RemotePurchaseOrderHome home =
(RemotePurchaseOrderHome) PortableRemoteObject
    .narrow(o, RemotePurchaseOrderHome.class);

// Create a new Purchase Order
RemotePurchaseOrder po = home. create ( poBean.getPurchaseOrderNum(),
                    poBean.getItem(),
                    poBean.getDescription(),
                    poBean.getUnitPrice(),
                    poBean.getQuantity(),
                    poBean.getRequestorEmail());

log.info("Purchase Order Number # :" + po.getPurchaseOrderNum());

} catch (Exception e) {
     e.printStackTrace();
     log.severe(""+e);
}}}

如 清單 10 所示,為了在數據表中創建一個采購訂單行,您在 JNDI 服務器中查找 PurchaseOrderEJB,並調用主接口上的 create() 方法。

定義 MDB 描述符

既然已經實現了 PurchaseOrderMDB,就該在描述符中定義 MDB 了。您不必為 MDB 定義單獨的描述符。它們是在與 EJB 相同的描述符 中定義的,也就是 ejb-jar.xml(參見 清單 11)和 openejb-jar.xml(參見 清單 12)。

清單 11. 定義 MDB 的 ejb-jar.xml 代碼片段

<message-driven>
<ejb-name>PurchaseOrderMDB</ejb-name>
<ejb-class>examples.po.mdb.PurchaseOrderMDB</ejb-class>
<transaction-type>Container</transaction-type>
<message-destination-type>javax.jms.Topic
    </message-destination-type>
</message-driven>

在 openejb-jar.xml 中,您定義了 MDB 應偵聽的主題/隊列 JNDI 名(POTopic)(參見 清單 12)。您還要定義 MDB 在 ejb-ref 部 分中調用的 EJB。

清單 12. 定義 MDB 的 openejb-jar.xml 代碼片段

<message-driven>
<ejb-name>PurchaseOrderMDB</ejb-name>
<resource-adapter>
<target-name>
geronimo.server:J2EEApplication=null,J2EEServer=geronimo,
JCAResource=geronimo/activemq/1.0/car,j2eeType=JCAResourceAdapter,
name=ActiveMQ RA 
</target-name>
</resource-adapter>

<activation-config>
<activation-config-property>
    <activation-config-property-name>
    destination
    </activation-config-property-name>
    <activation-config-property-value>
    POTopic
    </activation-config-property-value>
</activation-config-property>
<activation-config-property>
    <activation-config-property-name>
    destinationType
    </activation-config-property-name>
    <activation-config-property-value>
    javax.jms.Topic
    </activation-config-property-value>
</activation-config-property>
</activation-config>

<!--This is a reference to PurchaseOrderEJB CMP deployed in
Geronimo Server. -->
<ejb-ref>
<ref-name>ejb/PurchaseOrderEJB</ref-name>
<ejb-link>PurchaseOrderEJB</ejb-link>
</ejb-ref>
</message-driven>

PurchaseOrderMDB 在 addPurchaseOrder() 方法中調用 PurchaseOrderEJB,因此 EJB 是在 <ejb-ref> 部分中定義的。

Geronimo 服務器配置

既然已經實現了 PurchaseOrderMDB 和 PurchaseOrderEJB,現在就可以配置 Geronimo 服務器以便部署。首先使用 Geronimo 服務器 中的 Derby 為 PurchaseOrderEJB 配置數據庫表 PURCHASEORDER。

Geronimo 中不需要任何 JMS 配置,因為 JMS 主題/隊列是在部署期間由服務器動態創建的。Geronimo 為 JMS 主題或隊列使用 openejb-jar.xml 描述符中的 JNDI 名。

數據庫配置

運行 $GERONIMO_HOME/bin/startup.bat 啟動您的 Geronimo 服務器。如果您未在系統屬性中設置 JAVA_HOME,可在 $GERONIMO_HOME/bin/setjavaenv.bat 中進行設置。為 Geronimo 使用默認用戶名 system 和口令 manager。

在 http://localhost:8080/console 處可使用 Geronimo 管理控制台,在左窗格中的 Misc > Embedded DB 菜單下單擊 DB Manager。

創建 ExampleDatabase,如 圖 3 所示。

圖 3. 在 Geronimo 服務器中創建數據庫

成功創建了 ExampleDatabase 之後,您將會看到它出現在數據庫列表中,如 圖 4 所示。

圖 4. 數據庫創建成功

現在創建表 PURCHASEORDER,方法是在 SQL Command 文本區域中輸入 SQL 腳本(參見 清單 13)。務必確保首先在 Use DB 下拉列表 中選中 ExampleDatabase,然後再單擊 Run SQL 按鈕(參見 圖 5)。

清單 13. 創建表的 SQL 腳本

CREATE TABLE PURCHASEORDER (

   PURCHASEORDERNUM VARCHAR(30) PRIMARY KEY,
   ITEM VARCHAR(30) NOT NULL,
   DESCRIPTION VARCHAR(255),
   UNITPRICE INTEGER,
   QUANTITY INTEGER,
   REQUESTOREMAIL VARCHAR(30) NOT NULL
)

圖 5. 在 Geronimo 服務器中創建數據庫

成功創建了 PURCHASEORDER 表之後,您將看到它出現在 DB Viewer 中,如 圖 6 所示。

圖 6. 表創建成功

數據庫池配置

現在您可以使用 http://localhost:8080/console 處的 Geronimo 管理控制台在 Geronimo 中創建數據庫池 PurchaseOrderDataSource。

在左窗格中選擇 Database Pools,然後選擇 Using the Geronimo database pool wizard,如 圖 7 所示。完成後續步驟,如 圖 8 和 圖 9 所示。

圖 7. 創建數據庫池

鍵入 PurchaseOrderDataSource 作為數據庫池名、Derby Embedded 作為類型,如 圖 8 所示。

圖 8. 選擇數據庫類型

從 Driver JAR 下拉列表中選擇 org.apache.derby/derby/10.1.1.0/jar。您可將用戶名和口令字段留空。選擇 ExampleDatabase 作 為數據庫名(參見 圖 9)。

圖 9. 選擇數據庫驅動和數據庫名

只要將未填充的字段留空,即可使用默認值,單擊 Test Connection 按鈕來測試連接(參見 圖 10)。

圖 10. 測試數據庫連接池

現在,您應看到測試結果,表示您已連接到 Derby,如 圖 11 所示。

圖 11. 成功測試連接

選擇 Deploy 按鈕後,您應看到數據庫池已成功創建(參見 圖 12)。

圖 12. 數據庫池創建成功

部署

既然已完成了數據庫配置,那麼也就准備好在 Geronimo 中部署包含 EJB 和 MDB 的應用程序了(po-ejb.jar)。po-ejb.jar 文件位 於 $part1.home/deploy 目錄下。

您可以使用命令行,也可以使用基於控制台的部署,分別介紹如下。

命令行部署

下載文件 part1.zip 的 $part1.home 目錄中有用於部署(deploy.cmd)和取消部署(undeploy.cmd)的腳本。

務必在使用前修改命令文件中的 JAVA_HOME 和 GERONIMO_HOME。

控制台部署

使用 http://localhost:8080/console 處的 Geronimo 管理控制台部署 po-ejb.jar 文件,如 圖 13 所示。

圖 13. 部署新應用程序

成功部署應用程序後,您將接收到如 圖 14 所示的消息。

圖 14. 部署成功

測試

最後,您可創建一個客戶機或測試程序來測試您的應用程序。

創建客戶機

您的客戶機程序(參見 清單 14)將向 POTopic 發布一條帶有采購請求信息的 JMS 消息。由於 PurchaseOrderMDB 偵聽 POTopic,服 務器將調用 onMessage() 方法,此方法又會調用 PurchaseOrderEJB 在數據庫中創建采購訂單。

客戶機 PurchaseOrderPublisher.java 位於 $part1.home/src/examples/po/test 目錄中。

清單 14. 發布 JMS 消息的客戶機程序

public class PurchaseOrderPublisher {

    public static void main(String a[]) throws Exception {

       Logger log = Logger.getLogger("PurchaseOrderPublisher");

       javax.jms.TopicConnection conn = null;
       javax.jms.TopicPublisher publisher = null;
       javax.jms.TopicSession session = null;

       try {
       // JMS JNDI Properties for Apache Geronimo Server
       java.util.Hashtable env = new java.util.Hashtable();
       env.put("java.naming.factory.initial",
           "org.activemq.jndi.ActiveMQInitialContextFactory");
       env.put("java.naming.provider.url",
         "tcp://localhost:61616");
       env.put("topic.POTopic", "POTopic");
       env.put("connectionFactoryNames", "POConnectionFactory");

       // create a new initial context with jndi properties 
       javax.naming.Context ctx =
          new javax.naming.InitialContext(env);

       // lookup the connection factory 
       javax.jms.TopicConnectionFactory factory =
          (javax.jms.TopicConnectionFactory) ctx 
           .lookup("POConnectionFactory");

       // create a new TopicConnection
       conn = factory.createTopicConnection();

       javax.jms.Topic mytopic =
(javax.jms.Topic) ctx.lookup("POTopic");

       // create a new TopicSession
       session = conn.createTopicSession(false,
          javax.jms.Session.AUTO_ACKNOWLEDGE);

       //create a Topic Publisher to publish messages to 'POTopic'
       publisher = session.createPublisher(mytopic);

       // start the topic connection
       conn.start();

       // create a new purchase order with test data
       PurchaseOrderBean poBean = new PurchaseOrderBean();
       Random random = new Random();
       String poNum = "PO" + random.nextInt();
       poBean.setPurchaseOrderNum(poNum);
       poBean.setItem("Pens");
       poBean.setDescription("Need pens for Marketing dept.");
       poBean.setUnitPrice(new Integer(2));
       poBean.setQuantity(new Integer(100));
       poBean.setRequestorEmail("[email protected]");

       // create a jms message
       javax.jms.ObjectMessage poMsg =
session.createObjectMessage(poBean);

       // publish the jms message to 'POTopic'
       publisher.publish(poMsg);

       } catch (Exception e) {
          log.severe("Error Occurred: " + e);
       } finally {

          // release all jms resources 
          if (publisher != null)
             publisher.close();

          if (session != null)
             session.close();

          if (conn != null)
              conn.close();
       }

    }// end main

}// end class

運行測試

下載的 part1.zip 文件中提供了一個腳本文件(參見 下載 部分),修改 $part1.home/runtester.cmd 中的 JAVA_HOME、J2EE_JAR 和 GERONIMO_HOME(參見 圖 15)。

圖 15. 測試應用程序

現在您應看到 Geronimo 控制台中顯示出一些日志記錄,如 圖 16 所示。

圖 16. Geronimo 服務器日志

如果 PURCHASEORDER 數據庫中添加了一條新記錄,則本測試將被視為成功。

結果

現在檢查數據庫,看看 PURCHASEORDER 表中是否有記錄項,如 圖 17 所示。

圖 17. 檢查數據庫表中是否有新記錄項

太棒了!您已經完成了本系列教程第 1 部分的學習。

在第 2 部分中,您將開發一個電子郵件應用程序,此應用程序將在 Apache James 中部署。

結束語

您已成功完成了這個共分三部分的系列教程的第 1 部分。您創建了一個 MDB 和一個帶有 CMP 的實體 bean。這些 bean 協同工作,向 系統中添加采購訂單。

請繼續關注第 2 部分,您將使用 Apache James 郵件應用程序平台來構建一個電子郵件應用程序;另外還有第 3 部分,在第 3 部分 中您要將這篇教程中創建的兩個 bean 以及第 2 部分中創建的電子郵件應用程序聯系在一起,完成整個應用程序。

本文配套源碼

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved