Javafree

Iniciando no SOAP com Apache Axis

Publicado por Tutoriais Admin em 17/08/2009 - 84.794 visualizações

Cleuber Batista Silva
cleuber_s @ hotmail.com

Eduardo Manuel de Freitas Jorge
emjorge @ reconcavotecnologia.org.br

Introdução

Grande parte das necessidades de usuários de sistemas hoje, é ter informações em tempo hábil. Há também o grande desafio de conciliar sistemas legados ou de plataformas diferenciadas. Os webservices vieram para resolver esse problema. No entanto não há uma definição universalmente aceita. Definições de webservices têem sido temas para grandes debates no W3C (grupo para regulamentação de padrões para a web). Embora exista essa dificuldade na definição, é geralmente aceito que webservices são serviços orientados à arquitetura (SOA) com características adicionais:

 

  • Interface deve ser baseada em protocolos da família IP como, http, ftp ou smtp;

  • Com exceção de anexos, dados devem trafegar via XML.

Há dois tipos principais para desenvolvimento de web services o SOAP, e o REST (baseado no conceito de recurso); Iremos nos ater apenas ao SOAP como método de aprendizado prático para webservices.

Webservices SOAP

SOAP (acrônimo do inglês Simple Object Access Protocol ) é um protocolo para intercâmbio de mensagens entre programas de computador. Servidores SOAP são implementados utilizando-se servidores http pré-existentes, embora isto não seja uma restrição para funcionamento do protocolo.

Para implementação de um Webservices SOAP, existem duas restrições:

  • Dados devem trafegar via XML, exceto para anexos (em binário).

  • A descrição do serviço deve estar em um arquivo WSDL (Web Services Description Language).

[image]

fig. 01

Hoje existem diversos frameworks que facilitam a geração de webservices baseados no SOAP. Estaremos adotando o Apache Axis versão 1.3, é uma ferramenta open source e muito adotada entres desenvolvedores em todo o mundo.


Recursos

A seguir os recursos empregados neste tutorial e como conseguí-los:

 

Recursos
URL
Versão
TomCat
5.5.16
AXIS
1.3
Xerces
2.8.0


O axis é um framework para desenvolvimento de web services. Veremos em breve como ele facilita o trabalho de geração dos mesmos e a publicação (deploy) de um serviço.

Passos para a instalação do TomCat, podem ser obtidos na documentação oficial do produto disponível em http://tomcat.apache.org/tomcat-5.5-doc/index.html .

Instalação do Axis

1. Descompacte o arquivo *. zip do Axis na pasta C:\axis

2. Dentro de C:\axis\webapps há um diretório chamado axis. Copie esse diretório para dentro da pasta webapps do Tomcat.

3. Descompacte o arquivo *. zip do Xerces e copie os arquivos xml-apis.jar e xml-apis.jar para a pasta lib do Axis.

4. Precisaremos configurar as seguintes variáveis de ambiente conforme abaixo:

  AXIS_HOME=C:\axis 
  AXIS_LIB   =%AXIS_HOME%\lib 
  AXISCLASSPATH=%AXIS_LIB%\wsdl4j-1.5.1.jar;%AXIS_LIB%\axis.jar;%AXIS_LIB%\commons-discovery-0.2.jar;
%AXIS_LIB%\commons-logging- 1.0.4.jar;%AXIS_LIB%\jaxrpc.jar;%AXIS_LIB%\saaj.jar; 
%AXIS_LIB%\log4j-1.2.8.jar;%AXIS_LIB%\xml-apis.jar;%AXIS_LIB%\xercesImpl.jar;%AXIS_LIB%\jaxrpc.jar

 5. Após isso é necessário inicializar o tomCat e verificar se o Axis está funcionando. Isso é feito através do endereço: http://localhost:8080/axis.

Será exibida uma tela como a seguinte:


fig. 02

O Axis possui um recurso de validação da configuração da instalação, no link validation é possível verificar se há algum componente do framework que está faltando:



fig. 03

Criando o WebService

Estaremos criando uma agenda com nomes e telefones, que será acessada remotamente. Para isso temos as seguintes classes implementadas, elas representam a nossa aplicação já desenvolvida.

Contato.Java
package tutorial;

public class Contato {
private String nome;

private String telefone;

public Contato() {
}

public Contato(String n, String t) {
setNome(n);
setTelefone(t);
}

public String getNome() {
return this.nome;
}

public String getTelefone() {
return this.telefone;
}

public void setNome(String n) {
this.nome = n;
}

public void setTelefone(String t) {
this.telefone = t;
}

public String toString() {
return "Nome: " + getNome() + "\tTelefone: " + getTelefone();
}

public boolean equals(Object o) {
Contato c = (Contato) o;
return this.telefone.equals(c.getTelefone());
}
}
IF_Agenda.java
package tutorial;

import java.util.*;

public interface IF_Agenda {
public void adicionaContato(Contato c) throws Exception;

public void removeContato(String t) throws Exception;

public Contato localizaContato(String t) throws Exception;

public Collection listaContato() throws Exception;
}
AgendaList.java
package tutorial;

