Segundo o W3C (World Wide Web Consortium), responsável pela padronização dos Web Services e diversas outras tecnologias, um Web Service é um sistema de software projetado para suportar a interoperabilidade entre máquinas sobre a rede. Portanto, Web Services é uma solução utilizada para a integração de sistemas. Utilizando Web Services podemos criar novas aplicações que podem interagir com aquelas que já existem. Outra vantagem é a independência de plataforma, sistemas desenvolvidos em diferentes plataformas podem conversar sem nenhum problema, isso é possível porque os Web Services são componentes que permitem às aplicações enviar e receber dados em formato XML. Dessa forma, cada componente pode ter a sua própria linguagem, que é traduzida para uma linguagem universal, o formato XML.

Os Web Services são padronizados por grandes empresas como W3C e tem o apoio de grandes empresas como IBM e Microsoft, duas gigantes do setor de tecnologia.

Para a representação e estruturação dos dados nas mensagens recebidas e enviadas utilizamos o XML (eXtensible Markup Language). As chamadas às operações, incluindo os parâmetros de entrada e saída, são codificadas no protocolo SOAP (Simple Object Access Protocol), e por fim os serviços (operações, mensagens, etc) são descritos usando a linguagem WSDL (Web Services Description Language). O processo de publicação/pesquisa/descoberta de Web Services utiliza o protocolo UDDI (Universal Description, Discovery and Integration).

Como podemos verificar é no arquivo WSDL que temos as operações disponíveis no Web Service e o que ele espera receber e retornar. Nas próximas seções veremos o que é stubs e como utilizar o Eclipse, o Ant, e algumas bibliotecas necessárias para gerarmos os nossos stubs.

O que são Stubs

A criação de Stubs, que muitas vezes são feitas de forma automática, permitem que possamos usar um Web Service de forma mais fácil.

As interfaces utilizam rotinas stubs e skeletons para fazer a comunicação cliente/servidor. O stub são rotinas que ficam no cliente passando-se por um servidor e no momento em que são acionadas, através da rede ela busca o skeleton. O skeleton possui a implementação real da operação desejada pelo cliente, ou seja, ele quem irá executar a operação no servidor. No caso de necessidade do retorno de algum dado pela operação, o skeleton devolve o retorno via rede para o stub que o repassa para o cliente. Esta estrutura é muito similar para quem já trabalhou com CORBA ou RMI.

Portanto, temos que um cliente SOAP contém os objetos stubs e o servidor SOAP contém os objetos skeletons. Dado isso temos os seguintes passos na comunicação cliente/servidor:

  • Quando um objeto de negócio do cliente faz uma chamada a um Web Service, em um nível mais baixo o objeto stub se comunica com o skeleton no servidor.
  • O código do Web Service no servidor se conecta com outra aplicação.
  • A outra aplicação executa algum processo ou função.
  • A outra aplicação retorna algum valor para o código do Web Service no Servidor.
  • O skeleton no servidor envia o valor para o objeto stub no cliente.
  • O objeto stub no cliente retorna o valor para o objeto de negócio do cliente.

Primeiro de tudo devemos saber que apesar de termos um monte de protocolos e linguagens, os programadores frequentemente nunca escrevem uma única linha de SOAP ou WSDL. Uma vez que sabemos onde nossa aplicação cliente precisa invocar um Web Server, delegamos a tarefa para um software chamado client stub. Temos várias ferramentas que geram esses stubs automaticamente apenas possuindo o WSDL do Web Service como a ferramenta wsimport que é padrão do Java e veremos posteriormente.

Portanto, a melhor sequencia de eventos se da na seguinte forma:

  • Localizamos o Web Service através do UDDI ou por outra forma (algumas vezes já recebemos a sua localização de um fornecedor)
  • Obtemos o WSDL desse Web Service (normalmente disponível numa URL pública)
  • Geramos os stubs uma vez e incluímos eles na nossa aplicação.
  • A aplicação usa os stubs cada vez que precisar invocar o Web Service.

Programar o lado servidor é ainda mais fácil. Não precisamos escrever um programa servidor complexo que interpreta dinamicamente requisições SOAP e gera respostas SOAP. Simplesmente implementamos todas as funcionalidades do nosso Web Service e gerados os server stub (ou skeleton que é mais comum) na qual se encarregará de interpretar as requisições e repassar para a implementação do serviço. Quando a implementação do serviço obtém um resultado, ele repassará para o skeleton, que irá gerar a resposta SOAP apropriada para o cliente. O skeleton também pode ser gerado por um WSDL.

A figura abaixo mostra todo o processo descrito acima.

Comunicação entre Cliente e Web Service

Figura 1: Comunicação entre Cliente e Web Service.

Imaginando que um Web Service foi localizado, seus stubs no cliente foram gerados através do seu WSDL, e além disso, no lado servidor um programador já implementou os serviços necessários e gerou o skeleton, dessa forma temos a seguinte sequencia:

  • Quando o cliente precisar invocar o Web Service, ele chamará o cliente stub. O cliente stub transformará essa "invocação local" em uma requisição SOAP apropriada. Isto normalmente é chamado de um processo de serialização.
  • A requisição SOAP é enviada pela rede usando o protocolo HTTP. O Container do Web Service no lado servidor recebe a requisição SOAP e envia para o server stub (skeleton). O skeleton converte a requisição SOAP em algo que o serviço de implementação pode entender. Isto normalmente é chamado de um processo de deserialização.
  • O serviço de implementação recebe a requisição do skeleton e faz o seu serviço. Por exemplo, se estamos invocando uma operação de adição como "int adiciona(int a, int b)", o serviço de implementação irá realizar esse serviço.
  • O resultado da operação requisitada é retornada para o skeleton, que então transformará isto numa resposta SOAP.
  • A resposta SOAP é enviada para a rede usando o protocolo HTTP. O Cliente stub recebe a resposta SOAP e transforma isso em algo que a aplicação cliente possa entender.
  • Finalmente a aplicação recebe o resultado do Web Service e usa isto para efetuar as suas operações.

