1. 程式人生 > >根據已有的wsdl,開發web service的服務端和客戶端

根據已有的wsdl,開發web service的服務端和客戶端

折騰了好長時間,今天終於把這次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介面實現類中,刪掉了

@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的註解會不好用,這到底是為啥