Tutorial do Apache Axis 1.3

em 28/07/2006 , por Daniel Destro
OBJETIVO Este tutorial visa demonstrar a utilização da ferramenta Apache Axis para a criação, publicação e utilização de Web Services. Através de uma aplicação de exemplo, será demonstrado como: publicar uma classe de aplicação em Java, o processo de deploy e como criar aplicações clientes em Java para Web Services publicados. Os exemplos utilizam a ferramenta Apache Axis, versão 1.3, que é open source e de uso comercial livre. O site oficial do projeto é: http://ws.apache.org/axis/index.html. É recomendado que o leitor tenha um conhecimento mínimo prévio sobre do que se tratam os Web Services e as siglas relacionadas ao assunto (WSDL, SOAP, HTTP), além de ter conhecimento necessário sobre aplicações web com Java (Servlet, WAR). INTRODUÇÃO Com a ferramenta Apache Axis, a criação e publicação de Web Services e a criação dos clientes de acesso é simplificada e gerada de forma automática, com o auxílio das ferramentas disponíveis no próprio Apache Axis. Para se trabalhar com o Axis de forma efetiva, é necessária a utilização de três ferramentas: Java2WSDL, WSDL2Java e AdminClient. A ferramenta Java2WSDL gera um documento WSDL a partir de uma classe ou interface Java. Este WSDL gerado é o documento na qual o próprio Axis se baseia para criar as classes (stub e skeleton) do Web Service. A ferramenta WSDL2Java gera as classes Java responsáveis tanto pela parte servidor (skeleton), quanto a parte cliente (stub) dos Web Services. E, por último, a ferramenta AdminClient é utilizada para registrar o Web Service no servidor de aplicações. Para ver a documentação oficial, acesse: http://ws.apache.org/axis/java/index.html, ou verifique o diretório docs que vem junto com o download da ferramenta. PREPARAÇÃO DO AMBIENTE DE DESENVOLVIMENTO Primeiro, é necessário preparar o ambiente de desenvolvimento antes de iniciar a utilização das ferramentas do Apache Axis. É importante que as bibliotecas do Axis sejam configuradas no CLASSPATH corretamente. Adicione as seguintes bibliotecas (JAR) ao CLASSPATH:
  • axis.jar
  • commons-discovery-0.2.jar
  • commons-logging-1.0.4.jar
  • jaxrpc.jar
  • saaj.jar
  • wsdl4j-1.5.1.jar
Estas bibliotecas vêm junto com a distribuição do Apache Axis e estão no diretório lib. Caso seja utilizada uma IDE para o desenvolvimento, como o Eclipse, por exemplo, adicione as bibliotecas ao projeto. Caso utilize as ferramentas do Axis via linha de comando, configure o CLASSPATH como abaixo. Linha de comando para Windows:

Linha de comando para Unix:

No caso do Windows é possível ainda configurar as variáveis de ambiente AXIS_HOME e CLASSPATH no menu de propriedades do ícone Meu Computador. A estrutura de diretórios do projeto de exemplo está baseada como na figura abaixo: Os diretórios descritos devem conter:
  • bin - binários gerados (.class)
  • src - fontes Java (.java)
  • config/META-INF - arquivos de configuração da aplicação J2EE (application.xml e jboss-app.xml)
  • config/WEB-INF - arquivos de configuração da aplicação web e outros arquivos desta estrutura (web.xml)
  • config/resource - outros arquivos de configuração (ex: o arquivo WSDL gerado)
  • deploy - arquivos de deploy gerados (.jar, .war e .ear)
  • web/jsp - arquivos JSP de aplicação
  • web/html - arquivos HTML da aplicação
O diretório raiz do projeto será tomado como o diretório corrente, pois é lá que ficam os arquivos de projeto da IDE utilizada e o build.xml da ferramenta Apache Ant.
PREPARAÇÃO DA APLICAÇÃO WEB J2EE Os Web Services feitos em Java dependem da publicação de uma aplicação web (padrão J2EE) em um servidor de aplicações, como o JBoss, por exemplo. É nesta aplicação que os Web Services serão publicados. Alguns pré-requisitos devem ser atendidos para que esta aplicação web seja capaz de publicar um Web Service utilizando a ferramenta Apache Axis. Na própria distribuição do Apache Axis, existe uma aplicação web inicial já configurada, é nela que as aplicações que publicam Web Services com Apache Axis serão baseadas. Esta aplicação se encontra no diretório webapps/axis do pacote de distribuição do Axis. Por objetividade, os dois passos seguintes deverão ser seguidos para satisfazer os pré-requisitos e preparar a aplicação web para servir Web Services com Apache Axis: 1 - Configurar o arquivo web.xml O web.xml da aplicação web que servirá os Web Services, utilizando Apache Axis, deve conter as mesmas configurações descritas no web.xml abaixo:

