7.18.2016

Web Service – JAX-WS, что нужно знать, часть 2



Давайте продолжим знакомиться с технологией 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>
--------------------------------------