O Apache Axis2 1.1 foi lançado e oferece interessantes recursos novos para os fãs da longa série Apache de estruturas de serviços Web. Vamos tratar do Axis2 em si em um artigo futuro, mas este artigo vai a fundo no modelo de documento XML AXIs Object Model (AXIOM) que fica no núcleo do Axis2. O AXIOM é uma das principais inovações por trás do Axis2, e uma das razões por que este oferece o potencial para desempenho substancialmente melhor do que o Axis original. Este o artigo o guiará sobre como o AXIOM funciona, como as várias partes do Axis2 se desenvolvem no AXIOM e termina com uma olhada no desempenho do AXIOM em comparação com outros™ modelos de objeto de documento em Java.
Os modelos de documento são uma abordagem usada comumente no processamento XML, e há muitos recursos diferentes à disposição para o desenvolvimento Java, incluindo várias implementações da especificação original W3C DOM, JDOM, dom4j, XOM, e outras. Cada modelo afirma ter certas vantagens em relação aos outros, seja no desempenho, flexibilidade, seja na aderência rígida ao padrão XML, e cada uma tem seus defensores. Por que, então, o Axis2 precisava de um novo modelo? A resposta está em como as mensagens SOAP são estruturadas e, especialmente, em como são acrescentadas extensões à estrutura SOAP básica.
O SOAP em si é realmente só um wrapper fino ao redor de uma carga útil de aplicativos
XML. A Listagem 1 dá uma amostra, na qual as únicas partes realmente definidas pelo
SOAP são os elementos com o prefixo soapenv. A maior
parte do documento são os dados do aplicativo que compõem o conteúdo do elemento
soapenv:Body.
Listagem 1. Amostra de SOAP
<soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header/> <soapenv:Body> <matchQuakes
xmlns="http://seismic.sosnoski.com/types">
<min-date>2001-01-06T11:10:43.446Z</min-date>
<max-date>2001-10-24T19:49:13.812Z</max-date>
<min-long>-150.94307</min-long>
<max-long>-22.594208</max-long>
<min-lat>-11.44651</min-lat>
<max-lat>55.089058</max-lat>
</matchQuakes> </soapenv:Body>
</soapenv:Envelope> |
Apesar da simplicidade do wrapper SOAP básico, ele oferece o potencial de extensões ilimitadas usando um componente opcional chamado de cabeçalho. O cabeçalho fornece um local para acrescentar todos os tipos de metadado que acompanharão os dados de aplicativo sem serem vistos pelo aplicativo (é possível incluir dados de aplicativo no cabeçalho, mas não há um caso suficientemente forte para fazer isso em vez de simplesmente usar o corpo para dados de aplicativo). Extensões desenvolvidas no SOAP (como toda a família WS-*) podem usar o cabeçalho para seus próprios fins sem afetar o aplicativo. Isso permite que as extensões operem como complementos, nos quais as funções estendidas específicas de que o aplicativo precisa podem ser simplesmente selecionadas no momento da implementação em vez de serem incluídas no código.
A Listagem 2 mostra os mesmos dados de aplicativo da amostra encontrada na Listagem 1 de SOAP, mas com informações de WS-Addressing incluídas. Embora a mensagem SOAP original provavelmente só fosse utilizável por transporte HTTP (visto que o HTTP fornece uma conexão bidirecional para que uma resposta imediata seja enviada de volta ao cliente), a versão da Listagem 2 poderia operar em outros protocolos, pois inclui os metadados de resposta diretamente na mensagem SOAP de solicitação. Seria fácil até mesmo ter uma etapa de armazenar e encaminhar envolvida no processamento da mensagem na Listagem 2 visto que os metadados fornecem informações de alvo de solicitação e de alvo de resposta.
Listagem 2. Amostra SOAP com WS-Addressing
<soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:wsa="http://www.w3.org/2005/08/addressing">
<soapenv:Header>
<wsa:To>http://localhost:8800/axis2/services/SeisAxis2XBean</wsa:To>
<wsa:ReplyTo>
<wsa:Address>http://www.w3.org/2005/08/addressing/anonymous</wsa:Address>
</wsa:ReplyTo>
<wsa:MessageID>urn:uuid:97AE2B17231A8584D811537402403691</wsa:MessageID>
</soapenv:Header> <soapenv:Body> <matchQuakes
xmlns="http://seismic.sosnoski.com/types">
<min-date>2000-03-28T13:13:08.953Z</min-date>
<max-date>2001-03-11T02:26:54.283Z</max-date>
<min-long>-81.532234</min-long>
<max-long>65.25895</max-long>
<min-lat>-14.234512</min-lat>
<max-lat>57.174187</max-lat>
</matchQuakes> </soapenv:Body>
</soapenv:Envelope> |
O dilema do modelo de documento
Visto que a função básica do cabeçalho SOAP é permitir que metadados arbitrários sejam acrescentados à mensagem, é importante que as estruturas SOAP sejam capazes de aceitar qualquer coisa que uma extensão decida acrescentar. Falando de forma geral, o modo mais fácil de trabalhar com XML arbitrário é usando um modelo de documento de uma forma ou outra. Afinal de contas, essa é a razão de ser de um modelo de documento -- representar fielmente o XML sem suposições sobre a forma daquele XML.
Mas modelos de documento não são um modo muito eficiente de trabalhar com XML que é usado para trocar dados entre aplicativos. Os dados de aplicativo normalmente têm uma estrutura predefinida, e a maioria dos desenvolvedores prefere trabalhar com esses dados na forma de objetos de dado em vez de XML puro. O trabalho de converter entre objetos de dado e XML fica no âmbito do que é chamado de ligação de dados. A ligação de dados não só é mais conveniente para os desenvolvedores do que trabalhar com um modelo de documento, mas também é muito mais eficiente em termos de desempenho e uso de memória.
Assim, a maioria dos aplicativos decide usar ligação de dados para trabalhar com a carga útil de aplicativo da mensagem SOAP, mas a abordagem do modelo de documento é melhor para trabalhar com os metadados presentes no cabeçalho. A abordagem ideal seria combinar as duas técnicas dentro da estrutura SOAP, mas os modelos de documento normais não são configurados para permitir isso. Eles esperam trabalhar com um documento inteiro, ou, pelo menos, uma subárvore inteira de documento. Não são configurados para trabalhar apenas com partes selecionadas de um documento, como é mais adequado no SOAP.
Além do AXIOM, há outra mudança entre o Axis e o Axis2. Enquanto o Axis original usava um analisador padrão em estilo push (SAX) para processar XML, o Axis2 usa um analisador estilo pull (StAX). Na abordagem push, o analisador fica no controle da operação de análise -- você lhe dá um documento para analisar e uma referência de manipulador. Ele usa então o manipulador para retornos de chamada no seu código ao processar o documento de entrada. O seu código manipulador pode usar as informações passadas pelos retornos de chamada, mas não pode afetar a análise (exceto ao gerar uma exceção). Por outro lado, na abordagem pull o analisador é na verdade um agente iterativo para percorrer os componentes de um documento on demand.
Tanto a abordagem push como a pull tem seus usos, mas o estilo pull tem um grande benefício no que se refere a XML que contenha componentes logicamente separados (como o SOAP). Com um analisador pull, o código que manipula uma parte do documento pode analisar apenas o que ele precisa e daí liberar o analisador para o que quer que venha a seguir no processamento do documento.
O AXIOM foi desenvolvido sobre uma interface de analisador pull StAX. O AXIOM fornece
um modelo de documento virtual que ele expande on demand, construindo apenas a parte
da representação de modelo de documento de estrutura de árvore solicitada pelo
aplicativo cliente. Esse modelo de documento virtual trabalha no nível dos elementos
do documento XML. é criada uma representação de elemento quando o analisador relata
a tag de início do elemento, mas a forma inicial daquele elemento é essencialmente
apenas um shell que contém uma referência ao analisador. Se o aplicativo precisar
obter detalhes sobre o conteúdo do elemento, ele simplesmente solicita as
informações chamando um método de interface (como o método org.apache.axiom.om.OMContainer.getChildren()). O elemento cria então o
conteúdo-filho a partir do analisador em resposta à chamada de método.
Visto que o analisador libera os dados na ordem do documento (os mesmos itens de ordem aparecem no texto do documento XML), a construção on demand implementada pelo AXIOM exige um manuseio inteligente. Por exemplo, é normal ter múltiplos elementos em um estado incompleto (sob construção), mas esses elementos precisam estar todos em uma linha direta de herança. Em termos de classificação padrão do diagrama de árvore do XML com o elemento raiz no topo, os elementos incompletos sempre estarão na linha abaixo à direita da árvore. à medida que o aplicativo for solicitando mais dados, a árvore vai crescer para a direita, e os elementos inferiores serão concluídos primeiro.
Todos os modelos de documento XML têm muito em comum no que se refere aos seus APIs (o que não é surpresa, visto que todos trabalham com os mesmos dados subjacentes), mas cada um tem algumas manhas que o distingue dos outros. O W3C Document Object Model (DOM) original foi projetado para compatibilidade entre linguagens e entre plataformas, de modo que ele se desenvolve sobre interfaces e evita usar coleções específicas de Java em favor das suas próprias versões. O JDOM usa classes concretas em vez de interfaces e incorpora as classes de coleções padrão Java para um API que muitos desenvolvedores Java consideram mais amigável que o DOM. O dom4j combina interfaces como as do DOM com classes de coleções Java para um obter um API muito flexível que oferece muita potência -- a custo de certa complexidade.
O AXIOM tem muito em comum com esses outros modelos de documento. Também tem algumas diferenças significativas relacionadas com seu processo de desenvolvimento on-demand, além de alguns recursos especializados para dar suporte ao seu uso em serviços Web.
O API do AXIOM é provavelmente mais próximo do DOM no geral, mas tem suas manhas. Por
exemplo, os métodos de acesso são projetados para uso de instâncias java.util.Iterator para acesso a componentes (como
retornado por org.apache.axiom.om.OMContainer.getChildren() e métodos relacionados),
em vez de alguma forma de lista. Em vez de indexar em uma lista de componentes, a
navegação usa os métodos org.apache.axiom.om.OMNode.getNextOMSibling() e org.apache.axiom.om.OMNode.getPreviousOMSibling() para se mover
sequencialmente pelos nós em um nível da árvore de documento (similar ao DOM nesse
aspecto). Essa estruturação do acesso e métodos de navegação combinam com o modo de
funcionamento da construção de árvore on-demand, visto que significa que o AXIOM lhe
permite mover-se para o primeiro filho do seu elemento inicial sem ter de primeiro
processar todos os elementos-filhos.
Como o DOM e o dom4j, o AXIOM define o API usado para acessar e manipular a
representação de árvore usando interfaces. A distribuição AXIOM inclui várias
implementações especializadas diferentes dessas interfaces. Uma implementação (no
pacote org.apache.axiom.om.impl.dom) tem cabeçalho duplo,
suportando interfaces AXIOM e DOM com as mesmas classes de implementação. Isso pode
ser útil em vista do número de complementos de serviços Web que esperam trabalhar
com a visualização DOM dos dados. Para uso mais geral, o pacote org.apache.axiom.om.impl.llom fornece uma implementação baseada em
listas vinculadas de objetos (a parte "ll" do nome do pacote). Há também extensões
das interfaces org.apache.axiom.om básicas e as
implementações na árvore de pacote org.apache.axiom.soap
que foram customizadas para uso com mensagens SOAP.
Para uma olhada rápida no API AXIOM em ação, veremos algumas amostras do código usado
para teste de desempenho do AXIOM em comparação com outros modelos de documento. A
Listagem 3 apresenta a primeira amostra, baseada no código usado para criar a
representação AXIOM de um documento de entrada. Como no caso do DOM e do dom4j,
antes de fazer qualquer coisa com o AXIOM você precisa de um factory que construa os
objetos de componente do modelo. O código da Listagem 3 seleciona a implementação da
lista vinculada básica das interfaces do AXIOM usando a implementação org.apache.axiom.om.impl.llom.factory.OMLinkedListImplFactory da
interface org.apache.axiom.org.OMFactory. A interface
factory inclui métodos para criar um documento diretamente a partir de várias
fontes, e para criar componentes individuais da representação de documento XML. A
Listagem 3 usa o método para criar um documento a partir de um fluxo de entrada. O
objeto retornado pelo método build() é na verdade uma
instância de org.apache.axiom.om.OMDocument, embora isso
não seja especificado por esse código.
Listagem 3. Analisando um documento no AXIOM
import org.apache.axiom.om.*; import
org.apache.axiom.om.impl.builder.StAXOMBuilder; import
org.apache.axiom.om.impl.llom.factory.OMLinkedListImplFactory; ...
private
XMLInputFactory m_parserFactory = XMLInputFactory.newInstance();
private OMFactory
m_factory = new OMLinkedListImplFactory(); ... protected Object build
(InputStream in) { Object doc = null; try { XMLStreamReader reader =
m_parserFactory.createXMLStreamReader(in); StAXOMBuilder builder = new
StAXOMBuilder(m_axiomFactory, reader); doc = builder.getDocument(); }
catch (Exception ex) { ex.printStackTrace(System.out); System.exit(0); }
return doc; } |
A Listagem 3 usa a classe org.apache.axiom.om.impl.builder.StAXOMBuilder para criar a
representação de documento ao analisar um fluxo de entrada. Isso cria apenas uma
instância do analisador StAX e a estrutura básica do documento antes de retornar,
deixando o analisador posicionado dentro do elemento-raiz do documento, com o
restante da representação do documento para ser criada depois, se necessário. O
AXIOM não precisa ser criado usando um analisador StAX. De fato, org.apache.axiom.om.impl.builder.SAXOMBuilder é uma
implementação parcial de um construtor com base no analisador push SAX. Mas se você
o construir de qualquer outra maneira, não terá os benefícios da construção
on-demand.
A Listagem 4 mostra o código usado para "caminhar" pelos elementos em uma
representação do documento e acumula informações de resumo (a contagem dos
elementos, a contagem e comprimento total do texto de valor do atributo e a contagem
e comprimento total do conteúdo de texto). O método walk() na parte inferior faz um documento ser resumido, junto com a
estrutura de dados de resumo, enquanto o método walkElement() no alto processa um elemento (chamando a si mesmo de forma
recorrente para processar os elementos-filhos).
Listagem 4. Navegando no AXIOM
/** * Walk subtree for element. This recursively walks through
the document * nodes under an element, accumulating summary information.
* * @param
element element to be walked * @param summary document summary
information */
protected void walkElement(OMElement element, DocumentSummary summary) {
// include
attribute values in summary for (Iterator iter =
element.getAllAttributes();
iter.hasNext();) { OMAttribute attr = (OMAttribute)iter.next();
summary.addAttribute(attr.getAttributeValue().length()); } // loop
through children
for (Iterator iter = element.getChildren(); iter.hasNext();) { // handle
child by
type OMNode child = (OMNode)iter.next(); int type = child.getType(); if
(type ==
OMNode.TEXT_NODE) { summary.addContent(((OMText)child).getText().length
()); } else
if (type == OMNode.ELEMENT_NODE) { summary.addElements(1);
walkElement((OMElement)child, summary); } } } /** * Walk and summarize
document.
This method walks through the nodes * of the document, accumulating
summary
information. * * @param doc document representation to be walked * @param
summary
output document summary information */ protected void walk(Object doc,
DocumentSummary summary) { summary.addElements(1);
walkElement(((OMDocument)doc).getOMDocumentElement(), summary); } |
Por fim, a Listagem 5 mostra o código usado para escrever a representação do
documento em um fluxo de saída. O AXIOM define muitos métodos de saída como parte da
interface OMNode, incluindo variações de destino (como
fluxo de saída, gravador normal de caractere ou gravador de fluxo StAX), com e sem
informações de formatação, e com e sem a habilidade de acessar a representação do
documento depois de ser gravada (o que exige que a representação inteira seja
criada, se já não tiver sido). A interface OMElement
define outro modo de acessar informações do documento, obtendo um analisador StAX do
elemento. Essa habilidade de fazer o pull do XML a partir da representação usando um
analisador oferece uma simetria interessante, e funciona bem quando a representação
do AXIOM é criada on demand (visto que o analisador em uso para criar a
representação pode então ser retornado diretamente).
Listagem 5. Gravando um documento a partir do AXIOM
/** * Output a document as XML text. * * @param doc
document representation to be output * @param out XML document output
stream */
protected void output(Object doc, OutputStream out) { try {
((OMDocument)doc).serializeAndConsume(out); } catch (Exception ex) {
ex.printStackTrace(System.err); System.exit(0); } } |
O AXIOM fornece alguns métodos básicos para modificar um componente de documento
existente (como OMElement.setText() para configurar o
conteúdo de um elemento para um valor de texto). Se você estiver começando do zero,
precisará criar diretamente novas instâncias de componentes. Visto que o API AXIOM
se baseia em interfaces, ele usa factories para criar implementações reais dos
componentes.
Para mais detalhes sobre o API AXIOM, veja os links do tutorial de AXIOM e JavaDocs na seção de Recursos.
Um dos recursos mais interessantes do AXIOM é seu suporte integrado aos padrões W3C XOP e MTOM, usados nas versões mais recentes dos anexos SOAP. Essas duas normas trabalham juntas: o XML-binary Optimized Packaging (XOP) fornece um modo de os documentos XML incluírem logicamente blobs de dados binários arbitrários e o MTOM (SOAP Message Transmission Optimization Mechanism) aplica a técnica XOP às mensagens SOAP. O XOP e o MTOM são recursos fundamentais na nova geração de estruturas de serviços Web visto que finalmente fornecem suporte a anexos interoperáveis e acabam com os problemas atuais nessa área.
O XOP trabalha com conteúdo de dados de caracteres codificados em base64. A codificação em base64 transforma os valores de dados arbitrários em caracteres ASCII imprimíveis usando um caractere ASCII para representar cada seis bits dos dados originais. Visto que os dados binários em geral não podem ser incluídos no XML (o XML trabalha apenas com caracteres, não bytes puros; até mesmo vários códigos de caractere não são permitidos no XML), a codificação em base64 é útil para incluir dados binários em mensagens XML.
O XOP substitui o texto real em base64 por um elemento especial "Incluir" do espaço de nomes XOP. O elemento Incluir apresenta um URI que identifica uma entidade separada (fora do documento XML) que são os dados reais a serem incluídos no documento XML. Normalmente esse URI identifica um bloco separado dentro da mesma transmissão como documento XML (embora não seja um requisito ele fazer isso, o que oferece benefícios potenciais para troca de documentos por meio de documentos intermediários ou de armazenamento). Os benefícios de substituir o texto em base64 com uma referência aos dados puros são um tamanho de documento um pouco menor (até 25% menor do que em codificações normais de caracteres) e processamento mais rápido sem overhead de codificação e decodificação dos dados em base64.
O MTOM é desenvolvido sobre XOP, primeiro definindo um modelo abstrato de como o XOP pode ser usado para mensagens SOAP, depois especializando esse modelo para uso com o pacote MIME Multipart/Related e finalmente aplicando-o ao transporte HTTP. No conjunto, isso fornece um modo padrão de aplicar o XOP a mensagens SOAP usando o amplamente usado transporte HTTP.
O AXIOM suporta o XOP/MTOM pela interface org.apache.AXIOM.om.OMText e as implementações dessa interface. OMText define métodos para dar suporte a itens de texto
apoiados em dados binários (na forma de javax.activation.DataHandler, parte do Java Activation API amplamente
usado para suporte a anexos em estruturas de serviço Web Java), junto com um
sinalizador "otimizar" que diz se o item pode ser processado usando XOP. A
implementação org.apache.AXIOM.om.impl.llom.OMTextImpl
acrescenta uma ID de conteúdo compatível com MTOM que pode ser configurada quando
uma instância da classe é criada, ou então gerada automaticamente se não for
configurada.
A Listagem 6 exibe uma amostra de como criar uma mensagem usando XOP/MTOM em AXIOM. Esse código é tirado de um exemplo de teste de desempenho que usa serialização Java para converter uma estrutura de dados de resultado em um array de bytes, e daí retorna esse conjunto como anexo.
Listagem 6. Criando uma mensagem XOP/MTOM
public OMElement matchQuakes(OMElement req) { Query query =
new Query(); Iterator iter = req.getChildElements(); try { ... //
retrieve the matching quakes Response response = QuakeBase.getInstance()
.handleQuery(query); //
serialize response to byte array ByteArrayOutputStream bos = new
ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream
(bos);
oos.writeObject(response); byte[]byts = bos.toByteArray(); // generate
response
structure with reference to data ByteArrayDataSource ds = new
ByteArrayDataSource(byts); OMFactory fac = OMAbstractFactory.getOMFactory
();
OMNamespace ns = fac.createOMNamespace("http://seismic.sosnoski.com/types",
"qk");
OMElement resp = fac.createOMElement("response", ns); OMText data =
fac.createOMText(new DataHandler(ds), true); resp.addChild(data); return
resp; }
catch (ParseException e) { e.printStackTrace(); } catch (IOException e) {
e.printStackTrace(); } return null; } |
Embora o código da Listagem 6 gere uma resposta que pode ser enviada usando o
XOP/MTOM, na versão atual do Axis2, o suporte a XOP/MTOM fica desabilitado como
padrão. Para ativá-lo, é preciso incluir um parâmetro <parameter
name="enableMTOM">true</parameter> no arquivo
axis2.xml do Axis2 ou no arquivo services.xml para o seu serviço.
Forneceremos o código completo desse exemplo como parte de comparações de desempenho
mais à frente, mas agora concluiremos com uma amostra do XOP/MTOM em uso.
A Listagem 7 mostra a estrutura da mensagem de resposta gerada pelo serviço da Listagem 6, com e sem XOP/MTOM ativado (sem os cabeçalhos MIME e o anexo binário real, no primeiro caso, e com a maior parte dos dados deixados de fora, no segundo caso).
Listagem 7. Mensagem de resposta com e sem XOP/MTOM
<?xml version='1.0' encoding='UTF-8'?>
<soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header /> <soapenv:Body> <qk:response
xmlns:qk="http://seismic.sosnoski.com/types"
xmlns:tns="http://ws.apache.org/axis2"> <xop:Include
href="cid:1.urn:uuid:966CA4565647BEBA3D115028348657315@apache.org"
xmlns:xop="http://www.w3.org/2004/08/xop/include" />
</qk:response> </soapenv:Body>
</soapenv:Envelope> [actual binary data follows as separate MIME part
with referenced content id] <?xml version='1.0' encoding='UTF-8'?>
<soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header /> <soapenv:Body> <
qk:response
xmlns:qk="http://seismic.sosnoski.com/types"
xmlns:tns="http://ws.apache.org/axis2">rO0ABXNyACdjb20uc29zb...
</qk:response>
</soapenv:Body> </soapenv:Envelope> |
-
A maioria dos desenvolvedores que trabalham com serviços Web precisam trabalhar com dados na forma de objetos Java, em vez de documentos XML (ou mesmo modelos de documento, como o AXIOM). As estruturas de última geração, como Axis e JAX-RPC, implementavam suas próprias formas de ligação de dados para converter entre XML e objetos Java, mas essa era uma solução muito limitada. As implementações de ligação de dados em estruturas de serviços Web em geral não podiam competir com estruturas especializadas de ligação de dados, de modo que usuários que quisessem melhor controle sobre o manuseio de XML tinham de "colar" as estruturas por meio de ineficientes códigos de conversão. Em vista dessas questões, o Axis2 foi projetado desde o início para dar suporte a ligação de dados por "plug-in" usando uma grande variedade de estruturas de ligação de dados.
O suporte à ligação de dados usa extensões customizadas para a ferramenta WSDL2Java
incluída no Axis2. Essa ferramenta gera um código de ligação do Axis2 com base na
descrição de serviço WSDL na forma de stub para o lado de cliente ou um receptor de
mensagem do lado do servidor. O stub do lado do cliente funciona como proxy para
fazer chamadas ao serviço, definindo chamadas de método que implementam operações de
serviço. O receptor de mensagens do lado do servidor funciona como proxy para o
cliente, chamando o método de serviço real definido pelo usuário. Quando a ligação
de dados é solicitada na linha de comando WSDL2Java, a ferramenta chama a extensão
de estrutura de ligação de dados especificada para gerar o código no stub ou
receptor de mensagens que converte entre OMElement e
objetos Java. No caso do stub, os objetos Java (ou valores primitivos) são passados
na chamada de método e o XML convertido é enviado para o servidor como solicitação.
O XML retornado é então reconvertido em objeto Java, que é então retornado como
resultado da chamada de método. O receptor de mensagens no lado do servidor faz as
mesmas conversões em reverso.
No lado de entrada ou unmarshalling (conversão de XML recebido em objetos Java), o
manuseio é fácil. A carga útil do documento XML a ser convertida em objetos Java
está disponível na forma de OMElement, e a estrutura de
ligação de dados simplesmente precisa processar os dados daquele elemento. OMElement fornece acesso aos dados do elemento na forma de
StAX javax.xml.stream.XMLStreamReader, que a maioria das
estruturas de ligação de dados atuais podem usar diretamente como entrada.
O lado de saída ou de marshalling (conversão de objetos Java em XML transmitido) é um
pouco mais difícil. O principal objetivo o AXIOM é evitar a construção de uma
representação total dos dados do XML a menos que isso seja absolutamente necessário.
Para suportar esse princípio no marshalling, é preciso haver um jeito de a estrutura
de ligação de dados ser invocada apenas quando necessário. O AXIOM manuseia isso
usando um org.apache.AXIOM.om.OMDataSource como wrapper
for para a conversão de ligação de dados. OMDataSource
define os métodos para gravar o conteúdo do wrapper usando um dos métodos suportados
pelo AXIOM (para java.io.OutputStream, java.io.Writer ou StAX javax.xml.stream.XMLStreamWriter), junto com outro método que retorna
uma instância de analisador para o conteúdo do wrapper. Uma implementação OMElement pode usar uma instância de OMDataSource para fornecer dados on demand, e a interface OMFactory fornece um método para criar esse tipo de
elemento.
Vamos concluir nossa análise do AXIOM com uma olhada rápida no desempenho. Na época em que este artigo é escrito, o AXIOM está disponível no release 1.1 o que significa que as interfaces descritas aqui devem estar estáveis. Por outro lado, o desempenho está sujeito a mudanças ao longo do tempo à medida que o código de implementação em si é modificado. Não esperamos ver grandes mudanças no desempenho do AXIOM em relação a outros modelos de documento, mas é possível que alguns detalhes mudem.
Para comparar o AXIOM com outros modelos de documento, atualizamos os códigos de um
estudo anterior sobre modelos de documento (veja a seção de Recursos), acrescentando
o AXIOM e mais um novo modelo de documento (XOM), convertendo o código para usar o
padrão de analisador StAX em vez do padrão antigo SAX e mudando para o método de
cronometragem melhorado System.nanoTime() introduzido no
Java 5. O código de teste de desempenho primeiro lê para a memória os documentos a
serem usados no teste, daí executa uma sequência de operações nos documentos.
Primeiro, várias cópias de representações do documento são construídas a partir dos
analisadores, e cada objeto de documento resultante é retido. A seguir, cada objeto
de documento precisa "caminhar", o que significa que o código varre a inteira
representação do documento (incluindo todos os atributos, valores e conteúdo de
texto). Por fim, cada objeto de documento é gravado em um fluxo de saída. O tempo é
gravado para cada operação individual e sua média é tirada no fim da execução de
teste.
Visto que o principal foco do AXIOM (em especial seu uso no Axis2) é no manuseio de mensagens SOAP, usamos três casos de teste de mensagem SOAP diferentes para verificar o desempenho. O primeiro é uma resposta de amostra de um teste de desempenho de serviço Web que dá informações sobre terremotos dentro de um intervalo específico de tempo e latitude/longitude ("quakes", 18 KB). Este documento contém elementos muito repetidos com certo aninhamento e muito uso de atributos. O segundo é uma amostra maior do teste de interoperabilidade Microsoft WCF, que consiste em uma única estrutura repetida com pequenas variações de valores ("persons", 202 KB). Esse documento tem elementos-filhos com conteúdo de texto, mas sem o uso de atributos. O terceiro caso de teste é uma coleção de 30 pequenos documentos de mensagem SOAP tirados de alguns testes antigos de interoperabilidade (tamanho total: 19 KB). Todos os espaços em branco de formatação foram removidos dos documentos de teste para tornar os documentos representativos do XML trocado por serviços reais de produção (que em geral desligam a formatação para manter pequeno o tamanho das mensagens).
As tabelas abaixo mostram o tempo médio necessário para 50 passagens em cada documento. O ambiente de teste foi um sistema de notebook Compaq com processador AMD Turion 1600 MHz ML-30 e 1.5 GB de RAM, executando o 1.5.0_07-b03 JVM da Sun no Mandriva 2006 Linux. Testamos o AXIOM 1.0, dom4j 1.6.1, JDOM 1.0, Xerces2 2.7.0 e XOM da distribuição Nux 1.6. Os construtores customizados de analisadores StAX foram usados no dom4j, JDOM e Xerces2, e o construtor de analisador Nux StAX foi usado no XOM. Todos os testes usaram o analisador Woodstox StAX 2.9.3.
A Figura 1 mostra a soma dos tempos médios necessários para as primeiras duas etapas da sequência de teste, construindo um documento a partir do analisador, e fazendo a representação de documento caminhar para verificar o conteúdo. Se você observar a primeira etapa do isolamento (tempo não mostrado aqui), o AXIOM funciona muito melhor que os outros modelos de documento, pelo menos para os primeiros dois documentos. Contudo, isso apenas mostra que o AXIOM está trabalhando como esperado e não está realmente construindo o documento completo até que seja necessário. Queríamos usar o tempo usado para realmente construir a representação completa na memória para ter uma comparação justa, e é por isso que os dois tempos nessa tabela foram somados.
Figura 1. Tempos para construir e expandir documentos (em milissegundos)
Como visto na Figura 1, o AXIOM é mais lento no geral do que qualquer outro modelo de documento testado, exceto o Xerces2.
Vários dos modelos de documento mostraram problemas de desempenho no que se refere à coleta de pequenos documentos ("soaps"). O Xerces2 se saiu especialmente mal nesse caso, mas o AXIOM também mostrou bastante overhead que é, provavelmente, a questão mais problemática revelada por essa tabela. Mensagens pequenas são comuns em muitos serviços Web e o AXIOM deve poder processá-las de forma eficiente. Visto que o AXIOM foi realmente projetado em relação à expansão da árvore on-demand, o tempo dos dois documentos maiores não é uma grande preocupação visto que estão pelo menos próximos dos outros modelos de documento.
Figura 2. Tempo para gravar os documentos (em milissegundos)
A Figura 2 mostra os tempos médios de gravação de documentos para um fluxo de saída usando cada modelo. Aqui, o Xerces2 tem o melhor tempo por uma diferença substancial (mas não o bastante para compensar seu desempenho ruim na etapa de construção; as escalas das duas tabelas são diferentes), enquanto o AXIOM é o pior. Novamente, o AXIOM parece se sair especialmente ruim com documentos pequenos.
Figura 3. Tamanho de memória dos documentos (em KB)
Por fim, a Figura 3 mostra a memória usada por cada estrutura para representar os documentos. Novamente, o dom4j é o melhor e o AXIOM o pior por uma diferença considerável. Parte do desempenho ruim do AXIOM no uso da memória se deve ao analisador ser referenciado pelo documento construído de modo que a instância do analisador é mantida enquanto a instância do documento está em uso. Novamente, essa é provavelmente parte da razão por que o AXIOM se sai especialmente mal com documentos pequenos. Contudo, os objetos usados pelo AXIOM como componentes do documento também são consideravelmente maiores do que seus equivalentes em outros modelos de documento, e essa diferença é provavelmente a razão de o AXIOM usar muito mais espaço mesmo para os dois maiores documentos de teste (nos quais o overhead de tamanho fixo do analisador e outras estruturas de dados têm proporção menor de uso total da memória).
Se você somar os tempos das primeiras duas tabelas, o líder geral no desempenho é o dom4j, enquanto o "lanterninha" do desempenho foi o Xerces2 (com o AXIOM só um pouquinho à frente do último). No que se refere ao uso da memória, o dom4j é também o melhor, mas nessa disputa o AXIOM é o perdedor absoluto. Parece ruim para o AXIOM?
Seria ruim se a representação completa da árvore sempre fosse criada, mas lembre que o objetivo do AXIOM é que normalmente não é necessária a representação completa. A Figura 4 mostra o tempo apenas da construção inicial do documento no AXIOM, em comparação com o tempo correspondente para outros modelos de documento construírem a representação do documento. Aqui, o AXIOM é muito mais rápido que os outros (rápido demais até para registrar, no caso dos dois documentos maiores). O mesmo tipo de comparação se aplica ao lado da memória. O resultado líquido é que se você precisar trabalhar apenas com parte do modelo de documento (a "primeira" parte, em termos de ordem de documento), o AXIOM terá um ótimo desempenho.
Figura 4. Construção inicial do documento
Este artigo foi escrito como análise detalhada do modelo de objeto de documento do AXIOM no núcleo do Axis2. O AXIOM inclui algumas inovações interessantes, em especial em termos de sua abordagem integrada on demand para construir a representação completa. Não está completamente de acordo com outros modelos de documento Java quando se precisa de representação totalmente expandida. Seu desempenho com pequenos documentos é especialmente perturbador, mas a flexibilidade que ele fornece para processamento de serviços Web compensa muitas dessas preocupações.
Agora você sabe como o Axis2 gerencia representações de mensagens SOAP usando AXIOM, incluindo como ele passa XML para e de estruturas de ligação de dados. O próximo artigo analisa com o Axis2 dá suporte a diferentes trabalhos com estruturas de ligação de dados da perspectiva do usuário, incluindo amostras de código usando três das estruturas.
| Descrição | Nome | Tamanho | Método de download |
|---|---|---|---|
| Source code | j-java2.zip | 98KB | HTTP |
Informações sobre métodos de download
Aprender
- Para uma comparação mais antiga e mais detalhada dos
modelos de objeto de documento Java, veja "Modelos de
documento, Parte 1: Desempenho" e "Uso de modelo de
documento Java", de Dennis Sosnoski.
- Procure em livrarias
de tecnologia livros sobre esses e outros tópicos técnicos.
-
Zona de tecnologia Java da
developerWorks: Ali há centenas de artigos sobre todo aspecto da programação
Java.
- Veja na biblioteca de padrões de serviços Web da developerWorks informações sobre uma grande
variedade de tecnologias WS-*.
- Você pode ter uma ótima visão geral do Axis2 por
meio de serviços Web e arquitetura Axis2 de Eran Chinthaka.
Obter produtos e tecnologias
- Desenvolva seu próximo
projeto de desenvolvimento com o software de teste IBM, disponível para download diretamente na
developerWorks.
- Obtenha mais informações e
teste você mesmo o AXIOM fazendo o download dele no Apache AXIOM Project.
- O modelo de objeto de
documento dom4j é rápido, eficiente no uso da
memória e também oferece grande extensibilidade.
- O modelo de objeto de
documento JDOM é conhecido por sua facilidade de
uso.
- O modelo de objeto de
documento XOM protege os usuários contra erros
comuns no uso do XML, enquanto oferece bom desempenho e eficiência no uso da
memória.
- O Nux é um projeto de software livre voltado
para middleware de mensagens XML de alto rendimento que visa integrar os melhores
componentes para o processamento XML em um único kit de ferramentas.
- O Xerces2 é a implementação Apache
do modelo de objeto de documento padrão W3C.
- Obtenha as mais recentes
informações e downloads do Apache
Axis2.
- O WoodStox é uma implementação de
software livre do analisador pull StAX padrão.

Dennis Sosnoski é um consultor e instrutor especializado em XML e serviços da Web baseados em Java. Sua experiência em desenvolvimento de software profissional se estende por mais de 30 anos, sendo que nos últimos 10 focou tecnologias XML e Java do lado do servidor. Dennis é o desenvolvedor líder da estrutura de software livre JiBX XML Data Binding e a estrutura de serviços da Web associada JiBX/WS, assim como um committer na estrutura de serviços da Web Apache Axis2. Também foi um dos membros do Grupo de Especialistas para as especificações JAX-WS 2.0 e JAXB 2.0. O material para a série Serviços da Web Java é baseado nas aulas de treinamento de Dennis.