Java Web Services: Axis2 Data Binding

O Axis2 suporta diversas estruturas de ligação de dados para facilitar o acesso aos dados XML

A estrutura de serviços de Web do Apache Axis2 foi projetada desde o início para suportar diversas abordagens de ligação de dados XML. A liberação atual oferece suporte completo para a ligação de dados do XMLBeans e JiBX, assim como para a abordagem customizada do Axis Data Binding (ADB) desenvolvida especificamente para o Axis2. Este artigo mostra como utilizar estas diferentes ligações de dados com o Axis2 e explica por que talvez você prefira uma em relação às outras para seu aplicativo.

Dennis Sosnoski, Consultant, Sosnoski Software Solutions, Inc.

Photo of Dennis SosnoskiDennis Sosnoski é um consultor e facilitador de treinamento especializado em serviços SOA e da Web baseados em Java. Sua experiência em desenvolvimento de software profissional se estende por mais de 30 anos, sendo que a última década focou tecnologias XML e Java do lado do servidor. Dennis é o desenvolvedor líder da ferramenta de ligação de dados XML JiBX de software livre, assim como um dos compromissados com a estrutura de serviços da Web Apache Axis2. Ele também foi um dos membros do grupos de especialistas para as especificações JAX-WS 2.0 e JAXB 2.0. Consulte seu Web site para obter informações sobre seus serviços de treinamento e consultoria.



26/Jul/2007

Embora a troca de mensagens XML esteja no núcleo dos Serviços da Web, a maioria dos aplicativos de serviço da Web não está interessada no XML. Ao invés disso, estes aplicativos desejam trocar dados de negócios que são específicos para o aplicativo. Neste caso, o XML é apenas um formato utilizado para representar os dados de negócios para suportar uma interface de serviço da Web. O XML funciona bem para este propósito, pois ele fornece uma representação independente de plataforma que pode ser manipulada por diversas ferramentas. Mas no final, os aplicativos precisam converter o XML para ou a partir de suas próprias estruturas de dados internos para utilizar os dados no aplicativo.

Ligação de Dados é o termo utilizado para técnicas que tratam desta conversão entre o XML e as estruturas de dados do aplicativo. é possível escrever um código de ligação de dados para um aplicativo, mas a maioria dos desenvolvedores acha mais conveniente trabalhar com as estruturas de ligação de dados que tratam das conversões de uma maneira geral, aplicáveis a uma grande variedade de aplicativos. Um dos principais pontos fortes da estrutura de serviços da Web do Apache Axis2 é que ela foi projetada, desde o início, para trabalhar com diversas estruturas de ligação de dados. é possível selecionar a abordagem da ligação de dados que melhor atende suas necessidades e utilizar tal abordagem para tratar das conversões entre o XML e as estruturas de dados enquanto utiliza a estrutura Axis2 (e as extensões) para tratar do trabalho atual dos serviços da Web.

Este artigo mostra como utilizar a flexibilidade da ligação de dados do Axis2 com o código de para o mesmo serviço da Web implementado utilizando três das ligações de dados suportadas. Descubra por que você deve preferir uma das ligações de dados em relação às outras.

Link para o Axis2

No artigo anterior desta série, você aprendeu sobre as utilizações do modelo de documento AXIOM do Axis2 para o tratamento de mensagens XML. O AXIOM se diferencia dos outros modelos de documento pelo fato de suportar a criação do modelo on demand ao invés de tudo junto. Quando uma estrutura de ligação de dados for utilizada para realizar a conversão para XML e das estruturas de dados de aplicativos, normalmente a ligação de dados XML é a única parte virtual do modelo de documento AXIOM. Ele não é expandido para um modelo de documento completo a menos que o modelo seja necessário por alguma razão (como criptografia ou marcação ao utilizar o WS-Security).

Para afastar os aplicativos da necessidade de trabalhar diretamente com o AXIOM, o Axis2 suporta a geração de códigos de vinculação a partir das descrições de serviço do Web Services Description Language (WSDL). O código de vinculação gerado trata dos detalhes da conversão das estruturas de dados para e a partir do XML utilizando sua estrutura de ligação de dados escolhida, fornecendo ao sei aplicativo o acesso direto às estruturas de dados. O Axis2 também oferece um suporte limitado para ir em outra direção, gerando WSDL a partir do código existente.

O Axis2 gera o código de vinculação tanto para os clientes do serviço quanto para os provedores do serviço. O código de vinculação do cliente está no formato de uma classe stub, que sempre estende a classe do org.apache.axis2.client.Stub Axis2. O código de vinculação do provedor (ou servidor) tem o formato de um esqueleto de implementação específico do serviço, juntamente com a classe do receptor de mensagens que implementa a org.apache.axis2.engine.MessageReceiver interface. A geração do código de vinculação do cliente e do servidor é tratada pela ferramenta WSDL2Java. A seguir você verá o código de vinculação atual, então conhecerá os detalhes da utilização da ferramenta WSDL2Java e finalizará esta seção com uma visualização rápida de maneiras de iniciar a partir do código existente.

Código de vinculação do cliente

O código stub do lado do cliente define os métodos de acesso para seu código de aplicativo invocar as operações de serviço. Primeiramente você deve criar uma instância da classe stub, normalmente utilizando tanto o construtor padrão (se seu terminal em serviço irá ser sempre o mesmo definido no WSDL utilizado para gerar o stub) ou um construtor que utilize uma referência de terminal diferente como uma cadeia de caractere. Após criar uma instância do stub, é possível, opcionalmente, utilizar métodos definidos pela classe org.apache.axis2.client.Stub de base para configurar diversos recursos. é possível, então, chamar os métodos de acesso específicos do serviço para realmente invocar as operações.

A Lista 1 mostra um exemplo de como criar um stub com o terminal em serviço alterado (independentemente do que era no WSDL) para a porta 8800 Tcpmon no sistema do cliente (host local). O Tcpmon é uma ferramenta popular para monitorar as trocas de mensagens de serviço na Web, então, tê-lo como uma opção em seu código do cliente geralmente é útil. Após a instância stub ser criada, o valor de tempo limite é alterado a partir do padrão (também é útil ao depurar o código do provedor, pois é possível facilmente exceder o tempo de espera padrão de 20 segundos), e um método de serviço é chamado.

Lista 1. Exemplo de utilização do stub do cliente
LibraryStub stub = new LibraryStub("http://localhost:8800/axis2/services/library");
stub.getServiceClient().getOptions().setTimeoutInMilliseconds(10000000);
Types[] types = stub.getTypes();

O código da Lista 1 mostra uma chamada de método de serviço simultâneo em que o encaminhamento do cliente é bloqueado na chamada do serviço e não retorna até que a chamada seja concluída e os resultados sejam disponibilizados. O Axis2 também suporta chamadas assíncronas, utilizando a interface de retorno de chamada. A Lista 2 mostra o código da Lista 1 modificado para utilizar uma camada assíncrona trivial (o trivial no código do aplicativo apenas espera que a operação seja concluída, ao invés de fazer algo útil).

