JBoss EAPJakarta EEJava 21企業系統升級

JBoss EAP 03:明明有 jar,為什麼找不到類別?模組與 Jakarta 入門

··閱讀約 3 分鐘
回到 JBoss EAP 系列導讀

Maven 已經 build 成功,EAP 卻報 ClassNotFoundException。編譯成功回答的是編譯器當時找不找得到類別;執行時則要看載入該元件的 class loader 能看到什麼。兩個問題有關,但不是同一張依賴清單。

三張清單一起看

清單看什麼不能推論什麼
Maven 依賴樹版本、scope、傳遞依賴EAP 一定載入同一版
WAR/EAR 內容實際打包的 jar 與類別每個模組都看得到
EAP 模組與部署依賴容器提供者與可見關係程式的所有路徑都已測過
先辨認證據回答哪一層。
bash
# Use your project checkout and an already built artifact.
mvn dependency:tree
jar tf orders.war

Maven 可能需要解析外掛與下載依賴;不想連網時,先讀既有建置紀錄與產物。EAP 採模組化載入,部署與 server module 的依賴有規則;EAR 子模組與 WAR 的隔離也有差別。jboss-deployment-structure.xml 可以影響依賴,但應在知道衝突來源之後再改,不要套用一份「排除全部」的網路範本。

javax 到 jakarta,不是全域取代

這次 Java EE 到 Jakarta EE 的 API,例如 javax.servlet、javax.persistence、javax.jms,要對應到目標 Jakarta API;Java SE 的 javax.sql、javax.naming、javax.crypto 則保留。連 XML schema、反射字串、服務註冊檔與第三方套件也可能受影響。程式碼 import 改完後,仍要檢查那些間接引用。

舊 javax.jms 的類別與 jakarta.jms 的類別不是同一種型別,不能靠同名介面互換。若應用與 adapter 各站在不同命名空間,先確認整條路徑使用哪套 API,再挑對應套件;不要先把兩套都加進去。

每種依賴先指定提供者

資源要回答的問題
Servlet/Jakarta API編譯用 API 與容器實作是否分清?
Spring哪些版本跟著應用打包?
Hibernate/JPA採容器提供者,還是有文件支持的應用提供者方案?
JDBC driver由 server 管理還是應用建立?對應哪個 DataSource?
這是決策表,不是通用的排除設定。

練習:兩個版本的同一個類別

假設 WAR 打包了 A 套件新版,server module 也有 A 的舊版,程式呼叫新方法時出現 NoSuchMethodError。這通常要查實際載入的類別版本與呼叫端預期,而不是再加第三個 jar。ClassNotFoundException 也要追是哪個 loader 查找失敗。答案要附上產物清單、有效依賴設定與完整 cause chain;先確定提供者,再調整 scope 或模組依賴,最後重跑會走到該方法的案例。

下載 EAP 離線學習包:盤點工具、練習與工作表下一課:04:JNDI、DataSource 與交易

參考資料