Java发布Webservice之一:出现小问题及解决

本文记录了在使用Java发布Web Service时遇到的问题及解决过程。从wsimport生成接口和实现类,到通过META-INF发布自定义wsdl,期间遇到了多个错误,包括:多schema目标命名空间错误、wsdl操作缺失、方法参数与wsdl不匹配等。通过查阅文档和添加正确注解,最终成功发布并验证了wsdl和xsd的一致性。

        最近学习做Webservice项目,模仿物流发货,A公司每向B公司一车货,发2次消息,分A出发时和到达B时,2消息内容相同。消息包含车号、司机、货物清单及可能是集装箱等。wsdl文件:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<wsdl:definitions
	xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
	xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap12/"
	xmlns:tsr="http://hjs.com/services/atob/lgsservice/v1.0/"
	xmlns:tns="http://hjs.com/schema/atob/logistics/"
	xmlns:resp="http://hjs.com/schema/atob/common/"
	xmlns:xsd="http://www.w3.org/2001/XMLSchema"
	name="LGSService"
	targetNamespace="http://hjs.com/services/atob/lgsservice/v1.0/">
	<!--  Revision History -->
	<!-- 
		v1.0 - 25 Jul 16 - For client review
	 -->
	<wsdl:types>
		<xsd:schema targetNamespace="http://hjs.com/schema/atob/logistics/">
			<xsd:include schemaLocation="ABLGS.xsd"/>
		</xsd:schema>
		<xsd:schema targetNamespace="http://hjs.com/schema/atob/common/">
			<xsd:include schemaLocation="ResponseMessage.xsd"/>
		</xsd:schema>
	</wsdl:types>
	<wsdl:message name="CommonResponse">
		<wsdl:part name="payload" element="resp:ResponseMessage"></wsdl:part>
	</wsdl:message>
	<wsdl:message name="CargoArrivalRequest">
		<wsdl:part name="payload" element="tns:CargoArrival"></wsdl:part>
	</wsdl:message>
	<wsdl:message name="CargoPreannounceRequest">
		<wsdl:part name="payload" element="tns:CargoPreannounce"></wsdl:part>
	</wsdl:message>
	<wsdl:portType name="LGSService">
		<wsdl:operation name="CargoArrival">
			<wsdl:input name="CargoArrivalRequest" message="tsr:CargoArrivalRequest"/>
			<wsdl:output name="CargoArrivalResponse" message="tsr:CommonResponse"/>
		</wsdl:operation>
		<wsdl:operation name="CargoPreannounce">
			<wsdl:input name="CargoPreannounceRequest" message="tsr:CargoPreannounceRequest"/>
			<wsdl:output name="CargoPreannounceResponse" message="tsr:CommonResponse"/>
		</wsdl:operation>
	</wsdl:portType>
	<wsdl:binding name="LGSServiceSOAP" type="tsr:LGSService">
		<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
		<wsdl:operation name="CargoArrival">
			<soap:operation soapAction="http://hjs.com/services/atob/lgsservice/v1.0/CargoArrival"/>
			<wsdl:input>
				<soap:body use="literal"/>
			</wsdl:input>
			<wsdl:output>
				<soap:body use="literal"/>
			</wsdl:output>
		</wsdl:operation>
		<wsdl:operation name="CargoPreannounce">
			<soap:operation soapAction="http://hjs.com/services/atob/lgsservice/v1.0/CargoPreannounce"/>
			<wsdl:input>
				<soap:body use="literal"/>
			</wsdl:input>
			<wsdl:output>
				<soap:body use="literal"/>
			</wsdl:output>
		</wsdl:operation>
	</wsdl:binding>
	<wsdl:service name="LGSService">
		<wsdl:port name="LGSServiceSOAP" binding="tsr:LGSServiceSOAP">
			<soap:address location="http://localhost:8090/services/atob/lgsservice/v1.0/"/>
		</wsdl:port>
	</wsdl:service>
	
</wsdl:definitions>

         用wsimport生成相应的类,主要的是接口LGSService,

