Consumindo web service do Protheus com JAX-WS
O que é web service?
De acordo com a W3C, web service é um software projetado para suportar interação máquina-máquina de forma interoperável através de uma rede. Ele tem uma interface descrita em um formato máquina-processável (especificamente WSDL). Sistemas que interagem com o web service de uma maneira prescrita por sua descrição, utilizam mensagens SOAP, normalmente transmitidas através de HTTP com uma serialização XML em conjunto com outros padrões web.
O caminho.
Para a integração com outros sistemas, o ERP Protheus da Totvs provê uma série de web services e ainda existe a possibilidade de desenvolver e publicar serviços customizados dentro da plataforma.
Figura 1 – Página com a descrição dos serviços disponíveis do Protheus.
O problema.
Ao iniciar o desenvolvimento de uma aplicação em Java 6, utilizando o Netbeans 7.0 como IDE e a biblioteca JAX-WS para o consumo dos serviços, foi exibida a mensagem “WEBSERVICE ERROR : Soap Prefix Missing : USERPORTAL : PRTLOGIN : Formato do Pacote Soap DESCONHECIDO.” ao tentar executar uma chamada simples ao serviço USERPORTAL, método PRTLOGIN.
A solução.
Será demostrado um passo-a-passo de como iniciar um projeto até o consumo com sucesso do web service especificado.
No Netbeans, clique no menu Arquivo, seguido por Novo Projeto. Na tela que irá abrir, selecione em Categorias: “Java” e em Projetos: “Aplicativo Java”. Clique em Próximo.
Informe o nome do projeto (neste caso SigaWS), faça modificações caso ache necessário e clique em Finalizar.
Figura 3 – Novo Aplicativo Java
Com o projeto criado, deverá ser criada a classe para consumo do serviço USERPORTAL, para isto clique em Arquivo, seguido por Novo Arquivo.
Figura 4 – Arquivo, Novo Arquivo.
Na tela de Novo Arquivo selecione em Categorias: “Serviços Web” e em Tipos de arquivos: “Cliente para serviço Web”, clicando em Próximo.
Na próxima tela deverá ser selecionada a opção WSDL URL e informado o caminho do arquivo de definição do serviço de acordo com o publicado no Protheus. Clique em Finalizar.
Figura 6 – Novo cliente para serviço Web.
Voltando para a tela principal do Netbeans, vá na aba Projetos e abra os nós de Referência de serviços Web até localizar o método PRTLOGIN.
Selecione o nó PRTLOGIN, arraste-o e solte dentro da classe SigaWS, isto fará com que o código de chamada ao método seja gerado automaticamente. Em seguida defina os parâmetros para execução da chamada do serviço.
Figura 7 – Definição da classe de execução do Web Service.
Executando o projeto neste momento, será verificado o erro citado no início do artigo.
Para solucionar o problema, o proposto é adicionar um manipulador de mensagem SOAP e realizar algumas modificações nos dados retornados pelo serviço, assim possibilitando a serialização.
Clique em Arquivo, seguido por Novo Arquivo. Na tela seguinte, selecione em Categorias: “Serviços Web” e em Tipos de arquivos: “Manipulador de mensagens”, clique em Próximo.
Figura 9 – Novo arquivo – Manipulador de mensagens.
Informe o nome para o arquivo, neste caso SigaHandler, clique em Finalizar.
Figura 10 – Novo manipulador de mensagens.
Com o arquivo gerado o código deverá ficar desta forma:
package sigaws.ws; import java.io.ByteArrayOutputStream; import java.util.Collections; import java.util.Set; import javax.xml.namespace.QName; import javax.xml.soap.SOAPException; import javax.xml.soap.SOAPMessage; import javax.xml.transform.Source; import javax.xml.transform.stream.StreamSource; import javax.xml.ws.handler.MessageContext; import javax.xml.ws.handler.soap.SOAPHandler; import javax.xml.ws.handler.soap.SOAPMessageContext; /** * * @author Eduardo Folly */ public class SigaHandler implements SOAPHandler { @Override public boolean handleMessage(SOAPMessageContext messageContext) { boolean outbound = (Boolean) messageContext.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY); if (outbound) { try { SOAPMessage msg = messageContext.getMessage(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); msg.writeTo(baos); String teste = baos.toString(getMessageEncoding(msg)); teste = teste.replaceAll("S:", "soap:"); teste = teste.replaceAll("S=", "soap="); Source src = new StreamSource(new java.io.StringReader(teste)); msg.getSOAPPart().setContent(src); } catch (Exception e) { e.printStackTrace(); } } return true; } @Override public Set getHeaders() { return Collections.EMPTY_SET; } @Override public boolean handleFault(SOAPMessageContext messageContext) { return true; } @Override public void close(MessageContext context) { } private String getMessageEncoding(SOAPMessage msg) throws SOAPException { String encoding = "utf-8"; if (msg.getProperty(SOAPMessage.CHARACTER_SET_ENCODING) != null) { encoding = msg.getProperty(SOAPMessage.CHARACTER_SET_ENCODING).toString(); } return encoding; } }
Assim o resultado final da classe é apresentado.
Figura 11 – Classe SigaHandler.
Agora é necessário relacionar o manipulador de mensagens com o serviço USERPORTAL. Para isto na aba Projetos clique com o botão direito do mouse no serviço USERPORTAL, seguido por Configurar manipuladores…
Figura 12 – Configurar manipuladores…
Na próxima tela, clique em Adicionar.
Figura 13 – Configurar os manipuladores de mensagens.
Selecione o arquivo manipulador, neste caso o arquivo SigaHandler.java, e clique em OK.
Figura 14 – Selecionar classe de manipuladores de mensagens.
Após a confirmação será exibido o manipulador de mensagens associado ao serviço. Clique em OK.
Figura 15 – Associação do manipulador de mensagens.
Desta forma a execução do programa funciona perfeitamente.
Figura 16 – Execução do programa.
Considerações finais.
Até o presente momento a Totvs não disponibilizou uma modificação no padrão do retorno da mensagem do serviço Web para o Protheus 10.
Gostaria de agradecer a Vicente de Paula (vicenterecife@gmail.com) por ter originado os questionamentos que deram origem a este artigo.






Olá, meus parabéns pelo artigo!
Tivemos o mesmo problema e o tratamento feito foi algo bem parecido com isso. Porém, como você trata caso o XML a ser enviado contenha algum texto como “Código do projeto TELAS: 001″?
Abraços!
Obrigado Filipe.
Vejo que a melhor forma é utilizar uma expressão regular para fazer a substituição no raw data do webservice. Sabendo que String.replaceAll(String regex, String replacement) é aplicado por Pattern.compile(regex).matcher(str).replaceAll(replacement).
No mais esperamos que a Totvs se adeque aos padrões mais atuais.