1
resposta

Sobrecarga no service

Prezados, a ideia abaixo é ter dois métodos getItens. Um com filtro e outro sem. Tudo isso funciona. O soapui cria duas requisições: todosOsitens e todosOsItensComFiltro

O problema é que ambos ficam iguais, contendo o parâmetro opcional "filtros". Se eu comentar o método getItens(@WebParam(name = "filtros") Filtros filtros), funciona. Ou seja, o parâmetro "filtros" desaparece do soap.

É possível criar dois métodos com mesmo nome mas com assinaturas distintas?

Veja como fica no soap:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ws="http://ws.estoque.caelum.com.br/">
   <soapenv:Header/>
   <soapenv:Body>
      <ws:listaItens>
         <!--Optional:-->
         <filtros>
            <!--Zero or more repetitions:-->
            <filtro>
               <!--Optional:-->
               <nome>?</nome>
               <!--Optional:-->
               <tipo>?</tipo>
            </filtro>
         </filtros>
      </ws:listaItens>
   </soapenv:Body>
</soapenv:Envelope>

Código java:
package br.com.caelum.estoque.ws;

import java.util.List;

import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.jws.soap.SOAPBinding.ParameterStyle;
import javax.jws.soap.SOAPBinding.Style;
import javax.jws.soap.SOAPBinding.Use;
import javax.xml.ws.RequestWrapper;
import javax.xml.ws.ResponseWrapper;

import br.com.caelum.estoque.exception.AuthorizationException;
import br.com.caelum.estoque.modelo.Filtro;
import br.com.caelum.estoque.modelo.Filtros;
import br.com.caelum.estoque.modelo.Item;
import br.com.caelum.estoque.modelo.ItemDao;
import br.com.caelum.estoque.modelo.usuario.TokenDao;
import br.com.caelum.estoque.modelo.usuario.TokenUsuario;

@WebService
// O padrão é DOCUMENT, LITERAL e WRAPPER.
@SOAPBinding(style = Style.DOCUMENT, use = Use.LITERAL, parameterStyle = ParameterStyle.WRAPPED)
public class EstoqueWS {

    private ItemDao dao = new ItemDao();
    @WebMethod(operationName = "todosOsItens") // dá nome a operação no wsdl
    @WebResult(name = "item") // dá nome ao nó de resposta do wsdl enviado pelo servidor (response)
    @ResponseWrapper(localName = "itens")
    @RequestWrapper(localName = "listaItens")
    public List<Item> getItens() {
        System.out.println("Chamando getItens()");
        List<Item> itensResultado = dao.todosItens();
        return itensResultado;
    }

    @WebMethod(operationName = "todosOsItensComFilto") // dá nome a operação no wsdl
    @WebResult(name = "item") // dá nome ao nó de resposta do wsdl enviado pelo servidor (response)
    @ResponseWrapper(localName = "itens")
    @RequestWrapper(localName = "listaItensComFiltro")
    public List<Item> getItens(@WebParam(name = "filtros") Filtros filtros) {
        System.out.println("Chamando getItens()");
        List<Filtro> lista = filtros.getLista();
        List<Item> itensResultado = dao.todosItens(lista);
        return itensResultado;
    }

    @WebMethod(operationName = "cadastrarItem")
    @WebResult(name = "itens")
    public Item cadastrarItem(@WebParam(name = "tokenUsuario", header = true) TokenUsuario token,
            @WebParam(name = "item") Item item) throws AuthorizationException {

        System.out.println("Cadastrando " + item + ", " + token);

        boolean valido = new TokenDao().ehValido(token);

        if (!valido) {
            throw new AuthorizationException("Token invalido");
        }

        this.dao.cadastrar(item);
        return item;
    }
}
1 resposta

Olá DIRLEY, tudo bem?

Sim, é possível ter dois métodos com o mesmo nome, desde que eles tenham assinaturas distintas. No seu código, você tem dois métodos getItens, um com parâmetro Filtros e outro sem parâmetros.

O problema que você está enfrentando é que o SOAPUI está gerando requisições com o parâmetro filtros mesmo quando você chama o método sem parâmetros. Isso acontece porque o SOAPUI está seguindo a definição do WSDL, que indica a presença do parâmetro filtros para o método getItens. No entanto, como o parâmetro é opcional, você pode deixá-lo em branco ou não enviar.

Para evitar essa confusão, você pode renomear um dos métodos, dando a eles nomes distintos, mesmo que no WSDL eles sejam chamados da mesma forma. Por exemplo, você pode renomear o método getItens(@WebParam(name = "filtros") Filtros filtros) para getItensComFiltro(@WebParam(name = "filtros") Filtros filtros).

Dessa forma, o SOAPUI irá gerar uma requisição todosOsItens sem o parâmetro filtros, e uma requisição todosOsItensComFiltro com o parâmetro filtros. Isso deixará claro que o método com parâmetros é destinado à filtragem dos itens.

Lembrando que é importante atualizar o WSDL com as alterações feitas nos métodos e garantir que o cliente SOAP também esteja utilizando a versão atualizada do WSDL.

Quer mergulhar em tecnologia e aprendizagem?

Receba a newsletter que o nosso CEO escreve pessoalmente, com insights do mercado de trabalho, ciência e desenvolvimento de software