JiBX 1.2, Parte 1: Código Java para Esquema XML

Melhorar a qualidade do esquema com a conversão customizada de modelos de dados Java para, e a partir de, documentos XML

As definições de esquema XML são a base para muitos tipos de trocas de dados, incluindo a maioria dos formulários de serviços da Web. Mas o Esquema XML é um padrão complexo e a maioria das ferramentas para criar e modificar definições de esquema não é tão poderosa nem fácil de usar como aquelas para trabalhar com código Java™ . Os novos recursos de JiBX 1.2 sobre os quais você irá aprender neste tutorial — Parte 1 de uma série em duas partes— permitem iniciar com código Java e facilmente gerar definições de esquema de qualidade para corresponderem a suas estruturas de dados. Você pode, então, usar os esquemas diretamente, usando ligação de dados JiBX ou não.

Dennis Sosnoski, President, 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.



03/Mar/2009

Antes de Iniciar

Sobre este Tutorial

JiBX é uma ferramenta para fazer a ligação de dados XML a objetos Java. A ligação de dados de JiBX é conhecida há muito tempo como a abordagem mais rápida e mais flexível para fazer a ligação de código Java com XML. Mas a complexidade de suas definições de ligação e seu suporte limitado para definições de esquema XML cada vez mais usadas frustraram usuários em alguns momentos. Felizmente, a versão 1.2 de JiBX percorreu um longo caminho para eliminar esses problemas. Neste tutorial, você aprenderá sobre como usar os novos recursos de JiBX 1.2 para gerar definições de esquema XML facilmente a partir de código Java e ler e gravar documentos XML que correspondem às definições de esquema geradas — tudo sem precisar entrar nos detalhes de definições de ligação de JiBX. A Parte 2 cobre o lado inverso de iniciar com as definições de esquema XML e gerar código Java.

Objetivos

Este tutorial o guia através do processo de usar JiBX para gerar definições de esquema XML a partir de código Java. Você verá primeiro como iniciar com um simples modelo de dados Java e gerar um esquema padrão que corresponda a esse modelo. A partir dessa base, você aprenderá como é possível aplicar facilmente um intervalo de customizações para controlar os valores reais usados a partir de suas classes Java e como são acessados, se são necessários ou opcionais, nomes e espaços de nomes usados no XML e até mesmo a estrutura de definição do esquema gerado. Ao longo do caminho, você verá como JiBX agrega valor a seus esquemas gerados, usando seu investimento em Javadocs para documentar a definição de esquema automaticamente. Após ler este tutorial e trabalhar com os exemplos fornecidos, você poderá usar JiBX para gerar definições de esquema XML de suas próprias classes de estrutura de dados Java.

Pré-requisitos

Para entender este tutorial, você deve ter pelo menos um conhecimento básico de código Java e XML. Você não precisa de um entendimento detalhado de definições de esquema XML, mas alguma familiaridade com o esquema ajudará a entender os exemplos de uma melhor forma.

Requisitos do Sistema

Para executar os exemplos, é necessário instalar:

As instruções de download e instalação de JiBX estão incluídas no tutorial.


Introdução

Nesta seção, você obterá uma visão geral de JiBX e instalará JiBX e o código de amostra do tutorial.

Introduzindo JiBX

JiBX é uma das muitas ferramentas usadas para converter entre estruturas de dados Java e documentos XML (consulte Recursos). O que diferencia JiBX dos outros são os recursos de desempenho e flexibilidade. O desempenho de JiBX tem uma avaliação alta de forma consistente, superando a de outras ferramentas comuns (como JAXB 2.0) por um ou dois fatores ou mais. JiBX também é mais flexível do que a maioria das outras ferramentas Java-XML, usando definições de ligação para desacoplar a estrutura Java da representação de XML, de forma que cada uma possa ser alterada independentemente da outra.

Com o release 1.2, JiBX incluir recursos importantes que suportam as definições de esquema XML. Você pode usar ferramentas incluídas no release de JiBX para gerar uma definição de esquema que corresponda a seu código Java ou para gerar código Java que corresponda a sua definição de esquema. De qualquer forma, você também obtém uma definição de ligação que permite que você use JiBX para converter entre o código Java e os documentos XML que correspondem à definição de esquema. Neste tutorial, você verá como aplicar o primeiro tipo de geração: do código Java até uma definição de esquema.

Instalando JiBX

É necessário instalar JiBX antes de prosseguir com este tutorial. Faça download do ZIP de distribuição 1.2.x mais recente expanda-o em um local conveniente em seu sistema. Você acabará com um diretório denominado jibx, que contém todos os JARs, documentação, exemplos e até mesmo código de origem de JiBX.

Instalando o Código do Tutorial

Agora, faça download do código de amostra do tutorial, também fornecido como um arquivo ZIP. A maneira mais fácil de instalá-lo em seu sistema é expandindo o ZIP para o diretório-raiz de sua distribuição JiBX (ou, no Windows®, copie o diretório dwcode1 de dentro do arquivo ZIP para o diretório-raiz de sua distribuição JiBX). Isso deve criar um subdiretório dwcode1 no diretório jibx, com os arquivos de exemplo (incluindo build.xml, custom1.xml e outros) dentro desse diretório dwcode1.

O código de amostra inclui um arquivo de construção Apache Ant para automatizar a execução das ferramentas JiBX e tratar das outras etapas envolvidas nos exemplos. Se você instalar o código de amostra diretamente no diretório de instalação JiBX, a construção pode acessar os JARs de JiBX sem qualquer configuração adicional. Se você instalar o código de amostra em outro local, você ainda pode usar a construção Ant. Nesse caso, é necessário somente configurar uma variável de ambiente JIBX_HOME no caminho da instalação de JiBX. Como alternativa, é possível editar o arquivo build.xml dentro do diretório sample-code e remover comentário da linha próxima ao início do arquivo que configura a propriedade jibx-home diretamente.


Gerando Ligação Padrão e Esquema a partir do Código

Uso de Não-Java 5

O código de exemplo do tutorial usa recursos de coleta e enum por tipo Java 5, mas o próprio JiBX é totalmente compatível com versões mais antigas de Java. O tempo de execução padrão de JiBX funciona com JVMs 1.3 e posteriores e também pode ser construído para compatibilidade com J2ME. A maioria dos outros componentes de JiBX, incluindo BindGen, pode ser executada em JVMs 1.4.1 e posterior. A documentação de BindGen no download de JiBX inclui um exemplo mostrando como as customizações podem fornecer a BindGen o equivalente de coletas por tipo quando você usa código pré-Java 5.

É fácil gerar uma definição de ligação JiBX e a definição do esquema XML correspondente, a partir do código Java. Você aprenderá como nesta seção.

Introduzindo o Código de Exemplo Java

Como um exemplo, vou iniciar com o código Java para um conjunto de classes estilo bean (campos privados, métodos de acesso público get e set) usadas para representarem um pedido de uma loja on-line. A Listagem 1 mostra uma versão abreviada do código, com a maioria dos métodos get/set deixados de fora. O código de amostra integral está no diretório src do código de amostra.

