首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

讓您的應用程式呼叫我的應用程式,第 1 部分 (上)

     編輯:Java 相關知識

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

Apache Geronimo 包含頂尖的訊息傳遞實作,還有世界級的 Enterprise JavaBeans (EJB) 實作,從而使您可在自己的應用程式中使用訊息驅動 Bean (MDB)。這也就意味著只要具備恰當的資源適配器,其他元件就可以使用訊息傳遞與您的應用程式互動。本系列教學詳細敘述了 Java EE 應用程式的建立,在這個應用程式中,使用者、管理員甚至其他應用程式都可利用 MDB 進行互動,方法是向 Java Apache Mail Enterprise Server (Apache James) 發送電子郵件,而 Apache James 隨後又使用 J2EE Connector Architecture (JCA) 資源適配器反過來與 Geronimo 通訊。

開始之前

本系列教學面向希望學習如何使用各種 Java EE 元件 (包括 MDB 和 JCA 資源適配器) 建構整合解決方案的 Java EE 程式設計師。本教學假設您熟悉基本的 Java 和 Java EE 概念,例如 EJB、JMS、MDB 和 UML 圖。

關於本系列

在這個共分三部分的系列教學中,您將建構一個範例應用程式,透過這種方式了解如何將不同的 Java EE 元件集成在一起,來開發複雜的應用程式。您可下載本文的範例應用程式,它示範了 Apache James 中電子郵件的資料是如何透過 JCA 資源適配器、MDB、EJB 流向 Apache Geronimo 應用程式伺服器的。

  • 第 1 部分:介紹了如何開發 MDB、實體 Bean 和容器管理持久性 (CMP),以及如何在 Apache Geronimo 中部署和測試這些元件。
  • 第 2 部分:將解釋如何建立電子郵件應用程式 (Mailet 和 Matcher) 並將它們部署在 Apache James 電子郵件伺服器中。
  • 第 3 部分:將整個應用程式串聯在一起。您將學習為 Apache James 電子郵件伺服器 (它透過 MDB 與 James 和 Geronimo 互動) 開發、部署和測試 JCA 資源適配器。

關於本教學

本教學是共分三部分的系列教學中的第 1 部分,集中關注開發、部署和測試一個整合式 Java EE 應用程式的各種元件。該應用程式示範了 Apache James 電子郵件伺服器中一封電子郵件的資料是如何透過 JCA 資源適配器和 MDB 流向 Apache Geronimo 應用程式伺服器的。

系統需求

完成本教學需要以下工具:

  • Apache Geronimo — Apache 提供的 Java EE 應用程式伺服器
  • Apache James 2.2 — 基於 Java 的 SMTP、POP3 和 NNTP 新聞伺服器
  • Apache Derby 資料庫 — 開放原始碼、輕量級資料庫,內嵌於 Geronimo 內,因此無需單獨安裝
  • Sun Microsystems 提供的 Java 1.4.2
  • 範例原始檔

在本教學的下載部分可獲得 geronimo.mdb.part1source.zip 檔案,其中包含原始碼、EJB JAR 和本教學的描述符檔案。以下詳細列出 .zip 檔案的組成部分:

  • dds (包含描述符 XML 檔案)
  • deploy (po-ejb.jar)
  • lib (examples.jar 和 tester.jar)
  • src (MDB 和實體 EJB 的 Java 檔案)
  • deploy.cmd
  • undeploy.cmd
  • runtester.cmd

EJB 封裝