import java.util.*;

public class AgendaList implements IF_Agenda {
private ArrayList listaContato = new ArrayList();

private int localizaContatoI(String t) {
Contato c = new Contato();
c.setTelefone(t);
return this.listaContato.indexOf(c);
}

public void adicionaContato(Contato c) throws Exception {
if ((localizaContatoI(c.getTelefone()) == -1)) {
this.listaContato.add(c);
} else {
throw new Exception("Contato já cadastrado!");
}
}

public Contato localizaContato(String t) throws Exception {
Contato c = (Contato) this.listaContato.get(this.localizaContatoI(t));
if (c instanceof Contato) {
return c;
} else {
throw new Exception("Contato não cadastrado!");
}
}

public void removeContato(String t) throws Exception {
if (!(this.localizaContatoI(t) == -1)) {
this.listaContato.remove(this.localizaContatoI(t));
} else {
throw new Exception("Contato não cadastrado!");
}
}

public Collection listaContato() throws Exception {
if (this.listaContato.size() > 0) {
return this.listaContato;
} else {
throw new Exception("Não existem contatos cadastrados");
}
}
}
AgendaMap.java
package tutorial;

import java.util.*;

public class AgendaMap implements IF_Agenda {
private HashMap listaContato = new HashMap();

public void adicionaContato(Contato c) throws Exception {
if (!(this.listaContato.containsKey(c.getTelefone()))) {
this.listaContato.put(c.getTelefone(), (Contato) c);
} else {
throw new Exception("Contato já cadastrado!");
}
}

public Contato localizaContato(String t) throws Exception {
Contato c = (Contato) this.listaContato.get(t);
if (c instanceof Contato) {
return c;
} else {
throw new Exception("Contato não cadastrado!");
}
}

public void removeContato(String t) throws Exception {
if (this.listaContato.containsKey(t)) {
this.listaContato.remove(t);
} else {
throw new Exception("Contato não cadastrado!");
}
}

public Collection listaContato() throws Exception {
if (this.listaContato.size() > 0) {
return this.listaContato.values();
} else {
throw new Exception("Não existem contatos cadastrados");
}
}
}
FabricaAgenda.java
package tutorial;

public class FabricaAgenda {
public static final int AGENDAMAP = 1;

public static final int AGENDALIST = 2;

private static IF_Agenda ifa;

private FabricaAgenda(int tipo) {
switch (tipo) {
case FabricaAgenda.AGENDAMAP:
ifa = new AgendaMap();
case FabricaAgenda.AGENDALIST:
ifa = new AgendaList();
}
}

public static IF_Agenda getInstance(int tipo) {
if (ifa == null)
new FabricaAgenda(tipo);
return ifa;
}
}


Estas são classes normais, com seus padrões adotados, a classe a seguir a simples implementação do webservice, uma classe que irá obter uma instância do tipo IF_Agenda.

WebAgenda.java
package tutorial;

import java.util.*;

public class WebAgenda {

private static IF_Agenda agenda = inicialize();

private static IF_Agenda inicialize() {
return FabricaAgenda.getInstance(FabricaAgenda.AGENDALIST);
}

public void adicionaContato(Contato c) throws Exception {
agenda.adicionaContato(c);
}

public void removeContato(String t) throws Exception {
agenda.removeContato(t);
}

public Contato localizaContato(String t) throws Exception {
return agenda.localizaContato(t);
}

public Collection listaContato() throws Exception {
return agenda.listaContato();
}
}

É necessário compilar todas as classes acima e colocá-las no diretório WEB-INF / classes do contexto do AXIS, ou também existe a possibilidade de empacotar em um JAR e colocá-las no WEB-INF / lib do contexto.

Publicando o WebService

O Axis disponibiliza uma ferramenta para fazer o deploy / undeploy do seu webservice de uma forma mais ?profissional?, é o AdminClient. Um recurso do Axis para publicação de webservices. Para utilizar essa ferramenta é necessário criar um arquivo WSDD, que é o doumento que descreve a forma como será implantado o seu webservice. Abaixo segue um exemplo de WSDD, ele se refere à classe que será o webservice.

deploy.wsdd
<deployment xmlns="http://xml.apache.org/axis/wsdd/" xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">


<service name="WEBAGENDA" provider="java:RPC">
<parameter name="className" value="tutorial.WebAgenda"/>
<parameter name="allowedMethods" value="*"/>
<parameter name="scope" value="application"/>
<beanMapping qname="myNS:Contato" xmlns:myNS="urn:BeanService" languageSpecificType="java:tutorial.Contato"/>
</service>


</deployment>