Listagem 1. Código Java Base

Clique aqui para ver lista de códigos

Listagem 1. Código Java Base

package org.jibx.starter;

/**
 * Informações de pedido.
 */
public class Order
{
    private long orderNumber;
    private Customer customer;

    /** Informações do endereço para cobrança. */
    private Address billTo;
    private Shipping shipping;

    /** Informações do endereço de remessa. Se estiver faltando, o endereço para cobrança também é usado como o endereço de remessa. */
    private Address shipTo;
    private List<Item> items;

    /** Data em que o pedido foi colocado no servidor. */
    private Date orderDate;

    /** Data em que o pedido foi enviado. Será <code>null</code> se o pedido ainda não foi enviado. */
    private Date shipDate;
    private Float total;

    public long getOrderNumber() {
        return orderNumber;
    }
    ...
}
/**
 * Informações do cliente.
 */
public class Customer
{
    private long customerNumber;

    /** Nome pessoal. */
    private String firstName;

    /** Nome de família. */
    private String lastName;

    /** Nome do meio, se houver. */
    private List<String> middleNames;
    ...
}
/**
 * Informações de endereço.
 */
public class Address
{
    /** Primeira linha de informações de rua (necessário). */
    private String street1;

    /** Segunda linha de informações de rua (opcional). */
    private String street2;
    private String city;

    /** Abreviação de estado (necessário para os EUA e Canadá, do contrário, opcional). */
    private String state;

    /** Código de endereçamento postal (necessário para os EUA e Canadá, do contrário, opcional). */
    private String postCode;

    /** Nome do país (opcional, supõe-se EUA se não fornecido). */
    private String country;
    ...
}
/**
 * Informações do item de linha do pedido.
 */
public class Item
{
    /** Identificador de estoque. Espera-se que tenha 12 caracteres de comprimento, com dois caracteres alfa à esquerda seguidos por dois dígitos decimais.
*/
    private String id;

    /** Descrição de texto do item. */
    private String description;

    /** Número de unidades pedidas. */
    private int quantity;

    /** Preço unitário. */
    private float price;
    ...
}
/**
 * Métodos suportados de envio. Os métodos de envio "INTERNATIONAL" podem ser usados somente para
 * pedidos com endereços de remessa fora dos EUA e um desses métodos é necessário
 * nesse caso.
 */
public enum Shipping
{
    STANDARD_MAIL, PRIORITY_MAIL, INTERNATIONAL_MAIL, DOMESTIC_EXPRESS,
    INTERNATIONAL_EXPRESS
}

Gerando a Ligação e o Esquema Padrão

Para gerar uma ligação JiBX e um esquema XML a partir de algumas classes Java, você primeiro precisa compilar as classes, em seguida, executar a ferramenta org.jibx.binding.generator.BindGen incluída no jibx-tools.jar a partir da distribuição JiBX. Você pode executar a ferramenta diretamente a partir da linha de comandos ou indiretamente através de uma ferramenta de construção, como Ant.

O download do tutorial inclui um script Ant build.xml com o destino compile para compilar o código de exemplo e o destino bindgen para executar o programa BindGen no código compilado.

Para testar isso, abra um console no diretório dwcode1 do download instalado e digite ant compile bindgen. Se você tiver Ant instalado em seu sistema e tiver instalado o código de download de acordo com as instruções, você deve ver saída semelhante à mostrada na Figura 1:

Figura 1. Usando a Construção Ant
Ant build output for generation from code

Você também pode executar BindGen diretamente a partir do console. Para fazer isso, é necessário incluir jibx-tools.jar em seu caminho de classe Java, juntamente com o caminho para os arquivos de classe compilados que você usará como entrada para a geração. Se você quiser duplicar o efeito do destino Ant bindgen fornecido, você também precisa passar o diretório-raiz para os arquivos de origem de suas classe na linha de comando. Por fim, é necessário listar as classes-raiz que deseja usar para a geração. Nos sistemas UNIX® e Linux® , a linha de comando Java (que consiste em uma única linha, mesmo se aparecer quebrada em sua exibição) para duplicar o destino Ant bindgen a partir de um console no diretório dwcode1 (supondo que você tenha seguido as instruções de instalação recomendadas) é:

java -cp ../lib/jibx-tools.jar:bin org.jibx.binding.generator.BindGen
   -s src org.jibx.starter.Order

No Windows, o comando (uma única linha, independentemente de sua aparência aqui) é:

java -cp ..\lib\jibx-tools.jar;bin org.jibx.binding.generator.BindGen
   -s src org.jibx.starter.Order

Muitas outras opções podem ser passadas para BindGen a partir da linha de comando. Você dará uma olhada neles posteriormente no tutorial. Agora, vamos dar uma olhada no esquema gerado.

Artefatos Gerados

A Listagem 2 mostra a saída do esquema gerada a partir de BindGen (como starter.xsd), ligeiramente reformatada para se ajustar à largura da página e com alguns detalhes removidos. A tag inicial para a definição do esquema que corresponde a cada classe Java é exibida em negrito para enfatizar a estrutura.

Listagem 2. Esquema Gerado
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:tns="http://jibx.org/starter" elementFormDefault="qualified"
  targetNamespace="http://jibx.org/starter">
 <xs:complexType name="address">
  <xs:annotation>
   <xs:documentation>Address information.</xs:documentation>
  </xs:annotation>
  <xs:sequence>
   <xs:element type="xs:string" name="street1" minOccurs="0">
    <xs:annotation>
     <xs:documentation>First line of street information (required).</xs:documentation>
    </xs:annotation>
   </xs:element>
   ...
  </xs:sequence>
 </xs:complexType>
 <xs:element type="tns:order" name="order"/>
 <xs:complexType name="order">
  <xs:annotation>
   <xs:documentation>Order information.</xs:documentation>
  </xs:annotation>
  <xs:sequence>
   <xs:element name="customer" minOccurs="0">
    <xs:complexType>
     ...
    </xs:complexType>
   </xs:element>
   <xs:element type="tns:address" name="billTo" minOccurs="0">
    <xs:annotation>
     <xs:documentation>Billing address information.</xs:documentation>
    </xs:annotation>
   </xs:element>
   <xs:element name="shipping" minOccurs="0">
    <xs:simpleType>
     <xs:annotation>
      <xs:documentation>Supported shipment methods. The "INTERNATIONAL" shipment methods
        can only be used for orders with shipping addresses outside the U.S., and one of
        these methods is required in this case.</xs:documentation>
     </xs:annotation>
     <xs:restriction base="xs:string">
      <xs:enumeration value="STANDARD_MAIL"/>
      ...
     </xs:restriction>
    </xs:simpleType>
   </xs:element>
   <xs:element type="tns:address" name="shipTo" minOccurs="0">
    <xs:annotation>
     <xs:documentation>Shipping address information. If missing, the billing address is
       also used as the shipping address.</xs:documentation>
    </xs:annotation>
   </xs:element>
   <xs:element name="item" minOccurs="0" maxOccurs="unbounded">
    <xs:complexType>
     <xs:sequence>
      <xs:element type="xs:string" name="id" minOccurs="0">
       <xs:annotation>
        <xs:documentation>Stock identifier. This is expected to be 12 characters in
          length, with two leading alpha characters followed by ten decimal
          digits.</xs:documentation>
       </xs:annotation>
      </xs:element>
      <xs:element type="xs:string" name="description" minOccurs="0">
       <xs:annotation>
        <xs:documentation>Text description of item.</xs:documentation>
       </xs:annotation>
      </xs:element>
     </xs:sequence>
     <xs:attribute type="xs:int" use="required" name="quantity">
      <xs:annotation>
       <xs:documentation>Number of units ordered.</xs:documentation>
      </xs:annotation>
     </xs:attribute>
     <xs:attribute type="xs:float" use="required" name="price">
      <xs:annotation>
       <xs:documentation>Price per unit.</xs:documentation>
      </xs:annotation>
     </xs:attribute>
    </xs:complexType>
   </xs:element>
  </xs:sequence>
  <xs:attribute type="xs:long" use="required" name="orderNumber"/>
  <xs:attribute type="xs:date" name="orderDate">
   <xs:annotation>
    <xs:documentation>Date order was placed with server.</xs:documentation>
   </xs:annotation>
  </xs:attribute>
  <xs:attribute type="xs:date" name="shipDate">
   <xs:annotation>
    <xs:documentation>
     <![CDATA[Date order was shipped. This will be <code>null</code> if the order
       has not yet shipped.]]></xs:documentation>
   </xs:annotation>
  </xs:attribute>
 </xs:complexType>