@WebService(name = "LGSService", targetNamespace = "http://hjs.com/services/atob/lgsservice/v1.0/")
@XmlSeeAlso({
    com.hjs.schema.atob.logistics.ObjectFactory.class,
    com.hjs.schema.atob.common.ObjectFactory.class
})
public interface LGSService {
    @WebMethod(operationName = "CargoArrival", action = "http://hjs.com/services/atob/lgsservice/v1.0/CargoArrival")
    @RequestWrapper(localName = "CargoArrival", targetNamespace = "http://hjs.com/schema/atob/logistics/", className = "com.hjs.schema.atob.logistics.CargoArrival")
    @ResponseWrapper(localName = "ResponseMessage", targetNamespace = "http://hjs.com/schema/atob/common/", className = "com.hjs.schema.atob.common.ResponseMessageType")
    public void cargoArrival(
        @WebParam(name = "Head", targetNamespace = "http://hjs.com/schema/atob/logistics/")
        com.hjs.schema.atob.logistics.BaseMessageType.Head head,
        @WebParam(name = "LGS", targetNamespace = "http://hjs.com/schema/atob/logistics/")
        List<LGSType> lgs,
        @WebParam(name = "REFF_NO", targetNamespace = "http://hjs.com/schema/atob/common/", mode = WebParam.Mode.OUT)
        Holder<BigInteger> reffNO,
        @WebParam(name = "SENDER", targetNamespace = "http://hjs.com/schema/atob/common/", mode = WebParam.Mode.OUT)
        Holder<String> sender,
        @WebParam(name = "RECEIVER", targetNamespace = "http://hjs.com/schema/atob/common/", mode = WebParam.Mode.OUT)
        Holder<String> receiver,
        @WebParam(name = "RECEIVED_DTTM", targetNamespace = "http://hjs.com/schema/atob/common/", mode = WebParam.Mode.OUT)
        Holder<XMLGregorianCalendar> receivedDTTM,
        @WebParam(name = "ACKNSTAT", targetNamespace = "http://hjs.com/schema/atob/common/", mode = WebParam.Mode.OUT)
        Holder<BigInteger> acknstat,
        @WebParam(name = "ACKNREMARK", targetNamespace = "http://hjs.com/schema/atob/common/", mode = WebParam.Mode.OUT)
        Holder<String> acknremark);

    
    @WebMethod(operationName = "CargoPreannounce", action = "http://hjs.com/services/atob/lgsservice/v1.0/CargoPreannounce")
    @RequestWrapper(localName = "CargoPreannounce", targetNamespace = "http://hjs.com/schema/atob/logistics/", className = "com.hjs.schema.atob.logistics.CargoPreannounce")
    @ResponseWrapper(localName = "ResponseMessage", targetNamespace = "http://hjs.com/schema/atob/common/", className = "com.hjs.schema.atob.common.ResponseMessageType")
    public void cargoPreannounce(
        @WebParam(name = "Head", targetNamespace = "http://hjs.com/schema/atob/logistics/")
        com.hjs.schema.atob.logistics.BaseMessageType.Head head,
        @WebParam(name = "LGS", targetNamespace = "")
        List<LGSType> lgs,
        @WebParam(name = "REFF_NO", targetNamespace = "http://hjs.com/schema/atob/common/", mode = WebParam.Mode.OUT)
        Holder<BigInteger> reffNO,
        @WebParam(name = "SENDER", targetNamespace = "http://hjs.com/schema/atob/common/", mode = WebParam.Mode.OUT)
        Holder<String> sender,
        @WebParam(name = "RECEIVER", targetNamespace = "http://hjs.com/schema/atob/common/", mode = WebParam.Mode.OUT)
        Holder<String> receiver,
        @WebParam(name = "RECEIVED_DTTM", targetNamespace = "http://hjs.com/schema/atob/common/", mode = WebParam.Mode.OUT)
        Holder<XMLGregorianCalendar> receivedDTTM,
        @WebParam(name = "ACKNSTAT", targetNamespace = "http://hjs.com/schema/atob/common/", mode = WebParam.Mode.OUT)
        Holder<BigInteger> acknstat,
        @WebParam(name = "ACKNREMARK", targetNamespace = "http://hjs.com/schema/atob/common/", mode = WebParam.Mode.OUT)
        Holder<String> acknremark);

}


