Axis2 é a próxima geração do Apache Axis. Axis2 é inspirado pelo modelo do manipulador Axis 1.x, mas é baseado em uma nova arquitetura muito mais flexível e extensível. O Axis2 é completamente reescrito baseado na nova arquitetura e não possui nenhum código comum com o Axis 1.x. A motivação por trás do Axis2 é a busca por uma arquitetura mais modular, flexível e eficiente que possa efetuar facilmente plug-in da implementação de outros padrões e protocolos de serviços da Web associados, como WS-Security, WS-ReliableMessaging, etc.
Os recursos do Axis2 incluem:
- Um novo modelo de processamento XML principal chamado AXIOM (AXIs O bject Model)
- Suporte para padrões de troca de mensagens (MEP) Somente de Entrada e de Entrada e Saída.
- Uma API (interface de programação de aplicativos) de cliente de bloqueio e não de bloqueio
- Suporte integrado para WS-Addressing
- Suporte à ligação de dados de XMLBeans
- Um novo modelo de implementação
- Suporte para HTTP (Protocolo de Transporte de Hipertexto), SMTP (Protocolo Simples de Transporte de Correio) e TCP (Protocolo de Controle de Transmissões)
Esta série é baseada no Axis2 release 0.92. Você pode obter a versão mais recente do Axis2 no Web site da Apache .
Visão Geral da Arquitetura Axis
Figura 1. Arquitetura Axis2
A arquitetura Axis2 separa lógica e estado; isso permite que a lógica execute em encadeamentos
paralelos. O estado estático e dinâmico do serviço e da chamada estão armazenados nas classes
Description e Context , respectivamente. A arquitetura Axis2 é
implementada usando-se sete módulos independentes:
-
Modelo de informações: Este módulo gerencia o estado do mecanismo SOAP. Esse
modelo define uma coleta de classes para conter o estado e o mecanismo gerencia o ciclo de vida desses
objetos de informações. O modelo de informações possui dois tipos de classes para conter o estado. As classes
Descriptioncontêm dados de natureza estática e que existem ao longo da vida da instância do mecanismo Axis, como configuração de transportes, serviços e operações.As classes Contextcontêm informações dinâmicas do serviço e da operação que são válidas no contexto de uma chamada, como a mensagem SOAP do pedido e resposta atual, o endereço De, o endereço Para e outros elementos. - Modelo de processamento XML: O Axis2 introduz um novo modelo chamado AXIOM para processar mensagens SOAP. O AXIOM usa StAX (Streaming API for XML) para analisar o XML. StAX é um padrão que efetua o fluxo API Java™ do analisador pull. O AXIOM é muito leve e efetua construção adiada do conjunto de informações XML -- ou seja, um objeto é criado somente quando é absolutamente necessário. Em geral, o AXIOM e Axis2 têm uma pequena área de cobertura de memória em comparação ao Axis 1.
-
Modelo de processamento SOAP: A arquitetura Axis2 define dois canais (ou Fluxos)
chamados InPipe (InFlow) e OutPipe (OutFlow) para manipulação de mensagens de pedido e mensagens de resposta
do lado do servidor. Do lado do cliente, os canais são invertidos -- ou seja, a mensagem de pedido SOAP
flui através do OutPipe e a mensagem de resposta flui através do InPipe. Um canal ou fluxo contém uma série
de manipuladores agrupados em fases. As fases são executadas em ordem predefinida, conforme mostrado na
Figura 1 acima. Além do conjunto de fases e manipuladores predefinidos, os usuários podem configurar
fases do usuário e manipuladores associados no nível da operação, serviço ou global. Os manipuladores agem
como interceptores da mensagem SOAP e podem processar o cabeçalho ou o corpo da mensagem SOAP. O InPipe é
configurado com as seguintes fases:
- TransportIn
- PreDispatch
- Dispatch
- PostDispatch
- PolicyDetermination
- Fases do usuário
- Validação da mensagem
- Inicialização da mensagem
- Determinação da política
- Fases do usuário
- MessageOut
-
Módulo de implementação: Este módulo configura o mecanismo Axis e implementa os
serviços e módulos. axis2.xml (localizado em webapps/axis2/WEB-INF) contém a configuração global do
mecanismo Axis2, incluindo:
- Módulos globais
- Receptores globais
- Transportes
- Definições de fase do usuário
- WSDL e geração de códigos: Este módulo cuida da geração de código stub cliente e estrutura do servidor do arquivo WSDL. O gerador de código Axis2 emite arquivos XML aplicados com as folhas de estilo XML corretas para gerar código na linguagem necessária.
- API do cliente: A API do cliente Axis2 chama operações seguindo padrões de mensagens Somente de Entrada e de Entrada e Saída definidos por WSDL 2.0. A API do cliente suporta chamada de bloqueio e não de bloqueio de operações de Entrada e Saída.
- Transportes: Este módulo contém manipuladores que interagem com a camada de transporte. Há dois tipos de manipuladores de transporte, TransportListener e TransportSender. O TransportListener recebe a mensagem SOAP da camada de transporte e passa a mesma para o InPipe para processamento. Um TransportSender envia a mensagem SOAP recebida do OutPipe pelo transporte especificado. O Axis2 fornece manipuladores para HTTP, SMTP e TCP. Para transporte HTTP, o AxisServlet do lado do servidor e um servidor HTTP independente simples (fornecido pelo Axis2) do lado do cliente funcionam como o TransportReceiver.
Implementar o Axis2 é tão simples quanto o Axis 1. Primeiro, localize o aplicativo da Web do Axis2, axis2.war, no diretório webapps de distribuição binária do Axis2. Implemente esse arquivo war em um contêiner de servlet. No Tomcat, quando unpackWARs é configurado para true na configuração do servidor, simplesmente copiar o axis2.war para o diretório $TOMCAT_HOME/webapps é suficiente para implementar o Axis2. Agora, inicie o Tomcat e acesse http://localhost:<port>/axis2. Isso mostrará a página de boas-vindas do Axis2, clique no link 'Validar' nessa página. Você deve obter 'Página de Felicidade do Axis2' sem nenhum erro.
Desenvolvendo um StockQuoteService
Aqui você verá como desenvolver um StockQuoteService com duas operações, uma operação subscribe() Somente de Entrada e uma operação getQuote() de Entrada e Saída. A operação subscribe() assinará cotações por hora para o símbolo em questão e getQuote() obterá a cotação atual para o símbolo em questão.
A Lista 1 abaixo é uma implementação de amostra do StockQuoteService:
Lista 1. Implementação do StockQuoteService
package stock;
import org.apache.axis2.om.OMAbstractFactory;
import org.apache.axis2.om.OMElement;
import org.apache.axis2.om.OMFactory;
import org.apache.axis2.om.OMNamespace;
public class StockQuoteService {
public void subscribe(OMElement in){
String symbol = in.getText();
System.out.println("Subscription request for symbol ="+symbol);
// coloque o código de assinatura real aqui...
}
public OMElement getQuote(OMElement in){
// Obtenha o símbolo da mensagem de pedido
String symbol = in.getText();
int quote = 0;
if(symbol.equals("IBM")){
quote = 100;
}
// Coloque mais cotações aqui...
// Crie a resposta
OMFactory fac = OMAbstractFactory.getOMFactory();
OMNamespace omNs = fac.createOMNamespace(
"http://www.developerworks.com/example", "example");
OMElement resp = fac.createOMElement("getQuoteResponse", omNs);
resp.setText(String.valueOf(quote));
return resp;
}
}
|
Pensando sobre as assinaturas de método? Vamos falar sobre o OMElement nos métodos indicados acima em um momento.
Descritor de Implementação
No Axis2, as informações de implementação de serviço estão contidas no arquivo services.xml (em versões mais antigas do que a 0.92, o arquivo é denominado service.xml). Para o StockQuoteService acima, o descritor de implementação do serviço terá a aparência da Lista 2 abaixo.
Lista 2. Services.xml
<service name="StockQuoteService">
<parameter name="ServiceClass" locked="xsd:false">
stock.StockQuoteService
</parameter>
<operation name="getQuote">
<messageReceiver
class="org.apache.axis2.receivers.RawXMLINOutMessageReceiver"/>
</operation>
<operation name="subscribe">
<messageReceiver
class="org.apache.axis2.receivers.RawXMLINOnlyMessageReceiver"/>
</operation>
</service>
|
O atributo nome do serviço define o nome do serviço. O Axis2 usa o nome do serviço
para criar o endereço do terminal do serviço como
http://localhost:<port>/axis2/services/<nameofservice>. Portanto, para o StockQuoteService, o
terminal em serviço será http://localhost:<port>/axis2/services/StockQuoteService. O parâmetro
ServiceClass especifica a classe de implementação do serviço.
Cada elemento <operation> define a configuração de uma operação no serviço. O atributo
nome da <operation> deve ser configurado para o nome do método na classe de implementação do
serviço. O elemento messageReceiver define o receptor de mensagem a ser usado para
manipulação dessa operação. O Axis2 fornece dois MessageReceivers integrados para operações Somente de
Entrada e de Entrada e Saída sem ligação de dados;
org.apache.axis2.receivers.RawXMLINOnlyMessageReceiver para a operação Somente de Entrada e
org.apache.axis2.receivers.RawXMLINOutMessageReceiver para a operação de Entrada e Saída. Quando
nenhum messageReceiver for especificado, o Axis2 tentará usar
org.apache.axis2.receivers.RawXMLINOutMessageReceiver como o padrão. Os receptores de mensagens RAWXML
mencionados acima passam o conteúdo de <Body> da mensagem SOAP de entrada para a implementação de
serviço como um OMElement (OMElement é a abstração do AXIOM de um elemento XML). A operação deve retornar o
conteúdo XML que vai no elemento <Body> da resposta SOAP como um OMElement. Isso explica porque as
operações subscribe() e getQuote() aceitam e retornam OMElement.
O services.xml também pode conter diversos serviços agrupados como um servicegroup.
Pacote
Os serviços Axis 2 estão empacotados como Axis Archive (.aar). É um arquivo JAR (criado usando os utilitários jar ou zip) com o arquivo services.xml empacotado no diretório META-INF do archive. O StockQuoteService quando empacotado como StockQuoteService.aar terá as seguintes estruturas:
./stock/StockQuoteService.class |
Um archive StockQuoteService pré-empacotado pode ser localizado na seção Download deste artigo.
Implementação
A implementação do serviço no Axis2 é bem simples; simplesmente copie o arquivo .aar para o diretório axis2/WEB-INF/services no aplicativo da Web axis2 em seu contêiner de servlet. No caso do Tomcat, será $TOMCAT_HOME/webapps/axis2/WEB-INF/services.
Outra maneira interessante de implementar o serviço é usando a ferramenta 'Fazer Upload do Serviço' no console de administração do Axis2. Vá para http://localhost:<port>/axis2 e selecione o link 'Administração' . Insira admin/axis2 como nome do usuário e senha e efetue login. (É possível configurar o nome do usuário/senha no axis2.xml.) Selecione o link 'Fazer Upload do Serviço' na seção de ferramenta, selecione o arquivo .aar e clique em Upload. É isso! Você obterá uma mensagem de êxito verde quando tiver transferido por upload com sucesso. O serviço está implementado e pronto para ser chamado. Esse recurso é muito útil quando você deseja implementar o serviço em um servidor Axis2 remoto.
Consumindo Serviços da Web Usando o Axis2
A natureza da chamada do serviço da Web é decidida pelo MEP, o protocolo de transporte e o comportamento síncrono e/ou assíncrono da API do cliente. O Axis2 atualmente suporta MEPs Somente de Entrada e de Entrada e Saída definidos pelo WSDL 2.0. A API do cliente do Axis2 suporta chamada síncrona e assíncrona de serviços. O comportamento assíncrono é fornecido no nível da API e no nível do transporte ao chamar as operações de Entrada e Saída. A assincronia no nível da API é obtida por retorno de chamada e usa uma conexão de transporte única para transferir pedido e resposta (por exemplo, pedido e resposta transferidos por uma única conexão HTTP). Na assincronia no nível do transporte, conexões de transporte separadas são usadas para enviar o pedido e receber a resposta -- por exemplo, quando você usa SMTP para transporte.
São fornecidos abaixo os detalhes de chamada das operações Somente de Entrada e de Entrada e Saída usando a API do cliente do Axis2.
Chamando Operação Somente de Entrada
A classe org.apache.axis2.clientapi.MessageSender é usada para
chamar uma operação Somente de Entrada, conforme mostrado na Lista 3 abaixo, que
chama a operação subscribe() do StockQuoteService.
Lista 3. Chamando Operação Somente de Entrada
try{
EndpointReference targetEPR = new EndpointReference(
"http://localhost:8080/axis2/services/StockQuoteService");
// Faça a mensagem de pedido
OMFactory fac = OMAbstractFactory.getOMFactory();
OMNamespace omNs = fac.createOMNamespace(
"http://www.developerworks.com/example", "example");
OMElement payload = fac.createOMElement("subscribe", omNs);
payload.setText("IBM");
// Envie o pedido
MessageSender msgSender = new MessageSender();
msgSender.setTo(targetEPR);
msgSender.setSenderTransport(Constants.TRANSPORT_HTTP);
msgSender.send("subscribe", payload);
}catch (AxisFault axisFault) {
axisFault.printStackTrace();
}
|
MessageSender.send() envia a mensagem de pedido e retorna a mesma
imediatamente. O transporte a ser usado é especificado por
MessageSender.setSenderTransport(). Este exemplo envia a mensagem sobre HTTP.
Chamando uma Operação de Entrada e Saída
A classe org.apache.axis2.clientapi.Call é uma maneira conveniente de chamar
uma operação de Entrada e Saída. Essa classe Call suporta os quatro padrões a
seguir para chamar operações de Entrada e Saída:
-
Padrão Transporte Único com Bloqueio: Essa é a maneira mais simples de chamar uma operação de serviço da Web de Entrada e Saída. A chamada do serviço é bloqueada até a operação ser concluída e a resposta ou falha ser recebida. Usa uma única conexão de transporte para enviar e receber a resposta, conforme mostrado na Lista 4 abaixo.
Lista 4. Padrão Transporte Único com Bloqueiotry { EndpointReference targetEPR = new EndpointReference( "http://localhost:8080/axis2/services/StockQuoteService"); // Crie a mensagem de pedido OMFactory fac = OMAbstractFactory.getOMFactory(); OMNamespace omNs = fac.createOMNamespace( "http://www.developerworks.com/example", "example"); OMElement payload = fac.createOMElement("getQuote",omNs); payload.setText("IBM"); // Crie a chamada Call call = new Call(); call.setTo(targetEPR); call.setTransportInfo(Constants.TRANSPORT_HTTP, Constants.TRANSPORT_HTTP, false); // Chame o bloqueio OMElement result = call.invokeBlocking("getQuote", payload); System.out.println("Quote ="+result.getText()); }catch (AxisFault axisFault) { axisFault.printStackTrace(); }
A primeira parte do código cria a mensagem de pedido usando o AXIOM.
Call.setTransportInfo()configura os transportes a serem usados para enviar o pedido e obter a resposta. O argumento booleano da operaçãoCall.setTransportInfo()indica se uma conexão de transporte separada deve ser usada para enviar o pedido e receber a resposta. Nesse caso, solicite uma única conexão HTTP para enviar e receber. -
Padrão Transporte Único sem Bloqueio: Neste padrão de chamada, você obtém uma chamada sem bloqueio usando somente uma conexão de transporte único por baixo. Esse tipo de comportamento é necessário quando há diversas chamadas de serviço da Web a serem realizadas em um único aplicativo cliente e você não deseja que o cliente seja bloqueado para cada chamada. Aqui, a chamada retorna imediatamente e o cliente obtém um retorno de chamada quando a resposta está disponível, conforme mostrado na Lista 5 abaixo.
Lista 5. Padrão Transporte Único sem Bloqueiotry { EndpointReference targetEPR = new EndpointReference( "http://localhost:8080/axis2/services/StockQuoteService"); //Crie o pedido OMFactory fac = OMAbstractFactory.getOMFactory(); OMNamespace omNs = fac.createOMNamespace( "http://www.developerworks.com/example", "example"); OMElement payload = fac.createOMElement("getQuote", omNs); payload.setText("IBM"); // Crie a chamada Call call = new Call(); call.setTo(targetEPR); // Configure as informações de transporte. call.setTransportInfo(org.apache.axis2.Constants.TRANSPORT_HTTP, org.apache.axis2.Constants.TRANSPORT_HTTP, false); // Retorno de chamada para tratar da resposta Callback callback = new Callback() { public void onComplete(AsyncResult result) { System.out.println("Quote = " + result.getResponseEnvelope().getBody().getFirstElement() .getText()); } public void reportError(Exception e) { e.printStackTrace(); } }; // Chame não bloqueio call.invokeNonBlocking("getQuote", payload, callback); //Aguarde até o retorno de chamada receber a resposta. while (!callback.isComplete()) { Thread.sleep(1000); } call.close(); } catch (AxisFault axisFault) { axisFault.printStackTrace(); } catch (Exception ex) { ex.printStackTrace(); }
O método
Call.invokeNonBlocking()retorna imediatamente sem bloqueio.Call.invokeNonBlocking()aceita um objeto deorg.apache.axis2.clientapi.CallBack, que será acionado quando a resposta vier do serviço. OCallBackpossui dois métodos abstratos, onComplete(AsynchResult)ereportError(Exception), que precisam ser implementados pela classeCallBackconcreta. O mecanismo Axis2 chama o métodoonComplete()quando a chamada do serviço é concluída normalmente. Em uma mensagem de falha do servidor, o métodoreportError()doCallbacké chamado.Callback.isComplete()indica se a chamada da operação foi concluída ou não.Como ambas as abordagens acima usam uma única conexão de transporte para enviar e receber mensagens, não são adequadas para transações de longa execução. Isso ocorre porque a conexão de transporte pode ter o tempo limite excedido antes da resposta estar disponível. Para abordar esse problema, duas conexões de transporte separadas podem ser usadas para pedido e resposta. Mas como uma conexão de transporte diferente é usada para recuperar a resposta, o pedido e a resposta precisam ser correlacionados. O Axis2 suporta WS-Addressing, que fornece uma solução para esse problema usando os cabeçalhos <wsa:MessageID> e <wsa:RelatesTo>. Portanto, a abordagem do módulo precisa ser ativada ao usar-se transporte duplo, conforme mostrado nos dois padrões abaixo.
-
Padrão Transporte Duplo com Bloqueio: Esse padrão é útil quando a operação de serviço é de natureza de Entrada e Saída, mas o transporte usado é Unidirecional (por exemplo, SMTP) ou quando a execução do serviço leva muito tempo e a conexão HTTP tem o tempo limite excedido. Consulte a Lista 6 abaixo.
Lista 6. Padrão Transporte Duplo com Bloqueiotry{ EndpointReference targetEPR = new EndpointReference( "http://localhost:8080/axis2/services/StockQuoteService"); OMFactory fac = OMAbstractFactory.getOMFactory(); OMNamespace omNs = fac.createOMNamespace( "http://www.developerworks.com/example", "example"); OMElement payload = fac.createOMElement("getQuote",omNs); payload.setText("IBM"); Call call = new Call(); call.setTo(targetEPR); call.setTransportInfo( Constants.TRANSPORT_HTTP, Constants.TRANSPORT_HTTP, true); //Chamada de Bloqueio OMElement result = call.invokeBlocking("getQuote", payload); System.out.println("Quote = "+result.getText()); }catch (AxisFault axisFault) { axisFault.printStackTrace(); }catch (Exception ex) { ex.printStackTrace(); }
-
Padrão Transporte Duplo sem Bloqueio: Esse padrão fornece flexibilidade máxima, em termos de não bloquear no nível da API e no nível do transporte, conforme mostrado na Lista 7 abaixo.
Lista 7. Padrão Transporte Duplo sem Bloqueiotry { EndpointReference targetEPR = new EndpointReference( "http://localhost:8080/axis2/services/StockQuoteService"); OMFactory fac = OMAbstractFactory.getOMFactory(); OMNamespace omNs = fac.createOMNamespace( "http://www.developerworks.com/example", "example"); OMElement payload = fac.createOMElement("getQuote",omNs); payload.setText("IBM"); Call call = new Call(); call.setTo(targetEPR); call.setTransportInfo( Constants.TRANSPORT_HTTP, Constants.TRANSPORT_HTTP, true); // Retorno de chamada para tratar da resposta Callback callback = new Callback() { public void onComplete(AsyncResult result) { System.out.println("Quote = " + result.getResponseEnvelope().getBody().getFirstElement() .getText()); } public void reportError(Exception e) { e.printStackTrace(); } }; // Chamada Não de Bloqueio call.invokeNonBlocking("getQuote", payload, callback); //Aguarde até o retorno de chamada receber a resposta. while (!callback.isComplete()) { Thread.sleep(1000); } call.close(); }catch (AxisFault axisFault) { axisFault.printStackTrace(); }catch (Exception ex) { ex.printStackTrace(); }
Na Parte 1 desta série em duas partes, você aprendeu sobre a arquitetura Axis2 e viu como implementar e consumir um serviço da Web simples usando diferentes padrões de chamada. Na Parte 2 desta série, você revisará a arquitetura em mais detalhes e verá como customizar o Axis2 incluindo manipuladores e receptores de mensagens do Axis2. Você também verá como usar o suporte à ligação de dados XMLBeans fornecido pelo Axis2.
| Descrição | Nome | Tamanho | Método de download |
|---|---|---|---|
| StockQuoteService Axis2 Archive file | StockQuoteService.aar | 3 KB | HTTP |
Informações sobre métodos de download
Aprender
-
Especificação do WSDL 2.0
-
SOA e Serviços da Web -- hospeda
centenas de artigos informativos e tutoriais de introdução, intermediários e avançados sobre como desenvolver
aplicativos de serviços da Web.
- A equipe do IBM developerWorks realiza centenas de
briefings técnicos em todo o mundo, dos quais você pode participar gratuitamente.
Obter produtos e tecnologias
-
Entre em contato com ferramentas de desenvolvimento de aplicativos e produtos de middleware do DB2®,
Lotus®, Rational®, Tivoli® e WebSphere®. Você pode
fazer download de versões de avaliação dos produtos gratuitamente ou selecionar a versão Linux® ou
Windows® do
Software Evaluation Kit do developerWorks.
Discutir
-
Mala Direta do Axis2 discute uso,
problemas e solução no Axis2.
-
Blogs do developerWorks: Envolva-se na
comunidade developerWorks.
Gopalakrishnan U está trabalhando atualmente com o Grupo de Pesquisa dos Laboratórios de Software da IBM Índia. Ele vem trabalhando em diversos projetos de pesquisa e desenvolvimento em tecnologias de Serviços da Web nos últimos 3 anos e fez contribuições para o IBM Emerging Technologies Tool Kit (ETTK). É coautor de um artigo sobre segurança dos serviços da Web no developerWorks. Gopalakrishnan pode ser contatado em ugopalak@in.ibm.com.
Shreevidya Rao é uma Engenheira de Software do Grupo de Pesquisa dos Laboratórios de Software da IBM. Ela está na IBM há um ano e tem cinco anos de experiência em Java e J2EE. Atualmente, ela está trabalhando no desenvolvimento de um criador de logs gerenciável distribuído. E pode ser contatada em shreerao@in.ibm.com.