</xs:schema>

Por padrão, BindGen gera um esquema com definições complexType e simpleType aninhadas para tipos que são usados somente uma vez e definições separadas para tipos que são usados mais de uma vez. Nesse caso, o estilo aninhado resulta em um esquema com somente três definições globais: os tipos complexos address e order e o elemento order . A classe Address é usada em dois locais na classe Order (para endereços para cobrança e de remessa), por isso essa classe é representada por uma definição global separada no esquema. (O esquema permite reutilizar as definições somente se forem globais.) As outras classes da estrutura de dados Java (Customer, Item e Shipping) são referidas, cada uma, em somente um ponto da classe Order , portanto, as definições de tipo correspondente são integradas diretamente na definição de tipo de esquema order .

Um dos melhores recursos de BindGen é que pode gerar documentação de esquema a partir de Javadocs nas classes de entrada. Você pode ver a documentação do esquema na Listagem 2 para cada campo com um Javadoc na Listagem 1 e para cada tipo global correspondente a uma classe com um Javadoc. Nem todos os formulários de Javadocs podem ser correspondidos com os componentes do esquema através da manipulação padrão de BindGen — e alguns Javadocs, como aqueles nos métodos de acesso "get", podem parecer estranhos quando convertidos para a documentação do esquema — mas a documentação do esquema resultante pode ser extremamente útil para esclarecer o uso apropriado da representação XML. Você pode até mesmo definir sua própria classe do formatador para Javadocs usados como documentação do esquema, se você quiser fazer algumas mudanças no texto no processo de conversão (como remover as sentenças de entrada "Get the ..." dos Javadocs do método "get").

Esse recurso de conversão de Javadoc funciona somente se você tiver o código de origem disponível para as classes e fornecer um argumento para BindGen indicando o caminho 0(ou caminhos) do código de origem. Nas amostras da linha de comando que forneci anteriormente (consulte Gerando a Ligação e o Esquema Padrão), o caminho de origem é fornecido como -s src.

Ligação JiBX Gerada

Além da definição do esquema, BindGen também produz uma definição de ligação JiBX (como o arquivo binding.xml, neste caso) que indica ao compilador de ligação JiBX como fazer a conversão entre as classes Java e XML. Essa definição de ligação é realmente a saída principal de BindGen, com o esquema gerado a partir da ligação. As definições de ligação contêm detalhes integrais das conversões a serem feitas por JiBX, portanto, são necessariamente complexas. Felizmente, não é necessário entender a definição de ligação para trabalhar com JiBX usando geração de ligação e esquema BindGen, de forma que esse tutorial não cubra os detalhes.


Trabalhando com Documentos XML

Nesta seção, você aprenderá sobre como executar o compilador de ligação JiBX e como usar JiBX no tempo de execução para trabalhar com documentos XML.

Executando o Compilador de Ligação JiBX

Para usar a definição de ligação gerada no trabalho com documentos XML, primeiro, você precisa executar a ferramenta do compilador de ligação JiBX. O compilador de ligação inclui bytecode em seus arquivos de classe compilados que realmente implementa as conversões para, e a partir de, XML, conforme especificado pela definição de ligação. Você deve executar o compilador de ligação toda vez que recompilar suas classes Java ou modificar a definição de ligação, portanto, geralmente é melhor incluir a etapa do compilador de ligação como parte do processo de construção padrão de seu projeto.

O compilador de ligação está incluído na distribuição JiBX como parte do jibx-bind.jar. A documentação de JiBX fornece detalhes integrais sobre as diferentes maneiras de executar o compilador de ligação, inclusive como você pode executá-lo no tempo de execução em vez de como parte da construção. JiBX também fornece plug-ins para o Eclipse e o IntelliJ IDEA que executam o compilador de ligação automaticamente quando você está trabalhando nesses IDEs.

Para os propósitos deste tutorial, vamos manter as coisas simples e simplesmente executar o compilador de ligação através de Ant, usando o destino bind do build.xml. A Figura 2 mostra a saída que você deve ver ao executar esse destino, supondo que você já tenha executado os destinos compile e bindgen . (Você também pode executar todos os três destinos em seqüência, listando-os em ordem na linha de comando: ant compile bindgen bind.)

Figura 2. Tarefa de Construção Antbind
Ant build output for binding compiler

Usando JiBX no Tempo de Execução

A Listagem 3 mostra um documento de teste simples que corresponde ao esquema gerado, incluído no download do código do tutorial como data.xml:

Listagem 3. Documento de Teste de Ligação Padrão
<order orderNumber="12345678" orderDate="2008-10-18" shipDate="2008-10-22"
    xmlns="http://jibx.org/starter">
  <customer customerNumber="5678">
    <firstName>John</firstName>
    <lastName>Smith</lastName>
  </customer>
  <billTo>
    <street1>12345 Happy Lane</street1>
    <city>Plunk</city>
    <state>WA</state>
    <postCode>98059</postCode>
    <country>USA</country>
  </billTo>
  <shipping>PRIORITY_MAIL</shipping>
  <shipTo>
    <street1>333 River Avenue</street1>
    <city>Kirkland</city>
    <state>WA</state>
    <postCode>98034</postCode>
    <country>USA</country>
  </shipTo>
  <item quantity="1" price="5.99">
    <id>AC4983498512</id>
    <description>Left-handed widget</description>
  </item>
  <item quantity="2" price="9.50">
    <id>IW2349050499</id>
    <description>Right-handed widget</description>
  </item>
  <item quantity="1" price="8.95">
    <id>RC3000488209</id>
    <description>High-speed MP3 rewinder</description>
  </item>
