根据已有的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的注解会不好用,这到底是为啥

猜你喜欢

转载自kyfxbl.iteye.com/blog/1483953