以下列出了 po-ejb.jar 檔案的組成部分 (部署在 Geronimo 中):

  • 描述符檔案:META-INF/ejb-jar.xml、META-INF/openejb-jar.xml
  • 類別檔案:examples/po/ejb/*.class、examples/po/bean/*.class、examples/po/mdb/*.class

基本應用程式

本教學的目的是介紹在 Apache Geronimo 上編寫可輕鬆與其他基於 Java 的技術整合的 Java EE 應用程式的概念和基礎知識。您將透過使用 Java EE 元件開發一個範例應用程式來學會這些知識。

在本教學的場景示例和編碼練習中,您將使用 Foo, Inc.,這是一家虛擬企業。雖然 Foo, Inc. 是虛擬的,但業務場景和示例都是真實的。

Foo, Inc. 的舊有採購訂單流程

讓我們來看一下 Foo, Inc 的舊有採購訂單 (PO) 流程。這是一個手工流程,員工填寫採購申請單,將申請單提交給採購部門進行授權、批准,最終將 PO 提交給廠商。這看起來是一個效率極低、耗費時間的流程,可以透過軟體進行自動化。因此,Foo, Inc. 決定購買一套新的 PO 系統 (假設是一種基於資料庫的產品),實現將內部採購申請單提交給廠商的電子化通訊。

新的採購訂單流程

新的 PO 流程允許一名員工發送電子郵件請求,由 PO 經理授權進行電子化批准,從而自動建立 PO 並將其提交給廠商。新流程詳述如下:

  1. 員工透過電子郵件將採購請求發送給採購部門。
  2. 採購請求電子郵件由一個 Java EE 應用程式處理,該應用程式確保請求者是經過授權的。若授權流程成功完成,電子郵件將轉發到指定資料夾中,以便進一步處理。
  3. Java EE 應用程式的另一個元件輪詢包含經過授權的請求的電子郵件資料夾,並在 PO 系統中建立一個新採購訂單。
  4. 隨後可在 PO 系統中檢索採購訂單並將訂單發送給廠商。

應用程式設計

既然已經了解了 Foo, Inc 的新採購訂單流程,那麼下一步就是設計我們的 Java EE 範例應用程式,來實現新流程。

範例應用程式需求

您將從為範例應用程式收集需求開始。

  • 應用程式需要處理來自員工的傳入採購請求電子郵件,並將其移動到可由採購部門存取的特定資料夾。
  • 隨後,您的應用程式將讀取請求,並檢查該員工是否確實來自 Foo, Inc.。
  • 一旦經過授權,即建立一份新的採購訂單,以便提交給廠商。

這樣,您確定了三個需求,現在您需要將其建模為用例。

用例分析

用例分析捕獲整體需求,並描述範例應用程式的單個特性和功能性。它由一組用例和參與者構成。

參與者和用例

用例

用例代表業務需求。在我們的例子中,也就是我們剛剛為 Foo, Inc. 的新採購訂單流程確定出的需求:

  • 發送採購請求電子郵件:需求:Foo, Inc. 的員工向採購部門發送帶有採購請求的電子郵件。
  • 處理採購請求電子郵件:需求:應用程式透過授權和將採購請求電子郵件移動到其他資料夾中來處理這些電子郵件。
  • 檢查採購請求電子郵件:需求:應用程式將連續檢查等待處理的新採購請求電子郵件。
  • 在 PO 系統中新增採購訂單:需求:應用程式將在 PO 系統中新增新採購訂單。

參與者

參與者是在應用程式或系統中承擔一個角色的實體。參與者可以是人、組織或應用程式。以下列表包含了您的參與者:

  • Foo, Inc. 的員工
  • 電子郵件應用程式
  • J2EE 應用程式

參與者與應用程式互動,因而也顯示為與圖 1 中所示的用例互動。

元件

確定出您的應用程式中的用例之後,下一步就是將這些需求/用例建模為 Java EE 元件。圖 2 中的元件圖顯示了各種元件及其互動。讓我們從詳細了解應用程式流程和各應用程式元件在更高層面中的角色開始。

元件圖

應用程式流程

Foo, Inc. 的員工發送一封採購請求電子郵件。這種電子郵件將由您的範例應用程式處理 (元件:Mailet 和 Matcher),它將授權採購請求,並將請求轉發到屬於採購部門的特定電子郵件資料夾中。您的應用程式 (元件:JCA 適配器) 將不斷輪詢新採購請求。一旦接收到新的採購請求電子郵件,範例應用程式 (元件:JCA 資源適配器和 MDB) 將呼叫訊息偵聽器來非同步處理採購請求。應用程式 (元件:MDB 和 EJB) 隨後在 PO 系統 (資料庫) 中建立一份新的採購訂單。

以下列舉了元件及其相應用例。您將分三部分建構這個應用程式 (在本系列的三篇教學中):

  • 實體 Bean — CMP:在 PO 系統中新增採購訂單 (第 1 部分)。
  • MDB:在 PO 系統中新增採購訂單 (第 1 部分)。
  • 電子郵件客戶端應用程式:發送採購請求電子郵件 (第 2 部分)。
  • 電子郵件應用程式:處理採購請求電子郵件 (第 2 部分)。
  • JCA 資源適配器:檢查採購請求電子郵件 (第 3 部分)。

通常,可以在完全不了解將用於部署的應用程式伺服器的情況下設計和開發 Java EE 應用程式。

在開發、部署和測試過程中,您要在 Apache Geronimo 和 Apache James 中部署範例應用程式。您將使用 Apache Derby 作為 PO 系統資料庫。(在本教學開始處的系統需求部分中可找到下載這些產品的連結。)

既然您已經了解了應用程式流程和範例應用程式的設計,接下來就該動手開發第 1 部分的應用程式元件了。

第 1 部分的應用程式開發

在這裡,您將為用例在 PO 系統中新增採購訂單開發元件。在元件設計中,您將使用 MDB 非同步接收來自 JCA 資源適配器和實體 EJB (CMP) 的採購請求,在 PO 系統中新增新採購訂單。

您將呼叫您的 MDB PurchaseOrderMDB 和實體 Bean (CMP) PurchaseOrderEJB。PurchaseOrderMDB 接收到一個採購請求之後,它將呼叫 PurchaseOrderEJB 在資料中插入一個新的採購訂單。

以下詳細介紹了在 Geronimo 內對 MDB 和 CMP 實體 Bean 的實作和部署。

實體 Bean (PurchaseOrderEJB)

您要根據 EJB 2.1 規格將 PurchaseOrderEJB 作為 CMP 實體 Bean 實作。實體 Bean 代表持久資料,在本例中,它表示作為 PO 系統的資料庫內的一行。由於您使用的是 CMP,Java EE 容器會讀/寫資料庫中的資料。

在範例應用程式中,PurchaseOrderEJB 與資料庫表 PURCHASEORDER 互動,定義參見程式碼片段 1。

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

接下來您將實作處理採購訂單的 EJB。

實作 PurchaseOrderEJB

EJB 2.1 規格要求實體 Bean 必須具有一個主介面、一個遠端介面、一個 Bean 類別和一個部署描述符。本節介紹以下所有必備 EJB 介面和類別的實作。

  • EJB 主介面 — RemotePurchaseOrderHome.java (程式碼片段 2)
  • EJB 遠端介面 — RemotePurchaseOrder.java (程式碼片段 3)
  • EJB Bean 類別 — PurchaseOrderEJB.java (程式碼片段 4 和 5)
  • 描述符 — ejb-jar.xml 和 openejb-jar.xml (程式碼片段 6 和 7)

可在 $part1.home/src/examples/po/ejb 目錄下找到 PurchaseOrderEJB 的原始檔 (.java),兩個描述符檔案均位於 $part1.home/dds 目錄中。

EJB 主介面

EJB 主介面用於在伺服器中建立、刪除或查找 Bean 實例。這個介面在部署期間綁定到伺服器 Java Naming and Directory Interface (JNDI) 樹中。在執行時,客戶端程式查找 JNDI 中的主介面來使用此 EJB。RemotePurchaseOrderHome 是 PurchaseOrderEJB 的主介面,它按照 EJB 2.1 規格實作了 EJBHome (程式碼片段 2)。

public interface RemotePurchaseOrderHome extends EJBHome, Remote {
 public RemotePurchaseOrder create(String purchaseOrderNum, String item, String description, Integer unitPrice, Integer quantity, String requestorEmail) throws CreateException, RemoteException;
 public Collection findByRequestorEmail(String requestorEmail) throws FinderException, RemoteException;
 public RemotePurchaseOrder findByPrimaryKey(String poNum) throws FinderException, RemoteException;
}

您有一個 create() 方法,它實際上是一個 Bean 實例,在 PURCHASEORDER 表中插入新記錄。存在兩個查找方法:

  • findByRequestorEmail() 返回指定請求者電子郵件為 REQUESTOREMAIL 的採購訂單行的集合。
  • findByPrimaryKey 返回帶有特定主鍵的一行。

EJB 遠端介面

EJB 遠端介面 (程式碼片段 3) 為實體 Bean 定義業務方法。遠端介面中的這些方法應定義為公共方法,以使其可被遠端客戶端程式所存取。RemotePurchaseOrder 是 PurchaseOrderEJB 的遠端介面。

public interface RemotePurchaseOrder extends EJBObject, Remote {
 public String getPurchaseOrderNum() throws RemoteException;
 public void setPurchaseOrderNum(String purchaseOrderNum) throws RemoteException;
 public String getItem() throws RemoteException;
 public void setItem(String item) throws RemoteException;
 public String getDescription() throws RemoteException;
 public void setDescription(String description) throws RemoteException;
 public Integer getUnitPrice() throws RemoteException;
 public void setUnitPrice(Integer unitPrice) throws RemoteException;
 public Integer getQuantity() throws RemoteException;
 public void setQuantity(Integer quantity) throws RemoteException;
 public String getRequestorEmail() throws RemoteException;
 public void setRequestorEmail(String requestorEmail) throws RemoteException;
}

RemotePurchaseOrder 為資料庫表 PURCHASEORDERSYSTEM 中的欄位定義了 getters 和 setters。

EJB Bean 類別

EJB Bean 類別實作遠端介面,並為遠端介面中定義的方法提供實際實作。了解此 EJB 是如何作為 CMP 部署之後,您不必實作 getter 和 setter 方法,而是將其定義為抽象方法 (程式碼片段 4)。

public abstract class PurchaseOrderEJB implements EntityBean {
 private EntityContext context;
 // CMP 欄位的存取方法
 public abstract String getPurchaseOrderNum();
 public abstract void setPurchaseOrderNum(String purchaseOrderNum);
 public abstract String getItem();
 public abstract void setItem(String item);
 // ...
}

create() 方法 (程式碼片段 5) 在 PURCHASEORDER 表中插入一個帶有特定參數值的新行。

private String create(String purchaseOrderNum, String item, String description, Integer unitPrice, Integer quantity, String requestorEmail) throws CreateException {
 setPurchaseOrderNum(purchaseOrderNum);
 setItem(item);
 setDescription(description);
 setUnitPrice(unitPrice);
 setQuantity(quantity);
 setRequestorEmail(requestorEmail);
 return purchaseOrderNum;
}

定義 EJB 描述符

既然已經建立好遠端介面、主介面和 Bean 類別,那麼接下來就該轉向部署描述符了。您將定義兩個描述符:根據 EJB 2.1 規格定義的 ejb-jar.xml 以及在 Geronimo 中部署 EJB 所必需的 openejb-jar.xml。如程式碼片段 6 所示,ejb-jar.xml 定義主介面、遠端介面和 Bean 類別。請注意,持久類型為 Container。

<ejb-jar version="2.1" xmlns="https://java.sun.com/xml/ns/j2ee" ...>
 <display-name>PurchaseOrderEJB</display-name>
 <enterprise-beans>
 <entity>
 <display-name>PurchaseOrderEJB</display-name>
 <ejb-name>PurchaseOrderEJB</ejb-name>
 <home>examples.po.ejb.RemotePurchaseOrderHome</home>
 <remote>examples.po.ejb.RemotePurchaseOrder</remote>
 <ejb-class>examples.po.ejb.PurchaseOrderEJB</ejb-class>
 <persistence-type>Container</persistence-type>
 <prim-key-class>java.lang.String</prim-key-class>
 <reentrant>false</reentrant>
 <cmp-version>2.x</cmp-version>
 <abstract-schema-name>PurchaseOrder</abstract-schema-name>
 <cmp-field><field-name>purchaseOrderNum</field-name></cmp-field>
 <cmp-field><field-name>item</field-name></cmp-field>
 <cmp-field><field-name>description</field-name></cmp-field>
 ...
 <primkey-field>purchaseOrderNum</primkey-field>
 <resource-ref>
 <description>Reference to Datasource in Geronimo.</description>
 <res-ref-name>jdbc/PurchaseOrderDataSource</res-ref-name>
 <res-type>javax.sql.DataSource</res-type>
 <res-auth>Container</res-auth>
 </resource-ref>
 </entity>
 </enterprise-beans>
</ejb-jar>

EJB 描述符 ejb-jar.xml 為一個 EJB 定義了 CMP 欄位 (程式碼片段 7)。這些欄位對應於 PurchaseOrderEJB 將與之互動的底層資料庫表的欄位。您還在 resource-ref 部分中定義了綁定在伺服器 JNDI 中的資料庫資料源 (jdbc/PurchaseOrderDataSource)。

描述符中定義的兩個查找方法是:

  • findByPrimaryKey,給定採購訂單號,返回採購訂單。
  • findByRequestorEmail,返回一個特定電子郵件地址所請求的採購訂單集合。

ejb-jar.xml 用 EJB Query Language (EJBQL) 為上述查找方法定義查詢。

<query>
 <query-method>
 <method-name>findByRequestorEmail</method-name>
 <method-params><method-param>java.lang.String</method-param></method-params>
 </query-method>
 <result-type-mapping>Local</result-type-mapping>
 <ejb-ql>SELECT OBJECT(p) FROM PurchaseOrder AS p WHERE p.requestorEmail = ?1</ejb-ql>
</query>
<query>
 <query-method>
 <method-name>findByPrimaryKey</method-name>
 <method-params><method-param>java.lang.String</method-param></method-params>
 </query-method>
 <result-type-mapping>Local</result-type-mapping>
 <ejb-ql>SELECT OBJECT(p) FROM PurchaseOrder AS p WHERE p.purchaseOrderNum = ?1</ejb-ql>
</query>

隨 Java EE 描述符 ejb-jar.xml 一起,您還必須為 Geronimo 定義一個 EJB 描述符 (openejb-jar.xml),如程式碼片段 8 所示。

<openejb-jar xmlns="https://www.openejb.org/xml/ns/openejb-jar-2.0" ... inverseClassloading="true" configId="PurchaseOrderEJB" parentId="geronimo/activemq/1.0/car">
 <cmp-connection-factory>
 <resource-link>PurchaseOrderDataSource</resource-link>
 </cmp-connection-factory>
 <enterprise-beans>
 <entity>
 <ejb-name>PurchaseOrderEJB</ejb-name>
 <jndi-name>PurchaseOrderEJB</jndi-name>
 <table-name>PurchaseOrder</table-name>
 <cmp-field-mapping>
 <cmp-field-name>purchaseOrderNum</cmp-field-name>
 <table-column>purchaseOrderNum</table-column>
 </cmp-field-mapping>
 <cmp-field-mapping>
 <cmp-field-name>item</cmp-field-name>
 <table-column>item</table-column>
 </cmp-field-mapping>
 ...
 <primkey-field>purchaseOrderNum</primkey-field>
 </entity>
 </enterprise-beans>
</openejb-jar>

程式碼片段 8 中的這個描述符定義了 JNDI 名稱 (PurchaseOrder),該名稱用於將 EJB 主介面綁定到伺服器 JNDI 樹中。<ejb-name> 應與 ejb-jar.xml 中使用的名稱匹配。Java EE 伺服器將使用該描述符中定義的表名和 CMP 欄位來執行資料庫操作。

本文配套原始碼

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved