本文延續「三種方法連接資料庫到 Geronimo」,完整示範如何擴充簡單資料庫應用,導入 Apache Struts 前端與 EJB 後端,並以 Maven 自動化建構、封裝、部署企業級應用 (EAR)。
maven 指令。geronimo-deployment-plugin-1.0-SNAPSHOT.jar 裝入 $MAVEN_HOME/plugins。.jar 至本地倉庫 .maven/repository/xdoclet/jars,並加入 maven-xdoclet-plugin-1.2.3.jar 至 plugins 目錄。滿足條件後,專案根目錄執行 maven 應顯示 BUILD SUCCESSFUL。Geronimo 需先啟動 (java -jar bin/server.jar org/apache/geronimo/DebugConsole org/apache/geronimo/RuntimeDeployer)。
src/webapp:JSP、Tiles 模板 (site-template.jsp)、資源檔。ListPhoneNumbersPage.jsp (DisplayTag 分頁顯示)、EditPhoneNumberPage.jsp (Struts 表單標籤)。src/java/org/acme/phonebook/struts):ListNumbers、SaveEntry、EditEntry、DeleteEntry 等。Action 類別 Javadoc 標籤產生 struts-config.xml:
/** @struts.action path="/pages/SaveEntry" name="phoneBookEntryForm" scope="request" input="/pages/EditPhoneNumberPage.jsp" ... */
/** @struts.action-forward name="success" path="/pages/ListNumbers.do" redirect="true" */
PhoneBookSessionLocal session = PhoneBookSessionUtil.getLocalHome().create();
Collection c = session.listEntries();
request.setAttribute("numbers", c); // 供 JSP 顯示
PhoneBookSessionUtil 為 XDoclet 產生的輔助類別。
<display:table name="numbers" requestURI="ListNumbers.do" pagesize="5">
<display:column property="name" title="Name"/>
<display:column property="phoneNumber" title="Phone"/>
<display:column title="Actions">
<html:link action="/pages/EditEntry" paramId="id" paramName="row_obj" paramProperty="name">Edit</html:link>
<html:link action="/pages/DeleteEntry" ... onclick="return confirmDelete('Number')">Delete</html:link>
</display:column>
</display:table>
PhoneBookEntryBean:CMP Entity Bean,對應資料表 phone,XDoclet 產生部署描述符與介面。PhoneBookSessionBean:Stateless Session Facade,提供業務邏輯與交易邊界 (@ejb.transaction type="Required"),隔離 Web 層與持久化細節。/** @ejb.interface-method view-type="both" @ejb.transaction type="Required" */
public Collection listEntries() {
Collection entries = PhoneBookEntryUtil.getLocalHome().findAll();
// 轉換為 Value Object 回傳
}
src/resources/ear)application.xml、geronimo-application.xml:定義模組、應用層級 JDBC 連接器 (參考前文)。geronimo-application.xml 的 configId="org/acme/PhoneBook" 必須與 maven.xml 部署目標 id 一致,否則自動部署失敗。src/resources/ejb/META-INF/openejb-jar.xml)<cmp-connection-factory><resource-link>MysqlDataSource</resource-link></cmp-connection-factory>:名稱必須與連接器配置一致。<local-jndi-name>java:comp/env/ejb/PhoneBookEntryLocal</local-jndi-name>:JNDI 名稱錯誤會導致找不到 Bean。<table-name>、<cmp-field-mapping>:對應資料表/欄位。src/webapp/WEB-INF/geronimo-jetty.xml)<web-app ... configId="org/acme/PhoneBookWeb">
<context-priority-classloader>true</context-priority-classloader>
</web-app>
關鍵:context-priority-classloader=true 解決 Geronimo 庫與 Struts 類別衝突,隔離應用類別載入範圍 (Geronimo M4 版檔名改為 geronimo-web.xml)。
src/resources/merge 放置 taglibs.xml 等片段,XDoclet 產生 web.xml、struts-config.xml 時自動合併。
maven.xml)<goal name="start">
<deploy:distribute uri="deployer:geronimo:jmx:rmi://localhost/jndi/rmi:/JMXConnector" ... module="target/${pom.artifactId}.ear"/>
<deploy:start ... id="org/acme/PhoneBook"/>
</goal>
自動化部署極便利,惟需定期清理暫存目錄避免舊部署檔堆積。
範例應用展示 Maven 降低 EAR 巢狀結構複雜度、XDoclet 自動化 EJB/Struts/Web 成品產生、Geronimo 嚴格分離部署與配置關注點。以此為骨架,增減 CMP/Session Bean 即可快速建構企業級 Web 應用。