Você recebe um novo projeto e em uma das etapas é necessário realizar a integração do seu sistema via Web Services com outra empresa e vice-versa. Duas empresas de TI que podem inclusive possuir produtos concorrentes, mas que necessitam trabalhar em conjunto para atender o cliente em comum.
Aparentemente a primeira coisa a ser feita é ligar para a empresa em questão e solicitar os arquivos pdf que contenham exemplos de chamadas ao Web Services deles, certo? Ou talvez o nosso cliente já tenha conseguido esses documentos na versão 1.00 e tenhamos que mandar alguns e-mails para verificar se o documento está atualizado? Também temos que atualizar a nossa documentação para refletir as últimas modificações que a equipe realizou, correto?
Bom, se o parágrafo acima parece familiar, saiba que isso deveria ser bem mais simples. A única pergunta a ser feita para ambas as empresas é “Qual a URL do seu WSDL?”
WSDL, que significa Web Services Description Language, é um padrão de mercado para descrever Web Services de forma a eliminar ao máximo a necessidade de comunicação entre as partes envolvidas em uma integração de dados. Ele normalmente é encontrado quando acrescentarmos “?wsdl” ao final da URL onde o Web Service está hospedado.
Observe a Listagem 1 onde temos um WSDL como exemplo.
Listagem 1. Exemplo de um arquivo WSDL.
<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="http://www.mayconoliveira.org/webservices/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="webservices"
targetNamespace="http://www.mayconoliveira.org/webservices/">
<wsdl:documentation>Prezado fornecedor, este é um Web Service de
exemplo, voltado a inclusao de clientes.
</wsdl:documentation>
<wsdl:types>
<xsd:schema targetNamespace="http://www.mayconoliveira.org/webservices/">
<xsd:element name="ClienteRequest">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="nome" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
Aqui você deve enviar o nome do cliente
exatamente como consta em seu RG
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="idade" type="xsd:int" minOccurs="0">
<xsd:annotation>
<xsd:documentation>
Informe a idade do cliente a ser utilizado no
email marketing.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="ClienteResponse">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="mensagem" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
Mensagem devolvida do Web Service.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="numeroRecibo" type="xsd:int"
minOccurs="0">
<xsd:annotation>
<xsd:documentation>
Recibo da inclusão. Somente é devolvido em
caso de sucesso.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
</wsdl:types>
<wsdl:message name="ClienteRequest">
<wsdl:part element="tns:ClienteRequest" name="parameters" />
</wsdl:message>
<wsdl:message name="ClienteResponse">
<wsdl:part element="tns:ClienteResponse" name="parameters" />
</wsdl:message>
<wsdl:portType name="webservicesPortType">
<wsdl:operation name="incluirCliente">
<wsdl:input message="tns:ClienteRequest" />
<wsdl:output message="tns:ClienteResponse" />
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="webservicesSOAP" type="tns:webservicesPortType">
<soap:binding style="document"
transport="http://schemas.xmlsoap.org/soap/http" />
<wsdl:operation name="incluirCliente">
<soap:operation soapAction=
"http://www.mayconoliveira.org/webservices/incluirCliente" />
<wsdl:input>
<soap:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="webservices">
<wsdl:port binding="tns:webservicesSOAP" name="webservicesSOAP">
<soap:address location="http://www.mayconoliveira.org/meuwebserviceaqui" />
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
O WSDL da Listagem 1 é um descritor de um WebService simples que recebe o nome e a idade de um cliente e retorna um número de recibo em caso de sucesso. Mas essa explicação já foi possível de extrair ao ler o documento, correto? A tag documentation nos possibilita a inclusão da nossa documentação, dispensando um documento auxiliar como um pdf para explicar os objetivos do Web Service ou para que serve cada campo. Isso não só garante que a informação fique centralizada, como também facilita a leitura por terceiros.
Também podemos extrair deste WSDL a informação que a idade do cliente a ser enviada pelo invocador do serviço e o número do recibo devolvido pelo servidor são opcionais, ou seja, podem não ser informados. Isso pode ser verificado através do atributo minOccurs com o valor 0 (O default, caso não informado, é 1, ou seja, obrigatório). Sabemos também que idade é tipo “int” (inteiro) e o nome é do tipo string. Para maiores informações sobre todos os tipos de dados, verifique a documentação oficial em http://www.w3.org/TR/xmlschema-2/#datatype.
Existem outras informações que podemos verificar, tais como o endereço real a qual o Web Service está hospedado (tag address), valores que temos que informar no Header da requisição HTTP, tais como a SOAPAction disponível na tag soapAction, entre outras. Todas elas juntas servem para gerar uma requisição HTTP válida ao servidor destino, como na Listagem 2.
Listagem 2. Requisição http gerada a partir do WSDL da Listagem 1
POST http://www.mayconoliveira.org/ HTTP/1.1
Content-Type: text/xml;charset=UTF-8
SOAPAction: "http://www.mayconoliveira.org/webservices/incluirCliente"
Content-Length: 332
Host: www.mayconoliveira.org
Connection: Keep-Alive
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:web="http://www.maycon.org/webservices/">
<soapenv:Header/>
<soapenv:Body>
<web:ClienteRequest>
<nome>Maycon Fabio de Oliveira</nome>
<idade>27</idade>
</web:ClienteRequest>
</soapenv:Body>
</soapenv:Envelope>
Agora, observe o WSDL da Listagem 3(Uma parte está omitida para facilitar visualização).
Listagem 3. Exemplo de um arquivo WSDL de difícil compreensão .
<wsdl:definitions>
...
<wsdl:types>
<xsd:schema targetNamespace="http://www.mayconoliveira.org/webservices2/">
<xsd:element name="ClienteRequest">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="in" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="ClienteResponse">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="out" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
</wsdl:types>
...
</wsdl:definitions>
Com um WSDL como o da Listagem 3, o que conseguimos saber? Não muita coisa. Sabemos que existe uma operação no Web Service em que o nome da primeira tag após a tag raiz (ClienteRequest) se chama “in” para o envio e “out” para o retorno. Mas o que devemos informar nessas tags? Valores separados por vírgula? Outro XML? Ambas as opções representam uma má prática, pois novamente estamos escondendo a informação dos interessados. A requisição HTTP mais próxima que podemos montar sem ter que entrar em contato com a empresa é algo como a Listagem 4.
Listagem 4. Requisição HTTP gerada a partir do WSDL da Listagem 3
POST http://www.mayconoliveira.org/ HTTP/1.1
Content-Type: text/xml;charset=UTF-8
SOAPAction: "http://www.mayconoliveira.org/webservices2/incluirCliente"
Content-Length: 287
Host: http://www.mayconoliveira.org
Connection: Keep-Alive
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:web="http://www.mayconoliveira.org/webservices2/">
<soapenv:Header/>
<soapenv:Body>
<web:ClienteRequest>
<in> O QUE DEVEMOS INFORMAR AQUI? </in>
</web:ClienteRequest>
</soapenv:Body>
</soapenv:Envelope>
Apesar de todas as vantagens do uso adequado do WSDL, o mesmo é normalmente negligenciado pelas empresas de TI devido a sua complexidade. Ao invés disto, utilizam-se do que se chama de abordagem de desenvolvimento bottom-up, a qual você escreve o seu Web Service utilizando sua linguagem de programação favorita e a mesma gera o documento WSDL para você. A princípio, isso parece ser muito bom, mas em longo prazo, isso pode gerar problemas como:
- Em uma migração de tecnologia (linguagem de programação, troca de servidor de aplicação), pode ser que o novo Web Service, criado para substituir o anterior, não aceite a requisição que está sendo enviada pelos programas clientes, que pode vir a parar de funcionar.
- Cada linguagem de programação ou ferramenta vai gerar um documento WSDL diferente.
- Dependendo da linguagem de programação ou da ferramenta utilizada, pode ser que sejam gerados tipos de dados não suportados oficialmente pela W3C (Órgão “regulamentador” do padrão WSDL, SOAP e XML).
E para aqueles que acreditam não precisar mais se preocupar com esse tipo de integração porque Web Service do tipo SOAP não é mais utilizado desde o surgimento do REST (outro tipo de Web Service), fica a informação de que hoje temos muitos projetos contemplando Web Services do tipo SOAP, tais como Nota fiscal eletrônica e TISS (Troca de informações na Saúde Suplementar da ANS).
Mas, como tudo na informática, nem tudo é como deveria ser. Em diversas ocasiões, mesmo com o endereço de um WSDL, passamos por situações em que a requisição que deve ser montada não chega nem perto do que o mesmo especifica. Neste caso, somente o contato com o fornecedor resolve. Claro que neste momento estaremos munidos da informação de que o fornecedor está fazendo errado e que cada segundo do nosso tempo gasto com informações inválidas estará correndo por conta do mesmo. O WSDL é o contrato do serviço, ou seja, ele é a regra!
Neste artigo, vimos a importância que o documento WSDL tem em uma integração de dados entre duas organizações. Ele é um documento complexo e com muitas funcionalidades, que se bem utilizadas, podem facilitar muito a utilização e a reutilização de Web Services. Certamente vale se aprofundar no assunto.