</order>

O pacote de download também inclui um programa de teste simples, mostrado aqui como Listagem 4, que demonstra o uso de JiBX para desserializar e serializar documentos. (Serializar é o processo de gerar uma representação XML para um objeto em memória, potencialmente incluindo objetos vinculados a partir do objeto original. Desserializar é o processo inverso de serializar, construir um objeto (e potencialmente um gráfico de objetos vinculados) em memória de uma representação XML.) O destino Ant run executa esse programa de teste, usando o documento Listagem 3 como entrada e gravando a cópia serializada do documento em um arquivo denominado out.xml.

Listagem 4. Programa de Teste

Clique aqui para ver lista de códigos

Listagem 4. Programa de Teste

public class Test
{
    /**
     * Desserializar o documento de amostra de um arquivo, computar e configurar total do pedido, em seguida,
     * serializá-lo novamente em outro arquivo.
     *
     * @param args
     */
    public static void main(String[] args) {
        if (args.length < 2) {
            System.out.println("Usage: java -cp ... " +
                "org.jibx.starter.Test in-file out-file");
            System.exit(0);
        }
        try {

            // desserializar informações do cliente a partir do arquivo
            IBindingFactory bfact = BindingDirectory.getFactory(Order.class);
            IUnmarshallingContext uctx = bfact.createUnmarshallingContext();
            FileInputStream in = new FileInputStream(args[0]);
            Order order = (Order)uctx.unmarshalDocument(in, null);

            // computar o valor total do pedido
            float total = 0.0f;
            for (Iterator<Item> iter = order.getItems().iterator(); iter.hasNext();) {
                Item item = iter.next();
                total += item.getPrice() * item.getQuantity();
            }
            order.setTotal(new Float(total));

            // serializar objeto novamente para o arquivo (com bom deslocamento, como UTF-8)
            IMarshallingContext mctx = bfact.createMarshallingContext();
            mctx.setIndent(2);
            FileOutputStream out = new FileOutputStream(args[1]);
            mctx.setOutput(out, null);
            mctx.marshalDocument(order);
            System.out.println("Processed order with " +  order.getItems().size() +
                " items and total value " + total);

        } catch (FileNotFoundException e) {
            e.printStackTrace();
            System.exit(1);
        } catch (JiBXException e) {
            e.printStackTrace();
            System.exit(1);
        }
    }
}

A Figura 3 mostra a saída que você deve ver ao executar o destino run :

Figura 3. Tarefa de Construção Ant run
Ant build output from running test program

Você pode inspecionar o arquivo out.xml gerado para ver como ele corresponde à entrada original mostrada na Listagem 3. Além da declaração de namespace, da ordem dos atributos e do atributo total incluído na saída (computador e configurados pelo programa de teste), os dois documentos devem ser idênticos. Isso nem sempre será o caso! JiBX, como a maioria dos formulários de ligação de dados, funciona somente com dados "significativos" no documento, o que significa que esses valores que estão sendo usados por seu aplicativo. Partes não significativas do documento (como espaço em branco em uma tag de início e de finalização, texto entre elementos e comentários) são perdidas quando quando você desserializa um documento. Parte da razão dos documentos de entrada e saída serem tão semelhantes nesse caso é que o código da Listagem 4 configura o formato de saída para usar deslocamento de dois espaços por nível de aninhamento de elemento, correspondendo ao documento de entrada.

Observadores mais detalhistas observarão uma diferença entre a entrada e saída que parece significativa, na parte da lista de itens do documento de saída, mostrada na Listagem 5:

Listagem 5. Lista de Itens do Documento de Saída
<item quantity="1" price="5.99">
    <id>AC4983498512</id>
    <description>Left-handed widget</description>
  </item>
  <item quantity="2" price="9.5">
    <id>IW2349050499</id>
    <description>Right-handed widget</description>
  </item>
  <item quantity="1" price="8.95">
    <id>RC3000488209</id>
    <description>High-speed MP3 rewinder</description>
  </item>

Se você comparar a linha mostrada em negrito na Listagem 5 com a linha correspondente no documento original da Listagem 3 , você pode ver que o preço foi alterado de 9.50 para 9.5, com a remoção do zero à direita. Isso não é um erro, no entanto. A representação usada para o valor do preço é um float e em termos de esquema Java e XML, zeros à esquerda antes do ponto decimal e zeros à direita após o ponto decimal não são significativos para um float.


Customizações de BindGen

Nesta seção, você aprenderá como customizar a operação BindGen para controlar a representação XML de dados, alterar o estilo de nomes e espaços de nomes e controlar alguns aspectos da estrutura do esquema.

Customizando a Operação BindGen

BindGen suporta customizações extensivas para todos os aspectos de ligação e geração de esquema. O conjunto de customizações a serem aplicadas é passado para BindGen como um documento XML, com elementos aninhados que espelham a estrutura de seu código Java. A Listagem 6 fornece um exemplo simples:

Listagem 6. Exemplo de Customizações Simples
<custom>
  <package name="org.jibx.starter" property-access="true">
    <class name="Address" includes="street1 street2 city state postCode country"/>
    <class name="Item" excludes="description"/>
  </package>
</custom>

Esse exemplo funciona com um único pacote de código Java, portanto, a Listagem 6 usa apenas um elemento <package> filho do elemento <custom> raiz. <package> e <class> são elementos de customização que usam atributos de nome que são relativos a qualquer elemento <package> de anexação, portanto, no exemplo da Listagem 6 somente um nome de classe simples é necessário para cada elemento <class> . <package> são elementos que podem ser aninhados dentro de outro, portanto, se você estiver lidando com classes em uma hierarquia de pacotes, é fácil tratar quaisquer opções usando elementos <package> aninhados. A estrutura aninhada é especialmente conveniente, pois muitos atributos de customização são herdados através do aninhamento de elemento, como discutirei posteriormente nesta seção. Usar aninhamento é opcional, no entanto — você pode ignorar os elementos <package> completamente e usar os elementos <class> com nomes de classe completos diretamente, se preferir.

Um arquivo de customização é passado para BindGen como um parâmetro da linha de comando usando o formato -c file-path. Customização sempre são opcionais e você nunca precisa usar um arquivo de customização, a menos que queira alterar o comportamento padrão de BindGen.

Controlando como BindGen Funciona com seu Código

BindGen realiza uma tarefa razoável com sua manipulação padrão de classes Java, mas há limites sobre o que pode ser feito sem a orientação do usuário. Por exemplo, a manipulação padrão é incluir cada campo na representação XML, exceto para campos estáticos, temporários ou finais. Essa abordagem funciona bem para classes que representam objetos de dados simples; no entanto, se suas classes incluírem informações de estado ou valores computados, você pode acabar com uma representação XML que inclui valores que você preferiria não expor fora da classe.

Customizações permitem que você controle de duas maneiras o que BindGen usa na representação XML. Primeiro, é possível alternar facilmente para usar métodos de acesso de estilo bean getXXX(), setXXX() e isXXX() em vez de acessar os campos diretamente. Segundo, você pode optar por listar os valores que você deseja incluir na representação XML para uma classe ou listar os valores que você deseja excluir. As customizações da Listagem 6 demonstram ambas as técnicas.

