最近在做一個呼叫webservice的客戶端,之前做過,我以為很容易,但這過程中遇到的一些問題讓我發現自己懂的還是太少。
webservice的服務端是需要憑證認證的,憑證已經寄給我了,cer格式的,使用java的keytool工具提取憑證後,在呼叫webservice時執行以下語句:
System.setProperty("javax.net.ssl.trustStore", "xxxx.truststore");
告訴服務端我客戶端是有憑證的,目前來看沒問題。
接下來,我用axis2的wsdl2java產生了客戶端的程式碼,結果一執行就出現以下錯誤:
org.apache.axis2.AxisFault: [ISS.0088.9125] SOAP request does not conform to the SOAP message model
在soap的開發文件中查到這個錯,是因為請求的soap message格式錯誤,文檔地址:http: //documentation.softwareag.com/webmethods/wmsuite7/Developer/Guides/7-1-1_SOAP_Developers_Guide.pdf (89頁)
這時對方要求我把soap request message發過去,我對webservice只是停留在用的階段,會用axis,xfire之類的工具寫服務端和客戶端,但是對soap就是一知半解了,上網找資料,問同事,折騰了半天,總算把request message找出來了。同事給的方法是用tcp monitor之類的工具,但是webservice是https格式的,不能用,後來在生成的客戶端程式碼裡把SOAPEnvelope.toString()打出來才得到,如下:
<?xml version='1.0' encoding='utf-8'?>
<soapenv:Envelope xmlns:soapenv=" http://schemas.xmlsoap.org/soap/envelope/ ">
<soapenv:Body>
<ns1:UPLGenerate xmlns:ns1=" http://www.alcatel-lucent.com/webService/WS_UPL ">
<OperationCode>1 </OperationCode>
<Plant>2 </Plant>
<QuoteNumber>3 </QuoteNumber>
<UserID>4 </UserID>
<IncludePriceType>5 </IncludePriceType>
</ns1:UPLGenerate>
</soapenv:Body>
</soapenv:Envelope>
其實這個問題的原因是axis2客戶端預設的transfer-encoding是chunked,所以在soap 請求報文的body首尾會有兩個數字,可以用tcpmon測試一下,.net或者其他一些server是不支援這種模式的,程式碼中設定一下就可以了,如下:
stub._getServiceClient().getOptions().setProperty(HTTPConstants.CHUNKED, false);
週末研究出來的,之前諮詢了公司的一個senior,幫我查,也給了我一些建議,非常感謝他!
現在執行應該沒問題了吧,我倒是想,結果又有問題了
Exception in thread "main" org.apache.axis2.AxisFault: org.apache.axis2.databinding.ADBException: Unexpected subelement xxxxResponse
at org.apache.axis2.AxisFault.makeFault(AxisFault.java:430)
這個問題折騰了我三天,在網路上查到很多,有的說要用wstx-asl-3.2.1.jar等等,都試了,不通,至少我這邊不是因為這個錯,很急,一點頭緒沒有,後來偶然在stub裡把org.apache.axiom.soap.SOAPEnvelope _returnEnv印出來了,就是_returnEnv.toString(),發現和用soapUI回傳的結果不一樣,因為這個webservice是https的,所以不能用tcpmon,這下明白了,因為返回response裡的一下元素不是一直有的,但是在wsdl定義裡卻沒有定義,即沒寫minOccurs="0",結果用這個wsdl生成的客戶端代碼如果沒取到那些沒回傳的元素,自然會報錯,在wsdl裡加上minOccurs="0",重新產生客戶端程式碼,測試,通過。
最後一步,部署到websphere上後,執行webservice呼叫出錯:
java.net.SocketException: Unconnected sockets not implemented
是證書的問題,花了好幾天時間,後來又反复,是因為缺少這個證書的父證書,總之如果在websphere裡無法通過host和port得到所有證書,包括從直接使用的證書到證書頒發機構的證書,只有透過導入.cer文件的方法了,問題的根源就在這裡:證書! ! !
遇到的問題很煩人,但是收穫也不小,這短短幾天,讓我對webservice的認識加深很多,很慚愧的說,以前只知道用axis等寫服務端,然後用wsdl生成客戶端,不知道用wsdl還可以產生服務端的。還好有這次機會,我進步了,大家共勉。
-