在大型企業環境中,同一套 Java EE 應用往往需部署至多個叢集節點、配置差異化資料源與 JNDI 名稱。手動操作 WebSphere 管理主控台不僅繁瑣,極易出錯。本文基於 WebSphere JMX 管理 API(AdminClient、ConfigService、AppManagement),系統闡述資料源自動建立、EAR 封裝修改、應用自動安裝與監聽的完整自動化部署流程與核心代碼範例。
ejb-jar.xml、web.xml、ibm-ejb-jar-bnd.xmi 中的資源參考、EJB JNDI 名稱、Web Context Root。AppDeploymentTask,註冊 NotificationListener 監控安裝狀態。Properties props = new Properties();
props.setProperty(AdminClient.CONNECTOR_TYPE, AdminClient.CONNECTOR_TYPE_SOAP);
props.setProperty(AdminClient.CONNECTOR_HOST, ipAddress);
props.setProperty(AdminClient.CONNECTOR_PORT, port);
AdminClient adminClient = AdminClientFactory.createAdminClient(props);
ConfigService configService = new ConfigServiceProxy(adminClient);
Session session = new Session();
// 解析 Cell/Node 下的 JDBCProvider
ObjectName[] providers = configService.resolve(session,
"Cell=" + cell + ":Node=" + node + ":JDBCProvider");
ObjectName db2Provider = null;
for (ObjectName provider : providers) {
String name = (String) configService.getAttribute(session, provider, "name");
if ("XXX JDBC Provider".equals(name)) { db2Provider = provider; break; }
}
// 若不存在,需先建立 JDBCProvider(略)
// 建立 DataSource 配置物件(使用 AdminConfig 任務或直接操作 ConfigService)
// 設定 JNDI 名稱、連線池參數、映射至 db2Provider
// ...
configService.save(session, true); // 持久化至主配置庫
configService.discard(session); // 釋放會話
EAR 內部結構:
app.ear
├── META-INF/application.xml
├── module-ejb.jar
│ ├── META-INF/ejb-jar.xml
│ └── META-INF/ibm-ejb-jar-bnd.xmi
└── module-web.war
├── WEB-INF/web.xml
└── WEB-INF/ibm-web-bnd.xmi
修改重點:
ejb-jar.xml/web.xml 中 <resource-ref> 的 <res-ref-name> 對應邏輯 JNDI,需替換為目標環境實際 JNDI(如 jdbc/MyDS → jdbc/ProdDS)。ibm-ejb-jar-bnd.xmi 中 ejbBinding.xmi:jndiName 設定 EJB 遠端介面 JNDI。application.xml 中 <context-root> 及 ibm-web-bnd.xmi 中 webApp.xmi:contextRoot。實作可使用 JAXP (DOM/SAX)、JDOM 或 XStream 解析修改 XML/XMI,建議建立映射規則表(來源 JNDI → 目標 JNDI)驅動批次替換。
public class DeployListener implements NotificationListener {
private AdminClient adminClient;
private ObjectName appMgmtMbean;
private volatile boolean isFinish = false;
public void handleNotification(Notification notif, Object handback) {
try {
AppNotification ev = (AppNotification) notif.getUserData();
if (AppNotification.INSTALL.equals(ev.taskName)) {
if (AppNotification.STATUS_COMPLETED.equals(ev.taskStatus)) {
System.out.println("安裝成功,移除監聽器");
adminClient.removeNotificationListener(appMgmtMbean, this);
isFinish = true;
} else if (AppNotification.STATUS_FAILED.equals(ev.taskStatus)) {
System.out.println("安裝失敗: " + ev.getMessage());
adminClient.removeNotificationListener(appMgmtMbean, this);
isFinish = true;
}
}
} catch (Exception ex) { ex.printStackTrace(); }
}
public boolean isFinish() { return isFinish; }
}
AppManagement appMgmt = new AppManagementProxy(adminClient);
ObjectName appMgmtMbean = appMgmt.getAppManagement();
// 註冊監聽器
DeployListener listener = new DeployListener();
listener.setAdminClient(adminClient);
listener.setAppMgmtMbean(appMgmtMbean);
adminClient.addNotificationListener(appMgmtMbean, listener, null, null);
// 建立部署任務參數
Map options = new HashMap<>();
options.put("appName", "MyApp");
options.put("earPath", "/deploy/app.ear");
options.put("cluster", "MyCluster");
// ... 其他選項:預編譯 JSP、啟動應用等
// 執行安裝
ObjectName task = appMgmt.installApp(options); // 返回任務 ObjectName
// 輪詢 listener.isFinish() 或同步等待
採用 WebSphere JMX API 自動化部署,將原本數小時的人工作業壓縮至分鐘級,消除配置漂移,是實現持續交付(CD)在傳統 WAS 環境的關鍵技術棧。