Conversões Unidirecionais

Este tutorial usa JiBX para conversões bidirecionais entre estruturas de dados Java e documentos XML. BindGen também suporta conversões unidirecionais, que podem ser mais convenientes em alguns casos. Por exemplo, as classes de objeto de valor são geralmente imutáveis e definem somente campos final e lêem os métodos de acesso ("get"). Isso dificulta o uso das classes de objeto de valor para conversões bidirecionais com BindGen. Se, em vez disso, você indicar a BindGen para gerar uma conversão somente de saída, funcionará bem com os campos ou as propriedades, o que você preferir. Para gerar uma conversão unidirecional, use direction="output" ou direction="input" no elemento raiz <custom> das customizações.

O elemento <package> na Listagem 6 usa um atributo property-access="true" para indicar a BindGen para procurar propriedades de estilo bean definidas por métodos de acesso públicos não-estáticos, em vez de campos, ao determinar quais valores incluir na representação XML. Esse atributo é um exemplo de uma configuração de customização herdada, que se aplica a tudo aninhado dentro do elemento com o atributo. No exemplo da Listagem 6 , a configuração se aplica aos dois elementos <class> aninhados. Também se aplica a todas as outras classes do pacote, mesmo nenhum elemento de customização <class> estando presente para essas outras classes. Além de determinar como os valores são localizados a partir da representação da classe, a configuração property-access também controla como os valores são acessados pelo código JiBX gerado — diretamente a partir dos campos ou chamando os métodos de acesso.

O primeiro elemento <class> da Listagem 6 usa um atributo includes="street1 street2 city state postCode country" para lista os valores específicos da classe que BindGen precisa para incluir na representação XML. O segundo elemento <class> da listagem usa um atributo excludes="description" , que lista valores a serem excluídos da representação XML. Como você está usando acesso de propriedade em vez de acesso de campo para valores, esses nomes são correspondidos com propriedades definidas pelos métodos de acesso get/set/is. Se você estivesse usando campos, os nomes dos valores seriam correspondidos com nomes de campos.

O destino Ant custgen1 executa BindGen usando as customizações da Listagem 6 . Esse destino é uma alternativa para o destino bindgen mostrado anteriormente, portanto, para executar a construção completa você usaria a linha de comando Ant: ant compile custgen1 bind. A Listagem 7 mostra a definição do tipo de item a partir do esquema gerado quando esse destino é executado:

Listagem 7. Fragmento de Saída do Esquema Customizado
<xs:element name="item" minOccurs="0" maxOccurs="unbounded">
  <xs:complexType>
    <xs:sequence>
      <xs:element type="xs:string" name="id" minOccurs="0"/>
    </xs:sequence>
    <xs:attribute type="xs:int" use="required" name="quantity"/>
    <xs:attribute type="xs:float" use="required" name="price"/>
  </xs:complexType>
</xs:element>

Você pode ver da Listagem 7 que o valor da descrição agora está faltando na representação do esquema, conforme especificado pelas customizações.

É necessário usar um documento XML diferente como entrada ao usar essa customização, pois o elemento <description> presente no XML original não é mais usado. O destino Ant run1 executa o programa de teste usando uma entrada data1.xml e gerando out1.xml como saída. Você também pode executar toda a sequência, da compilação do código de origem até a execução do programa de teste, com o destino Ant custom1 .

Controlando a Criação da Instância

A criação da instância durante a desserialização também pode ser controlada usando-se customizações. Por padrão, JiBX espera ter um construtor sem argumento (padrão) definido para cada classe (que o compilador Java gera automaticamente, se você não definir nenhum outro construtor). Quando uma nova instância da classe é necessária durante a desserialização, JiBX usa esse construtor sem argumento para criar a instância. Se algumas de suas classes definirem somente construtores com argumentos, você pode usar customizações de BindGen para torná-los usáveis por JiBX. Uma maneira de fazer isso é definindo um método de factory para ser usado para a criação de instâncias da classe, usando um atributo factory="xxx" no elemento de customizações <class> para fornecer o nome completo (com as informações de pacote e classe líder) de um método estático que retorna uma instância da classe. Você também pode simplesmente incluir add-constructors="true" no elemento raiz <custom> , que irá gerar uma ligação que inclui construtores sem argumento em classes, conforme necessário. Essa segunda abordagem funciona bem para classes de dados normais, mas você ainda precisará fornecer um factory para qualquer interface ou classes abstratas (que nunca podem ser construídas diretamente). É claro, se você estiver gerando uma ligação somente de saída (consulte a barra lateral Conversões Unidirecionais ), a criação de instância não é um problema e você não precisa se preocupar com os construtores.

Outras Customizações para Trabalhar com Classes de Entrada

BindGen suporta muitas outras customizações usadas para controlar como funciona com as classes de entrada Java. Por exemplo, se você usar uma convenção de nomenclatura para seus nomes de campos Java, pode configurar BindGen para ignorar strings específicas de prefixo ou sufixo usando os atributos strip-prefixes ou strip-suffixes . (Portanto, para ignorar prefixos m_ e s_ , por exemplo, você usaria strip-prefixes="m_ s_"). Essas modificações nos nomes de campos são aplicadas antes dos campos serem correspondidos a nomes de valores usados em outras customizações e naturalmente também se aplicam quando nomes XML são gerados a partir dos nomes de campos.

Você também pode customizar a manipulação de campos individuais ou propriedades bean de uma classe, usando elementos <value> aninhados. Você verá como trabalhar com esses elementos de customização de valor em um exemplo posterior.

Controlando a Representação XML

Além de controlar como BindGen interpreta seu código Java, você pode usar customizações para controlar a representação de dados XML. Essas customizações XML incluem a representação real (como um elemento ou um atributo) de valores, a ordem e os nomes dos elementos e atributos, seja o valor opcional ou necessário, e mais.

O exemplo de customização anterior da Listagem 6 demonstra uma customização XML no formato do atributo includes="street1 street2 city state postCode country" usando no primeiro elemento <class> . Discuti como isso seleciona os valores da classe incluído na representação XML. Também controla a representação XML sendo que a ordem na qual os valores são listados torna-se a ordem na qual são expressados na representação XML. Esse não é um problema significativo para atributos (que sempre são considerados sem ordem em XML), mas é importante para elementos.

Se você não especificar a ordem dos valores usando um atributo includes na customização <class> , BindGen gera os valores na ordem em que são fornecidos usando reflexo Java nas classes. Para a maioria dos compiladores Java e JVMs, essa ordem de reflexo corresponderá a ordem das definições no código de origem Java. No entanto, os compiladores Java e JVMs não são necessários para preservar essa ordem do código de origem, portanto, alguns compiladores ou JVMs podem fazer com que BindGen altere a ordem dos elementos filhos. Se quiser ter certeza de que a representação XML sempre será a mesma, independentemente do compilador Java e da JVM usados, o atributo includes fornece uma maneira fácil de corrigir a ordem.

