Guia para JAXB

Guia para JAXB

1. Introdução

Este é um artigo introdutório sobre JAXB (Java Architecture for XML Binding).

Primeiro, mostraremos como converter objetos Java em XML e vice-versa, e depois nos concentraremos na geração de classes Java a partir do esquema XML e vice-versa usando o plugin JAXB-2 Maven.

2. Visão geral

O JAXB fornece uma maneira rápida e conveniente de empacotar objetos Java em XML e descompactar (ler) XML em objetos. Ele suporta uma estrutura de ligação que mapeia elementos e atributos XML para campos e propriedades Java usando anotações Java.

O plugin JAXB-2 Maven delega a maior parte de seu trabalho a qualquer uma das duas ferramentas fornecidas pelo JDKXJCeSchemagen.

3. Anotações JAXB

O JAXB usa anotações Java para aumentar as classes geradas com informações adicionais. A inclusão de tais anotações em classes Java existentes as prepara para o tempo de execução JAXB.

Vamos primeiro criar um objeto Java simples para ilustrar o marshalling e o desempacotamento:

@XmlRootElement(name = "book")
@XmlType(propOrder = { "id", "name", "date" })
public class Book {
    private Long id;
    private String name;
    private String author;
    private Date date;

    @XmlAttribute
    public void setId(Long id) {
        this.id = id;
    }

    @XmlElement(name = "title")
    public void setName(String name) {
        this.name = name;
    }

    @XmlTransient
    public void setAuthor(String author) {
        this.author = author;
    }

    // constructor, getters and setters
}

A classe acima acima contém as seguintes anotações:

  • @XmlRootElement: to nome do elemento raiz XML é derivado do nome da classe e também podemos especificar o nome do elemento raiz do XML usando seu atributo name

  • @XmlType: define a ordem em que os campos são escritos no arquivo XML

  • @XmlElement: define o nome real do elemento XML que será usado

  • @XmlAttribute: define que o campo id é mapeado como um atributo ao invés de um elemento

  • @XmlTransient: anota campos que não queremos incluir no XML

Para obter mais detalhes sobre a anotação JAXB, você pode verificar o seguintelink.

4. Marshalling - convertendo objeto Java em XML

A Marshalling fornece a um aplicativo cliente a capacidade de converter uma árvore de objetos Java derivada de JAXB em dados XML. Por padrão, oMarshaller usa a codificação UTF-8 ao gerar dados XML. Em seguida, geraremos arquivos XML a partir de objetos Java.

Vamos criar um programa simples usandoJAXBContext que fornece uma abstração para gerenciar as informações de ligação XML / Java necessárias para implementar as operações da estrutura de ligação JAXB:

public void marshal() throws JAXBException, IOException {
    Book book = new Book();
    book.setId(1L);
    book.setName("Book1");
    book.setAuthor("Author1");
    book.setDate(new Date());

    JAXBContext context = JAXBContext.newInstance(Book.class);
    Marshaller mar= context.createMarshaller();
    mar.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
    mar.marshal(book, new File("./book.xml"));
}

A classejavax.xml.bind.JAXBContext fornece um ponto de entrada do cliente para a API JAXB. Por padrão, o JAXB não formata o documento XML. Isso economiza espaço e evita que qualquer espaço em branco seja acidentalmente interpretado como significativo.

Para que o JAXB formate a saída, simplesmente definimos a propriedadeMarshaller.JAXB_FORMATTED_OUTPUT paratrue emMarshaller. O método marshal usa um objeto e um arquivo de saída onde armazenar o XML gerado como parâmetros.

Quando executamos o código acima, podemos verificar o resultado embook.xml para verificar se convertemos com êxito o objeto Java em dados XML:



    Book1
    2016-11-12T11:25:12.227+07:00

5. Un-marshalling - convertendo XML em objeto Java

A remoção do empacotamento fornece a um aplicativo cliente a capacidade de converter dados XML em objetos Java derivados do JAXB.

Vamos usar JAXBUnmarshaller para desempacotar nossobook.xml de volta para um objeto Java:

public Book unmarshall() throws JAXBException, IOException {
    JAXBContext context = JAXBContext.newInstance(Book.class);
    return (Book) context.createUnmarshaller()
      .unmarshal(new FileReader("./book.xml"));
}

Quando executamos o código acima, podemos verificar a saída do console para verificar se convertemos dados XML com êxito em um objeto Java:

Book [id=1, name=Book1, author=null, date=Sat Nov 12 11:38:18 ICT 2016]

6. Tipos de dados complexos

Ao manipular tipos de dados complexos que podem não estar diretamente disponíveis no JAXB, podemos escrever um adaptador para indicar ao JAXB como gerenciar um tipo específico.

UsandoXmlAdapter de JAXB, podemos definir um código personalizado para converter uma classe não mapeável em algo que JAXB pode manipular. A anotação@XmlJavaTypeAdapter usa um adaptador que estende a classeXmlAdapter para empacotamento personalizado.

Vamos criar um adaptador para especificar um formato de data ao empacotar:

public class DateAdapter extends XmlAdapter {

    private static final ThreadLocal dateFormat
      = new ThreadLocal() {

        @Override
        protected DateFormat initialValue() {
            return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        }
    };

    @Override
    public Date unmarshal(String v) throws Exception {
        return dateFormat.get().parse(v);
    }

    @Override
    public String marshal(Date v) throws Exception {
        return dateFormat.get().format(v);
    }
}

Usamos um formato de data “yyyy-MM-dd HH:mm:ss” para converterDate emString ao empacotar eThreadLocal para tornar nossoDateFormat thread-safe.

Vamos aplicar oDateAdapter ao nossoBook:

@XmlRootElement(name = "book")
@XmlType(propOrder = { "id", "name", "date" })
public class Book {
    private Long id;
    private String name;
    private String author;
    private Date date;

    @XmlAttribute
    public void setId(Long id) {
        this.id = id;
    }

    @XmlTransient
    public void setAuthor(String author) {
        this.author = author;
    }

    @XmlElement(name = "title")
    public void setName(String name) {
        this.name = name;
    }

    @XmlJavaTypeAdapter(DateAdapter.class)
    public void setDate(Date date) {
        this.date = date;
    }
}

Quando executamos o código acima, podemos verificar o resultado embook.xml para verificar se convertemos com sucesso nosso objeto Java em XML usando o novo formato de data “yyyy-MM-dd HH:mm:ss“:



    Book1
    2016-11-10 23:44:18final

7. Plug-in JAXB-2 Maven

Este plug-in usa a API Java para ligação em XML (JAXB), versão 2+, para gerar classes Java a partir de esquemas XML (e, opcionalmente, arquivos de ligação) ou para criar esquema XML a partir de uma classe Java anotada.

Observe que existem duas abordagens fundamentais para construir serviços da web,Contract LasteContract First. Para obter mais detalhes sobre essas abordagens, você pode verificar o seguintelink.

7.1. Gerando uma classe Java a partir de XSD

O plug-in JAXB-2 Maven usa a ferramenta fornecida pelo JDK XJC, uma ferramenta do compilador JAXB Binding que gera classes Java a partir do XSD (XML Schema Definition).

Vamos criar um arquivouser.xsd simples e usar o plugin JAXB-2 Maven para gerar classes Java a partir deste esquema XSD:




    
    

    
        
            
            
        
    

    
        
            
            
            
            
        
    

Vamos configurar o plugin JAXB-2 Maven:


    org.codehaus.mojo
    jaxb2-maven-plugin
    2.3
    
        
            xjc
            
                xjc
            
        
    
    
        
            src/main/resources/global.xjb
        
        
            src/main/resources/user.xsd
        
        ${basedir}/src/main/java
        false
    

Por padrão, este plugin localiza arquivos XSD emsrc/main/xsd. Podemos configurar a pesquisa XSD modificando a seção de configuração deste plugin nopom.xml de acordo.

Por padrão, essas classes Java são geradas na pastatarget/generated-resources/jaxb. Podemos mudar o diretório de saída adicionando um elementooutputDirectory à configuração do plugin. Também podemos adicionar um elementoclearOutputDir com um valor false para evitar que os arquivos neste diretório sejam apagados.

Também podemos configurar uma ligação JAXB global que substitui as regras de ligação padrão:




    
        
        
        
    

Oglobal.xjb acima substitui o tipodateTime pelo tipojava.util.Calendar. Quando construímos o projeto, ele gera arquivos de classe na pastasrc/main/javae no pacotecom.example.jaxb.gen.

7.2. Gerando Esquema XSD de Java

O mesmo plug-in usa a ferramenta fornecida pelo JDKSchemagen. Esta é uma ferramenta do compilador JAXB Binding que pode gerar um esquema XSD a partir de classes Java. Para que uma classe Java seja elegível para um candidato a esquema XSD, a classe deve ser anotada com uma anotação@XmlType.

Reutilizamos os arquivos de classe Java do exemplo anterior. Vamos configurar o plugin:


    org.codehaus.mojo
    jaxb2-maven-plugin
    2.3
    
        
            schemagen
            
                schemagen
            
        
    
    
        
            src/main/java/com/example/jaxb/gen
        
        src/main/resources
        false
        
            
                /jaxb/gen
                user
                user-gen.xsd
            
        
    

Por padrão, o JAXB verifica todas as pastas emsrc/main/java recursivamente em busca de classes JAXB anotadas. Podemos especificar uma pastasource diferente para nossas classes anotadas JAXB adicionando um elementosource à configuração do plug-in.

Também podemos registrar umtransformSchemas, um pós-processador responsável por nomear o esquema XSD. Ele funciona combinandonamespace com o namespace de@XmlType de sua classe Java.

Quando construímos o projeto, ele gera um arquivouser-gen.xsd no diretóriosrc/main/resources.

8. Conclusão

Neste artigo, abordamos conceitos introdutórios no JAXB. Para obter detalhes, podemos dar uma olhada emJAXB home page.

Podemos encontrar o código-fonte deste artigo emGitHub.