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.