再做一个类LGSServiceImpl实现此接口

@WebService(name = "LGSService", targetNamespace = "http://hjs.com/services/atob/lgsservice/v1.0/")
@BindingType(value = javax.xml.ws.soap.SOAPBinding.SOAP12HTTP_BINDING)
public class LGSServiceImpl implements LGSService {

	@Override
	public void cargoArrival(Head head, List<LGSType> lgs, Holder<BigInteger> reffNO, Holder<String> sender,
			Holder<String> receiver, Holder<XMLGregorianCalendar> receivedDTTM, Holder<BigInteger> acknstat,
			Holder<String> acknremark) {
		// 代码省略。。。
	}

	@Override
	public void cargoPreannounce(Head head, List<LGSType> lgs, Holder<BigInteger> reffNO, Holder<String> sender,
			Holder<String> receiver, Holder<XMLGregorianCalendar> receivedDTTM, Holder<BigInteger> acknstat,
			Holder<String> acknremark) {
		// 代码省略。。。
	}

}

发布此服务

	LGSService ls = new LGSServiceImpl();
	Endpoint.publish("http://localhost:8090/services/atob/lgsservice/v1.0/", ls);


可以正常发布,打开http://localhost:8090/services/atob/lgsservice/v1.0/?wsdl,可以看到wsdl,但那是系统生成的,看起来别扭,也不方便客户端查看。