Lista 2. Amostra assíncrona do stub do cliente
LibraryStub stub = new LibraryStub("http://localhost:8800/axis2/services/library");
TypesCallback cb = new TypesCallback();
stub.startgetTypes(cb);
Type[] types;
synchronized (cb) {
 while (!cb.m_done) {
  try {
   cb.wait();
  } catch (Exception e) {}
 }
 types = cb.m_result;
 if (types == null) {
  throw cb.m_exception;
 }
}
...
private static class TypesCallback extends LibraryCallbackHandler
{
 private boolean m_done;
 private Types[] m_result;
 private Exception m_exception;
            
 public synchronized void receiveResultgetTypes(Type[] resp) {
   m_result = resp;
   m_done = true;
   notify();
 }
            
 public synchronized void receiveErrorgetTypes(Exception e) {
   m_exception = e;
   m_done = true;
   notify();
 }
}

Com uma conexão HTTP, como a utilizada na Lista 2, normalmente a resposta é imediatamente retornada para o cliente. As chamadas assíncronas são mais úteis ao operar em transportes que separam a solicitação da resposta —como o Java™ Message Service (JMS) ou Simple Mail Transfer Protocol (SMTP)—, pois pode haver um atraso significativo nestes casos entre o momento que a solicitação é enviada e quando a resposta é recebida. Certamente, os serviços acessados utilizando o HTTP também envolvem atrasos significativos de processamento. Para os serviços de HTTP com tais atrasos, é possível utilizar o WS-Addressing para permitir respostas separadas, as chamadas assíncronas são úteis tratar destas respostas.

Além da classe stub (e da classe do manipulador de retorno de chamada, se você gerar com suporte assíncrono), há também uma interface gerada por seu código do cliente. A interface define os métodos de serviço adequados para as operações definidas pelo WSDLportType. O stub implementa esta interface e adiciona alguns métodos especializados utilizados internamente. é possível trabalhar tanto com o stub diretamente, conforme mostrado na Lista 1 e Lista 2, ou apenas utilizar a interface para ver apenas os métodos que fazem parte da definição do serviço. De qualquer maneira, quando chamar um dos métodos de serviços, o stub trata da conversão dos objetos de dados de solicitação para XML, e retorna o XML para os objetos de dados de resposta, utilizando sua estrutura de ligação de dados selecionada.

Caso deseje apenas trabalhar diretamente com o XML no cliente, não é necessário utilizar uma classe de cliente gerada de nenhuma maneira, ao invés disso, é possível utilizar a org.apache.axis2.client.ServiceClient classe. Fazer isso significa que é necessário primeiro configurar o serviço e a operação e, então, chamar o ServiceClient.createClient() método para criar um org.apache.axis2.client.OperationClient para a operação. Como uma comodidade, a ferramenta WSDL2Java (tratada posteriormente neste artigo) oferece uma opção para gerar uma classe stub mesmo quando estiver trabalhando diretamente com XML. O stub gerado para este caso se parece bastante com os exemplos de ligação de dados, exceto pelo fato de que ele transmite um elemento AXIOM ao invés de objetos de dados.

Código de vinculação do servidor

O código de vinculação do server side para o Axis2 é um receptor de mensagem que é definido como parte da configuração do serviço do Axis2. Este receptor de mensagem precisa implementar a org.apache.axis2.engine.MessageReceiver interface. A interface define um único void receive(org.apache.axis2.context.MessageContext) método. A estrutura do Axis2 chama este método quando uma mensagem de solicitação é recebida e, então, este método é responsável por tratar de todo o processamento da solicitação (incluindo a geração de uma resposta, caso seja adequado).

Caso esteja trabalhando diretamente com XML (no formato dos elementos AXIOM), é possível utilizar uma das classes org.apache.axis2.receivers.RawXML*MessageReceiver padrão para a vinculação do server side (em que * descreve o tipo de troca de mensagens utilizado por um servidor). Caso contrário, utilize uma classe de receptor de mensagens gerado que se adapte entre a interface baseada no AXIOM do Axis2 e o código de serviço que utiliza os objetos de dados. O código do serviço é gerado na forma de uma implementação de esqueleto, com métodos de serviço que apenas lançam uma exceção. é necessário adicionar seu próprio código ao esqueleto para concluir a transmissão simultânea do server side.

A Lista 3 mostra um exemplo de um esqueleto do server side (reformatado para a possibilidade de leitura), com o getBook() método deixado conforme gerado e o getTypes() método implementado ao ser delegado a uma classe de implementação real.

Lista 3. Amostra de esqueleto do servidor
public class LibrarySkeleton
{
    private final LibraryServer m_server;
    
    public LibrarySkeleton() {
        m_server = new LibraryServer();
    }
    
    /**
     * Auto generated method signature
     *
     * @param isbn
     * @return book value
     */
    public com.sosnoski.ws.library.Book getBook(java.lang.String isbn) {
        //Todo fill this with the necessary business logic
        throw new java.lang.UnsupportedOperationException("Please implement " +
            this.getClass().getName() + "#getBook");
    }

    /**
     * Get the types of books included in library.
     *
     * @return types
     */
    public com.sosnoski.ws.library.Type[] getTypes() {
        return m_server.getTypes();
    }
}

A desvantagem de adicionar o código diretamente a esta classe é que se a interface do serviço for alterada, será necessário gerar a classe novamente e mesclar suas alterações. é possível evitar isso ao utilizar uma classe de implementação à parte que se estende para o esqueleto gerado, permitindo que você substitua os métodos sem alterar o código gerado. Para que isso funcione, é necessário alterar a descrição do serviço services.xml gerado. é fácil, apenas substitua o nome de classe do esqueleto pelo seu nome de classe de implementação. Os exemplos de ligação de dados tratados posteriormente neste artigo utilizam uma abordagem de classe de implementação a parte. é possível consultar os arquivos Ant build.xml na seção de Download para estes exemplos para ver como automatizar a substituição.


Ferramentas do Axis2

O Axis2 oferece uma variedade de ferramentas para ajudar os desenvolvedores utilizando a estrutura. A mais importante delas são as ferramentas que permitem que você gere o código de vinculação Java (tratado na última seção) a partir de uma definição de serviço WSDL e gerar uma definição de serviço WSDL a partir do código Java existente.

Gerar o código a partir do WSDL

O Axis2 oferece uma ferramenta WSDL2Java utilizada para a geração de código a partir de uma descrição de serviço WSDL. é possível utilizar esta ferramenta diretamente ao executar a org.apache.axis2.wsdl.WSDL2Java classe como um aplicativo Java ou através de uma Ant Task, um plug-in do Maven, ou do Eclipse ou um dos plug-ins do IDEA. A desvantagem de ter tantas opções é que as alternativas normalmente deixam o aplicativo Java básico para trás em termos dos recursos e correção de erros, então, normalmente é melhor apenas executar o aplicativo Java diretamente (de que este artigo trata).

