根據已有的wsdl,開發web service的服務端和客戶端
阿新 • • 發佈:2019-02-13
折騰了好長時間,今天終於把這次web service對接的需求完全開發完了,在此總結一下
spring的版本是3.0.6,cxf的版本是2.0.13,jboss版本是jboss4.2.3 GA,jdk6。此外客戶端和服務端的wsdl檔案,都是客戶提供好現成的,我們只能照著開發
主要用wsdl2java命令,根據第1個wsdl開發比較順利,見另外一篇部落格http://kyfxbl.iteye.com/blog/1481330
可是根據第2個wsdl檔案開發就悲劇了,用的命令也是wsdl2java -p packageName -d distLocation -all xxx.wsdl
結果報以下錯誤:
WSDLToJava Error: Thrown by JAXB : A class/interface with the same name "xxx.xxx.Message" is already in use. Use a class customization to resolve this conflict.
不知道是不是wsdl檔案本身的問題,我們也沒法改,於是就用了以下命令:
wsdl2java -p packageName -d distLocation -all -autoNameResolution xxx.wsdl
這次倒是生成了,可是釋出起來的時候,又報了以下錯誤:
Schema name conflict in collection. Namespace:xxxxxx
卡了一天也沒搞定,今天一個同事發現了一個辦法,改用以下命令:
wsdl2java -d distLocation -all xxx.wsdl
這次沒有用-p引數強制指定包名,結果cxf生成了很多個包,沒有再報原先的錯誤:
WSDLToJava Error: Thrown by JAXB : A class/interface with the same name "xxx.xxx.Message" is already in use. Use a class customization to resolve this conflict.
然後把所有生成的程式碼拷貝到工程裡面,刪掉了_Client、_Server、Service結尾的3個多餘檔案
說句題外話,用wsdl2java命令生成的程式碼,裡面冗餘是比較多的,不過一般都分成以下幾類,看多了就會分辨了:
第1類是request/response的model類,有時候會有巢狀,比如XXXRequest,XXXRequestBody之類的
第2類是_Client、_Server、_Service結尾的類,這些類基本都是可以放心刪除的
第3類是web service介面類和實現類,介面類是必須的,實現類在客戶端不需要,在服務端需要修改
第4類是package-info和ObjectFactory,需要保留,好像主要是跟packageName和targetNamespace有關,我也不太懂
然後在web service介面實現類中,刪掉了
之中的
刪掉它是覺得程式碼都生成了,這個wsdl檔案應該沒啥用了
結果啟動還是報剛才的錯誤:
Schema name conflict in collection. Namespace:xxxxxx
最後又把
加回去了,只是改成
然後把這個檔案放到伺服器上,這次終於成功了
釋出成功了,但是實際用soapUI調了一下,程式碼又出異常了,根據日誌定位了一下,發現是一個Spring裡宣告的bean找不到:
2012-04-11 21:28:06,859 ERROR [STDERR] org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'AcceptMsgImpl' is defined
我TMD就納悶了,這怎麼能找不到呢,程式碼裡是有的:
配置檔案也沒錯:
而且這段程式碼其實已經用過很長時間了,測試都測了幾輪,完全沒有問題。今天只是把web service介面相關的東西換了換,這裡居然就bean出異常了,實在理解不了
聯想到之前有一次,也是整合cxf和spring,結果@Autowired有異常,說找不到<jaxws:client>宣告的bean,我就想是不是spring和cxf有點啥東西我不清楚,造成註解不好使呢
為了先解決問題,把這裡改了,不用註解了,用普通的配置檔案
這樣一弄就行了,bean找到了。可是在我心裡就留下一個很大的問題,為什麼註解就不行了呢?
同樣用註解方式配置bean和依賴關係,這部分程式碼完全沒有變化。只是之前相關的web service的介面、實現類、Model,換了另外一套web service的介面、實現類、Model。其他的完全沒有變化,可是就是不行了,搞不懂
不管怎麼樣,問題還算是解決了,總結一下:
1、如果wsdl檔案有點問題,還是儘量不要用wsdl2java -p引數會好一點
2、web service實現類裡的@WebService註解裡的wsdlLocation屬性還是不能亂刪
3、我感覺spring和cxf整合的時候,spring的註解不太正常,時靈時不靈,保險起見,不要用就不會有問題了
遺留了一個問題,希望以後有機會能搞清楚是為什麼:
Spring和CXF整合的時候,有時候Spring的註解會不好用,這到底是為啥
spring的版本是3.0.6,cxf的版本是2.0.13,jboss版本是jboss4.2.3 GA,jdk6。此外客戶端和服務端的wsdl檔案,都是客戶提供好現成的,我們只能照著開發
主要用wsdl2java命令,根據第1個wsdl開發比較順利,見另外一篇部落格http://kyfxbl.iteye.com/blog/1481330
可是根據第2個wsdl檔案開發就悲劇了,用的命令也是wsdl2java -p packageName -d distLocation -all xxx.wsdl
結果報以下錯誤:
WSDLToJava Error: Thrown by JAXB : A class/interface with the same name "xxx.xxx.Message" is already in use. Use a class customization to resolve this conflict.
不知道是不是wsdl檔案本身的問題,我們也沒法改,於是就用了以下命令:
wsdl2java -p packageName -d distLocation -all -autoNameResolution xxx.wsdl
這次倒是生成了,可是釋出起來的時候,又報了以下錯誤:
Schema name conflict in collection. Namespace:xxxxxx
卡了一天也沒搞定,今天一個同事發現了一個辦法,改用以下命令:
wsdl2java -d distLocation -all xxx.wsdl
這次沒有用-p引數強制指定包名,結果cxf生成了很多個包,沒有再報原先的錯誤:
WSDLToJava Error: Thrown by JAXB : A class/interface with the same name "xxx.xxx.Message" is already in use. Use a class customization to resolve this conflict.
然後把所有生成的程式碼拷貝到工程裡面,刪掉了_Client、_Server、Service結尾的3個多餘檔案
說句題外話,用wsdl2java命令生成的程式碼,裡面冗餘是比較多的,不過一般都分成以下幾類,看多了就會分辨了:
第1類是request/response的model類,有時候會有巢狀,比如XXXRequest,XXXRequestBody之類的
第2類是_Client、_Server、_Service結尾的類,這些類基本都是可以放心刪除的
第3類是web service介面類和實現類,介面類是必須的,實現類在客戶端不需要,在服務端需要修改
第4類是package-info和ObjectFactory,需要保留,好像主要是跟packageName和targetNamespace有關,我也不太懂
然後在web service介面實現類中,刪掉了
@WebService(serviceName = "inbound.webServices.ticket.saService", portName = "inbound.webServices.ticket.saServiceSoap12", targetNamespace = "urn:services-astea.huawei.cz:inbound.webServices.tickets/v1.0/saService", wsdlLocation = "file:saService.wsdl", endpointInterface = "cz.huawei.astea.services.inbound_webservices_tickets.v1_0.saservice.InboundWebServicesTicketSaServiceSoap")
之中的
wsdlLocation = "file:saService.wsdl",
刪掉它是覺得程式碼都生成了,這個wsdl檔案應該沒啥用了
結果啟動還是報剛才的錯誤:
Schema name conflict in collection. Namespace:xxxxxx
最後又把
wsdlLocation = "file:saService.wsdl",
加回去了,只是改成
wsdlLocation = "file:/opt/xxx/saService.wsdl",
然後把這個檔案放到伺服器上,這次終於成功了
釋出成功了,但是實際用soapUI調了一下,程式碼又出異常了,根據日誌定位了一下,發現是一個Spring裡宣告的bean找不到:
2012-04-11 21:28:06,859 ERROR [STDERR] org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'AcceptMsgImpl' is defined
我TMD就納悶了,這怎麼能找不到呢,程式碼裡是有的:
@Service("AcceptMsgImpl") public class AcceptMsgImpl implements AcceptMsgService { @Autowired private WoCmDao woDao;
配置檔案也沒錯:
<import resource="classpath:META-INF/cxf/cxf.xml" /> <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" /> <import resource="classpath:META-INF/cxf/cxf-servlet.xml" /> <context:component-scan base-package="com.huawei.wfm.czekh" />
而且這段程式碼其實已經用過很長時間了,測試都測了幾輪,完全沒有問題。今天只是把web service介面相關的東西換了換,這裡居然就bean出異常了,實在理解不了
聯想到之前有一次,也是整合cxf和spring,結果@Autowired有異常,說找不到<jaxws:client>宣告的bean,我就想是不是spring和cxf有點啥東西我不清楚,造成註解不好使呢
為了先解決問題,把這裡改了,不用註解了,用普通的配置檔案
public class AcceptMsgImpl implements AcceptMsgService {
private WoCmDao woDao;
public void setWoDao(WoCmDao woDao) {
this.woDao = woDao;
}
<bean id="AcceptMsgImpl" class="com.huawei.wfm.czekh.service.impl.AcceptMsgImpl"> <property name="transitionDao" ref="tblWfconfTransitionHibernate" /> <property name="woDao" ref="woCmHibernateDao" /> </bean>
這樣一弄就行了,bean找到了。可是在我心裡就留下一個很大的問題,為什麼註解就不行了呢?
同樣用註解方式配置bean和依賴關係,這部分程式碼完全沒有變化。只是之前相關的web service的介面、實現類、Model,換了另外一套web service的介面、實現類、Model。其他的完全沒有變化,可是就是不行了,搞不懂
不管怎麼樣,問題還算是解決了,總結一下:
1、如果wsdl檔案有點問題,還是儘量不要用wsdl2java -p引數會好一點
2、web service實現類裡的@WebService註解裡的wsdlLocation屬性還是不能亂刪
3、我感覺spring和cxf整合的時候,spring的註解不太正常,時靈時不靈,保險起見,不要用就不會有問題了
遺留了一個問題,希望以後有機會能搞清楚是為什麼:
Spring和CXF整合的時候,有時候Spring的註解會不好用,這到底是為啥