blob: c0dcde919efaccdb6f6ee892c47b85691a5a6645 [file] [log] [blame]
: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>
----