Java 2 企業版(J2EE)是開發部署企業應用的環境,由服務、API 及協定組成,提供開發多層、基於 Web 應用的功能。本文彙整針對 J2EE 體系結構與設計的常見問題,提供深度解析與實務建議。
問: EJB 或 Web 服務的 BEA 控制及註解看似強大且易用,您如何看待?在 WebSphere 中使用這些技術有多容易?
答: 您似乎想獲得 BEA WebLogic Workshop 與 IBM WebSphere Studio Application Developer(以下簡稱 WebSphere Studio)的比較。我未使用過 Workshop,無法直接評論其特性。WebSphere Studio 確實包含許多元資料編輯器(如部署描述符),使用這些編輯器比編輯原始 XML 容易得多(雖 Source 頁面也允許那樣做)。同樣,WebSphere Studio V5 重新設計編輯器,使其與 J2EE 指定及 WebSphere 指定配置設定區別更明顯。
問: 若啟用 WebSphere Application Server V5.1 Global Security,Web 服務與 WAS 間傳輸是否自動轉為 HTTPS?例如使用 defaultSSLsettings 和 jmserver 認證,無需在 Web 與 Application 伺服器間建新憑證。已有 Web 與瀏覽器客戶端間 HTTPS,目前僅缺 Web<>WAS HTTPS。全域安全性尚未啟用。
答: 啟用全域安全性不會自動進行 Web 服務 HTTPS 轉換。您需手動完成。請參閱 WebSphere Application Server Information Center 中的「調用 HTTPS 上的 Web 服務」與「使用 HTTP 基礎認證來安全化安全的 Socket 層上的簡單物件存取協定服務」。
問: 專案有套 EJB,EAR 檔安裝於 WebSphere Studio V5.1.2。測試環境伺服器運行時,EJB 專案與客戶端專案代碼變更不生效,每次需重啟測試環境伺服器。有解決方案或配置裝置嗎?
答: 若使用偵錯器編輯代碼時(如編輯 EJB 實作類但不改變介面)啟用 hot-method 替換,將立即變更正在運行應用程式代碼。請見 WebSphere Studio 線上說明「Hot-method 替換」。也可重啟個別專案,比重啟整個伺服器快得多。然而許多變更仍需重啟測試伺服器;請見「何時需要重啟測試伺服器」、「調試伺服器上的企業級 Bean」與「調試伺服器上的 Servlet」。
問: Web 應用中欲將 uid、pwd 傳至 EJB 層,讓會話 EJB 連接後端系統。不想作為參數傳遞或儲於從 Web 層傳至 EJB 層的物件中。存在不同流程需用 uid、pwd 連接後端。請推薦解決方案。
答: J2EE 應用中,所有使用者使用相同登錄資訊存取後端系統。J2EE 不能讓每個應用使用者用各自登錄資訊。EJB 層應為無狀態服務,由無狀態會話 Bean 管理,故不能儲存使用者資料(如用戶名/密碼)。可儲於使用者 HttpSession,但這是巨大潛在安全漏洞,且登錄資訊可能不實用。需使用 J2EE 服務存取後端系統,對所有使用者使用相同登錄資訊。
問: 非 EJB 專家,但學習大量 IBM 教程與紅皮書。個人認為 WebSphere Studio 生成「受管代碼」(優化管理容器)能力激發開發人員創造力,遠超不使用 EJB 開發,甚至適用於用不到 EJB 情況。問題:應糾正嗎?公司從純生產角度學習 WebSphere Studio/EJB 開發,但外部顧問發現所有 EJB 負面案例。若 IBM 有針對中小企業白皮書,展示比「Banking」應用更複雜的基於 Web EJB 應用(用 WebSphere Studio/Application Server vs Spring/Hibernate/JDO),將有幫助。認為加快設計開發速度應與減少實際代碼量同步,WebSphere Studio 能使代碼編寫更高效。花費時間、代碼量、效能、成本細節能證明用 WebSphere Studio 使 J2EE/EJB 開發比逐行推敲業務管理代碼更高效可維護。權衡硬體成本與縮短開發時間、維護龐大代碼庫成本,前者可忽略。
答: 贊同您對提供更多中小企業市場技術材料的意見,但我部門不切實際。我能做的是嘗試回答技術問題。您在正確軌道:最大化利用工具簡化工作、最大化利用容器簡化代碼編寫。簡短代碼更易編寫、測試、偵錯、維護、移植。代碼應以您獨特業務價值為主,而非尋找每個典型應用需求——容器可處理。對 EJB 負面案例無濃厚興趣。許多源於 EJB 1.0 時期並忽視本地介面、容器管理關聯(CMR)改進。大多負面案例包含實體 Bean 並忽視會話與訊息驅動 EJB 風險程度。
即使用實體 Bean,O/R 映射仍極難。您用什麼會更好?建議開發者從 CMP 實體 Bean 開始建模領域、處理資料庫 O/R 映射。「然而 CMP 很慢!」也許,O/R 映射是通用的,至少對 CMP 而言,您用容器優化流程。IBM 許多開發者致力將 O/R 映射做到最好。我問每位客戶:您真認為團隊能開發更好代碼嗎?(特別是他們已認為 EJB 太難?)我建議先嘗試 CMP。若證實太慢(或無法忍受),找出問題具體 Bean 並替換。再跑負載測試,驗證新代碼真優於被取代 CMP 代碼。若開發者嚴格檢查結果、不信傳聞,我認為他們會發現標準 J2EE 特性與 WebSphere 支持對實際工作極有利。
問: 用 WebSphere Studio 5.0 開發 J2EE 應用,欲部署至 WebSphere Application Server 4.0。EAR 由 Studio 5.0 產生,兼容 WAS 5.0,部署至 4.0 給 DTD 錯誤。僅使用無狀態會話 Bean。需哪些變更?在 WAS 4.0 哪裡部署?
答: 您意圖用 Studio 5.0(最新 5.1.2,建議升級)開發、部署至 WAS 4.0。您為 WAS 5.0 開發(Studio 5.0 預設模式),無法部署至 4.0。好消息:Studio 5.0 確可開發 WAS 4.0 應用,讓開發者升級工具即使產品未升級。做法:為 WAS 4.0 開發而非預設 WAS 5.0。
問: 單獨 DB2 實例(非分散式事務)上編碼的事務管理與回滾設計問題。應用用 DAO 模式存儲多張表,每 DAO 對應一表。會話外觀 EJB 業務方法調用多 DAO 存多表。啟用容器管理事務。閱讀聲明式事務管理文章,需做其中一件事:業務方法用 setRollBackOnly()、或業務方法拋出運行時異常。目前選第二項:構造 DAOException 擴展 RuntimeException,錯誤發生時所有 DAO 拋出實例。請建議哪選擇最好?哪能使代碼復用性更好?第一項需每業務方法加 setRollBackOnly() 代碼行,覺得麻煩。用 Studio V4 IDE 測試環境事務管理回滾良好,但部署至 WAS V4 從無回滾。有特定配置啟用 WAS V4 聲明式事務管理嗎?
答: 您善用模式。DAO 與 Session Facade 值得採用。因用 EJB,進入普遍困境:如何實作 EJB 代碼、使用應用異常?何時用 setRollbackOnly()?如何配合使用?
應用異常表示業務邏輯錯誤:提款超過餘額、預訂已訂座位、收取凍結信用卡費用等。不同於系統異常(記憶體耗盡、陣列越界等系統級錯誤)。依 EJB 規範(第 18 章),應用異常必須是 Exception 子類,不能是 RuntimeException 或 RemoteException 子類——極佳建議。規範規定:容器必須捕獲系統異常、標記事務回滾、向 EJB 客戶端拋出 RemoteException 或 EJBException。容器必須傳遞應用異常至 EJB 客戶端且不改變異常與事務。
我認為這矛盾:系統異常觸發自動回滾,應用異常不回滾。已拋出異常,您真想執行事務嗎(哪個是自動行為)?我不這麼認為。但這是 EJB 運作方式。
您的應用異常類是 RuntimeException 子類。這不好。雖自動回滾,但將有意義描述的應用異常轉為通用異常。規範說不要這樣做。您必須自行處理回滾。意味著在 Session Facade(EJB 容器最高層)編碼需養成習慣:捕獲應用異常、調用 setRollbackOnly()、重拋相同異常讓 EJB 客戶端知曉發生何事。這是寫優秀 EJB 代碼之道:向 EJB 容器外拋出異常前,勿用 RuntimeException 子類與 setRollbackOnly()。
問: 應用基於 WAS 4.0 J2EE 1.2 開發,現用 Studio 5.0(WAS 5.0)J2EE 1.3 標準轉換。有 EJB 模組(含所有 EJB)與 Web 模組。Web 模組成功轉換,EJB 模組轉換出錯:
Info: Project structure did not need migration: SCLS-ejb.
Info: J2EE version level did not need migration: SCLS-ejb.
Info: Migration was not required for META-INF/ejb-jar.xml.
Error: java.lang.NullPointerException
Error: Unable to migrate the Map and Schema file structure in project SCLS-ejb
因錯誤無法正常運行,所有實體 Bean 不工作,無法用實體 Bean 插入記錄。
答: 您用 Studio 5.0 J2EE Migration Wizard 嘗試將 1.2 應用移植至 1.3,因 NullPointerException 失敗。不了解您代碼難判斷工具故障。或許需求助 IBM Support。EJB 代碼無法正常執行,可能與移植工具故障有關,也可能因需移植代碼。遷移嚮導僅更新部署描述符,未更新 EJB 實作代碼。請見 Studio 線上說明「移植 J2EE 應用」與「從 J2EE 1.2 移植到 1.3」。
問: 我真需要學習 EJB 嗎?
答: 分享一個在 WebSphere Technical Exchange 大會的故事。我提出分散式(XA)事務上的會話與實驗:如何編碼及運作。實驗由簡單範例代碼組成,主要由 JDBC 資料庫與 JMS 訊息系統更新的無狀態會話 Bean(EJB),需分散式事務。範例含被 SSB 簡單調用的 Servlet。實驗極順利,事務回滾按預期,一切暢通。實驗後客戶問:「真棒!如何僅用 Servlet 完成?」答:「不能。」問為何不用 EJB。他與夥伴覺得 EJB 難。即使 EJB 與容器管理能使複雜編程簡化,人們仍覺得不夠簡單。
故事寓意:若您有完成複雜任務的工具,並想完成那些任務,則需學習工具。我不辯論 EJB 容易,但我不認為用其他技術能非常容易完成複雜任務:事務、安全、池、遠程調用——當然還有實體 Bean 的容器管理持久性。其他哪些技術讓您用面向數百使用者的物件支援上千使用者?其他哪些技術讓您在 XML 中宣告事務模型、安全模型、持久模型等並在運行時運作那些模型?
Java (J2SE) 包含龐大類庫,使開發不能任意妄為。J2EE 包含服務與框架,完成許多應用所需工作。讓容器做盡可能多工作,應用就不必做。以盡可能少代碼編寫應用,讓容器完成。代碼越少,開發越快、維護越易、移植越快。建議盡可能掌握容器帶來的益處、WebSphere Studio 等工具能完成的工作,並最大化利用它們。
問: 應用同步或非同步訊息傳遞?
答: 問題恆存在。我們用 RPC(RMI、CORBA、具遠程介面 EJB 等);為何用 JMS 或訊息傳遞?通常使用者等待回答時,因使用者同步,可同步調用。應用調用其他應用時,非同步調用。應用通告事件給其他應用時,也非同步。同步調用極易受破壞,為使遠程調用更穩固,要非同步調用。
有理解:訊息傳遞比 RPC 慢且低效。然而訊息傳遞確實有比 RPC 更高之處,僅一點效能差異,除非加入高品質服務如持久訊息傳遞。若訊息傳遞慢,因您網速慢,此情況 RPC 也會慢或完全不工作。
通常使用者介面不支援非同步調用,因 UI 阻礙調用,可能需等待。技術之一:重載頁面直到獲得結果。請見 Kyle Brown 著《J2EE 中的非同步查詢》。更好方法:重新設計 UI 使其非同步。如電子商務網站打包傳輸訂單時無瀏覽器阻礙,告知「謝謝訂購」,傳輸時發送含包裹號碼郵件。需 UI 打破工作流、非同步執行,故需如 Process Choreographer 等工作流引擎。處理以非同步方式完成,使用者可隨時檢查進度。
這是 Web 服務缺陷,無價值。目前 Web 服務(WS-I Basic Profile 1.1)是同步的。調用者發 HTTP 請求、阻塞等待 HTTP 回應。因 Web 服務用於應用間訊息傳遞,若支援非同步將更有用。
問: SOA 與 ESB 之間區別?
答: 面向服務架構(SOA)是架構方式,用於具自服務功能的應用,應用隨後透過 UI 或經工作流聚合成使用者功能。服務不僅可重用代碼組件,更是運行程序一部分,客戶端可不合併自身代碼直接調用程序。事實上應用邊界極模糊,包含所有能被調用執行其功能的服務。
企業服務總線(ESB)是調節 SOA 中調用者與服務提供者的機制。使調用者在不知提供者或提供者位址情況下調用服務。ESB 可在多提供者、提供者負載平衡、停用提供者(失效時)間選擇,並基於調用者需求在提供者間選擇(提供者提供各質量等級服務)。ESB 能調節同步或非同步服務,事實上對同一服務可提供同步與非同步存取。
因此 SOA 與 ESB 相對應。具備 SOA 應用應用 ESB 調用其服務。SOA 與 ESB 不必用 Web 服務實現。但常需 ESB 調用提供自我描述與發現能力的服務,Web 服務有助完成。SOA 中常需由一技術實現的調用者調用由其他技術實現的服務,Web 服務也有助完成。所以 SOA、ESB、Web 服務集中於創建領域——應用功能在其他應用中也可用,本質是重用性。