Давайте
продолжим знакомиться с технологией JAX-WS, рассмотрим следующую аннотацию @Oneway()
которая говорит нам что наш метод может иметь только входные параметры и ни
чего не возвращает нам, т.е. не будет от веб сервиса обратных сообщений. За чем
нам нужна эта аннотация? Вызов любого метода/операции веб сервиса происходит в
коде синхронно, т. е. пока не выполнится операция веб сервиса возврат в
программу на java не
произойдет. При вызове на клиенте
аннотированного метода аннотацией @Oneway(), возврат в программу произойдет
сразу же после отправки сообщения веб сервису. Есть один минус, мы никогда не
сможем узнать выполнилась наша операция
на веб сервисе или нет. Добавим метод void printLog(String
name); в наш предыдущий пример, рассмотренный
в прошлой статье:
package com.vit;
import javax.jws.Oneway;
import javax.jws.WebMethod;
import javax.jws.WebService;
@WebService(targetNamespace =
"http://lopanov.com")
public interface webService1 {
….
@WebMethod() @Oneway()
public void printLog(String name);
}
package com.vit;
import org.apache.cxf.annotations.Logging;
import org.apache.cxf.interceptor.InInterceptors;
import
org.apache.cxf.interceptor.OutInterceptors;
import javax.jws.HandlerChain;
import javax.jws.WebMethod;
import javax.jws.WebService;
@WebService(serviceName = "web",
portName = "HelloWorld", name = "Hello",
endpointInterface = "com.vit.webService1", targetNamespace =
"http://lopanov.com")
@org.apache.cxf.annotations.Logging
public class webService1Impl implements
webService1 {
….
@Override
public void printLog(String name) {
System.out.printf("My name is %s", name);
}
}
wsdl файл у операции <wsdl:operation name="printLog"> имеет только входящее сообщение, <wsdl:input message="tns:printLog"
name="printLog"> и не может послать обратное сообщение как операция <wsdl:operation name="getName"> смотрим wsdl файл:
…
<wsdl:message
name="printLog">
<wsdl:part
element="tns:printLog" name="parameters">
</wsdl:part>
</wsdl:message>
<wsdl:portType
name="webService1">
<wsdl:operation
name="getName">
<wsdl:input message="tns:getName"
name="getName"></wsdl:input>
<wsdl:output message="tns:getNameResponse"
name="getNameResponse">
</wsdl:output>
</wsdl:operation>
<wsdl:operation
name="printLog">
<wsdl:input
message="tns:printLog" name="printLog"></wsdl:input>
</wsdl:operation>
</wsdl:portType>
…
Перейдем к
расмотрению следующей аннотации @SOAPBinding. Как вы прекрасно знаете, веб
сервисы используют протокол SOAP
при передаче сообщений, он состоит из заголовка Header и тела сообщения Body. SOAP
body
сообщения по своему стилю делятся на два типа: DOCUMENT и RPC. SOAP
стиль
DOCUMENT – представляет собой xml
документ, которому сопоставлена xml schema и этой схемой можно проверить тело сообщения на правильность. SOAP стиль RPC – представляет собой, то же xml документ, но только параметры зашифрованы как
стек “вызова метода процедуры”(Remote Procedure Call - RPC). Стиль кодирования в аннотации @SOAPBinding выставляется параметром style и он может
принять одно из значений SOAPBinding.Style.DOCUMENT или SOAPBinding.Style.RPC. Следующий
момент, это то как могут быть закодированы значения параметров в SOAP сообщении, есть теоритически две
возможности LITERAL и ENCODED. LITERAL
– параметры представляются в “текстовом виде” xml, т.е. параметры сериализуются/преобразуются по подобию стандарта xml schema. ENCODED – параметры кодируются посредством правил из SOAP
Encoding. SOAP Encoding это расширение SOAP протокола, спешу вас расстроить стандарт JAX-WS
2.0 и выше не поддерживает SOAP Encoding и параметры только
кодируются как LITERAL. В аннотации @SOAPBinding стиль
преобразования значений параметров, вы можете выбрать посредством параметра use, который де-факто может
принимать только одно значение SOAPBinding.Use.LITERAL, а де-юре и значение SOAPBinding.Use.ENCODED.
Еще осталось сказать о количестве передаваемых параметров которое может
принимать операция веб сервиса, на это влияет параметр parameterStyle аннотации @SOAPBinding. Если выбрано значение
SOAPBinding.ParameterStyle.BARE – то операция может принят только один
параметр, если значение SOAPBinding.ParameterStyle.WRAPPED – то несколько
параметров, точнее сказать в SOAP
сообщение
могут вкладываться несколько тегов-параметров, а при BARE в теле сообщения
тегов-параметров нет. Значение BARE применимо
только к стилю кодирования DOCUMENT, RPC его не поддерживает. И так у нас
возможны только три варианта аннотации@SOAPBinding с такими значениями:
@SOAPBinding(style = SOAPBinding.Style.DOCUMENT,use = SOAPBinding.Use.LITERAL,parameterStyle = SOAPBinding.ParameterStyle.WRAPPED) для аннотации эти параметры выбраны по умолчанию
@SOAPBinding(style = SOAPBinding.Style.DOCUMENT,use =
SOAPBinding.Use.LITERAL,parameterStyle = SOAPBinding.ParameterStyle.BARE)
@SOAPBinding(style = SOAPBinding.Style.RPC,use =
SOAPBinding.Use.LITERAL,parameterStyle = SOAPBinding.ParameterStyle.WRAPPED)
Рассмотрим
все на нашем предыдущем примере, слегка поправим его.
package com.vit;
import javax.jws.Oneway;
import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
@WebService(targetNamespace =
"http://lopanov.com")
@SOAPBinding(style
= SOAPBinding.Style.DOCUMENT,use = SOAPBinding.Use.LITERAL,parameterStyle =
SOAPBinding.ParameterStyle.WRAPPED)
public interface webService1 {
@WebMethod(operationName = "", action = "", exclude
= false)
public String getName(String name, String soname);
….
}
Получаем
такой wsdl код,
обратите внимание на нашу операцию getName выделил его желтым цветом и тег <xs:schema в самом начале, который говорит нам
что SOAP стиль DOCUMENT
– представляет собой xml
документ которому сопоставлена <xml schema и этой
схемой можно проверить тело сообщения на правильность, повторю еще раз это
утверждение как мантру:
<?xml version="1.0" ?><wsdl:definitions
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:tns="http://lopanov.com"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:ns1="http://schemas.xmlsoap.org/soap/http"
name="web" targetNamespace="http://lopanov.com">
<wsdl:types>
<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:tns="http://lopanov.com"
elementFormDefault="unqualified"
targetNamespace="http://lopanov.com" version="1.0">
<xs:element name="getName"
type="tns:getName"></xs:element>
<xs:element name="getNameResponse"
type="tns:getNameResponse"></xs:element>
<xs:element name="printLog"
type="tns:printLog"></xs:element>
<xs:complexType name="getName">
<xs:sequence>
<xs:element minOccurs="0"
name="arg0" type="xs:string"></xs:element>
<xs:element minOccurs="0" name="arg1"
type="xs:string"></xs:element>
</xs:sequence>
</xs:complexType>
<xs:complexType name="getNameResponse">
<xs:sequence>
<xs:element minOccurs="0" name="return"
type="xs:string"></xs:element>
</xs:sequence>
</xs:complexType>
<xs:complexType name="printLog">
<xs:sequence>
<xs:element minOccurs="0" name="arg0"
type="xs:string"></xs:element>
</xs:sequence>
</xs:complexType>
</xs:schema>
</wsdl:types>
<wsdl:message name="getName">
<wsdl:part element="tns:getName"
name="parameters">
</wsdl:part>
</wsdl:message>
<wsdl:message name="getNameResponse">
<wsdl:part element="tns:getNameResponse"
name="parameters">
</wsdl:part>
</wsdl:message>
<wsdl:message name="printLog">
<wsdl:part element="tns:printLog"
name="parameters">
</wsdl:part>
</wsdl:message>
<wsdl:portType name="webService1">
<wsdl:operation name="getName">
<wsdl:input message="tns:getName"
name="getName">
</wsdl:input>
<wsdl:output message="tns:getNameResponse"
name="getNameResponse">
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="printLog">
<wsdl:input message="tns:printLog"
name="printLog">
</wsdl:input>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="webSoapBinding"
type="tns:webService1">
<soap:binding style="document"
transport="http://schemas.xmlsoap.org/soap/http"></soap:binding>
<wsdl:operation
name="getName">
<soap:operation
soapAction="" style="document"></soap:operation>
<wsdl:input name="getName">
<soap:body
use="literal"></soap:body>
</wsdl:input>
<wsdl:output name="getNameResponse">
<soap:body use="literal"></soap:body>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="printLog">
<soap:operation soapAction=""
style="document"></soap:operation>
<wsdl:input name="printLog">
<soap:body use="literal"></soap:body>
</wsdl:input>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="web">
<wsdl:port binding="tns:webSoapBinding"
name="HelloWorld">
<soap:address
location="http://localhost:8080/jboss_jaxws/web"></soap:address>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
SOAP сообщение выглядит как правильный xml документ, пометил желтым цветом:
21:10:08,316 INFO
[org.apache.cxf.services.web.HelloWorld.webService1] (default task-3)
Inbound Message
----------------------------
ID: 2
Address:
http://localhost:8080/jboss_jaxws/web
Encoding: UTF-8
Http-Method: POST
Content-Type: text/xml; charset=utf-8
Headers: {Accept=[text/xml,
multipart/related], connection=[keep-alive], Content-Length=[322], content-type=[text/xml;
charset=utf-8], Host=[localhost:8080], SOAPAction=[""],
User-Agent=[JAX-WS RI 2.2.9-b130926.1035
svn-revision#5f6196f2b90e9460065a4c2f4e30e065b245e51e]}
Payload: <?xml version="1.0"
?>
<S:Envelope
xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header></SOAP-ENV:Header>
<S:Body>
<ns2:getName xmlns:ns2="http://lopanov.com"> сообщение может содержать множество
тегов-параметров WRAPPED
<arg0 xmlns="">Vit</arg0>
<arg1
xmlns="">Lopanov</arg1>
</ns2:getName>
</S:Body>
</S:Envelope>
--------------------------------------
Поменяем наш
параметр на parameterStyle
= SOAPBinding.ParameterStyle.BARE
запускаем
пример на выполнение, получаем ошибку:
Exception in thread "main"
com.sun.xml.internal.ws.model.RuntimeModelerException: runtime modeler error:
SEI com.vit.webService1 has method getName annotated as BARE but it has more
than one parameter bound to body. This is invalid. Please annotate the method
with annotation:
@SOAPBinding(parameterStyle=SOAPBinding.ParameterStyle.WRAPPED)
Которая
предлагает сменить параметр с BARE на WRAPPED и говорит что у метода public String getName(String name, String
soname); больше чем один параметр, перепишем
код так и сново задеплоим веб сервис:
@SOAPBinding(style =
SOAPBinding.Style.DOCUMENT,use = SOAPBinding.Use.LITERAL,parameterStyle =
SOAPBinding.ParameterStyle.BARE)
public interface webService1 {
@WebMethod(operationName = "", action = "", exclude
= false)
public String getName(String name);//, String soname);
….
}
Получаем wsdl файл ищем различия с wsdl файлом WRAPPED, все осталось попрежнему кроме как в теге <xsd:schema стали использоваться простые типы:
<?xml version="1.0"
?><wsdl:definitions xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:tns="http://lopanov.com"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:ns1="http://schemas.xmlsoap.org/soap/http" name="web"
targetNamespace="http://lopanov.com">
<wsdl:types>
<xsd:schema
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:tns="http://lopanov.com"
attributeFormDefault="unqualified"
elementFormDefault="qualified"
targetNamespace="http://lopanov.com">
<xsd:element
name="getName" nillable="true"
type="xsd:string"></xsd:element>
<xsd:element
name="getNameResponse" nillable="true"
type="xsd:string"></xsd:element>
<xsd:element name="printLog"
nillable="true" type="xsd:string"></xsd:element>
</xsd:schema>
</wsdl:types>
<wsdl:message name="getName">
<wsdl:part element="tns:getName"
name="getName">
</wsdl:part>
</wsdl:message>
<wsdl:message name="getNameResponse">
<wsdl:part element="tns:getNameResponse"
name="getNameResponse">
</wsdl:part>
</wsdl:message>
<wsdl:message
name="printLog">
<wsdl:part element="tns:printLog"
name="printLog">
</wsdl:part>
</wsdl:message>
<wsdl:portType name="webService1">
<wsdl:operation name="getName">
<wsdl:input message="tns:getName"
name="getName">
</wsdl:input>
<wsdl:output message="tns:getNameResponse"
name="getNameResponse">
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="printLog">
<wsdl:input message="tns:printLog"
name="printLog">
</wsdl:input>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="webSoapBinding"
type="tns:webService1">
<soap:binding style="document"
transport="http://schemas.xmlsoap.org/soap/http"></soap:binding>
<wsdl:operation name="getName">
<soap:operation soapAction=""
style="document"></soap:operation>
<wsdl:input name="getName">
<soap:body use="literal"></soap:body>
</wsdl:input>
<wsdl:output name="getNameResponse">
<soap:body use="literal"></soap:body>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="printLog">
<soap:operation soapAction=""
style="document"></soap:operation>
<wsdl:input name="printLog">
<soap:body use="literal"></soap:body>
</wsdl:input>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="web">
<wsdl:port binding="tns:webSoapBinding"
name="HelloWorld">
<soap:address
location="http://localhost:8080/jboss_jaxws/web"></soap:address>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
SOAP сообщение выглядит опять же как
правильный xml
документ,
но только используется простой тип данных xml schema, пометил
желтым цветом:
21:26:28,833 INFO
[org.apache.cxf.services.web.HelloWorld.webService1] (default task-3)
Inbound Message
----------------------------
ID: 2
Address:
http://localhost:8080/jboss_jaxws/web
Encoding: UTF-8
Http-Method: POST
Content-Type: text/xml; charset=utf-8
Headers: {Accept=[text/xml,
multipart/related], connection=[keep-alive], Content-Length=[259],
content-type=[text/xml; charset=utf-8], Host=[localhost:8080],
SOAPAction=[""], User-Agent=[JAX-WS RI 2.2.9-b130926.1035
svn-revision#5f6196f2b90e9460065a4c2f4e30e065b245e51e]}
Payload:
<?xml version="1.0" ?>
<S:Envelope
xmlns:S="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header></SOAP-ENV:Header>
<S:Body>
<getName xmlns="http://lopanov.com">Vit</getName> в сообщение не
вкладываются ни какие теги-параметры, BARE
</S:Body>
</S:Envelope>
--------------------------------------
Осталось
расмотреть только последний пример SOAP RPC стиль, смотрим на java код:
@WebService(targetNamespace
= "http://lopanov.com")
@SOAPBinding(style
= SOAPBinding.Style.RPC,use = SOAPBinding.Use.LITERAL,parameterStyle =
SOAPBinding.ParameterStyle.WRAPPED)
public interface webService1 {
@WebMethod(operationName = "", action = "", exclude
= false)
public String getName(String name, String soname);
…
}
Получаем
файл wsdl сравниваем
с что нового дал нам RPC
стиль,
обратите внимание на тег <soap:operation и его атрибут style="rpc"> это
признаки RPC
стиля:
<?xml version="1.0"
?><wsdl:definitions
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:tns="http://lopanov.com"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:ns1="http://schemas.xmlsoap.org/soap/http" name="web"
targetNamespace="http://lopanov.com">
<wsdl:message name="getName">
<wsdl:part name="arg0" type="xsd:string">
</wsdl:part>
<wsdl:part name="arg1" type="xsd:string">
</wsdl:part>
</wsdl:message>
<wsdl:message name="getNameResponse">
<wsdl:part name="return" type="xsd:string">
</wsdl:part>
</wsdl:message>
<wsdl:message name="printLog">
<wsdl:part name="arg0" type="xsd:string">
</wsdl:part>
</wsdl:message>
<wsdl:portType name="webService1">
<wsdl:operation name="getName">
<wsdl:input message="tns:getName"
name="getName">
</wsdl:input>
<wsdl:output message="tns:getNameResponse"
name="getNameResponse">
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="printLog">
<wsdl:input message="tns:printLog"
name="printLog">
</wsdl:input>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="webSoapBinding"
type="tns:webService1">
<soap:binding style="rpc"
transport="http://schemas.xmlsoap.org/soap/http"></soap:binding>
<wsdl:operation
name="getName">
<soap:operation
soapAction="" style="rpc"></soap:operation>
<wsdl:input name="getName">
<soap:body namespace="http://lopanov.com"
use="literal"></soap:body>
</wsdl:input>
<wsdl:output name="getNameResponse">
<soap:body namespace="http://lopanov.com"
use="literal"></soap:body>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="printLog">
<soap:operation soapAction=""
style="rpc"></soap:operation>
<wsdl:input name="printLog">
<soap:body namespace="http://lopanov.com"
use="literal"></soap:body>
</wsdl:input>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="web">
<wsdl:port binding="tns:webSoapBinding"
name="HelloWorld">
<soap:address
location="http://localhost:8080/jboss_jaxws/web"></soap:address>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
Запустим
нашего java клиента и посмотрим особенности передачи
данных по протоколу SOAP
стиля
RPC, к сожалению он ни чем не отличается
от стиля DOCUMENT, для нашего простого примера:
21:04:45,771 INFO
[org.apache.cxf.services.web.HelloWorld.webService1] (default task-3)
Inbound Message
----------------------------
ID: 2
Address:
http://localhost:8080/jboss_jaxws/web
Encoding: UTF-8
Http-Method: POST
Content-Type: text/xml; charset=utf-8
Headers: {Accept=[text/xml,
multipart/related], connection=[keep-alive], Content-Length=[322],
content-type=[text/xml; charset=utf-8], Host=[localhost:8080],
SOAPAction=[""], User-Agent=[JAX-WS RI 2.2.9-b130926.1035
svn-revision#5f6196f2b90e9460065a4c2f4e30e065b245e51e]}
Payload: <?xml version="1.0"
?>
<S:Envelope
xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header></SOAP-ENV:Header>
<S:Body>
<ns2:getName
xmlns:ns2="http://lopanov.com">
<arg0
xmlns="">Vit</arg0>
<arg1
xmlns="">Lopanov</arg1>
</ns2:getName>
</S:Body>
</S:Envelope>
--------------------------------------
Перейдем к
следующей аннотации @WebParam() которая позволяет настраивать конкретный
параметр операции. Первый параметр этой аннотации name, он рассматривается через
призму выставленных параметров аннотации @SOAPBinding(): если DOCUMENT/LITERAL/WRAPPED
то имена являются именами сложного типа xml schema
<xs:complexType
name="getName">, смотрим
пример:
@WebService(targetNamespace
= "http://lopanov.com")
@SOAPBinding(style
= SOAPBinding.Style.DOCUMENT,use = SOAPBinding.Use.LITERAL,parameterStyle =
SOAPBinding.ParameterStyle.WRAPPED)
public interface webService1 {
@WebMethod(operationName = "", action = "", exclude
= false)
public String getName(
@WebParam(name =
"name1") String name,
@WebParam(name =
"soname2") String
soname);
…
}
На wsdl файл отобразится так:
….
<wsdl:types>
<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:tns="http://lopanov.com"
elementFormDefault="unqualified"
targetNamespace="http://lopanov.com" version="1.0">
<xs:element name="getName"
type="tns:getName"></xs:element>
….
<xs:complexType
name="getName">
<xs:sequence>
<xs:element minOccurs="0" name="name1"
type="xs:string"></xs:element>
<xs:element minOccurs="0" name="soname2"
type="xs:string"></xs:element>
</xs:sequence>
</xs:complexType>
….
</xs:schema>
….
Запустив java пример, мы получим такой SOAP лог:
20:59:26,504 INFO
[org.apache.cxf.services.web.HelloWorld.webService1] (default task-3)
Inbound Message
----------------------------
ID: 2
Address:
http://localhost:8080/jboss_jaxws/web
Encoding: UTF-8
Http-Method: POST
Content-Type: text/xml; charset=utf-8
Headers: {Accept=[text/xml,
multipart/related], connection=[keep-alive], Content-Length=[330],
content-type=[text/xml; charset=utf-8], Host=[localhost:8080],
SOAPAction=[""], User-Agent=[JAX-WS RI 2.2.9-b130926.1035
svn-revision#5f6196f2b90e9460065a4c2f4e30e065b245e51e]}
Payload: <?xml version="1.0"
?>
<S:Envelope
xmlns:S="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header></SOAP-ENV:Header>
<S:Body>
<ns2:getName
xmlns:ns2="http://lopanov.com">
<name1
xmlns="">Vit</name1>
<soname2
xmlns="">Lopanov</soname2>
</ns2:getName>
</S:Body>
</S:Envelope>
--------------------------------------
если RPC/LITERAL/WRAPPED то имена отобразятся на тег <wsdl:part wsdl файла, смотрим пример:
@WebService(targetNamespace
= "http://lopanov.com")
@SOAPBinding(style
= SOAPBinding.Style.RPC,use = SOAPBinding.Use.LITERAL,parameterStyle =
SOAPBinding.ParameterStyle.WRAPPED)
public interface webService1 {
@WebMethod(operationName = "", action = "", exclude
= false)
public String getName(
@WebParam(name =
"name1") String name,
@WebParam(name =
"soname2") String
soname);
…
}
На wsdl файл отобразится так:
….
<wsdl:message
name="getName">
<wsdl:part name="name1"
type="xsd:string">
</wsdl:part>
<wsdl:part name="soname2"
type="xsd:string">
</wsdl:part>
</wsdl:message>
….
Вывод SOAP лога будет подобен, параметрам аннотации @SOAPBinding():DOCUMENT/LITERAL/WRAPPED.
Расмотрим следующий параметр аннотации @WebParam() – это mode, этим параметром мы указываем является ли параметр операции
только входным, принимающим от нас значения (WebParam.Mode.IN), он установлен
по умолчанию, возвращающим нам значение - выходным параметром (WebParam.Mode.OUT), или и входным и возвращающим нам значения (WebParam.Mode.INOUT).
Входные параметры включаются только в исходящее от нас SOAP сообщения, а выходные только во входящие к нам SOAP сообщения.
Если параметр является выходным OUT или входным и выходным INOUT, то он должен обертываться в
специальный класс обертку javax.xml.ws.Holder<T> который эмулирует
передачу параметра по сылке клиету. Влучае если вы не обернете параметр в класс
Holder<T>, при
вызове операции веб сервиса произойдет Exception:
Exception in thread "main"
java.lang.ClassCastException: java.lang.String cannot be cast to javax.xml.ws.Holder
И так следующий
параметр это header, если он выставлен, то параметр передается в заголовке SOAP сообщения, иначе в теле. По умолчанию
он равен false.
Следующий параметр targetNamespace указывает пространство имен, но он работает
только для “стиля” DOCUMENT/LITERAL/WRAPPED.
Следующий параметр partName указывает имя для тега <wsdl:part справедливо
только для “стиля” RPC/LITERAL/WRAPPED
или DOCUMENT/LITERAL/BARE. Давайте рассмотрим,
как эти параметры влияют на wsdl
файл и какие при этом получаются SOAP
сообщение,
добавим их в наш предыдущий код:
package com.vit;
import javax.jws.Oneway;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.xml.ws.Holder;
@WebService(targetNamespace =
"http://lopanov.com")
@SOAPBinding(style =
SOAPBinding.Style.RPC,use = SOAPBinding.Use.LITERAL,parameterStyle =
SOAPBinding.ParameterStyle.WRAPPED)
public interface webService1 {
@WebMethod(operationName = "", action = "", exclude
= false)
public String getName(
@WebParam(name = "name1",mode = WebParam.Mode.INOUT)
Holder<String>
name, //строку обернули в тип Holder
@WebParam(header = true,//параметр
будет содержаться в заголовке сообщения SOAP
partName = "SonameWebParam2")
String soname);
….
}
Wsdl файл:
<?xml version="1.0"
?><wsdl:definitions
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:tns="http://lopanov.com"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:ns1="http://schemas.xmlsoap.org/soap/http" name="web"
targetNamespace="http://lopanov.com">
<wsdl:types>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:tns="http://lopanov.com"
attributeFormDefault="unqualified"
elementFormDefault="unqualified"
targetNamespace="http://lopanov.com">
<xsd:element name="arg1" nillable="true"
type="xsd:string"></xsd:element>
</xsd:schema>
</wsdl:types>
<wsdl:message name="getName">
<wsdl:part name="name1" type="xsd:string">
</wsdl:part>
<wsdl:part
element="tns:arg1" name="SonameWebParam2">
</wsdl:part>
</wsdl:message>
<wsdl:message name="getNameResponse">
<wsdl:part name="return" type="xsd:string">
</wsdl:part>
<wsdl:part
name="name1" type="xsd:string">
</wsdl:part>
</wsdl:message>
<wsdl:message name="printLog">
<wsdl:part name="arg0" type="xsd:string">
</wsdl:part>
</wsdl:message>
<wsdl:portType name="webService1">
<wsdl:operation name="getName" parameterOrder="name1
SonameWebParam2">
<wsdl:input message="tns:getName"
name="getName">
</wsdl:input>
<wsdl:output message="tns:getNameResponse"
name="getNameResponse">
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="printLog">
<wsdl:input message="tns:printLog"
name="printLog">
</wsdl:input>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="webSoapBinding"
type="tns:webService1">
<soap:binding style="rpc"
transport="http://schemas.xmlsoap.org/soap/http"></soap:binding>
<wsdl:operation name="getName">
<soap:operation soapAction=""
style="rpc"></soap:operation>
<wsdl:input name="getName">
<soap:header
message="tns:getName" part="SonameWebParam2" use="literal">
</soap:header>
<soap:body namespace="http://lopanov.com"
parts="name1" use="literal"></soap:body>
</wsdl:input>
<wsdl:output name="getNameResponse">
<soap:body namespace="http://lopanov.com"
use="literal"></soap:body>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="printLog">
<soap:operation soapAction=""
style="rpc"></soap:operation>
<wsdl:input name="printLog">
<soap:body namespace="http://lopanov.com"
use="literal"></soap:body>
</wsdl:input>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="web">
<wsdl:port binding="tns:webSoapBinding" name="HelloWorld">
<soap:address
location="http://localhost:8080/jboss_jaxws/web"></soap:address>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
SOAP сообщения:
21:01:44,514 INFO
[org.apache.cxf.services.web.HelloWorld.webService1] (default task-3)
Inbound Message
----------------------------
ID: 2
Address:
http://localhost:8080/jboss_jaxws/web
Encoding: UTF-8
Http-Method: POST
Content-Type: text/xml; charset=utf-8
Headers: {Accept=[text/xml,
multipart/related], connection=[keep-alive], Content-Length=[340],
content-type=[text/xml; charset=utf-8], Host=[localhost:8080],
SOAPAction=[""], User-Agent=[JAX-WS RI 2.2.9-b130926.1035
svn-revision#5f6196f2b90e9460065a4c2f4e30e065b245e51e]}
Payload: <?xml version="1.0"
?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<S:Header>
<ns2:arg1
xmlns:ns2="http://lopanov.com">Lopanov</ns2:arg1>
</S:Header>
<S:Body>
<ns2:getName
xmlns:ns2="http://lopanov.com">
<name1 xmlns="">Vit</name1>
</ns2:getName>
</S:Body>
</S:Envelope>
--------------------------------------
21:01:44,617 INFO
[org.apache.cxf.services.web.HelloWorld.webService1] (default task-3)
Outbound Message
---------------------------
ID: 2
Response-Code: 200
Encoding: UTF-8
Content-Type: text/xml
Headers: {}
Payload: <soap:Envelope
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
</SOAP-ENV:Header>
<soap:Body>
<ns1:getNameResponse
xmlns:ns1="http://lopanov.com">
<return>Hello
my is Vit</return>
<name1>Vit</name1>
</ns1:getNameResponse>
</soap:Body>
</soap:Envelope>
--------------------------------------
Рассмотрим следующую аннотацию @WebResult(), она описывает, как будет выглядеть возвращаемое значение параметра в SOAP сообщении. Параметр header аналогичен аннотации @WebParam(), если он выставлен, то параметр передается
в заголовке SOAP
сообщения, иначе в теле. По умолчанию он равен false. Следующий параметр targetNamespace указывает пространство имен в
SOAP сообщении возвращаемого тега.
Параметр name выставляет имя возвращаемого тега в SOAP
сообщении, для wsdl файла
опять играют роль параметры, выставленные в аннотации @SOAPBinding(): если DOCUMENT/LITERAL/WRAPPED
то значение параметра name является
именем типа xml
schema. Если RPC/LITERAL/WRAPPED то именем тега <wsdl:part. Следующий параметр partName,
выставляет имя тега <wsdl:part если только выставлены параметры RPC/LITERAL/WRAPPED, иначе нет никакого эффекта. Добавим
аннотацию в наш пример:
@WebService(targetNamespace
= "http://lopanov.com")
@SOAPBinding(style =
SOAPBinding.Style.DOCUMENT,use = SOAPBinding.Use.LITERAL,parameterStyle =
SOAPBinding.ParameterStyle.WRAPPED)
public interface webService1 {
@WebMethod(operationName = "", action = "", exclude
= false)
@WebResult(name =
"nameWebResult")
public String getName(
@WebParam(name = "name1",mode = WebParam.Mode.INOUT)
Holder<String> name,
@WebParam(header = true,partName = "SonameWebParam2")
String soname);
У нас
будет сгенерирован такой wsdl
файл:
<?xml version="1.0"
?><wsdl:definitions xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:tns="http://lopanov.com"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:ns1="http://schemas.xmlsoap.org/soap/http" name="web"
targetNamespace="http://lopanov.com">
<wsdl:types>
<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:tns="http://lopanov.com"
attributeFormDefault="unqualified"
elementFormDefault="unqualified"
targetNamespace="http://lopanov.com">
<xs:element name="getName" type="tns:getName"></xs:element>
<xs:element name="getNameResponse"
type="tns:getNameResponse"></xs:element>
<xs:element name="printLog"
type="tns:printLog"></xs:element>
<xs:complexType name="getName">
<xs:sequence>
<xs:element minOccurs="0" name="name1"
type="xs:string"></xs:element>
</xs:sequence>
</xs:complexType>
<xs:complexType name="getNameResponse">
<xs:sequence>
<xs:element
minOccurs="0" name="nameWebResult"
type="xs:string"></xs:element>
<xs:element minOccurs="0" name="name1"
type="xs:string"></xs:element>
</xs:sequence>
</xs:complexType>
<xs:complexType name="printLog">
<xs:sequence>
<xs:element minOccurs="0" name="arg0"
type="xs:string"></xs:element>
</xs:sequence>
</xs:complexType>
<xs:element name="arg1" nillable="true"
type="xs:string"></xs:element>
</xs:schema>
</wsdl:types>
<wsdl:message name="getName">
<wsdl:part element="tns:getName"
name="parameters">
</wsdl:part>
<wsdl:part element="tns:arg1"
name="SonameWebParam2">
</wsdl:part>
</wsdl:message>
<wsdl:message name="getNameResponse">
<wsdl:part element="tns:getNameResponse"
name="parameters">
</wsdl:part>
</wsdl:message>
<wsdl:message name="printLog">
<wsdl:part element="tns:printLog"
name="parameters">
</wsdl:part>
</wsdl:message>
<wsdl:portType name="webService1">
<wsdl:operation name="getName">
<wsdl:input message="tns:getName"
name="getName">
</wsdl:input>
<wsdl:output message="tns:getNameResponse"
name="getNameResponse">
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="printLog">
<wsdl:input message="tns:printLog"
name="printLog">
</wsdl:input>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="webSoapBinding"
type="tns:webService1">
<soap:binding style="document"
transport="http://schemas.xmlsoap.org/soap/http"></soap:binding>
<wsdl:operation name="getName">
<soap:operation soapAction=""
style="document"></soap:operation>
<wsdl:input name="getName">
<soap:header message="tns:getName"
part="SonameWebParam2" use="literal">
</soap:header>
<soap:body parts="parameters"
use="literal"></soap:body>
</wsdl:input>
<wsdl:output name="getNameResponse">
<soap:body use="literal"></soap:body>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="printLog">
<soap:operation soapAction=""
style="document"></soap:operation>
<wsdl:input name="printLog">
<soap:body
use="literal"></soap:body>
</wsdl:input>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="web">
<wsdl:port binding="tns:webSoapBinding"
name="HelloWorld">
<soap:address location="http://localhost:8080/jboss_jaxws/web"></soap:address>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
К нам
придет ответное SOAP
сообщение
такого вида:
21:40:44,299 INFO
[org.apache.cxf.services.web.HelloWorld.webService1] (default task-3)
Outbound Message
---------------------------
ID: 2
Response-Code: 200
Encoding: UTF-8
Content-Type: text/xml
Headers: {}
Payload: <soap:Envelope
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"></SOAP-ENV:Header>
<soap:Body>
<ns2:getNameResponse xmlns:ns2="http://lopanov.com">
<nameWebResult>Hello
my is Vit</nameWebResult>
<name1>Vit</name1>
</ns2:getNameResponse>
</soap:Body>
</soap:Envelope>
--------------------------------------
Комментариев нет:
Отправить комментарий