一、jar包信息
其他地區的同事開發的模塊,依賴該jar包用於cli-name轉換,暫且叫它A.jar。
該模塊基於dropwizard框架,內部依賴比較複雜。
依賴A.jar後,調試過程中產生了不少問題,做個記錄,有些解決方案比較蠢。
二、springboot依賴該jar包,問題記錄
1. IDEA中運行junit單元測試,報錯:command line is too long
一般情況下可採用的解決方案 : https://blog.csdn.net/kzadmxz/article/details/80322687
但是依賴的這個jar包中,cli-name轉換流程,有獲取classpath,掃描jar包中的xml文件這個邏輯
String javaClassPath = System.getProperty("java.class.path");
dynamic classpath造成獲取到的classpath不正確,掃描不到xml文件,產生的問題類似這個:https://blog.csdn.net/moneyshi/article/details/82459039
最終解決“command line is too long”的方法還是要使本地存儲庫的路徑儘可能短,參考 http://www.it1352.com/535521.html
2. Application Run failed
A.jar基於dropwizard框架,應用啓動失敗可能是dropwizard的一些註解的影響或者引入了衝突的jar包,具體原因沒有深究。
對A.jar做了依賴分析,排除掉其中的xxx-xx-rest,應用可正常啓動
<dependency>
<groupId>com.xxx.xxx.xxx.platform</groupId>
<artifactId>xx-xx-xxconverthelper</artifactId>
<version>xxxxx</version>
<exclusions>
<exclusion>
<groupId>com.xxx.xxx.xx.platform</groupId>
<artifactId>xxx-xx-rest</artifactId>
</exclusion>
</exclusions>
</dependency>
3. 框架不兼容
前面提到依賴的這個jar,它是基於dropwizard框架下的一個module,默認的IOC容器爲hk2,其中有個類中存在這樣的代碼:
serviceLocator = ServiceLocatorHolder.getLocator();
inventoryLtpService = (InventoryLtpService)serviceLocator.getService(InventoryLtpService.class, new Annotation[0]);
我們是springboot框架,用的是springboot的IOC,hk2的serviceLocator必然是獲取不到的,上面的代碼會報空指針異常。
沒有想到什麼更好的方案,採用的解決方法是覆蓋jar包中的這個類,重新實現代碼邏輯。可參考:https://blog.csdn.net/u013062329/article/details/86592385
三、osgi依賴該jar包,問題記錄
1. jar包衝突
運行UT,報錯,查找到log4j-over-slf4j是由umben-em-rest間接引入的,直接全部排除掉umben-em-rest,同2.2
2. osgi依賴第三方非bundle的jar包
umebn-em-rosngconverthelper是一個普通的jar包,非bundle。參考https://blog.csdn.net/sunquan291/article/details/89189318
採用的解決方案是第三方依賴作成JAR,嵌入到當前bundle中。存在的問題是A.jar提供的cli-name轉換功能,裏面依賴了比較多其他jar包,需要一起嵌入進來,依賴傳遞問題比較嚴重,調試起來複雜,還有import-package的處理需要比較仔細。
對於依賴傳遞問題,一開始是做了依賴分析,想盡量把依賴都嵌入進來,避免調試時一遍遍出現ClassDefNotFound。但是一些錯誤引入會造成一些麻煩,比如我把jdom錯誤地作爲依賴寫在了pom裏,造成
bundle安裝時報錯,直到看到 https://stackoverflow.com/questions/33395100/the-default-package-is-not-permitted-by-the-import-package-syntax 最後一個回答,才意識到錯誤所在。儘量還是隻嵌入代碼邏輯需要用到的jar包,一來避免類似這樣的低級錯誤,二來儘量減小bundle的體積。
3. classpath問題
上面提到cli-name轉換流程,有獲取classpath,掃描jar包中的xml文件這個邏輯。當運行karaf時,debug到 System.getProperty("java.class.path") 這一步,無法獲取到JDK目錄下的lib jar包,因此無法找到xml文件。https://stackoverflow.com/questions/3906222/printing-osgi-bundle-classpath 這個Answer描述的是類似的問題。
目前對OSGI的底層原理和類加載器瞭解比較少,針對這個問題,採用的方法還是覆蓋jar包中的類,將xml文件放在指定位置,不掃描jar,去指定位置讀取。
4. bundle的文件讀取問題
將xml文件放在src/resources文件夾下,採用的文件加載方式爲:
URL url = this.getClass().getClassLoader().getResource(directory);
運行karaf之後,獲取到的url爲 bundleresource://214.fwk1205445235/converclass/,並不是常規的file:// 開頭的協議,因此還是會報找不到文件錯誤。網絡上的一種解決方法爲https://blog.csdn.net/windrui/article/details/40581219
5. xml文件解析異常
javax.xml.parsers.FactoryConfigurationError: Provider com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl could not be instantiated: java.lang.ClassCastException: com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl cannot be cast to javax.xml.parsers.SAXParserFactory
相似問題記錄:
https://stackoverflow.com/questions/2619880/unbelievable-cannot-cast-from-class-x-to-its-super-class
http://www.voidcn.com/article/p-annolfiy-btt.html