| :index-group: Web Services :jbake-type: page :jbake-status: |
| status=published = parâmetros @WebService OUT via javax.xml.ws.Holder |
| |
| Com SOAP é possivel retornar multiplos valores em uma única requisição. |
| Isto é impossível em Java pois um método pode retornar somente um objeto. |
| |
| JAX-WS resolve esse problema com o conceito de Holders. Um |
| `javax.xml.ws.Holder` é um simples wrapper objeto que pode ser passado para |
| o método `@WebService` como um parâmetro. A aplicação atribui o valor |
| do mantenedor durante a requisição e o servidor enviará valor de volta |
| como um parâmetro OUT. |
| |
| == Usando @WebParam e javax.xml.ws.Holder |
| |
| A anotação `@WebParam` nos permite declarar os Holders `soma` e `multiplicação` |
| como parâmetros `WebParam.Mode.OUT`. Como mencionado, esses mantenedores |
| são simplesmente cestas vázias, a aplicação pode preencher com dados para poder |
| enviar para o cliente. O servidor irá passar então, em não inicializado. |
| |
| [source,java] |
| ---- |
| @Stateless |
| @WebService( |
| portName = "CalculatorPort", |
| serviceName = "CalculatorService", |
| targetNamespace = "http://superbiz.org/wsdl", |
| endpointInterface = "org.superbiz.ws.out.CalculatorWs") |
| public class Calculator implements CalculatorWs { |
| |
| public void sumAndMultiply(int a, int b, |
| @WebParam(name = "sum", mode = WebParam.Mode.OUT) Holder<Integer> sum, |
| @WebParam(name = "multiply", mode = WebParam.Mode.OUT) Holder<Integer> multiply) { |
| sum.value = a + b; |
| multiply.value = a * b; |
| } |
| } |
| ---- |
| |
| Se os Holders foram especificados como parâmetros `WebParam.Mode.INOUT`, então o |
| cliente consegueria utilizá-los para enviar dados e a aplicação também. A |
| instância `Holder` seria então inicializada com os dados que da |
| requisição do cliente. A aplicação poderia verificar os dados antes eventualmente |
| sobrescrevendo-os com os valores de resposta. |
| |
| == O WSDL |
| |
| O componente JAX-WS `@WebService` acima resulta no seguinte WSDL |
| que será criado automaticamente. Aviso o tipo complexo `sumAndMultiplyResponse` |
| retorna dois elementos. Estes correspondem as declarações `@WebParam` |
| e nossos dois parâmetros `Holder<Integer>`. |
| |
| [source,xml] |
| ---- |
| <?xml version="1.0" encoding="UTF-8"?> |
| <wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" |
| name="CalculatorService" |
| targetNamespace="http://superbiz.org/wsdl" |
| xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" |
| xmlns:tns="http://superbiz.org/wsdl" |
| xmlns:xsd="http://www.w3.org/2001/XMLSchema"> |
| <wsdl:types> |
| <xsd:schema attributeFormDefault="unqualified" elementFormDefault="unqualified" |
| targetNamespace="http://superbiz.org/wsdl" |
| xmlns:tns="http://superbiz.org/wsdl" |
| xmlns:xsd="http://www.w3.org/2001/XMLSchema"> |
| <xsd:element name="sumAndMultiply" type="tns:sumAndMultiply"/> |
| <xsd:complexType name="sumAndMultiply"> |
| <xsd:sequence> |
| <xsd:element name="arg0" type="xsd:int"/> |
| <xsd:element name="arg1" type="xsd:int"/> |
| </xsd:sequence> |
| </xsd:complexType> |
| <xsd:element name="sumAndMultiplyResponse" type="tns:sumAndMultiplyResponse"/> |
| <xsd:complexType name="sumAndMultiplyResponse"> |
| <xsd:sequence> |
| <xsd:element minOccurs="0" name="sum" type="xsd:int"/> |
| <xsd:element minOccurs="0" name="multiply" type="xsd:int"/> |
| </xsd:sequence> |
| </xsd:complexType> |
| </xsd:schema> |
| </wsdl:types> |
| <wsdl:message name="sumAndMultiplyResponse"> |
| <wsdl:part element="tns:sumAndMultiplyResponse" name="parameters"/> |
| </wsdl:message> |
| <wsdl:message name="sumAndMultiply"> |
| <wsdl:part element="tns:sumAndMultiply" name="parameters"/> |
| </wsdl:message> |
| <wsdl:portType name="CalculatorWs"> |
| <wsdl:operation name="sumAndMultiply"> |
| <wsdl:input message="tns:sumAndMultiply" name="sumAndMultiply"/> |
| <wsdl:output message="tns:sumAndMultiplyResponse" name="sumAndMultiplyResponse"/> |
| </wsdl:operation> |
| </wsdl:portType> |
| <wsdl:binding name="CalculatorServiceSoapBinding" type="tns:CalculatorWs"> |
| <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/> |
| <wsdl:operation name="sumAndMultiply"> |
| <soap:operation soapAction="" style="document"/> |
| <wsdl:input name="sumAndMultiply"> |
| <soap:body use="literal"/> |
| </wsdl:input> |
| <wsdl:output name="sumAndMultiplyResponse"> |
| <soap:body use="literal"/> |
| </wsdl:output> |
| </wsdl:operation> |
| </wsdl:binding> |
| <wsdl:service name="CalculatorService"> |
| <wsdl:port binding="tns:CalculatorServiceSoapBinding" name="CalculatorPort"> |
| <soap:address location="http://127.0.0.1:4204/Calculator?wsdl"/> |
| </wsdl:port> |
| </wsdl:service> |
| </wsdl:definitions> |
| ---- |
| |
| == Testando os parâmetros OUT |
| |
| Aqui nós vemos um cliente JAX-WS executando a operação `sumAndMultiply`. |
| Duas instâncias vázias do `Holder` são criadas e passadas como parâmetros. |
| Os dados da `sumAndMultiplyResponse` são colocados na instância `Holder` |
| e então ficam disponíveis para o cliente depois da operação completa. |
| |
| Os mantenedores não são realmente enviados na requisição, a menos que eles |
| estejam configurados como parâmetros INOUT via WebParam.Mode.INOUT em `@WebParam` |
| |
| [source,java] |
| ---- |
| import org.junit.BeforeClass; |
| import org.junit.Test; |
| |
| import javax.ejb.embeddable.EJBContainer; |
| import javax.xml.namespace.QName; |
| import javax.xml.ws.Holder; |
| import javax.xml.ws.Service; |
| import java.net.URL; |
| import java.util.Properties; |
| |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertNotNull; |
| |
| public class CalculatorTest { |
| |
| @BeforeClass |
| public static void setUp() throws Exception { |
| Properties properties = new Properties(); |
| properties.setProperty("openejb.embedded.remotable", "true"); |
| //properties.setProperty("httpejbd.print", "true"); |
| //properties.setProperty("httpejbd.indent.xml", "true"); |
| EJBContainer.createEJBContainer(properties); |
| } |
| |
| @Test |
| public void outParams() throws Exception { |
| final Service calculatorService = Service.create( |
| new URL("http://127.0.0.1:4204/Calculator?wsdl"), |
| new QName("http://superbiz.org/wsdl", "CalculatorService")); |
| |
| assertNotNull(calculatorService); |
| |
| final CalculatorWs calculator = calculatorService.getPort(CalculatorWs.class); |
| |
| final Holder<Integer> sum = new Holder<Integer>(); |
| final Holder<Integer> multiply = new Holder<Integer>(); |
| |
| calculator.sumAndMultiply(4, 6, sum, multiply); |
| |
| assertEquals(10, (int) sum.value); |
| assertEquals(24, (int) multiply.value); |
| } |
| } |
| ---- |
| |
| == Analisando as mensagens |
| |
| A execução acima resulta na seguinte mensagem SOAP. |
| |
| === requisição cliente SOAP sumAndMultiply |
| |
| [source,xml] |
| ---- |
| <?xml version="1.0" encoding="UTF-8"?> |
| <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> |
| <soap:Body> |
| <ns1:sumAndMultiply xmlns:ns1="http://superbiz.org/wsdl"> |
| <arg0>4</arg0> |
| <arg1>6</arg1> |
| </ns1:sumAndMultiply> |
| </soap:Body> |
| </soap:Envelope> |
| ---- |
| |
| === resposta do servidor SOAP sumAndMultiplyResponse |
| |
| [source,xml] |
| ---- |
| <?xml version="1.0" encoding="UTF-8"?> |
| <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> |
| <soap:Body> |
| <ns1:sumAndMultiplyResponse xmlns:ns1="http://superbiz.org/wsdl"> |
| <sum>10</sum> |
| <multiply>24</multiply> |
| </ns1:sumAndMultiplyResponse> |
| </soap:Body> |
| </soap:Envelope> |
| ---- |