O WSDL2Java oferece muitas opções de linha de comando diferentes, com o número de opções aumentando ao longo do tempo. A documentação do Axis2 inclui uma referência completa das opções, assim você verá apenas algumas das mais importantes aqui:

  • -o path Configura o diretório de destino para os arquivos e classes de saída (padrões para o diretório de trabalho)
  • -p package-name Define o pacote de destino para as classes geradas (o padrão é gerado a partir do espaço de nomes do WSDL)
  • -d name Define a estrutura de ligação de dados (adb para ADB, xmlbeans para XMLBeans, jibx para JiBX e none para nenhuma ligação de dados; adb é o padrão)
  • -uw Abre as mensagens doc/lit-wrapped, apenas para as estruturas suportadas (atualmente ADB e JiBX)
  • -s Gera uma interface síncrona do cliente apenas
  • -ss Gera o código do server side
  • -sd Gera os arquivos de implementação do server side
  • -uri path Define o caminho para o WSDL para o serviço a ser gerado

Há, também, algumas opções do WSDL2Java que são específicas para uma estrutura de ligação de dados específica. é possível ver algumas dessas opções quando chegar aos exemplos de ligação de dados posteriormente neste arquivo.

Gerar código a partir do WSDL

O Axis2 também fornece uma ferramenta Java2WSDL que pode ser utilizada para gerar uma definição de serviço WSDL a partir do código de serviço existente. Entretanto, esta ferramenta possui diversas limitações, incluindo a impossibilidade de trabalhar com classes de coleções Java e a inflexibilidade ao estruturar o XML gerado a partir das classes Java. As limitações ocorrem parcialmente em virtude de uma falta de interesse nesta área devido às alterações na maneira em que os serviços da Web são desenvolvidos.

Em geral, muitas autoridades nos campos de serviços da Web e arquivos SOA desaprovam o desenvolvimento de serviços da Web a partir de um código existente. Eles acreditam que iniciar a partir do código incentiva o acoplamento das estruturas de mensagens XML em uma implementação específica, quando todo o princípio dos serviços da Web é o de que o XML deve ser independentemente implementado. Certamente há algum fundamento nesta preocupação, mas também existem alguns argumentos contrários. Um deles é a dificuldade envolvida com a escrita das definições de serviço WSDL e do esquema XML desde o início. Tanto o WSDL quanto o esquema são padrões complexos e as ferramentas disponíveis para trabalhar com estas definições requerem uma boa compreensão dos padrões a serem utilizados de maneira efetiva. Caso seja utilizado por desenvolvedores sem um conhecimento dos fundamentos, os esquemas e WSDLs resultantes normalmente são mais confusos do que os gerados a partir do código. O outro problema é absolutamente prático. Os desenvolvedores frequentemente possuem um código existente para implementar uma funcionalidade que precisa ser exposta como um serviço da Web e eles desejam poder utilizar o código existente sem alterações significativas. Então, a geração do WSDL a partir do código provavelmente continuará a ser um problema no futuro imediato.

Para uma alternativa ao Java2WSDL mais poderosa você pode testar a ferramenta Jibx2Wsdl que eu desenvolvi (consulte a seção Recursos para obter mais informações). O Jibx2Wsdl gera um conjunto completo das definições do WSDL, esquema, e JiBX-binding de um ou mais classes de serviço fornecidas. Ele suporta as coleções genéricas e as enumerações do Java 5, enquanto possui a compatibilidade com as Java virtual machines (JVMs) anteriores e automaticamente exporta os Javadocs dos arquivos de origem do Java como documentação para as definições de esquema e WSDL geradas. O Jibx2Wsdl também oferece um amplo mecanismo de customização para controlar como as representações de XML e de serviços derivam das classes Java, que permite que mesmo as coleções anteriores ao Java 5 sejam utilizadas com os dados classificados. Embora o Jibx2Wsdl seja especificamente voltado para facilitar a implementação das classes existentes como os serviços da Web utilizando a estrutura de ligação de dados JiBX (também criada por mim), os esquemas e WSDLs gerados são ligações de dados agnósticas. é possível utilizá-los com outras estruturas de ligação de dados do Java, ou ainda em outras plataformas — apenas gere tudo e, então, ignore as ligações do JiBX e mantenha o restante.

Outra alternativa, caso esteja utilizando o Java 5 ou posterior, é utilizar as anotações da Architecture for XML Binding (JAXB) 2.0 e do Java API para Serviços da Web (JAX-WS) para expor seus objetos de dados e classes de serviço nos serviços da Web. Estas anotações não oferecem o mesmo nível de customização do Jibx2Wsdl, mas elas permitem que você incorpore suas informações de configuração diretamente no código fonte, o que alguns desenvolvedores acham atraente. O Axis2 oferece suporte experimental para o JAXB 2.0 para o JAX-WS a partir do release 1.2 e isso irá melhorar as futuras liberações. As futuras versões do Jibx2Wsdl também podem suportar a utilização das anotações do JAXB 2.0 e JAX-WS como customizações. (Um futuro artigo nesta série irá tratar do JAXB 2.0 e JAX-WS mais detalhadamente e retornará para este tópico de geração de WSDL a partir do código em tal momento).


Comparação das ligações de dados

O Axis2 (a partir do release 1.2) suporta completamente três alternativas de ligações de dados, e ainda serão mais. Este artigo compara o código de amostra utilizando as três estruturas de ligação de dados completamente suportados e trata de alguns pontos fortes e fracos de cada estrutura quando utilizadas com o Axis2.

O código de amostra exibido na Lista 4 (que também está incluído no download de amostra na seção de Download) foi criado para um serviço de biblioteca, que mantém uma coleção de livros organizados por tipo de assunto. Diversas operações são definidas na biblioteca, incluindo:

  • getBook
  • getTypes
  • addBook
  • getBooksByType

A Lista 4 oferece uma visualização parcial do WSDL para este serviço, exibindo apenas as partes envolvidas na getBook operação.

Lista 4. WSDL de serviços de biblioteca
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions targetNamespace="http://ws.sosnoski.com/library/wsdl"
    xmlns:wns="http://ws.sosnoski.com/library/wsdl"
    xmlns:tns="http://ws.sosnoski.com/library/types"
    xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
    xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/">
  <wsdl:types>
  
    <schema elementFormDefault="qualified"
        targetNamespace="http://ws.sosnoski.com/library/wsdl"
        xmlns="http://www.w3.org/2001/XMLSchema">
      
      <import namespace="http://ws.sosnoski.com/library/types"/>
        
      <element name="getBook">
        <complexType>
          <sequence>
            <element name="isbn" type="string"/>
          </sequence>
        </complexType>
      </element>
      
      <element name="getBookResponse">
        <complexType>
          <sequence>
            <element name="getBookReturn" minOccurs="0" type="tns:BookInformation"/>
          </sequence>
        </complexType>
      </element>
      ...
      
    </schema>
    
    <schema elementFormDefault="qualified"
        targetNamespace="http://ws.sosnoski.com/library/types"
        xmlns="http://www.w3.org/2001/XMLSchema">
      
      <complexType name="BookInformation">
        <sequence>
          <element name="author" minOccurs="0" maxOccurs="unbounded" type="string"/>
          <element name="title" type="string"/>
        </sequence>
        <attribute name="type" use="required" type="string"/>
        <attribute name="isbn" use="required" type="string"/>
      </complexType>
      ...
      
    </schema>

  </wsdl:types>

  <wsdl:message name="getBookRequest">
    <wsdl:part element="wns:getBook" name="parameters"/>
  </wsdl:message>

  <wsdl:message name="getBookResponse">
    <wsdl:part element="wns:getBookResponse" name="parameters"/>
  </wsdl:message>
  ...
  
  <wsdl:portType name="Library">

    <wsdl:operation name="getBook">
      <wsdl:input message="wns:getBookRequest" name="getBookRequest"/>
      <wsdl:output message="wns:getBookResponse" name="getBookResponse"/>
    </wsdl:operation>
    ...

  </wsdl:portType>

  <wsdl:binding name="LibrarySoapBinding" type="wns:Library">

    <wsdlsoap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>

    <wsdl:operation name="getBook">
    
      <wsdlsoap:operation soapAction="urn:getBook"/>
      
      <wsdl:input name="getBookRequest">
        <wsdlsoap:body use="literal"/>
      </wsdl:input>
      
      <wsdl:output name="getBookResponse">
        <wsdlsoap:body use="literal"/>
      </wsdl:output>
      
    </wsdl:operation>
    ...

  </wsdl:binding>
  ...

