1. 程式人生 > >Webservice客戶端工程導成runnable jar包執行時出現異常

Webservice客戶端工程導成runnable jar包執行時出現異常

一、問題描述
eclipse整合環境,spring 4.1.3.RELEASE + cxf 2.5.0框架,開發的Webservice客戶端程式。在eclipse開發環境下執行正常,匯出runnable jar包時出現如下異常:
java.lang.NullPointerException: null
at org.apache.cxf.wsdl11.WSDLServiceFactory.(WSDLServiceFactory.java:92)
at org.apache.cxf.jaxws.ServiceImpl.initializePorts(ServiceImpl.java:204)
at org.apache.cxf.jaxws.ServiceImpl.(ServiceImpl.java:148)
at org.apache.cxf.jaxws.spi.ProviderImpl.createServiceDelegate(ProviderImpl.java:90)
at javax.xml.ws.Service.(Unknown Source) ~[na:1.7.0_79]

二、初步分析
既然程式碼工程在eclipse能夠正常執行,匯出包後出現空指標異常,應該是打包的問題,runnable jar打包對依賴庫的處理方式有三種,如下圖所示:
這裡寫圖片描述
Library handing的三種處理方式解釋如下:
1、Extract required libraries into generated JAR。
把專案中所有的依賴jar包內的class,xml等檔案都拆開,放在jar的對應的目錄中,即匯出的jar檔案是一個獨立的,沒有其他依賴jar包的檔案,因為依賴的jar包已經全部拆散了。
2、Package required libraries into generated JAR。
把專案中所有的import jar都包在jar的根目錄下,還是以依賴包的形式存在,形成一個 完整的jar檔案。
3、Copy required libraries into a sub-folder next to the generated JAR。
把專案中所有import jar放在jar外面獨立的一個資料夾,jar包內只有工程的原始碼編譯的class檔案和其他配置檔案,這種方式匯出結果有兩個:一個工程jar包和一個資料夾。

以上三種方式,生成的效果基本相同,細心地可以發現,這三種方式生成的MANIFEST.MF檔案是不一樣的。
這三種方式匯出的jar包,執行命令都是 java -jar xxx.jar。

我們之前選的是第一種,執行後發現有異常,現在我們選第二種或第三種,試執行一下,OK。
由此可知,是第一種打包方式出現了問題,導致執行報錯。

三、解決方案
顯而易見,打包時選第二種或第三種方式即可。

四、問題深究
前面提到第一種打包方式導致異常,但具體是什麼原因導致的呢?
這樣我們必須除錯這個釋出包,確定是哪行程式碼導致的異常,這種情況我們需要用到遠端除錯,啟動命令該這樣寫了:
java -Xdebug -XRunjdwp;transport=dt_socket,server=y,address=8000 -jar test.jar
監聽8000埠(可以改成其他的),test.jar為示例jar包。
除錯的詳細過程就不贅述了,經過遠端除錯分析可知錯誤的原因:cxf框架有多個jar包都有bus-extensions.txt檔案,打包過程中是做的覆蓋操作,這點很重要,所有相同目錄,相同名稱的檔案會被覆蓋,例如cxf框架jar包內的META-INF\cxf目錄下就有幾個相同名稱的檔案,導致上述出現的錯誤。
有bus-extensions.txt的jar包:
cxf-rt-core-2.5.0.jar
cxf-rt-frontend-jaxws-2.5.0.jar
cxf-rt-bindings-xml-2.5.0.jar
cxf-rt-ws-addr-2.5.0.jar
cxf-rt-transports-http-2.5.0.jar
cxf-rt-bindings-soap-2.5.0.jar
共找到6個
綜上所述,導致包執行異常的原因還是出在打包的過程中,由於眾多jar包檔案存在重名可能性較大,尤其是META-INF目錄下,我們做不到逐一探查,建議慎重使用該打包方式。