Você também pode controlar a representação XML de um valor usando o atributo includes . BindGen permite que os caracteres iniciais do sinalizador sejam usados em cada nome da lista para indicar a representação: @ para um atributo e / para um atributo. Portanto, se você alterar a customização da Listagem 6 para includes="street1 street2 city state @postCode country", a representação do valor do código post é alterado de um elemento filho para um atributo.

Controlando Status Necessário

Controlar se um valor for considerado opcional ou necessário é outra fácil customização usando os seguintes atributos do elemento <class> : requireds e optionals . Como com o atributo includes , você pode preceder nomes nas listas requireds e optionals por um caractere sinalizador para indicar se devem ser expressados como um elemento filho ou um atributo.

Por padrão, BindGen trata todos os valores primitivos e valores de objeto simples (classes com tipos equivalentes XML diretos, diferentes de String) como atributos e trata todos os valores de objeto complexos como elementos filhos. Todos os valores primitivos são tratados conforme necessário e todos os valores de objeto como opcionais. Além de substituir esses padrões no nível de customização <class> usando os elementos includes, requiredse optionals , é possível alterar a representação padrão para usar elementos para todos os valores configurando um atributo value-style="element" em qualquer nível de customizações (elemento <custom>, <package> ou <class> ). Você também pode usar o atributo require para controlar quais tipos devem ser tratados como valores necessários no XML:

  • require="none" torna tudo opcional.
  • require="primitives" é o padrão, tornando somente os valores primitivos necessários.
  • require="objects" inverte o padrão, tornando os primitivos opcionais e os tipos de objetos necessários.
  • require="all" trata todos os valores necessários por padrão.

A Listagem 8 mostra o arquivo de customização custom2.xml do diretório dwcode1 do download do tutorial, ilustrando diversos recursos discutidos nesta seção:

Listagem 8. Customizando Pedido, Status Necessário e Representação
<custom property-access="true">
  <package name="org.jibx.starter">
    <class name="Address" includes="street1 street2 city @state @postCode country"
        requireds="street1 city"/>
    <class name="Customer" includes="customerNumber firstName lastName"
        requireds="lastName firstName /customerNumber"/>
    <class name="Item" excludes="description" requireds="@id quantity price"/>
    <class name="Order" requireds="/orderNumber customer billTo shipping orderDate"/>
  </package>
</custom>

Você pode tentar esse conjunto de customizações usando o destino Ant custgen2 (ant compile custgen2 bind, para executar a construção completa). A Listagem 9 mostra as partes selecionadas do esquema gerado usando essas customizações, mostrando o pedido resultante, o status necessário (com minOccurs="0" para elementos opcionais, que são necessários por padrão no esquema e use="required" para atributos necessários, que são opcionais por padrão no esquema) e representação do elemento ou atributo:

Listagem 9. Esquema Gerado Usando Customizações
<xs:complexType name="order">
  <xs:annotation>
    <xs:documentation>Order information.</xs:documentation>
  </xs:annotation>
  <xs:sequence>
    <xs:element type="xs:long" name="orderNumber">
      <xs:annotation>
        <xs:documentation>Get the order number.</xs:documentation>
      </xs:annotation>
    </xs:element>
    <xs:element name="customer">
      <xs:complexType>
        <xs:sequence>
          <xs:element type="xs:long" name="customerNumber"/>
          <xs:element type="xs:string" name="firstName"/>
          <xs:element type="xs:string" name="lastName"/>
        </xs:sequence>
      </xs:complexType>
    </xs:element>
    ...
  </xs:sequence>
  <xs:attribute type="xs:date" use="required" name="orderDate"/>
  <xs:attribute type="xs:date" name="shipDate"/>
  <xs:attribute type="xs:float" name="total"/>
</xs:complexType>
<xs:element type="tns:order" name="order"/>
<xs:complexType name="address">
  <xs:annotation>
    <xs:documentation>Address information.</xs:documentation>
  </xs:annotation>
  <xs:sequence>
    <xs:element type="xs:string" name="street1"/>
    <xs:element type="xs:string" name="street2" minOccurs="0"/>
    <xs:element type="xs:string" name="city"/>
    <xs:element type="xs:string" name="country" minOccurs="0"/>
  </xs:sequence>
  <xs:attribute type="xs:string" name="state"/>
  <xs:attribute type="xs:string" name="postCode"/>
</xs:complexType>

Após compilar a ligação usando a tarefa Ant bind , você pode testar isso usando a tarefa run2 que aceita o documento de teste data2.xml como entrada e gera um out2.xml de saída. Você também pode executar a sequência completa da compilação ao teste com o destino custom2 . A Listagem 10 mostra o documento de teste:

Listagem 10. Testar Customizações de Correspondência de Documento
<order orderDate="2008-10-18" shipDate="2008-10-22" xmlns="http://jibx.org/starter">
  <orderNumber>12345678</orderNumber>
  <customer>
    <customerNumber>5678</customerNumber>
    <firstName>John</firstName>
    <lastName>Smith</lastName>
  </customer>
  <billTo state="WA" postCode="98059">
    <street1>12345 Happy Lane</street1>
    <city>Plunk</city>
    <country>USA</country>
  </billTo>
  <shipping>PRIORITY_MAIL</shipping>
  <shipTo state="WA" postCode="98034">
    <street1>333 River Avenue</street1>
    <city>Kirkland</city>
  </shipTo>
  <item quantity="1" price="5.99" id="8394983498512"/>
  <item quantity="2" price="9.50" id="9912349050499"/>
  <item quantity="1" price="8.95" id="1293000488209"/>
</order>

Compare a Listagem 10 ao documento de teste original, mostrado na Listagem 3, para ver como suas customizações alteraram a representação XML dos dados (inclusive alterando o formato das representações dos itens de linha para elementos vazios, uma representação muito mais compacta do que a original).

Controlando Nomes e Espaços de Nome

Os nomes Java geralmente usam um estilo "caixa alternante": os nomes são, em sua maioria, em minúsculas, mas a letra inicial de cada palavra é maiúscula. Para o nomes de campo ou propriedade, a letra maiúscula inicial aplica-se somente a palavras após a primeira (resultando em nomes como postCode e customerNumber). Os nomes XML não são padronizados e diversos estilos diferentes são comumente usados. Eles incluem o estilo camelcase com minúscula inicial (o estilo do campo e do nome da propriedade), caixa alternante com um caractere maiúsculo inicial (o estilo do nome da classe Java), estilo de separador com hífen (palavras separadas por hifens), estilo de separador com ponto (palavras separadas por pontos) e estio de separador de sublinhado (palavras separadas por sublinhados).

BindGen assume o estilo caixa alternante para nomes XML por padrão, mas você pode alterar isso facilmente, configurando um atributo name-style em qualquer nível de customização (elemento <custom>, <package> ou <class> ). Os valores permitidos para esse atributo correspondem os estilos XML diferentes listados acima:

  • camel-case (o padrão)
  • upper-camel-case
  • hyphenated
  • dotted
  • underscored