Certamente as configurações adicionais exigidas pela sua aplicação web poderão ser adicionadas a este web.xml. O objetivo é demonstrar a configuração mínima exigida pelo Apache Axis. 2 - Disponibilizar as bibliotecas do Apache Axis na aplicação web J2EE Depois de configurado o arquivo web.xml, o próximo passo é fornecer à aplicação web as bibliotecas necessárias para a utilização do Apache Axis. Os arquivos JARS necessários dentro da aplicação web são:
  • axis.jar
  • axis-ant.jar
  • axis-schema.jar
  • commons-discovery-0.2.jar
  • commons-logging-1.0.4.jar
  • jaxrpc.jar
  • saaj.jar
  • wsdl4j-1.5.1.jar
NOTA: A biblioteca log4j-1.2.8.jar não é necessária no container JBoss, pois ele mesmo já fornece a biblioteca compartilhada.
CRIANDO WEB SERVICE COM APACHE AXIS Com o Apache Axis seguimos uma seqüência lógica de ações, ou passos, para criar um Web Service a partir de uma lógica de negócio já existente em uma classe Java, ou acessível através desta classe. Sempre se parte do princípio que existe uma classe Java que contém a lógica de negócio a ser publicada como Web Service. O que acontece dentro desta classe, na verdade, não é importante para a criação do Web Service. O que realmente é necessário é a interface de acesso à lógica. Os passos, que envolvem a criação e publicação do Web Service, basicamente são:
  • Gerar o documento WSDL a partir do binário (.class) da classe (ou interface) de negócio
  • Gerar as classes do Web Service (skeleton) e o descritor de deploy (wsdd) a partir do WSDL gerado
  • Compilar as classes Java geradas
  • Fornecer as classes à aplicação web J2EE
  • Fazer deploy da aplicação web J2EE (ear)
  • Registrar os Web Services (wsdd)
O diagrama a seguir mostra a seqüência destes passos: Para exemplificar a criação de um Web Service com Apache Axis, tomamos como exemplo uma classe que executa lógicas relativas à área de Recursos Humanos de uma empresa. Para isso temos a classe Java RecursosHumanos, do pacote rh, que define e implementa os seguintes métodos:

Estes métodos ilustram diferentes situações que podem ser encontradas nas definições dos sistemas que desejam publicar Web Services das suas classes de negócio. O primeiro método, incluirEmpregado, simplesmente recebe três parâmetros (String e double). O seguinte, contarEmpregados, não recebe nenhum argumento, porém retorna um valor inteiro. O método calcularSalarioEmDolar recebe um parâmetro do tipo double e retorna um valor também do tipo double. O último método recebe um argumento do tipo int e retorna um tipo complexo, chamado Empregado, que é uma classe Java com uma estrutura de dados simples, como mostra o código a seguir.

As classes demonstradas não possuem nenhum código extra para serem publicadas como um Web Service, deixando claro que nenhum código a mais é exigido além da própria regra de negócio. Por simplicidade foi omitida a implementação do acesso ao banco de dados que este componente faria.
CRIANDO O WSDL PARA O WEB SERVICE Definida a classe com a lógica de negócio que será publicada como um Web Service, o próximo passo é criar o descritor WSDL para o serviço. Com base no WSDL gerado, também serão geradas as classes que fazem a orquestração do acesso ao Web service, em conjunto com o Apache Axis. Certifique-se de ter as bibliotecas do Apache Axis configuradas corretamente no CLASSPATH, como demonstrado na introdução. Para gerar o WSDL utiliza-se a ferramenta Java2WSDL, do Apache Axis. A linha de comando para a geração do WSDL é a seguinte:

Para executar o comando acima é necessário estar no diretório bin do projeto, que é onde devem estar os binários (.class) gerados dos arquivos Java com a regra de negócio. O primeiro parâmetro do comando, o, indica onde o WSDL deve ser gerado. O parâmetro l define a URL na qual o Web Service responderá, ou seja, é o endereço informado no WSDL que os clientes utilizarão para fazer o acesso ao Web Service, mas não é tão importante que este endereço seja o endereço real do Web Service neste momento. O parâmetro n define o namespace do Web Service. Por fim, o nome completo da classe que implementa os métodos a serem publicados como Web Service. Com isso, o arquivo WSDL (rh.wsdl) é gerado dentro da pasta config/resource. CRIANDO AS CLASSES SERVER-SIDE DO WEB SERVICE Depois de gerado o WSDL do serviço, é necessário gerar as classes chamadas server-side e o descritor de deploy (wsdd), que são responsáveis pela orquestração do Web Service e pela chamada à classe de negócio. Essas classes são geradas com a ferramenta WSDL2Java. Certifique-se de ter as bibliotecas do Apache Axis configuradas corretamente no CLASSPATH, como demonstrado na introdução e que o diretório corrente seja o diretório Java do projeto. A linha de comando para a geração é a seguinte:

O primeiro parâmetro, o, indica o diretório onde os arquivos devem ser gerados. O parâmetro s indica que os arquivos para a parte server-side devem ser gerados. O parâmetro S seguido do valor true indica que a classe skeleton deve ser gerada. O parâmetro N define o mapeamento entre o namespace e o pacote Java onde as classes serão geradas. E, por fim, o caminho do arquivo WSDL do Web Service no qual a ferramenta se baseará para gerar os arquivos. Como o parâmetro N exige que o desenvolvedor saiba o nome dado ao namespace, que pode ser verificado dentro do WSDL, existe uma outra opção, que é usar o parâmetro p, informando diretamente o nome do pacote das classes. O comando ficaria assim:

Após a execução de algum destes comandos, os seguintes arquivos são gerados:
  • deploy.wsdd
  • undeploy.wsdd
  • Empregado.java
  • RecursosHumanos.java
  • RecursosHumanosService.java
  • RecursosHumanosServiceLocator.java
  • RecursosHumanosSoapWSBindingImpl.java
  • RecursosHumanosSoapWSBindingSkeleton.java
  • RecursosHumanosSoapWSBindingStub.java
Os arquivos wsdd são utilizados para fazer o deploy e o undeploy do Web Service. As classes RecursosHumanos.java, RecursosHumanosWSSoapBindingImpl.java e RecursosHumanosWSSoapBindingSkeleton.java são as classes relativas à parte servidor (server-side). As classes RecursosHumanosService.java, RecursosHumanosServiceLocator.java e RecursosHumanosWSSoapBindingStub.java são relativas à parte cliente, que não são necessárias neste momento, porém foram geradas pela ferramenta. A classe Empregado.java é uma implementação baseada na implementação original, que o Apache Axis gera por ela conter, internamente, um mapeamento entre seus atributos (campos) e o documento SOAP a ser gerado no transporte. Na verdade, RecursosHumanos.java é a definição da interface que descreve os serviços disponíveis no Web Service na parte server-side. A classe skeleton RecursosHumanosWSSoapBindingSkeleton implementa a interface RecursosHumanos. É a classe skeleton que recebe as chamadas diretamente do Apache Axis e as delega para a classe RecursosHumanosWSSoapBindingImpl. Esta última classe é quem deve delegar, de fato, as chamadas do Web Service à classe com a lógica de negócio propriamente dita. A classe RecursosHumanosWSSoapBindingImpl é gerada, originalmente, com o código abaixo:

O código acima não possui a implementação da lógica de negócio. Então o desenvolvedor precisa alterar esta classe para instanciar a classe com a lógica de negócio e delegar as chamadas a ela. O código pode ser alterado para a forma abaixo:

Note que a primeira linha dentro da classe instancia um objeto da classe de negócio rh.RecursosHumanos no atributo rh. Em seguida, em cada método, são feitas (delegadas) as chamadas aos métodos relativos da classe de negócio original. No método pesquisar existe uma peculiaridade, devido ao tipo de retorno do método. Como o método da classe de negócio retorna um objeto do tipo rh.Empregado e o método da classe de implementação server-side do Web Service retorna um objeto do tipo rh.ws.Empregado, que foi gerado, é necessário fazer a conversão entre os dois tipos, já que eles não seguem a mesma hierarquia de classes, embora tenham o mesmo nome e atributos. Neste caso, simplesmente obtem-se o retorno do método original, instância-se o objeto do novo tipo e copia os valores de cada atributo de um tipo para o outro, para então retornar o tipo gerado pelo Apache Axis. É importante salientar que são usadas as classes do pacote rh, onde estão as classes de lógica originais. Neste ponto já se tem toda a parte server-side da lógica e do Web Service preparada. O próximo passo é fazer a publicação (deploy) da aplicação com o Web Service.
PUBLICANDO UMA APLICAÇÃO WEB J2EE COM WEB SERVICE A publicação de uma aplicação web J2EE que possui Web Services se dá em duas fases: publicação (deploy) da aplicação no servidor de aplicações e depois a publicação (deloy) dos Web Services. A publicação de aplicação web J2EE se dá de forma padrão, seja num pacote WAR ou EAR. É importante que o pacote da aplicação contenha todas as classes, inclusive as classes com as lógicas de negócio e as classes geradas pela ferramenta Apache Axis, além do web.xml com as configurações necessárias para o funcionamento do Axis e suas bibliotecas. No exemplo utilizado, a aplicação foi disponibilizada com o nome de contexto rh. Depois de feita a publicação da aplicação web, certifique-se se o servidor de aplicações está em serviço e que a aplicação web esteja em pleno funcionamento, sem a ocorrência de problemas no deploy ou startup. Neste momento é possível publicar os Web Services para o Apache Axis, com o auxílio da ferramenta AdminClient. Por meio do arquivo wsdd é feita a publicação do Web Service. É importante salientar que o registro do Web Service via AdminClient só pode ser feito a partir da mesma máquina (localhost) em que a aplicação está rodando. Para fazer este registro a partir de host remoto, é necessário configurar a segurança do Apache Axis. Este assunto está além do escopo deste tutorial. Para publicar, execute a seguinte linha de comando:

Esta comando acessa o Servlet do Apache Axis no servidor definido pela URL informada no parâmetro l. Por fim é informado o caminho do arquivo wsdd em disco que contém as informações de deploy do Web Service. Neste momento a aplicação web J2EE e os Web Services estão publicados e já podem ser acessados. Acessando a URL http://localhost:8080/rh/servlet/AxisServlet, serão listados todos os Web Services e seus métodos, publicados pelo Apache Axis, como exemplificado na imagem abaixo: Ao lado de cada Web Service está disponível o link para o seu WSDL. É esta URL que será informada aos clientes (internos e externos) para gerarem os clientes de acesso a estes Web Services. Para testar e ver o WSDL, clique no link. Finalmente o Web Service e a aplicação foram publicados com sucesso. A próxima seção mostra como se faz para acessar e consumir um Web Service.
CRIANDO CLIENTE DE ACESSO A UM WEB SERVICE COM JAVA Até o momento foi demonstrado como criar e publicar um Web Service. Agora, o foco será demonstrar como acessar e consumir um Web Service publicado, interna ou externamente. Uma premissa básica para acessar um Web Service é ter acesso ao WSDL do serviço, seja a URL para o documento, seja o próprio arquivo em disco, localmente. Com acesso a este documento, pode-se utilizar a ferramenta WSDL2Java do Apache Axis para gerar o cliente Web Service em Java, lembrando que não importa a tecnologia na qual o Web Service foi criado. O comando para gerar o cliente é o seguinte:

O primeiro parâmetro indica a URL ou o caminho em disco para o WSDL. No caso, foi utilizada uma URL para o WSDL. O parâmetro o indica o diretório onde os arquivos Java serão criados. O parâmetro p define o nome do pacote Java onde as classes serão criadas. Após a execução deste comando, são criados os seguintes arquivos:
  • Empregado.java
  • RecursosHumanos.java
  • RecursosHumanosService.java
  • RecursosHumanosServiceLocator.java
  • RecursosHumanosWSSoapBindingStub.java
A interface RecursosHumanos define os métodos publicados no Web Service que podem ser utilizados. A interface RecursosHumanosService define os métodos do serviço de localização do Web Service, que é implementado pela classe RecursosHumanosServiceLocator. É neste locator que fica configurada a URL para o Web Service e que oferece métodos para acessar a classe stub, que faz o acesso proxy ao Web Service. A classe RecursosHumanosWSSoapBindingStub é o stub, ou seja, a classe que faz o binding, ou acesso proxy entre a aplicação cliente e o Web Service, traduzindo a comunicação entre o Java e o Web Service. Por fim, a classe Empregado, que é a implementação do tipo de retorno de um dos métodos, que retorna uma estrutura de dados complexa com o nome mencionado. Com estas classes geradas é possível criar um programa que faz o acesso aos Web Services de fato, como no código abaixo:

Esta classe recupera o stub através do locator e então invoca os métodos publicados. É tão simples quanto utilizar qualquer outra classe Java. O Apache Axis gera as classes que escondem os detalhes de acesso ao Web Service, deixando a comunicação simples e transparente. Um exemplo da execução da classe acima deve imprimir no console algo como:

SEGURANÇA NOS WEB SERVICES Os Web Services podem fornecer serviços que nem sempre são públicos e que necessitam de acesso autorizado. Como os Web Services, de preferência, devem contar apenas lógica funcional, as regras de autorização de acesso ficam fora do serviço, sendo controlado por partes externas ao Web Service propriamente dito. O Apache Axis suporta a implementação de segurança através do projeto WSS4J (http://ws.apache.org/wss4j/), que é uma implementação do padrão OASIS Web Services Security (WS-Security) (http://www.oasis-open.org/committees/tc_home.php?wg_abbrev=wss). Basicamente o WSS4J trabalha com dois níveis de segurança:
  • XML Security
    • XML Signature
    • XML Encryption
  • Tokens
    • Username Tokens
    • Timestamps
    • SAML Tokens
e suporta certificados X.509. Para utilizar o WSS4J, faça o download da sua distribuição (versão utilizada 1.1.0) e adicione o JAR wss4j.jar ao CLASSPATH. A segurança dos Web Services é feita no Apache Axis, com auxilio do WSS4J, através da configuração de handlers. O modo mais simples e prático de adicionar algum nível de segurança é utilizar a estratégia de Username Token, que adiciona informações de usuário e senha ao header (cabeçalho) do SOAP de requisição. A senha pode ser enviada no formato plain text, ou seja, literalmente, ou através de alguma encriptação, através de formato Digest. Este documento exemplifica apenas o uso do Username Token. A partir de um Web Service existente, é possível adicionar ao seu arquivo de deploy (deploy.wsdd), a configuração de um handler que cuida da validação do usuário e senha. Para começar, utilizando do mesmo exemplo deste documento, adicione o seguinte código (tag <requestFlow>) ao wsdd do Web Service:

A tag handler indica o nome da classe que vai tratar a verificação (org.apache.ws.axis.security.WSDoAllReceiver). O parâmetro passwordCallbackClass define o nome completo da classe que vai validar as credenciais enviadas no cabeçalho da requisição SOAP. O parâmetro action define o tipo de autenticação utilizada, no caso Username Token. A classe que faz a validação das credenciais informadas no SOAP de requisição, guj.GUJAxisAutorizacaoCallback, é uma implementação que valida o usuário e senha configurados em um arquivo de properties localizado dentro da aplicação. O código desta classe é o seguinte:

Esta classe apenas valida o usuário "wss4j" com a senha "security". Você pode modificar a implementação desta verificação conforme queira. Tendo a biblioteca do WSS4J (wss4j.jar) adicionada à aplicação, depois de sua publicação (deploy), é somente necessário registrar o Web Service (wsdd), que o serviço já estará com o acesso protegido por usuário e senha. Agora, toda a requisição feita ao Web Service necessitará das credenciais de acesso. Para que o WSS4J possa verificar e validar as credenciais de quem solicita o acesso ao Web Service, é necessário que o documento SOAP de requisição contenha as informações do cabeçalho, contidas na tag <soapenv:Header>:

Note que este é o cabeçalho do SOAP que contém as informações de segurança () através de Username Token (). Nas tags e são informados o usuário e a senha, respectivamente. Na senha também é informado o tipo usado. No caso, wsse:PasswordText informa que está no formato texto literal, que é pouco seguro. Uma forma mais segura de informar a senha á através do modo PasswordDigest, que criptografa a senha. A criptografia é baseada em 3 informações: Nonce, CreationTimestamp (data e hora da criação) + senha. É aplicado o algoritmo SHA-1 no resultado da concatenação destes dados e depois dividido na Base64, conforme a fórmula abaixo: PasswordDigest = Base64 / SHA1( Nonce + CreationTimestamp + Senha ) As especificação pode ser encontrada em: http://www.oasis-open.org/committees/wss/documents/WSS-Username-02-0223-merged.pdf. Segue abaixo um exemplo do SOAP com a senha no formato PasswordDigest:

O próprio WSS4J trata de trabalhar com a senha no formato criptografado. Mais informações sobre o WSS4J e sua utilização pode ser encontrada no site oficial, que conta também com um tutorial bem simples e objetivo: http://ws.apache.org/wss4j/axis.html.
CONCLUSÃO O documento abordou todas as fases no desenvolvimento relacionado aos Web Services com o auxílio da ferramenta Apache Axis. Além da geração via as ferramentas demonstradas, é possível utilizar tasks da ferramenta Ant para a geração via Apache Axis ( http://ws.apache.org/axis/java/ant/ant.html ). A configuração do build.xml do Ant para executar as tarefas descritas neste documento podem ser baseadas no exemplo abaixo:

Mais informações podem ser obtidas em: http://ws.apache.org/axis/java/ant/ant.html. Existe também um plugin que pode ser integrado à IDE Eclipse para gerar os arquivos a partir de um WSDL, chamado de WSDL2JavaWizard, disponível em: http://wsdl2javawizard.sourceforge.net/.