为了能让客户端查看原装的wsdl和其它schema,可以以META-DATA方式发布,如

	LGSService ls = new LGSServiceImpl();
	Endpoint lgsendpoint = Endpoint.create(ls);
	List<File> metadataFile = new ArrayList<File>();
	     metadataFile.add( new File("src/META-INF/wsdl/LGSService.wsdl"));
	     metadataFile.add( new File("src/META-INF/wsdl/BaseMessage.xsd"));
	     metadataFile.add( new File("src/META-INF/wsdl/ABAWBS.xsd"));
	     metadataFile.add( new File("src/META-INF/wsdl/CONTAINER.xsd"));
	     metadataFile.add( new File("src/META-INF/wsdl/ABLGS.xsd"));
	     metadataFile.add( new File("src/META-INF/wsdl/ResponseMessage.xsd"));
	     
	     List<Source> metadata = new ArrayList<Source>();
	     try {
	    	for(File file : metadataFile){
	    	 	Source source = new StreamSource(new FileInputStream(file));
	    	 	source.setSystemId(file.toURI().toURL().toExternalForm());
	    	 	metadata.add(source);
	    	}
			lgsendpoint.setMetadata(metadata);
			lgsendpoint.publish("http://localhost:8090/services/atob/lgsservice/v1.0/");
			
		} catch (FileNotFoundException | MalformedURLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

不能成功发布,系统报错:

服务器运行时错误: More than one schema for the target namespace http://hjs.com/schema/atob/logistics/

想了好久,什么问题?查看JAX-WS文档及网上资料,感觉是系统无法辨别是生成的wsdl和xsd还是原装META的,应该在类上指定,加上注释

	serviceName = "LGSService", portName = "LGSServiceSOAP",

再发布,系统报:

Method cargoPreannounce is exposed as WebMethod,
 but there is no corresponding wsdl operation with name {http://hjs.com/services/atob/lgsservice/v1.0/}cargoPreannounce in the wsdl:portType{http://hjs.com/services/atob/lgsservice/v1.0/}LGSService

原来是方法上没有加注释,那就加上吧

	@WebMethod(operationName = "CargoArrival", action = "http://hjs.com/services/atob/lgsservice/v1.0/CargoArrival")
    @RequestWrapper(localName = "CargoArrival", targetNamespace = "http://hjs.com/schema/atob/logistics/", className = "com.hjs.schema.atob.logistics.CargoArrival")
    @ResponseWrapper(localName = "ResponseMessage", targetNamespace = "http://hjs.com/schema/atob/common/", className = "com.hjs.schema.atob.common.ResponseMessageType")

再发布,还有错:

javax.xml.ws.WebServiceException: class com.hjs.schema.atob.logistics.CargoPreannounce do not have a property of the name arg0
再找资料,认为类内的方法参数与xsd不一致。参考接口方法的参数,全部复制到实现类里

public void cargoArrival(
		@WebParam(name = "Head", targetNamespace = "http://hjs.com/schema/atob/logistics/")
	        com.hjs.schema.atob.logistics.BaseMessageType.Head head,
	       @WebParam(name = "LGS", targetNamespace = "http://hjs.com/schema/atob/logistics/")
	        List<LGSType> lgs,
	        @WebParam(name = "REFF_NO", targetNamespace = "http://hjs.com/schema/atob/common/", mode = WebParam.Mode.OUT)
	        Holder<BigInteger> reffNO,
	        @WebParam(name = "SENDER", targetNamespace = "http://hjs.com/schema/atob/common/", mode = WebParam.Mode.OUT)
	        Holder<String> sender,
	        @WebParam(name = "RECEIVER", targetNamespace = "http://hjs.com/schema/atob/common/", mode = WebParam.Mode.OUT)
	        Holder<String> receiver,
	      @WebParam(name = "RECEIVED_DTTM", targetNamespace = "http://hjs.com/schema/atob/common/", mode = WebParam.Mode.OUT)
	        Holder<XMLGregorianCalendar> receivedDTTM,
	        @WebParam(name = "ACKNSTAT", targetNamespace = "http://hjs.com/schema/atob/common/", mode = WebParam.Mode.OUT)
	        Holder<BigInteger> acknstat,
	        @WebParam(name = "ACKNREMARK", targetNamespace = "http://hjs.com/schema/atob/common/", mode = WebParam.Mode.OUT)
	        Holder<String> acknremark
			) {
		// 省略代码。。。
	}


发布!OK啦!打开wsdl,与原装的一致。

<?xml version="1.0" encoding="UTF-8"?>

<!-- Published by JAX-WS RI (http://jax-ws.java.net). RI's version is JAX-WS RI 2.2.9-b130926.1035 svn-revision#5f6196f2b90e9460065a4c2f4e30e065b245e51e. -->

<wsdl:definitions name="LGSService" targetNamespace="http://hjs.com/services/atob/lgsservice/v1.0/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://hjs.com/schema/atob/logistics/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:resp="http://hjs.com/schema/atob/common/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:tsr="http://hjs.com/services/atob/lgsservice/v1.0/">

<!-- Revision History -->


<!-- v1.0 - 25 Jul 13 - For client review -->



<wsdl:types>


<xsd:schema targetNamespace="http://hjs.com/schema/atob/logistics/">

<xsd:include schemaLocation="http://localhost:8090/services/atob/lgsservice/v1.0/?xsd=2"/>

</xsd:schema>


<xsd:schema targetNamespace="http://hjs.com/schema/atob/common/">

<xsd:include schemaLocation="http://localhost:8090/services/atob/lgsservice/v1.0/?xsd=5"/>

</xsd:schema>

</wsdl:types>


<wsdl:message name="CommonResponse">

<wsdl:part name="payload" element="resp:ResponseMessage"/>

</wsdl:message>


<wsdl:message name="CargoArrivalRequest">

<wsdl:part name="payload" element="tns:CargoArrival"/>

</wsdl:message>


<wsdl:message name="CargoPreannounceRequest">

<wsdl:part name="payload" element="tns:CargoPreannounce"/>

</wsdl:message>


分别打开每一个xsd,也与原装发布的一致。算是成功发布了吧。


总结:在写实现类时,要按JAX-WS的要求,或参考接口,分别加上相应的注释,不只是简单实现。





评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值