</wsdl:definitions>

O código de implementação do serviço atual é simples, preenchendo uma instância da biblioteca com a lista de livros codificados permanentemente. O código do cliente executa uma sequência das consultas na seguinte ordem:

  1. A getBook
  2. A getTypes
  3. Um par de addBook, com o segundo retornando uma Falha SOAP por tentar adicionar um ID duplicado de um livro
  4. A getBooksByType

Os detalhes da implementação diferem entre os exemplos, pois cada um utiliza os objetos de dados adequados para tal ligação de dados. A menos que seja indicado contrário, todos os códigos exibidos são consistentes com o Axis2 1.1.1 e 1.2. O Axis2 liberação 1.3, em andamento enquanto este artigo vai para a publicação, requer algumas pequenas alterações ao código devido a uma alteração na nomenclatura das classes de exceção geradas correspondentes às falhas do serviço. Ambas as versões do código são fornecidas para download (consulte a seção Download).

Neste artigo, você verá apenas o código do cliente, embora o download oferecido (consulte a seção Download) inclua os códigos do cliente e servidor juntamente com os arquivos de compilação Ant para todos os exemplos. A seguir, revise o código do cliente para todas as três estruturas de ligação de dados e saiba mais sobre os pontos fortes e fracos de cada abordagem.

Axis2 Data Binding

ADB é uma extensão de ligação de dados para o Axis2. Diferente de outras estruturas de ligação de dados, o código ADB é utilizável apenas para serviços da Web do Axis2. Esta restrição é uma limitação significativa do ADB, mas também concede algumas vantagens. Devido ao fato de o ADB ser integrado com o Axis2, o código pode ser otimizado para os requisitos do Axis2. Um exemplo disso é que o ADB cria com base no modelo de documento Axis Object Model (AXIOM) no núcleo do Axis2 (conforme discutido no artigo anterior desta série). O ADB também oferece alguns recursos aprimorados que atualmente não estão disponíveis com outras estruturas de ligação de dados, incluindo a manipulação automática de anexos. O WSDL2Java oferece o suporte completo para a geração de código ADB, incluindo as classes de modelos de dados correspondentes aos componentes do esquema XML.

O suporte do esquema ADB possui algumas limitações. Na liberação atual do Axis2, a 1.2, estas limitações incluem recursos de esquema, como compositores com maxOccurs="unbounded", definições de esquema com attributeFormDefault="qualified" e algumas variações semelhantes. Mas o suporte do esquema ADB do Axis2 1.2 é muito melhor do que o do Axis2 liberação 1.1, e é provável que o suporte continue sendo melhorado com cada liberação da estrutura do Axis2 até que todos os recursos dos principais esquemas sejam suportados.

A forma básica de geração de código ADB utiliza um modelo direto em que as classes separadas correspondem às mensagens de entrada e saída utilizadas para cada operação. A Lista 5 mostra as partes mais interessantes do código do cliente para o exemplo do aplicativo utilizando esta forma básica da geração de código ADB. O código do cliente demonstra as interações com as classes geradas do ADB, como as classes GetBookDocument e GetBookDocument.GetBook utilizadas para o parâmetro da chamada do método getBook(), e as classes GetBookResponseDocument e BookInformation são usadas para retornar desta chamada.

Lista 5. Código do cliente ADB
// create the client stub
AdbLibraryStub stub = new AdbLibraryStub(target);
        
// retrieve a book directly
String isbn = "0061020052";
GetBook gb = new GetBook();
gb.setIsbn(isbn);
GetBookResponse gbr = stub.getBook(gb);
BookInformation book = gbr.getGetBookReturn();
if (book == null) {
  System.out.println("No book found with ISBN '" + isbn + '\'');
} else {
  System.out.println("Retrieved '" + book.getTitle() + '\'');
}
        
// retrieve the list of types defined
GetTypesResponse gtr = stub.getTypes(new GetTypes());
TypeInformation[] types = gtr.getGetTypesReturn();
System.out.println("Retrieved " + types.length + " types:");
for (int i = 0; i < types.length; i++) {
  System.out.println(" '" + types[i].getName() + "' with " +
    types[i].getCount() + " books");
}
        
// add a new book
String title = "The Dragon Never Sleeps";
isbn = "0445203498";
try {
  AddBook ab = new AddBook();
  ab.setType("scifi");
  ab.setAuthor(new String[] { "Cook, Glen" });
  ab.setIsbn(isbn);
  ab.setTitle(title);
  stub.addBook(ab);
  System.out.println("Added '" + title + '\'');
  ab.setTitle("This Should Not Work");
  stub.addBook(ab);
  System.out.println("Added duplicate book - should not happen!");
} catch (AddDuplicateFaultException e) {
  System.out.println("Failed adding '" + title +
    "' with ISBN '" + isbn + "' - matches existing title '" +
    e.getFaultMessage().getBook().getTitle() + '\'');
}
        
// create a callback instance
CallbackHandler cb = new CallbackHandler();
        
// retrieve all books of a type asynchronously
GetBooksByType gbbt = new GetBooksByType();
gbbt.setType("scifi");
stub.startgetBooksByType(gbbt, cb);
long start = System.currentTimeMillis();
synchronized (cb) {
  while (!cb.m_done) {
    try {
      cb.wait(100);
    } catch (Exception e) {}
  }
}
System.out.println("Asynchronous operation took " +
  (System.currentTimeMillis()-start) + " millis");