A tag service se refere ao seu webservice, o parâmetro name pode ser um nome qualquer para seu webservice. refere-se ao caminho da classe que será o webservice. são os métodos que terão chamadas remotas o * significa todos. Para fazer uma restrição é necessário colocar o nome do método, separado por vírgulas caso exista mais de um. o escopo pode ser de três formas aplicação (application), sessão (session) e requisição (request). O último é a tag beanMapping , que diz respeito ao objeto que queremos serializar / deserializar, neste caso colocamos um nome para chamadas (qname) de Contato, e o tipo do objeto que o gerenciará na rede será o BeanService e terá uma linguagem declarada e caminho completo da classe no atributo languageSpecificType .

Para publicarmos esse webservice é só executarmos o comando:

   java -cp %AXISCLASSPATH% org.apache.axis.client.AdminClient deploy.wsdd  

Ao ser exibida a mensagem ?Done Processing? o webservice foi publicado com êxito. Podemos também fazer um arquivo de undeploy desta forma:

  <undeployment xmlns="http://xml.apache.org/axis/wsdd/">

<service name="WEBAGENDA"/>

</undeployment>

O mesmo comando é executado para undeploy:

   java -cp %AXISCLASSPATH% org.apache.axis.client.AdminClient undeploy.wsdd  

Após isso o nosso webservice estará na lista de webservices publicados, e todos os métodos sendo exibidos. Caso ocorra algum problema na execução dos comandos, tente verificar se o Axis está configurado adequadamente (ver tópico instalação do Axis). Se clicarmos no link WSDL, ele irá exibir o arquivo com as interfaces descritas para acesso via SOAP.

fig. 04

Precisaremos do link para o WSDL, para gerarmos o cliente que irá acessar o nosso webservice.

Gerando o cliente do webservice

O Axis possui uma outra ferramenta que gera o código para o cliente acessar um webservice, é o WSDL2Java. Ele cria um ServiceLocator e gera o Stub para realização da chamada remota no servidor. Assim, como já dito, precisamos do link para o WSDL. O comando completo ficaria assim para o nosso caso:

  java -cp %AXISCLASSPATH% org.apache.axis.wsdl.WSDL2Java http://localhost:8080/axis/services/WEBAGENDA?wsdl 

Neste momento ele irá criar uma pasta localhost e uma beanService. Podem ser criadas outras pastas a depender do seu WSDL, porém a pasta localhost é padrão. É necessário compilar esses arquivos esses arquivos *. Java, e depois é só somente implementar o acesso desta forma, por exemplo:

MeuCliente.Java
import localhost.axis.services.WEBAGENDA.*;

public class MeuCliente {

public static void main(String[] args) {
try {
adicionar();
listar();
localizar();
excluir();
listar();
} catch (Exception e) {
System.out.println(e);
}
}

public static void adicionar() throws Exception {
System.out.println("Adicionando...");
WebAgendaService agenda = new WebAgendaServiceLocator();
WebAgenda web = agenda.getWEBAGENDA();
BeanService.Contato con = new BeanService.Contato();
con.setNome("Cleuber");
con.setTelefone("1234-1234");
web.adicionaContato(con);
con.setNome("José");
con.setTelefone("4567-8945");
web.adicionaContato(con);
}

public static void excluir() throws Exception {
System.out.println("Excluindo...");
WebAgendaService agenda = new WebAgendaServiceLocator();
WebAgenda web = agenda.getWEBAGENDA();
web.removeContato("1234-1234");
}

public static void localizar() throws Exception {
System.out.println("Localizando...");
WebAgendaService agenda = new WebAgendaServiceLocator();
WebAgenda web = agenda.getWEBAGENDA();
System.out.println(web.localizaContato("1234-1234").getNome());

}

public static void listar() throws Exception {
System.out.println("Listando...");
WebAgendaService agenda = new WebAgendaServiceLocator();
WebAgenda web = agenda.getWEBAGENDA();
for (int i = 0; i < web.listaContato().length; i++) {
System.out.println(((BeanService.Contato) web.listaContato()[i])
.getNome());
}
}

}

Ao executar o código acima o cliente fará as chamadas remotas ao webservice.Vale ressaltar que tipos como coleções são recebidos como arrays de objetos, porque nem todas as linguagens de programação possuem coleções, e beans são do tipo conforme gerado pelo WSDL2Java segundo a tag beanMapping .

Conclusão

Webservices são umas das grandes facilidades do momento, quando falamos em interoperabilidade de sistemas; hoje em dia temos vários webservices na internet, o mais popular é o RSSFeed. Apesar de a performance não agradar a todos, o SOAP pode passar sem problemas através de firewalls e proxy?s, isso porque é o XML que trafega na rede através de http. Além disso, o desacoplamento da sua aplicação com cliente, através de serviços orientados à arquitetura pode trazer grandes benefícios quando o mesmo é um desktop, celular, outros sistemas, ou até mesmo todos eles.

Referências:

Web Services. Construindo, disponibilizando e acessando Web Services via J2SE e J2ME: http://www.javafree.org/artigo/871485/Web-Services-Construindo-disponibilizando-e-acessando-Web-Services-via-J2SE-e-J2ME.html

comentários: 0

Tópicos Relacionados