Você também pode configurar o nome XML para um valor usando uma customização especificamente para esse valor. Usar uma customização de valor individual fornece controle integral sobre como esse valor será acessado e como ele será representado em XML. A Listagem 11 fornece dois exemplos de como usar elementos de customização para valores individuais, baseados no mesmo código de exemplo visto nos exemplos anteriores:

Listagem 11. Customizando Nomes e Namespace
<custom property-access="true" name-style="hyphenated" namespace="http://jibx.org/custom"
    namespace-style="fixed">
  <package name="org.jibx.starter">
    <class name="Address" includes="street1 street2 city @state @postCode country"
        requireds="street1 city"/>
    <class name="Customer" includes="customerNumber firstName lastName"
        requireds="lastName firstName /customerNumber"/>
    <class name="Item" excludes="description" requireds="@id quantity price"/>
    <class name="Order" requireds="orderNumber customer billTo shipping orderDate">
     <value property-name="orderNumber" element="order-num"/>
      <value property-name="items" item-name="line-item" element="order-items"/>
    </class>
  </package>
</custom>

A customização do primeiro valor na Listagem 11 é para a propriedade orderNumber , dentro do elemento <class name="Order"...> . Usando um atributo element="order-num" , a customização orderNumber indica a BindGen para expressar o valor como um elemento, em vez do formato do atributo padrão usado para um valor primitivo. A segunda customização é para a propriedade de coleta items . Essa customização usa os atributos item-name e element . O atributo item-name controla o nome usado para os valores individuais representados pela coleta, enquanto o atributo element força o uso do nome fornecido como um elemento wrapper em torno dos valores na coleta.

XML sem Espaços de Nomes

Todos os exemplos do tutorial usam espaços de nomes XML, pois o uso dos espaços de nomes é geralmente considerado uma boa prática para troca de dados. Se quiser trabalhar com XML sem espaços de nomes, você pode usar um atributo namespace-style="none" em qualquer nível das customizações para desativar espaços de nomes completamente para todos os componentes aninhados.

As customizações da Listagem 11 também definem o namespace a serem usados em documentos XML. Os exemplos anteriores dependem da manipulação de espaços de nomes de BindGen padrão, que é derivar a URI do namespace usada na representação XML do código Java do pacote Java. Essa manipulação padrão converteu o pacote org.jibx.starter para a URI do namespace http://jibx.org/starter. Na Listagem 11, o namespace é customizado incluindo um par de atributos — namespace="http://jibx.org/custom" e namespace-style="fixed" — no elemento raiz <custom> . O primeiro desses atributos define o namespace base, enquanto que o segundo evita o comportamento normal da modificação do namespace baseado no pacote Java. Esses atributos são ambos herdados através do aninhamento dos elementos de customização, portanto, eles podem ter sido colocados no elemento <package> em vez do elemento <custom> .

Você pode testar as customizações da Listagem 11 usando o destino Ant custgen3 para a ligação e geração do esquema e o destino run3 para executar um teste (após usar o destino bind padrão para executar o compilador de ligação JiBX — ou simplesmente use o destino full3 para realizar toda a sequência). A Listagem 12 mostra o documento de entrada usado com o código de teste:

Listagem 12. Amostra de XML com Nomes e Namespace Customizados
<order order-date="2008-10-18" ship-date="2008-10-22" xmlns="http://jibx.org/custom">
  <order-num>12345678</order-num>
  <customer>
    <customer-number>5678</customer-number>
    <first-name>John</first-name>
    <last-name>Smith</last-name>
  </customer>
  <bill-to state="WA" post-code="98059">
    <street1>12345 Happy Lane</street1>
    <city>Plunk</city>
    <country>USA</country>
  </bill-to>
  <shipping>PRIORITY_MAIL</shipping>
  <ship-to state="WA" postCode="98034">
    <street1>333 River Avenue</street1>
    <city>Kirkland</city>
  </ship-to>
  <order-items>
    <line-item quantity="1" price="5.99" id="AC4983498512"/>
    <line-item quantity="2" price="9.50" id="IW2349050499"/>
    <line-item quantity="1" price="8.95" id="RC3000488209"/>
  </order-items>
</order>

Se você comparar a Listagem 12 com a amostra da Listagem 10 , você verá como a representação foi alterada pelas customizações mais recentes.

Customizando as Representações do Esquema

Agora você viu como as customizações de BindGen podem alterar a representação XML de seus dados Java. As customizações também podem ser usadas para controlar alguns aspectos da estrutura real do esquema.

Lembre-se de que BindGen usa como padrão as definições aninhadas na preferência para tipos e elementos globais. Se você rever o esquema gerado na Listagem 9 , você verá essa estrutura de aninhamento. O esquema usa somente três definições globais: os tipos complexos address eorder e o elemento order . As outras classes da estrutura de dados Java (Customer, Item e Shipping) são referidas, cada uma, em somente um ponto da classe Order , portanto, as definições de tipo correspondente são integradas diretamente na definição de tipo de esquema order .

É possível alterar o estilo do esquema usando um atributo force-mapping="true" em qualquer um dos elementos de customização aninhados. A Listagem 13 mostra o arquivo de customizações custom4.xml, que inclui essa alteração nas customizações de custom2.xml correspondentes ao esquema gerado na Listagem 9 :

Listagem 13. Customização para a Estrutura do Esquema
<custom property-access="true" force-mapping="true">
  <package name="org.jibx.starter">
    <class name="Address" includes="street1 street2 city @state @postCode country"
        requireds="street1 city"/>
    <class name="Customer" includes="customerNumber firstName lastName"
        requireds="lastName firstName /customerNumber"/>
    <class name="Item" excludes="description" requireds="@id quantity price"/>
    <class name="Order" requireds="/orderNumber customer billTo shipping orderDate"/>
  </package>
</custom>

A Listagem 14 mostra a estrutura do esquema resultante (gerado como starter.xsd executando o destino Ant custgen4 ). Essa versão do esquema representa a mesma estrutura do documento XML que o esquema da Listagem 9 , mas inclui definições de tipos diferentes que correspondem a cada classe Java.