if (cb.m_response != null) {
  BookInformation[] books = cb.m_response.getGetBooksByTypeReturn();
  ...

A Lista 5 utiliza o código gerado com a opção -u WSDL2Java, que é específica para o ADB. Com esta opção, é gerado um arquivo de origem Java a parte para cada mensagem e classe de modelo de dados, caso você não utilize esta opção, a geração do código ADB cria todas essas classes como classes internas estáticas do stub gerado. é consideravelmente fácil trabalhar com as classes separadas, então a opção -u deve ser utilizada caso você utilize o ADB.

A forma direta da geração do código lega a um grande número de classes independentes para a entrada e saída de cada operação (independente da opção -u, que apenas organiza as mesmas classes de maneira diferente). Estas classes de mensagens geradas geralmente contêm poucos (ou mesmo nenhum, no caso da classe GetTypes) dados úteis, mas são necessários para as assinaturas de método geradas. Felizmente há uma forma alternativa para a geração do código que se aplica a diversos serviços comuns.

ADB não empacotado

Frequentemente os serviços da Web são desenvolvidos com base em um API de programação existente na forma de chamadas de métodos e neste caso é conveniente incorporar o API existente no serviço da Web. Isso é fácil de fazer, as operações definidas para um serviço (tecnicamente para um portType, caso alguém deseje procurar por detalhes) forem essencialmente equivalentes às chamadas de métodos em uma definição de interface, afinal. A única grande diferença é que o serviço define as entradas e saídas como mensagens XML ao invés de parâmetros de chamadas e valores de retorno. Assim, para incorporar um API existente em uma definição de serviço da Web, é necessário apenas ter uma convenção de como representar os parâmetros de chamada e os valores de retorno como estruturas da mensagem XML.

Felizmente, a Microsoft® estabeleceu uma convenção nesta área anteriormente, nos poupando o trabalho de fazermos algo por conta própria. Esta convenção é chamada de wrapped document/literal e é a representação padrão que o .NET utiliza ao expor o método de chamada como uma operação de serviço da Web. Por essência, esta abordagem wrapped significa que cada mensagem de entrada é um elemento XML que consiste apenas em uma sequência de elementos filho e que cada mensagem de saída é um elemento XML com um único elemento filho. Há outros detalhes técnicos da implementação da Microsoft que não são realmente importantes, exceto para a interoperabilidade completa do .NET, mas, exceto por estes detalhes, as mensagens usadas para o exemplo da biblioteca (consulte a Lista 4 para uma visualização parcial) seguem esta abordagem.

O WSDL2Java suporta o unwrapping de tais serviços wrapped doc/lit na geração do código ADB. Quando o unwrapping for utilizado com uma definição de serviço WSDL adequada, o stub gerado do cliente (e também o esqueleto do servidor) é mais simples e direta. A Lista 6 mostra o código do aplicativo do cliente equivalente à Lista 5, mas com o parâmetro -uw transmitido para o WSDL2Java gerar uma interface unwrapped. As classes de mensagem que adicionaram uma camada de complexidade nas Listas 5, foram, na maioria, eliminadas na Lista 6 (com exceção da classe GetTypes) e os métodos de serviço aceitam parâmetros e retornam os resultados diretamente ao invés estarem incorporadas às classes de mensagem. Nos bastidores, o ADB ainda gera classes de mensagem e as utiliza no código gerado, mas seu código normalmente pode ignorar estas classes e trabalhar diretamente com os dados.

Lista 6. Código do cliente unwrapped no ADB
// create the client stub
AdbUnwrapLibraryStub stub = new AdbUnwrapLibraryStub(target);
        
// retrieve a book directly
String isbn = "0061020052";
BookInformation book = stub.getBook(isbn);
if (book == null) {
  System.out.println("No book found with ISBN '" + isbn + '\'');
} else {
  System.out.println("Retrieved '" + book.getTitle() + '\'');
}
        
// retrieve the list of types defined
TypeInformation[] types = stub.getTypes(new GetTypes());
System.out.println("Retrieved " + types.length + " types:");
for (int i = 0; i < types.length; i++) {
  System.out.println(" '" + types[i].getName() + "' with " +
    types[i].getCount() + " books");
}
        
// add a new book
String title = "The Dragon Never Sleeps";
isbn = "0445203498";
try {
  stub.addBook("scifi", isbn, new String[] { "Cook, Glen" }, title);
  System.out.println("Added '" + title + '\'');
  title = "This Should Not Work";
  stub.addBook("xml", isbn, new String[] { "Nobody, Ima" }, title);
  System.out.println("Added duplicate book - should not happen!");
} catch (AddDuplicateFaultException e) {
  System.out.println("Failed adding '" + title +
    "' with ISBN '" + isbn + "' - matches existing title '" +
    e.getFaultMessage().getBook().getTitle() + '\'');
}
        
// create a callback instance
BooksByTypeCallback cb = new BooksByTypeCallback();
        
// retrieve all books of a type asynchronously
stub.startgetBooksByType("scifi", cb);
long start = System.currentTimeMillis();
synchronized (cb) {
  while (!cb.m_done) {
    try {
      cb.wait(100L);
    } catch (Exception e) {}
  }
}
System.out.println("Asynchronous operation took " +
  (System.currentTimeMillis()-start) + " millis");
if (cb.m_books != null) {
  BookInformation[] books = cb.m_books;
  ...

Atualização para o Axis2 1.3
Conforme este artigo vai para a publicação, o Axis2 liberação 1.3 está quase pronto para produção. As questões de unwrapping ADB discutidas nesta seção foram corrigidas, então, caso esteja capacitado pra começar a trabalhar com o código do Axis2 1.3 você terá uma experiência muito melhor utilizando o ADB do que nas versões anteriores do Axis2. Uma versão específica do 1.3 do código de amostra para este artigo está inclusa na seção de Download.

O principal problema com o suporte ao ADB não empacotado é que ele ainda não é completamente estável. O código da Lista 6 é adequado para utilização com o Axis2 1.2 e inclui algumas grandes melhorias em relação ao código que pode ter sido utilizado pelo ADB não empacotado no Axis2 1.1.1. Mas a ferramenta WSDL2Java requer que o documento WSDL utilizado com outros exemplos seja reestruturado para utilização neste exemplo, ao mover um esquema alinhado para as classes de dados em um documento de esquema a parte. De maneira mais significativa, o código exibido na Lista 6 o código completo, a última parte do código, que utiliza uma operação assíncrona, falha no tempo de execução com uma exceção de cast de classe devido a um erro no código stub do cliente ADB gerado.

Até o sucessor do Axis2 1.2 ser lançado, as questões do ADB não empacotado devem ser amplamente eliminadas. Mas o ADB não é a única estrutura de ligação de dados para o Axis2 que suporte o unwrapping. O JiBX também oferece suporte ao unwrapping e a versão do JiBX está estável desde o Axis2 liberação 1.1. é possível ver o código do cliente JiBX posteriormente neste artigo, após verificar a outra principal escolha para a ligação de dados do Axis2.

XMLBeans

O XMLBeans é uma estrutura de processamento de XML geral que inclui uma camada de ligação de dados. Ele foi originado com um projeto da BEA Systems, que então foi doado para a Apache Foundation. O XMLBeans foi a primeira forma de ligação de dados suportada pelo Axis2, e continua a ser uma escolha popular para trabalhar com o Axis2, especialmente para utilização com definições de sistema complexas.

A Lista 7 mostra as partes mais interessantes do código do cliente do XMLBeans para o aplicativo de exemplo. Da mesma maneira que com um código ADB (non-unwrapped), há uma classe a parte para a entrada e para saída de cada operação. Mas o XMLBeans se difere do ADB pelo fato de ter uma classe adicionada para o documento que contém a classe de entrada ou saída (um GetBookDocument além da classe GetBook, por exemplo). O efeito de rede é uma camada adicionada â criação do objeto ao utilizar o XMLBeans, em oposição ao ADB. Não há suporte para o unwrapping para o XMLBeans no Axis2, então não há como evitar camada adicional de objetos. O resultado é que as classes geradas pelo XMLBeans são, de alguma maneira, mais complexos de se utilizar do que os equivalentes para outras estruturas de ligação de dados.

Lista 7. Código do cliente no XMLBeans
// create the client stub
XmlbeansLibraryStub stub = new XmlbeansLibraryStub(target);
        
// retrieve a book directly
String isbn = "0061020052";
GetBookDocument gbd = GetBookDocument.Factory.newInstance();
GetBookDocument.GetBook gb = gbd.addNewGetBook();
gb.setIsbn(isbn);
gbd.setGetBook(gb);
GetBookResponseDocument gbrd = stub.getBook(gbd);
BookInformation book = gbrd.getGetBookResponse().getGetBookReturn();
if (book == null) {
  System.out.println("No book found with ISBN '" + isbn + '\'');
} else {
  System.out.println("Retrieved '" + book.getTitle() + '\'');
}
        
// retrieve the list of types defined
GetTypesDocument gtd = GetTypesDocument.Factory.newInstance();
gtd.addNewGetTypes();
GetTypesResponseDocument gtrd = stub.getTypes(gtd);
TypeInformation[] types =
  gtrd.getGetTypesResponse().getGetTypesReturnArray();
System.out.println("Retrieved " + types.length + " types:");
for (int i = 0; i < types.length; i++) {
  System.out.println(" '" + types[i].getName() + "' with " +
    types[i].getCount() + " books");
}
        
// add a new book
String title = "The Dragon Never Sleeps";
isbn = "0445203498";
try {
  AddBookDocument abd = AddBookDocument.Factory.newInstance();
  AddBookDocument.AddBook ab = abd.addNewAddBook();
  ab.setAuthorArray(new String[] { "Cook, Glen" });
  ab.setIsbn(isbn);
  ab.setTitle(title);
  ab.setType("scifi");
  stub.addBook(abd);
  System.out.println("Added '" + title + '\'');
  title = "This Should Not Work";
  ab.setTitle(title);
  stub.addBook(abd);
  System.out.println("Added duplicate book - should not happen!");
} catch (AddDuplicateFaultException e) {
  System.out.println("Failed adding '" + title +
    "' with ISBN '" + isbn + "' - matches existing title '" +
    e.getFaultMessage().getAddDuplicate().getBook().getTitle() +
    '\'');
}
        
// create a callback instance
BooksByTypeCallback cb = new BooksByTypeCallback();
        
// retrieve all books of a type asynchronously
GetBooksByTypeDocument gbtd =
  GetBooksByTypeDocument.Factory.newInstance();
gbtd.addNewGetBooksByType().setType("scifi");
stub.startgetBooksByType(gbtd, cb);
long start = System.currentTimeMillis();
synchronized (cb) {
  while (!cb.m_done) {
    try {
      cb.wait(100L);
    } catch (Exception e) {}
  }
}
System.out.println("Asynchronous operation took " +
  (System.currentTimeMillis()-start) + " millis");
if (cb.m_response != null) {
  BookInformation[] books =
    cb.m_response.getGetBooksByTypeResponse().getGetBooksByTypeReturnArray();
  ...

Atualização para o Axis2 1.3
Conforme este artigo vai para a publicação, o Axis2 liberação 1.3 está quase pronto para produção. O problema de manipulação de falha foi arrumado no Axis2 1.3. Uma versão específica do 1.3 do código de amostra para este artigo está inclusa na seção de Download.

O código do cliente e o código de servidor correspondente da Lista 7 são executados de maneira adequada no Axis2 1.1.1, mas devido a um problema na geração do código de manipulação de falha no XMLBeans na liberação 1.2, ele falha no momento da exceção esperada ao adicionar um ID duplicado de livro. Este problema deve ser corrigido na próxima liberação do Axis2.

Embora o XMLBeans afirme ter suporte total do Esquema XML, a precisão desta afirma que esta é uma questão de interpretação. é verdade que para quase toda construção de esquema o XMLBeans gera um conjunto de classes Java que podem ser utilizados para ler e gravar documentos correspondentes ao esquema. Mas diferente das outras estruturas de ligação de dados tratadas neste artigo, o XMLBeans, por padrão, faz pouco para reforçar o esquema. Por exemplo, se você comentar a linha que define o título do livro sendo adicionado no código da Lista 7, o XMLBeans felizmente lê e grava os documentos que não possuem o elemento <title> necessário e, então, são documentos inválidos. A Lista 8 mostra esta alteração do código juntamente com o XML que foi enviado para o servidor para adicionar a solicitação e o XML que retornou do servidor quando os livros foram recuperados. No caso da resposta de recuperação, o documento XML inclui o elemento <title>, mas utiliza um atributo xsi:nil="true", que não é permitido pelo esquema e é novamente inválido.

Lista 8. Cliente XMLBeans e documentos inválidos
      AddBookDocument abd = AddBookDocument.Factory.newInstance();
      AddBookDocument.AddBook ab = abd.addNewAddBook();
      ab.addAuthor("Cook, Glen");
      ab.setIsbn(isbn);
      ab.setType("scifi");
//            ab.setTitle(title);
      System.out.println("Validate returned " + abd.validate());
      stub.addBook(abd);
      ...

  <addBook xmlns="http://ws.sosnoski.com/library/wsdl">
   <type>scifi</type>
   <isbn>0445203498</isbn>
   <author>Cook, Glen</author>
  </addBook>
    
  <getBooksByTypeResponse xmlns="http://ws.sosnoski.com/library/wsdl">
   ...
   <getBooksByTypeReturn isbn="0445203498" type="scifi">
    <author xmlns="http://ws.sosnoski.com/library/types">Cook, Glen</author>
    <title xmlns="http://ws.sosnoski.com/library/types" xmlns:xsi="http://www.w3.org/2001
      /XMLSchema-instance" xsi:nil="true"/>
   </getBooksByTypeReturn>
  </getBooksByTypeResponse>

Este é um caso simples de não configuração de um valor necessário. Para esquemas mais complexos, o API gerado pelo XMLBeans pode ocultar ainda mais armadilhas. Uma discussão recente na lista de e-mails dos usuários do XMLBeans lidou com um caso em que os valores precisaram ser adicionados a duas listas diferentes, alternadamente para gerar a saída correta. Então o XMLBeans precisava que os desenvolvedores compreendessem o esquema e como o código gerado estaria relacionado ao esquema para garantir que fossem criados documentos XML válidos fossem criados pelo código do aplicativo. Um dos principais benefícios da estrutura de ligação de dados normalmente é ocultar os detalhes deste tipo de esquema dos desenvolvedores e, certamente o XMLBeans não chegam a este ponto.

é possível evitar os problemas de processamento ou geração de documentos XML inválidos com o XMLBeans ao chamar o método validate() incluso nas classes geradas. Caso esteja trabalhando com o XMLBeans, você deve, pelo menos, utilizar esta verificação para todos os documentos durante o teste e o desenvolvimento. Entretanto, a validação possui um impacto considerável no desempenho (e, como você verá no próximo artigo na série, o XMLBeans é lento mesmo sem chamar validate() em todos os documentos), então muitos aplicativos devem evitar a gasto adicional da validação nas implementações da produção. A validação também particularmente em termos das informações dos resultados. Para isolar a causa da falha da validação, você deve executar um esquema de validação padrão no documento com erro.

JiBX

JiBX (que eu também desenvolvi) é uma estrutura de ligação de dados que está focada em, principalmente, trabalhar com as classes Java existentes ao invés da geração do código a partir do esquema. Com o JiBX, primeiramente você cria uma definição da ligação para, então, definir como os objetos Java devem ser convertidos de e para XML, então compilar tal ligação utilizando uma ferramenta que melhore seus arquivos de classe de dados ao adicionar métodos (como bytecode) implementando as conversões. O tempo de execução da estrutura JiBX utiliza então estes métodos adicionados para converter os dados de e para XML.

A abordagem do JiBX oferece alguns pontos fortes e fracos exclusivos. Pelo lado positivo, o JIBX permite que você trabalhe diretamente com as classes existentes nos casos em que as interfaces dos serviços da Web estão sendo adicionadas ao código de serviço existente. A ferramenta Jibx2Wsdl é especialmente útil para este propósito, pois gera tudo o que é necessário para facilmente implementar seu código existente como um serviço do Axis2. é possível definir diversas ligações para as mesmas classes para trabalhar com diferentes versões XML dos documentos simultaneamente, utilizando um único modelo de dados. Ao modificar as ligações, geralmente é possível mesmo manter a mesma representação de XML conforme suas classes de dados são refatoradas.

A Lista 9 mostra partes interessantes do código do cliente JiBX, utilizando as classes que correspondem aos elementos da mensagem. Este código é semelhante ao ADB equivalente mostrado na Lista 5, então não entrarei em detalhes. A única diferença notável é a de que pelo fato de ambas as classes de dados e as classes de mensagem estão sob controle do usuário, é fácil de adicionar construtores de conveniência (como com o AddBookRequest) e outros métodos de suporte às classes que estão sendo utilizadas com o JiBX.

Lista 9. Código do cliente no JIBX
// create the server instance
JibxLibraryStub stub = new JibxLibraryStub(target);
        
// retrieve a book directly
String isbn = "0061020052";
GetBookResponse bresp = stub.getBook(new GetBookRequest(isbn));
Book book = bresp.getBook();
if (book == null) {
  System.out.println("No book found with ISBN '" + isbn + '\'');
} else {
  System.out.println("Retrieved '" + book.getTitle() + '\'');
}
isbn = "9999999999";
bresp = stub.getBook(new GetBookRequest(isbn));
book = bresp.getBook();
if (book == null) {
  System.out.println("No book found with ISBN '" + isbn + '\'');
} else {
  System.out.println("Retrieved '" + book.getTitle() + '\'');
}
        
// retrieve the list of types defined
GetTypesResponse tresp = stub.getTypes(new GetTypesRequest());
Type[] types = tresp.getTypes();
System.out.println("Retrieved " + types.length + " types:");
for (int i = 0; i < types.length; i++) {
  System.out.println(" '" + types[i].getName() + "' with " +
    types[i].getCount() + " books");
}
        
// add a new book
String title = "The Dragon Never Sleeps";
isbn = "0445203498";
try {
  AddBookRequest abr = new AddBookRequest("scifi", isbn, title,
    new String[] { "Cook, Glen" });
  stub.addBook(abr);
  System.out.println("Added '" + title + '\'');
  title = "This Should Not Work";
  abr = new AddBookRequest("scifi", isbn, title,
    new String[] { "Nobody, Ima" });
  System.out.println("Added duplicate book - should not happen!");
} catch (AddDuplicateFaultException e) {
  System.out.println("Failed adding '" + title +
  "' with ISBN '" + isbn + "' - matches existing title '" +
  e.getFaultMessage().getBook().getTitle() + '\'');
}
        
// create a callback instance
BooksByTypeCallback cb = new BooksByTypeCallback();
        
// retrieve all books of a type asynchronously
stub.startgetBooksByType(new GetBooksByTypeRequest("scifi"), cb);
long start = System.currentTimeMillis();
synchronized (cb) {
  while (!cb.m_done) {
    try {
      cb.wait(100);
    } catch (Exception e) {}
  }
}
System.out.println("Asynchronous operation took " +
  (System.currentTimeMillis()-start) + " millis");
if (cb.m_response != null) {
  Book[] books = cb.m_response.getBooks();

A Lista 10 mostra o código JiBX unwrapped equivalente. Da mesma maneira que com código ADB não empacotado, é muito mais fácil compreender e trabalhar com a forma unwrapped das chamadas de serviço do que com o código direto. A única diferença significativa entre as versões do JiBX e do ADB é que no caso do JiBX não é necessário criar um objeto quando nenhum valor estiver sendo transmitido, enquanto era exigida pelo ADB para a chamada getTypes(). O suporte ao JiBX unwrapped também é, de alguma maneira, mais estável do que a versão do ADB, pois ele é completamente suportado desde o Axis2 1.1.1.

Lista 10. Código do cliente JIBX unwrapped
// create the server instance
JibxUnwrapLibraryStub stub = new JibxUnwrapLibraryStub(target);
        
// retrieve a book directly
String isbn = "0061020052";
Book book = stub.getBook(isbn);
if (book == null) {
  System.out.println("No book found with ISBN '" + isbn + '\'');
} else {
  System.out.println("Retrieved '" + book.getTitle() + '\'');
}
        
// retrieve the list of types defined
Type[] types = stub.getTypes();
System.out.println("Retrieved " + types.length + " types:");
for (int i = 0; i < types.length; i++) {
  System.out.println(" '" + types[i].getName() + "' with " +
    types[i].getCount() + " books");
}
        
// add a new book
String title = "The Dragon Never Sleeps";
isbn = "0445203498";
try {
  stub.addBook("scifi", isbn, new String[] { "Cook, Glen" }, title);
  System.out.println("Added '" + title + '\'');
  title = "This Should Not Work";
  stub.addBook("xml", isbn, new String[] { "Nobody, Ima" }, title);
  System.out.println("Added duplicate book - should not happen!");
} catch (AddDuplicateFaultException e) {
  System.out.println("Failed adding '" + title +
    "' with ISBN '" + isbn + "' - matches existing title '" +
    e.getFaultMessage().getBook().getTitle() + '\'');
}
        
// create a callback instance
BooksByTypeCallback cb = new BooksByTypeCallback();
        
// retrieve all books of a type asynchronously
stub.startgetBooksByType("scifi", cb);
long start = System.currentTimeMillis();
synchronized (cb) {
  while (!cb.m_done) {
    try {
      cb.wait(100L);
    } catch (Exception e) {}
  }
}
System.out.println("Asynchronous operation took " +
  (System.currentTimeMillis()-start) + " millis");
if (cb.m_books != null) {
  Book[] books = cb.m_books;

O suporte ao JiBX unwrapped também se diferencia do no ADB em termos das classes utilizadas. Ao utilizar o ADB não empacotado, as classes ainda são geradas e utilizadas nos bastidores para todos os elementos de mensagem. Com o JiBX, as classes precisam ser definidas correspondendo aos elementos da mensagem quando a manipulação direta for utilizada, como na Lista 9, para a manipulação do unwrapped, apenas as classes transmitidas como valores precisam ser definidas e incluídas em sua definição de ligação. Em ambos os casos, a definição de ligação do JiBX precisa ser criada antes de executar a ferramenta WSDL2Java do Axis2 e precisa ser transmitida utilizando um parâmetro de linha de comando -Ebindingfile.

A maior desvantagem da abordagem de ligação do JiBX, pelo menos em termos do serviço da Web, é provável que atualmente o JiBX ofereça um suporte deficiente para trabalhar com uma definição de esquema XML. Mesmo este suporte deficiente para trabalhar com o esquema, no formato da ferramenta Xsd2Jibx, não está integrado na geração do código do WSDL2Java do Axis2. Isso significa que é necessário que a definição de ligação e as classes de dados Java sejam criadas antes de executar o WSDL2Java para gerar o código de vinculação do Axis2. A etapa de aprimoramento do bytecode exigida pelo JiBX também pode ser problemática em alguns ambientes, pois geralmente ela precisa ser realizada no momento da criação do aplicativo e resulta no código estar presente nas classes para as quais o código fonte está disponível.

A ligação de dados do JiBX oferece alguns benefícios exclusivos, conforme discutido no início desta seção. Em termos de utilização do Axis2, o JiBX também oferece uma vantagem sobre as outras estruturas pelo falto de ela ser suportada com liberações de correção de erros que podem ser incluídas nas liberações do Axis2 para corrigir os problemas encontrados após esta liberação (Consulte Obtenha produtos e tecnologias na seção de Recursos para obter detalhes). Para as outras estruturas, a única maneira de obter correções dos erros é mudar para as compilações noturnas do Axis2, que frequentemente podem levar a outros problemas. No futuro, espera-se que o JiBX ofereça uma geração de ligação e de códigos sólida para o suporte do esquema. Quando ela estiver disponível, o JiBX deve ser uma excelente alternativa de ligação de dados em todos os sentidos para o Axis2. Até lá, é o que possui mais benefícios ao trabalhar com o código Java existente, onde a ferramenta Jibx2Wsdl oferece um suporte excelente.


Resumo

Atualmente, o Axis2 oferece o suporte completo para três estruturas de ligação de dados diferentes:

  • ADB foi projetado especificamente para o Axis2 e pode ser utilizado apenas no ambiente do Axis2. A partir do Axis2 liberação 1.3, ele oferece um bom e — crescente — suporte para a geração de código do esquema. Ele também suporta métodos de serviço unwrapped e a manipulação de anexo automático, fazendo dele uma das principais opções ao trabalhar com definições de serviço WSDL existentes.
  • XMLBeans oferece o suporte mais completo para as estruturas de esquema de modelagem nos códigos Java gerados. Mas ele cria o modelo Java mais complexo para um determinado esquema e não suporta métodos de serviço unwrapped para uma interface mais simples. Por padrão, ele também não reforça nem as regras básicas de estrutura de esquema nos documentos XML de entrada ou saída, fazendo com que seja mais fácil de acidentalmente criar ou aceitar para processamento documentos XML inválidos.
  • JiBX é a única alternativa que suporta o trabalho com classes Java existentes. Ele também oferece um suporte excelente para os métodos de serviço unwrapped. Mas o suporte do JiBX integrado ao Axis2 não trata da geração do código a partir do esquema, e mesmo o suporte à geração de código separado a partir do esquema oferecido pelas ferramentas JiBX atualmente apresenta penas um suporte limitado ao esquema.

é ótimo que o Axis2 ofereça uma opção entre estas estruturas de ligação de dados, pois não há uma única 'melhor' opção para todas as necessidades. No futuro, o Axis2 também oferecerá suporte completo para o JAXB 2.0, que irei abordar como parte desta série em um artigo posterior sobre o JAX-WS 2.0 relacionado. Conhecer os pontos fortes e fracos de cada estrutura pode ajudar a fazer melhores opções para suas necessidades e alertam você sobre as potenciais áreas com problemas antes de encontrá-las na produção. No próximo artigo desta série, você aprenderá sobre outro aspecto de comparação para as estruturas de ligação de dados do Axis2: o desempenho.


Downloads

DescriçãoNomeTamanho
Sample code (Axis2 1.2 and earlier)j-java3code.zip82KB
Sample code (Axis2 1.3)j-java3code1_3.zip87KB

Recursos

Aprender

Obter produtos e tecnologias

  • Obtenha mais informações obre e efetue o download do Axis2 para testá-lo por si mesmo. O suporte completo para a ligação de dados do ADB e XMLBeans está incluso no download.
  • Efetue o download da estrutura de ligação de dados do JiBX, que permite que você adapte o código existente para ser utilizado como Axis2 ou outros aplicativos XML. é possível ainda obter as atualizações para corrigir os problemas relacionados ao JiBX nas liberações do Axis2.
  • Obtenha a ferramenta Jibx2Wsdl para simplificar a criação da definição de uma ligação do JiBX, do WSDL e do esquema a partir do código existente.
  • Valide suas trocas de mensagens XML no Axis2 utilizando um módulo de validação.
  • Inove seu novo projeto de desenvolvimento com o software de teste IBM, disponível para download ou em DVD.

Discutir

Comentários

developerWorks: Conecte-se

Los campos obligatorios están marcados con un asterisco (*).


Precisa de um ID IBM?
Esqueceu seu ID IBM?


Esqueceu sua senha?
Alterar sua senha

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


A primeira vez que você entrar no developerWorks, um perfil é criado para você. Informações no seu perfil (seu nome, país / região, e nome da empresa) é apresentado ao público e vai acompanhar qualquer conteúdo que você postar, a menos que você opte por esconder o nome da empresa. Você pode atualizar sua conta IBM a qualquer momento.

Todas as informações enviadas são seguras.

Elija su nombre para mostrar



Ao se conectar ao developerWorks pela primeira vez, é criado um perfil para você e é necessário selecionar um nome de exibição. O nome de exibição acompanhará o conteúdo que você postar no developerWorks.

Escolha um nome de exibição de 3 - 31 caracteres. Seu nome de exibição deve ser exclusivo na comunidade do developerWorks e não deve ser o seu endereço de email por motivo de privacidade.

Los campos obligatorios están marcados con un asterisco (*).

(Escolha um nome de exibição de 3 - 31 caracteres.)

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


Todas as informações enviadas são seguras.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=80
Zone=Software livre
ArticleID=395711
ArticleTitle=Java Web Services: Axis2 Data Binding
publish-date=07262007