Criando Stubs com wsimport

Para criarmos os stubs no lado cliente precisaremos primeiramente do Eclipse Kepler. Após isso, crie um novo projeto java clicando com o botão direito do mouse em “package explorer” e escolhendo “new -> java project” como ilustra a imagem abaixo:

Criando um novo projeto no eclipse

Figura 2: Criando um novo projeto no eclipse

Escolha um nome para o projeto e clique em Finish. Não esqueça de marcar a opção “Use default location”. Apesar da figura abaixo não estar marcado, marque a opção para usar o workspace default.

Escolhendo um nome para o projeto e finalizando.

Figura 3. Escolhendo um nome para o projeto e finalizando.

Agora baixe também as bibliotecas abaixo que serão utilizadas posteriormente pelo wsimport:

  • Baixe o jaxb e descompacte e coloque na raiz do projeto as bibliotecas jaxb.xjc.jar e jaxb-api.jar
  • Baixe o XmlStreamBuffer. Coloque na raiz do projeto a biblioteca streambuffer.jar
  • Baixe o jaxws. Descompacte e coloque na raiz do projeto as bibliotecas jaxws-rt.jar, jaxws-tools.jar e policy.jar
  • Baixe o stax-ex. Coloque na raiz do projeto a biblioteca stax-ex.jar

Agora precisamos criar um build.xml que será um arquivo ant que chamará o wsimport e gerará os stubs do nosso Web Service cliente. Para isso crie um novo arquivo clicando com o botão direito do mouse em cima do nome do nosso projeto e selecionando “new -> file”. Coloque o nome de build.xml.

Criando um novo arquivo que irá gerar os stubs.

Figura 4: Criando um novo arquivo que irá gerar os stubs.

Nesse arquivo novo, coloque o código ant abaixo:

Listagem 1: Código responsável por gerar os stubs do Web Service

<project name="wsimport" default="principal">
   
  <taskdef name="wsimport" classname="com.sun.tools.ws.ant.WsImport">
    <classpath>
        <pathelement location="C:/Users/higor/Desktop/TrabPersistencia/workspace/TesteWS/lib/jaxb-xjc.jar" />
        <pathelement location="C:/Users/higor/Desktop/TrabPersistencia/workspace/TesteWS/lib/jaxb-api.jar" />
        <pathelement location="C:/Users/higor/Desktop/TrabPersistencia/workspace/TesteWS/lib/jaxws-rt.jar" />
        <pathelement location="C:/Users/higor/Desktop/TrabPersistencia/workspace/TesteWS/lib/jaxws-tools.jar" />
        <pathelement location="C:/Users/higor/Desktop/TrabPersistencia/workspace/TesteWS/lib/stax-ex-1.7.4.jar" />
        <pathelement location="C:/Users/higor/Desktop/TrabPersistencia/workspace/TesteWS/lib/streambuffer-1.5.3.jar" />
    	<pathelement location="C:/Users/higor/Desktop/TrabPersistencia/workspace/TesteWS/lib/policy.jar" />
    </classpath>
  </taskdef>

  <target name="principal">
    <wsimport sourcedestdir="src" verbose="true"
        wsdl="http://webservices.amazon.com/AWSECommerceService/AWSECommerceService.wsdl">
    </wsimport>

  </target>
</project>

No exemplo acima nós referenciamos, através do elemento pathelement, todas as bibliotecas que baixamos e que serão usadas pelo wsimport para gerar os stubs. Também podemos notar que na tag <target> definimos onde serão gerados os stubs, que é na pasta src do nosso projeto, e também definimos qual o endereço do wsdl do Web Service que iremos gerar os stubs, no caso acima definimos o wsdl de um serviço público da Amazon.

Agora basta executar com um aplicativo ant que já vem no Eclipse e podemos verificar no console a geração dos stubs. Clique com o botão direito do mouse em cima de qualquer área do arquivo build.xml e seleciona “Run As -> Ant Build”.

Executando o arquivo build.xml.

Figura 5: Executando o arquivo build.xml.

 Stubs sendo gerados.

Figura 6: Stubs sendo gerados.

Por fim, basta visualiza na janela “Package Explorer” que na pasta “src” foi criado um novo pacote com os stubs gerados. Agora estamos aptos a usar esse Web Service, bastando descobrir quais classes chamar para executar o serviço apropriado e quais parâmetros serão passados.

Stubs e classes criados automaticamente pelo wsimport.

Figura 7: Stubs e classes criados automaticamente pelo wsimport.

Neste artigo estudamos o que são Web Services, Stubs, Skeletons e como podemos gerar os Stubs no cliente para acessar o skeleton de um Web Service num servidor remoto. Através da geração automática dos stubs temos uma grande facilidade em usar os Web Services. Também vimos como fazer na prática essa geração automática com bibliotecas padrão do java.

Bibliografia

  • Kalin, Martin. Java Web Services: Up and Running. Sebastopol, CA: O’Reilly. 318p. 2009.