Listagem 14. Estrutura do Esquema Customizado
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:tns="http://jibx.org/starter" elementFormDefault="qualified"
    targetNamespace="http://jibx.org/starter">
  <xs:simpleType name="shipping">
    <xs:annotation>
      <xs:documentation>Supported shipment methods. The "INTERNATIONAL" shipment
      methods can only be used for orders with shipping addresses outside the U.S., and
      one of these methods is required in this case.</xs:documentation>
    </xs:annotation>
    <xs:restriction base="xs:string">
      ...
    </xs:restriction>
  </xs:simpleType>
  <xs:complexType name="item">
    <xs:annotation>
      <xs:documentation>Order line item information.</xs:documentation>
    </xs:annotation>
    <xs:sequence/>
    <xs:attribute type="xs:string" use="required" name="id"/>
    <xs:attribute type="xs:int" use="required" name="quantity"/>
    <xs:attribute type="xs:float" use="required" name="price"/>
  </xs:complexType>
  <xs:element type="tns:order" name="order"/>
  <xs:complexType name="address">
    <xs:annotation>
      <xs:documentation>Address information.</xs:documentation>
    </xs:annotation>
    <xs:sequence>
      <xs:element type="xs:string" name="street1"/>
      <xs:element type="xs:string" name="street2" minOccurs="0"/>
      <xs:element type="xs:string" name="city"/>
      <xs:element type="xs:string" name="country" minOccurs="0"/>
    </xs:sequence>
    <xs:attribute type="xs:string" name="state"/>
    <xs:attribute type="xs:string" name="postCode"/>
  </xs:complexType>
  <xs:complexType name="customer">
    <xs:annotation>
      <xs:documentation>Customer information.</xs:documentation>
    </xs:annotation>
    <xs:sequence>
      <xs:element type="xs:long" name="customerNumber"/>
      <xs:element type="xs:string" name="firstName"/>
      <xs:element type="xs:string" name="lastName"/>
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="order">
    <xs:annotation>
      <xs:documentation>Order information.</xs:documentation>
    </xs:annotation>
    <xs:sequence>
      <xs:element type="xs:long" name="orderNumber">
        <xs:annotation>
          <xs:documentation>Get the order number.</xs:documentation>
        </xs:annotation>
      </xs:element>
      <xs:element type="tns:customer" name="customer"/>
      <xs:element type="tns:address" name="billTo"/>
      <xs:element type="tns:shipping" name="shipping"/>
      <xs:element type="tns:address" name="shipTo" minOccurs="0"/>
      <xs:element type="tns:item" name="item" minOccurs="0" maxOccurs="unbounded"/>
    </xs:sequence>
    <xs:attribute type="xs:date" use="required" name="orderDate"/>
    <xs:attribute type="xs:date" name="shipDate"/>
    <xs:attribute type="xs:float" name="total"/>
  </xs:complexType>
</xs:schema>

Os esquemas do tipo mostrado na Listagem 14, chamados de esquemas de estilo "Veneziana", são populares para uso com definições de estrutura XML complexas. Separando cada definição de tipo, esse estilo de esquema permite reutilizar facilmente as estruturas de componentes ao modificar ou estender um esquema. A flexibilidade do estilo Veneziana provavelmente não é importante se você simplesmente planejar usar seu código Java como a base para quaisquer mudanças adicionais (retornando BindGen toda vez que seu código for alterado), mas pode ser bom se você tiver a intenção de usar o esquema como base para desenvolvimento adicional.


Parâmetros da Linha de Comando de BindGen

BindGen suporta diversos parâmetros de linha de comando além dos usados no código do tutorial. A Tabela 1 lista as opções mais importantes:

Tabela 1. Opções da Linha de Comando de BuildGen
ComandoPropósito
-b nameNome do arquivo de definição de ligação da raiz gerada (nome padrão é binding.xml)
-c pathCorreção para inserir arquivo de customizações
-n uri=name,...Fornecer pares de URI do namespace do esquema e nome de arquivo (o padrão é gerar nomes de arquivos a partir de URIs do namespace do esquema)
-p path,...Caminhos para carregar arquivos de classe Java (o padrão é o caminho de classe usado para executar BindGen)
-s path,...Caminhos para carregar arquivos de origem Java (origem não é usada por padrão)
-t pathCaminho do diretório de destino para saída gerada (o padrão é o diretório atual)
-wLimpe todos os arquivos do diretório de destino antes de gerar a saída (ignorado se o diretório de destino for o mesmo que o diretório atual)

Você também pode passar customizações globais para BindGen como parâmetros da linha de comando, sem a necessidade de criar um arquivo de customizações, usando -- como um prefixo especial para o valor do atributo de customização. Portanto, para configurar as mesmas opções globais que as usadas nas customizações da Listagem 13 , você inclui --property-access=true --force-mapping=true na linha de comando de BindGen. Aspas não são necessárias para o valor do atributo quando você usa essa técnica. Se quiser configurar uma customização que aceita uma lista de diversos valores, simplesmente use vírgulas em vez de espaços como separadores entre os valores individuais (portanto, para ignorar os prefixos m_ e s_ nos nomes de campo, por exemplo, você usaria o parâmetro da linha de comando --strip-prefixes=m_,s_).


Indo Além

Neste tutorial, você aprendeu o básico de como usar JiBX para gerar uma definição de esquema XML a partir de seu código Java e, em seguida, converter documentos que correspondem ao esquema para e a partir das estruturas de dados Java. Há muitas outras customizações que você pode usar para controlar a geração de esquema, além das que cobri neste tutorial. A documentação de JiBX fornece detalhes integrais sobre todas essas opções de customização, juntamente com mais exemplos de geração de esquema a partir de código.

Você pode ir mais além com JiBX trabalhando com as definições de ligação reais, que fornecem controle sobre cada etapa do processo de conversão. Você pode facilmente incluir seu próprio código para seu executado como parte das conversões, usando ganchos de extensão do usuário integrados às definições de ligação. Você pode até mesmo criar seu próprio código customizado de serialização e desserialização que pode, seletivamente, assumir controle do código gerado por JiBX para tratar de estruturas de dados XML ou Java exclusivas. A documentação de JiBX inclui um tutorial que ilustra muitos aspectos de trabalhar com definições de ligação, incluindo esses recursos de extensão, juntamente com a documentação de referência para todos os detalhes.

JiBX é especialmente conveniente quando você deseja desenvolver uma definição de esquema rapidamente para troca de dados sem precisar aprender muito sobre o esquema. O padrão do Esquema XML é complexo e ferramentas para trabalhar com definições de esquema fornecem pouco suporte para reestruturar e refatorar esquemas. Usando código Java e BindGen como base para o desenvolvimento de seu esquema conforme mostrado neste tutorial, você pode aplicar toda a flexibilidade de IDEs de Java para criar definições de esquema de forma rápida e fácil sem, de alguma forma, se comprometer a usar JiBX.

JiBX também inclui uma ferramenta para gerar definições completas de WSDL e esquema para serviços da Web baseados em código Java. Essa ferramenta, denominada Jibx2Wsdl, é baseada em BindGen. Você pode usar todas as customizações de BindGen discutidas neste artigo para as classes de dados usadas como entradas e saídas para seus métodos de servi;co, de forma que o esquema gerado reflita suas preferências. A documentação de JiBX fornece detalhes sobre como usar Jibx2Wsdl.

Na Parte 2, você aprenderá como usar JiBX para gerar código Java a partir de definições de esquema XML.


Download

DescriçãoNomeTamanho
Sample code for this tutorialj-jibx1.zip13KB

Recursos

Aprender

Obter produtos e tecnologias

  • JiBX: Faça download de JiBX.
  • Ant: Faça download de Apache Ant.
  • Sun JDK 1.5 ou posterior: Você precisará de pelo menos a versão 1.5.0_09 para seguir os exemplos deste tutorial.
  • IBM® developer kits: IBM Java developer kits estão disponíveis para AIX e Linux.

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=387131
ArticleTitle=JiBX 1.2, Parte 1: Código Java para Esquema XML
publish-date=03032009