Soap soup
TL;DR: blablabla tive que fazer um parsing XML e depois descobri que ia conseguir usar o WSDL. Se não quiser ler o textão, vai pro próximo tópico sobre como eu resolvi primeiro o parsing XML.
O ano é 2023. Estamos falando em gRPC, tRPC, Rest, GraphQL blablabla. Pois eis que do nada surge uma integração que precisa ser feita via SOAP e XML. Sim... você não entendeu errado... um Web Service... SOAP... com direito a XML.. e tudo mais.
Pois é. Fui transportado no tempo e automaticamente me lembrei de quando eu estava na faculdade, nos idos de 2009. Quando em uma cadeira de Java nós falávamos de JAX-WS e de como poderíamos gerar classes stubs pelo Eclipse. Meu Deus... aqui a nostalgia não vem acompanhada de saudade. Também impossível não lembrar dos trocadilhos com sabão, sopa ou coisas que tem sonoridade parecida. Inclusive a capa desse artigo é uma Sopa de Sabão que eu pedi pro Midjourney gerar pra mim haha.
Mas bem. Estamos em 2023 e hoje eu estou construindo soluções em JavaScript... ou melhor: em TypeScript. E tenho como fiel companheiro o Fastify para que as coisas fiquem menos dolorosas.
Mas quem foi que disse que a vida é simples? Pois é. Eu contava que eu teria o WSDL pra facilitar minha vida e, em um primeiro momento eu tive uma negativa em relação a isso.
Dessa forma eu teria que fazer o parsing do XML... na mão. Dando um spoiler, depois eu consegui o WSDL e a vida vai ficar mais fácil, mas eu já tinha feito uma PoC de como eu faria o parsing desse XML na mão então vai ser a primeira parte dessa sequência de posts. Espero que você não tenha que precisar usa-los, mas se precisar, espero que sejam úteis hehe.
Alinhando os patos
Antes de irmos pro primeiro texto vamos alinhar alguns conceitos para quem não souber do que eu estou falando consiga ficar na mesma página.
WebService, SOAP, SOA e até mesmo REST
Talvez o termo menos problemático aqui seja WebService
. Vamos defini-lo como "uma aplicação distribuída cujos componentes podem ser aplicados e executados em dispositivos distintos." -- Martin Kalim
.
Provavelmente você pensou em APIs Rest
. E não está de todo errado. Inclusive há anos atrás, bibliografias dividiam WebServices em dois grupos: baseados em SOAP e de "estilo" REST. Inclusive considerando SOAP uma espécie de caso especial do REST. Muito disso tem relação com o fato de ambos rodarem em cima do protocolo HTTP.
Outro ponto que ajuda a confundir as definições é quando entra a definição de SOA no meio. Originalmente SOAP
significa Simple Object Access Protocol
enquanto SOA
significa Service Oriented Architecture
. Então como podemos ver pelos próprios nomes, SOA é um estilo arquitetural enquanto SOAP é um dialeto XML.
Aqui vale frisar que nosso foco não é SOA, então paramos por aqui em relação a esse termo e que, SOAP e SOA são conceitos que podem ser utilizados de forma totalmente independente entre si.
Se você quiser uma visualização simples de como funciona um WebService SOAP, abra seu postman e chame o seguinte serviço (exatamente da mesma forma que você faria com um endpoint Restful).
POST /webservicesserver/NumberConversion.wso HTTP/1.1
Host: www.dataaccess.com
Content-Type: text/xml
Content-Length: 276
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<NumberToWords xmlns="http://www.dataaccess.com/webservicesserver/">
<ubiNum>500</ubiNum>
</NumberToWords>
</soap:Body>
</soap:Envelope>
Esse WebService traduz um número inteiro para sua representação por extenso. E o retorno dele será.
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<m:NumberToWordsResponse xmlns:m="http://www.dataaccess.com/webservicesserver/">
<m:NumberToWordsResult>five hundred </m:NumberToWordsResult>
</m:NumberToWordsResponse>
</soap:Body>
</soap:Envelope>
const axios = require('axios');
let data = '<?xml version="1.0" encoding="utf-8"?>\n<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">\n <soap:Body>\n <NumberToWords xmlns="http://www.dataaccess.com/webservicesserver/">\n <ubiNum>500</ubiNum>\n </NumberToWords>\n </soap:Body>\n</soap:Envelope>';
let config = {
method: 'post',
maxBodyLength: Infinity,
url: 'https://www.dataaccess.com/webservicesserver/NumberConversion.wso',
headers: {
'Content-Type': 'text/xml'
},
data : data
};
axios.request(config)
.then((response) => {
console.log(JSON.stringify(response.data));
})
.catch((error) => {
console.log(error);
});
Perceba que ele é um XML bem diferentão, mas ainda é um XML. E como sua requisição usa como base o protocolo HTTP, fica muito fácil fazer uma requisição dessa forma.
O problema é que os serviços dificilmente são simples dessa forma. E se precisarmos integrar com um WebService que tenha uma quantidade grande de métodos ou a informação tenha uma estrutura mais complexa, fazer a requisição dessa forma será bem mais complicado. E veremos isso nos próximos dois artigos dessa série.
O WSDL
Eu comentei que dependendo do que tivermos no nosso WebService, essa integração pode ser bem complexa. Existe uma forma de tentar fazer com que isso seja menos problemático?
A resposta é sim. Não é bonito, mas torna a vida mais simples.
Lá pra 2010 quando eu estava ainda na faculdade, eu tive uma cadeira sobre isso e por mais que eu lembre de poucas coisas da época, uma coisa ficou na minha cabeça: os stubs que eram gerados via Eclipse por meio de um arquivo chamado WSDL.
O WSDL
significa WebService Description Language
e também é baseado em XML. Ele vai servir justamente pra definir a interface dos serviços SOAP e nele estarão coisas como o formato de entrada e de saída, os tipos que precisam ser passados, quais métodos estão disponíveis etc.
<wsdl:definitions
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
xmlns:tns="http://tempuri.org/"
xmlns:s="http://www.w3.org/2001/XMLSchema"
xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/"
xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
targetNamespace="http://tempuri.org/">
<wsdl:types>
<s:schema elementFormDefault="qualified" targetNamespace="http://tempuri.org/">
<s:element name="Add">
<s:complexType>
<s:sequence>
<s:element minOccurs="1" maxOccurs="1" name="intA" type="s:int"/>
<s:element minOccurs="1" maxOccurs="1" name="intB" type="s:int"/>
</s:sequence>
</s:complexType>
</s:element>
<s:element name="AddResponse">
<s:complexType>
<s:sequence>
<s:element minOccurs="1" maxOccurs="1" name="AddResult" type="s:int"/>
</s:sequence>
</s:complexType>
</s:element>
...
Repare que também é um XML, mas é diferente. Nele você encontra o nome dos parametros, os tipos aceitos e o nome dos métodos. Assim como o padrão de suas respostas.
Com essa documento a vida fica consideravelmente mais simples, pois muitas tecnologias oferecem ferramentas para que você crie o código que será usado pra integrar com o WebService por meio desse documento.
Em Java por exemplo, existe o wsimport
que vai escrever quase que completamente um cliente que será usado para consumir o serviço disponibilizado.
Conclusão
Esse texto é inicial pra dar o termômetro do que precisaremos fazer e também serve como alinhamento de entendimento de alguns termos que por muito se confundem entre si.
Pros próximos passos, vamos ver as duas maneiras de fazer uma integração com um WebService SOAP. Primeiro vamos fazer um parsing direto do XML e depois vamos usar libs que entendem o padrão WSDL para que nossas vidas sejam mais fáceis.
Até lá :)
Top comments (0)