WSDL
http://www.cnblogs.com/hujian/p/3494064.html
http://www.cnblogs.com/hujian/p/3497127.html
使用 WSDL 部署 Web 服务,第 2 部分: 简单对象访问协议(SOAP)
使用 WSDL 部署 Web 服务,第 3 部分: SOAP 互操作性
How does a simple WSDL file look?
There will be a portType element that is like an interface definition of the web-service. It would tell us :
- What type of input is expected and what output would be returned.
- Any headers they would be a part of the input/output messages.
- Faults generated if any.
There would be a binding element associated with the port type. Its like an implementation of the port type. It would give message format and protocol details:
- That the protocol used is SOAP.
- The message style - Document/RPC.
- The transport mechanism - HTTP/ SMTP.
- In case of SOAP, a SOAP action to help identify each of the operations.
The final component is the service element. It tells the web service clients
- where to access the service,
- via which port
- how the messages are defined.
The above information is represented in a port element. Each port elements is associated with a binding.
So why would a service have multiple port elements ? Why would you provide two ways to use the same operation to your clients?
The question is equivalent to "Why would an interface have two implementations ?" The one word answer to the two question would be - alternatives.
Maybe you have two versions of your web-service - Providing two ports in the service - say a OPERATION_NEW_PORT and OPERATION_OLD_PORT will allow the client to decide which of two implementations suit his need.
Maybe we need to provide transport layer variations - an HTTP version as well as an SMTP version. So an email client as well as an HTTP client could use the service.
Maybe you have varied implementations - a bare bones implementation for internal users and a more complex system (involving auditing, header checks etc) for external world users.
Or I just want to provide multiple endpoints (who is gonna stop me !!)
The point is there is a very good chance that the web-service will have to support multiple ports. I decided to add a new port to the random service.
I first defined a new binding (or a new implementation of the portType):
<wsdl:binding name="SampleServiceOperationsPortTypeSoap_V2"
type="tns:SampleServiceOperationsPortType">
<soap:binding style="document"
transport="http://schemas.xmlsoap.org/soap/http" /> <wsdl:operation name="random">
<soap:operation soapAction="/Service/random/V2" />
<wsdl:input name="GetRandomRequest">
<soap:body use="literal" />
</wsdl:input> <wsdl:output name="GetRandomResponse">
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
This binding is same as the existing binding (except for the name of course). The next step would be to update the service element:
<wsdl:service name="SampleServiceOperationsPortTypeSoap">
<wsdl:port binding="tns:SampleServiceOperationsPortTypeSoap"
name="SampleServiceOperationsPortTypeSoap">
<soap:address location="randomService" />
</wsdl:port> <wsdl:port binding="tns:SampleServiceOperationsPortTypeSoap_V2"
name="SampleServiceOperationsPortTypeSoap_V2">
<soap:address location="randomServiceV2" />
</wsdl:port>
</wsdl:service>
Here I now have two port elements - each associated with a different binding. I could also have associated the two with the same binding.
The most important part is the address element of the soap namespace. One port is exposed at "randomService" and the other is exposed at "randomServiceV2".
I decided to execute a wsdl2java (CXF) on the wsdl file. The dummy server class I received was for one of the ports only - the first one. So I decided to complete the implementations.
First the interface:
@WebService(targetNamespace = "http://ws.com/Service/samplews-ns", name = "SampleServiceOperationsPortType")
@XmlSeeAlso({ ObjectFactory.class })
@SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
public interface SampleServiceOperationsPortType{
/**
* Returns a random value from the application
*
*/ @WebResult(name = "GetRandomResponse",
targetNamespace = "http://ws.com/Service/xsd/random-schema", partName = "GetRandomResponse")
public GetRandomResponse random(
@WebParam(partName = "GetRandomRequest",
name = "GetRandomRequest", targetNamespace = "http://ws.com/Service/xsd/random-schema")
GetRandomRequest getRandomRequest); }
As seen the interface has exactly one operation - getRandom which is exposed by two endpoints. The old version is:
@javax.jws.WebService(serviceName = "SampleServiceOperationsPortTypeSoap",
portName = "SampleServiceOperationsPortTypeSoap", targetNamespace = "http://ws.com/Service/samplews-ns",
wsdlLocation = "random.wsdl",
endpointInterface = "com.ws.service.samplews_ns.SampleServiceOperationsPortType")
public class SampleServiceOperationsPortTypeImpl implements SampleServiceOperationsPortType { private static final Logger LOG = Logger.getLogger(SampleServiceOperationsPortTypeImpl.class.getName()); @Override
@WebMethod(action = "/Service/random")
public GetRandomResponse random(final GetRandomRequest getRandomRequest) {
LOG.info("Executing operation random - OLD VERSION !!!");
try {
final GetRandomResponse _return = new GetRandomResponse();
_return.setValue((int) (Math.random() * 165));
return _return;
} catch (final java.lang.Exception ex) {
ex.printStackTrace();
throw new RuntimeException(ex);
}
}
}
I manually added the second endpoint:
@javax.jws.WebService(serviceName = "SampleServiceOperationsPortTypeSoap",
portName = "SampleServiceOperationsPortTypeSoap",
targetNamespace = "http://ws.com/Service/samplews-ns", wsdlLocation = "random.wsdl",
endpointInterface = "com.ws.service.samplews_ns.SampleServiceOperationsPortType")
public class SampleServiceOperationsPortTypeImplV2 implements SampleServiceOperationsPortType { private static final Logger LOG = Logger.getLogger(SampleServiceOperationsPortTypeImplV2.class.getName()); @Override
@WebMethod(action = "/Service/random/V2")
public GetRandomResponse random(final GetRandomRequest getRandomRequest) {
LOG.info("Executing operation random - NEW VERSION !!!");
try {
final GetRandomResponse _return = new GetRandomResponse();
_return.setValue(-101);
return _return;
} catch (final java.lang.Exception ex) {
ex.printStackTrace();
throw new RuntimeException(ex);
}
}
}
As seen above the two classes implement the same webservice. The two endpoints have different soap action headers. Hence the WebMethod annotation has been placed not in the interface but in the implementation class.
If we were to test the two operations by posting our requests to the two URLs the different web services would be called.
An interesting thought that came to mind is, since the two endpoints differ in SOAP Action can we get them to have the same URL ? Would CXF use a combination of URL and SOAP Action header to uniquely identify the endpoint ?
The expectation would be that when a request is received at the operation address, CXF would check the SOAPAction header to decide where the URLs must be redirected to.
Accordingly I modified my endpoint beans to use the same URL:
<jaxws:endpoint id="randomWs_V1"
implementor="com.ws.service.samplews_ns.SampleServiceOperationsPortTypeImpl"
endpointName="SampleServiceOperationsPortTypeSoap" address="randomService" />
<jaxws:endpoint id="randomWs_V2"
implementor="com.ws.service.samplews_ns.SampleServiceOperationsPortTypeImplV2"
endpointName="SampleServiceOperationsPortTypeSoap_V2" address="randomService" />
The elements differ in their values for the endpointName attribute. This maps to the value of the port in the wsdl service element.
While the theory seemed fine (to me), the application failed at start up:
8135 [localhost-startStop-1] ERROR org.springframework.web.context.ContextLoader
- Context initialization failed
org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'randomWs_V2': Invocation of init method failed;
nested exception is javax.xml.ws.WebServiceException:
java.lang.RuntimeException: Soap 1.1 endpoint already registered on
address randomService
The Server was least interested in the Soap Action header. A few days later I had an opportunity to attend a training session on web services at our office. The trainer cleared my queries regarding SOAP Action header as:
I guess that kind of makes sense.
WSDL的更多相关文章
- webService学习之路(三):springMVC集成CXF后调用已知的wsdl接口
webService学习之路一:讲解了通过传统方式怎么发布及调用webservice webService学习之路二:讲解了SpringMVC和CXF的集成及快速发布webservice 本篇文章将讲 ...
- CXF:根据werservice代码生成WSDL(转)
原文:http://hongyegu.iteye.com/blog/619147,谢谢! import org.apache.cxf.tools.java2ws.JavaToWS; import ne ...
- WebServices:WSDL的结构分析
WSDL(Web Services Description Language,Web服务描述语言)是为描述Web Services发布的XML格式.W3C组织没有批准1.1版的WSDL,但是2.0版本 ...
- cxf webservice 生成wsdl方法参数名称为arg0问题
在通过cxf生成webservice服务时,如果你是用ServerFactoryBean,那么在生成wsdl时,方法的参数名称会被自动命名为arg0,arg1...,如: <xsd:comple ...
- cxf WebService设置wsdl中soapAction的值
用cxf开发一个WebService很简单,只需要下面几步: 1.定义接口 public interface HelloService { String hello(); } 2.实现 public ...
- 彻底理解webservice SOAP WSDL
WebServices简介 先给出一个概念 SOA ,即Service Oriented Architecture ,中文一般理解为面向服务的架构, 既然说是一种架构的话,所以一般认为 SOA 是包含 ...
- vs2013 手动生成webservice代理类wsdl
第一步: 第二步: 第三步: 至此wsdl代理类生成成功!
- Atitit wsdl的原理attilax总结
Atitit wsdl的原理attilax总结 1.1. 在 W3C 的 WSDL 发展史1 1.2. 获取wsdl,可能需要url后面加wsdl,也可能直接url1 1.3. Wsdl的作用2 1. ...
- C# 调用WebService的3种方式 :直接调用、根据wsdl生成webservice的.cs文件及生成dll调用、动态调用
1.直接调用 已知webservice路径,则可以直接 添加服务引用--高级--添加web引用 直接输入webservice URL.这个比较常见也很简单 即有完整的webservice文件目录如下图 ...
- 理解WebService SOAP WSDL
WebServices简介 先给出一个概念 SOA ,即Service Oriented Architecture ,中文一般理解为面向服务的架构, 既然说是一种架构的话,所以一般认为 SOA 是包含 ...
随机推荐
- async/await的实质理解
async/await关键字能帮助开发者更容易地编写异步代码.但不少开发者对于这两个关键字的使用比较困惑,不知道该怎么使用.本文就async/await的实质作简单描述,以便大家能更清楚理解. 一.a ...
- C# 平时碰见的问题【1】
1. SqlBulkCopy 可以利用这个类实现快速大批量新增数据的效果, 但在使用过程中发现了一个问题: 无法将数据源中的DateTime类型转换成数据库中的int类型 看起来就是数据列不对应导致的 ...
- GoogleMapApi 发布后提示安全问题
今天日本那边发过来一个Bug说是Google Map打不开,提示安全问题. 最后发现,日本那边的发布路径如下: https:xxxxx.gspserver.co.jp 而Source中Google M ...
- ORACLE DG之参数详解
1.DB_NAME 数据库名字,需要保持同一个Data Guard中所有数据库DB_NAME相同. 主库和备库相同 DB_NAME='chicago' DB_NAME='chicago' 2.DB_U ...
- PAT乙级真题1001. 害死人不偿命的(3n+1)猜想 (15)(解题)
卡拉兹(Callatz)猜想: 对任何一个自然数n,如果它是偶数,那么把它砍掉一半:如果它是奇数,那么把(3n+1)砍掉一半.这样一直反复砍下去,最后一定在某一步得到n=1.卡拉兹在1950年的世界数 ...
- andirod
于adnroid老手来说,SDK环境搭建是很简单的,但是对于我这样的小白来说,,,,,走啦很多弯路..特记下.希望对兄弟们有所帮助 因为我也是参考网上的高手知道,所以有的就直接复制啦,,^_^ 想要开 ...
- libevent简介 构成
libevent简介 libevent是一个事件驱动的网络库,支持跨平台,如Linux, *BSD, MacOS X, Solaris, Windows.支持I/O多路复用,epoll.poll./d ...
- MVC4.0 WebApi如何设置api支持namespace
1.自定义HttpControllerSelector /// <summary> /// 设置api支持namespace /// </summary> public cla ...
- MVC 中的@Html.DropDownList下拉框的使用
MVC 中的下拉框 实现方式,下面为大家介绍一个我自己认为比较好用的实现方式,而二话不说直接上代码: 第一步: 后台代码 //公共的方法 //在每次需要展示下拉框的时候,需要调用一下这个方法 [数据源 ...
- EF6 在原有数据库中使用 CodeFirst 总复习(一、搭建基础环境)
本来以为已经会了,可动手时发现许多问题还是模糊不清,正所谓眼高手低.只能重新查资料,再复习一遍. vs.net2013 ef6 mvc5 sqlserver2008 一.建立数据库 Bloggi ...