JAXB – XML e Java de mãos dadas
Postado em 27. fev, 2008 por Guilherme de Almeida Moreira em Java
Você já participou de um projeto que precisou ler um arquivo de configuração em xml? Já precisou consumir um xml e transformá-lo em objeto? O que você usou? Quem já trabalhou com xml sabe da dificuldade que podemos encontrar pelo caminho, e é esse tipo de dificuldade que a especificação Java Architecture for XML Binding ou simplesmente JAXB tenta resolver.
Imagine a seguinte situação: Precisarmos enviar os dados contidos em um objeto para um outro servidor. Temos muitas opções para fazer o envio, como por exemplo colocar essas informações em um arquivo de texto seguindo uma máscara pré-definida. Porém apenas as aplicações que conhecessem essa máscara entenderiam os dados, e perdemos portabilidade. Usando xml a situação já é outra: qualquer aplicação, independende de linguagem, entenderá os dados contidos no arquivo xml.
Antes de falarmos sobre o JAXB vamos primeiro conferir alguns conceitos:
XML
XML é uma linguagem de marcação que serve para guardar dados de uma forma estruturada. Essa estrutura é definida pelo próprio usuário ou por um schema. Um xml é um arquivo de texto puro, portanto independente de plataforma, por isso é muito utilizado para transmitir dados entre diferentes aplicações e sistemas. Exemplo:
carro.xml
<?xml version="1.0" encoding="UTF-8"?>
<carro>
<nome>Fusca</nome>
<portas>2</portas>
<motoristas>
<motorista>
<nome>Guilherme</nome>
</motorista>
<motorista>
<nome>Leonardo</nome>
</motorista>
</motoristas>
</carro>
XSD
XSD é o schema citado na seção anterior, ele define quais são as regras que a estrutura do xml deve seguir, possibilitando a validação desse xml. Exemplo:
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="carro" type="Carro" />
<xsd:complexType name="Carro">
<xsd:sequence>
<xsd:element name="nome" type="xsd:string" minOccurs="1"
maxOccurs="1" nillable="false"/>
<xsd:element name="portas" type="xsd:int" minOccurs="1"
maxOccurs="1" nillable="false"/>
<xsd:element name="motoristas" type="Motorista" minOccurs="0"
maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="Motorista">
<xsd:sequence>
<xsd:element name="nome" minOccurs="1" maxOccurs="1"
type="xsd:string" nillable="false"/>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
O primeiro ponto da especificação apresenta uma ferramenta chamada Binding Compiler, cuja função é transformar um xsd em um conjunto de classes que tenham uma estrutura compatível com a estrutura do xml que esse xsd define.
No XSD de exemplo definimos a seguinte estrutura: Um elemento carro deve ter um elemento nome e um elemento motoristas (do tipo Motorista), seguindo essa ordem, primeiro nome e depois motoristas. Depois definimos o tipo Motorista que deve conter apenas um nome.
O Binding Compiler é independente da implementação do JAXB, ou seja, quem define como ele será executado é quem implementa a especificação, porém a maioria e inclusive a própria RI(Reference Implementation) cria um comando que pode ser chamado pela linha de comando do Sistema Operacional, o xjc. Por exemplo no Linux:
xjc carro.xsd -d src -p br.com.caelum
Se você já está usando o Java 6, o JAXB já vêm junto com o JDK.
Com esse comando o Binding Compiler gera três classes: Carro.java, Motorista.java e a ObjectFactory.java. As classes Carro e Motorista seguem a estrutura do xsd.
Gerando e Lendo XML
A segunda parte da especificação define o que temos que fazer para transformar objetos em xml e vice-versa. A API do JAXB é quem se responsabiliza por essas transformações.
Transformando objetos em xml
O processo de transformar um objeto em xml é chamado de Marshal. Com o JAXB para transformar um objeto em xml precisamos de um JAXBContext, esse context é quem fornecerá o Marshaller. O Marshaller é quem finalmente transforma um objeto (JAXBElement) em xml. O JAXBElement contém o objeto de verdade a ser serializado e algumas propriedades do xml. É aqui que entra a importância do ObjectFactory criado pelo Binding Compiler, ele é responsável por criar uma instância do JAXBElement apropriada para o tipo de objeto a ser serializado.
JAXBContext context = JAXBContext.newInstance("br.com.caelum");
Marshaller marshaller = context.createMarshaller();
JAXBElement<Carro> element = new ObjectFactory().createCarro(carro);
marshaller.marshal(element, System.out);
Parseando xml em objetos java
Para fazer o caminho contrário, ou seja popular um objeto java com dados de um xml também precisamos de um JAXBContext, porém agora temos que pegar um Unmarshaller. O Unmarshaller recebe um arquivo xml e devolve um JAXBElement contendo um objeto populado.
JAXBContext context = JAXBContext.newInstance("br.com.caelum");
Unmarshaller unmarshaller = context.createUnmarshaller();
JAXBElement<Carro> element = (JAXBElement<Carro>) unmarshaller.unmarshal(new File("resources/carro.xml"));
Carro carro = element.getValue();
Conclusão
O JAXB facilita muito a vida dos programadores java, fazendo o consumo e criação de xml menos trabalhosos. Essa API também fornece outros recursos como, validação, geração de schema (a partir de classes java, cria um xsd), opções para trabalhar com Namespace e etc. Comente nesse post outras oções do JAXB e outras bibliotecas que você usa no seu dia-a-dia.
Guilherme de Almeida Moreira
Mais sobre o autor
23 Respostas para “JAXB – XML e Java de mãos dadas”
Trackbacks/Pingbacks
-
-
dezembro 15, 2009
[...] que esta anotação não é a responsável por serializar o objeto no formato XML. O JAX-RS usa o JAX-B como serializador padrão, basta para isso colocar a anotação @XmlRootElement na classe desejada, [...]
ASSINE NOSSO RSS




Rafael Naufal
27. fev, 2008
Ótimo post! Já usei também uma implementação open source da JAXB API, chamada JaxMe. Segue a mesma linha de manipulação de xml’s, por meio de Marshalling e UnMarshalling. XStream também é uma API interessante para serializar e deserializar objetos em XML também.
Leandro Silva
27. fev, 2008
Costumo usar o XStream, mas à vezes me deparo com algumas limitações. Algumas vezes já pensei em usar JAXB, mas o fato de ter que escrever um XSD e a partir dele gerar as classes, me desanimou um pouco. Mas outro dia desses, por conta de um XML fora do padrão que foi estabelecido aqui na empresa, acabei voltando a considerar o JAXB, justamente por causa do XSD.
Bem, de qualquer forma, já tenho uns 10 serviços trabalhando com XStream.
Eloy Lima
29. fev, 2008
Ótimo post! À alguns dias utilizei o xstream com Alias para ler serviços do Yahoo, tanto XML quanto JSON e achei a programação muito simples.
Bruno Pereira
12. mar, 2008
Eu uso XStream quase sempre, principalmente em web services REST. Para a maioria dos casos o simples uso de aliases dá conta do recado. Para situações mais complicadas eu normalmente implemento converters. Ainda não me deparei com nenhum mapeamento que eu não conseguisse fazer usando converters.
O XStream é tão fácil e flexível que eu tenho uma tremenda má vontade pra avaliar qualquer outra forma de binding
Para implementar web services WS-* eu utilizei o Axis 2 com Axis Data Binding na maioria das vezes. Ele gera uma estrutura horripilante para fazer os mapeamentos e validações, mas o desenvolvedor não precisa tocar nisso.
Para XML de uma maneira geral, XStream all the way
Luiz Gustavo
13. mar, 2008
Pois é, esse negócio de gerar Object Factory não gostei não, é uma boa, mas devia ter uma versão mais simples para se fazer como é XStream.
Joao Paulo
11. abr, 2008
Olá.. legal o tuto, mas…
porque eu usaria JAXB ao invés do XStream, sendo este último mais transparente e fácil??
jopss
maxwell
16. abr, 2008
tb utilizo o XStream….com as anotações fica muito simples criar a estrutura do xml….
Gustavo Touzo
16. mai, 2008
Alguém sabe como posso pegar os feriados que possam estar dentro do projeto ?
Gustavo Touzo
16. mai, 2008
Alguém sabe como posso pegar os feriados que possam estar dentro do projeto ?
meu e-mail: gtouzo@click21.com.br
Paulo Suzart
03. jul, 2008
Olá a todos,
uma pequena diferença, ao menos ao fazer a implementação aqui no projeto é que ao fazer o unmarshal, fizemos o cast direto para a entidade JAXB:
…
Carro carro = (Carro) un.unmarshal(new File(“resources/carro.xml”);
…
Ao tentar usar o unmarshal com JAXBElement, recebemos um class cast exception.
Abraços
julio khichfy
28. ago, 2008
HUMMMM
vou ter que usar o JAXB
valeu pelo começo!!!
Gustavo Touzo
15. set, 2008
Estou tendo um erro de caracter inválido ao ler ao fazer o unmarshal de um XML que segue o esquema do Project. Alguém sabe dizer o que pode ser ?
Claudson
03. out, 2008
Com o XStream eu não consigo fazer o marshal a partir de um XSD:
“Can XStream generate classes from XSD?
No. For this kind of work a data binding tool such as XMLBeans is appropriate.”
http://xstream.codehaus.org/faq.html
Sueli
11. nov, 2008
Estou utilizando o JAXB, mas meu arquivo gera sempre com ns2: na frente, alguem sabe se tem algo para que eu tire estes ns3 que aparece na frente ex:
001
37754
VENDAS
1
55
Alguem sabe como tirar ?
Dante
25. nov, 2008
Muito bom amigo… aprendi a usar a ferramenta… fácil e rápido, eu queria mesmo eh gerar as classes apartir do XDS!
Abraçosss
Eder Ignatowicz
19. jan, 2009
Muito obrigado pela ajuda.
isaias
19. fev, 2009
Conforme comentários de sueli, existe esse problema de ser gerado sempre :ns2 no namespace do xml, dependendo de como será lido, isso pode gerar problemas.
A solução que achei na web pode ser uma GAMBI, segue link:
http://www.guj.com.br/posts/list/83758.java
Ou então um código gambiarrento que resolve o problema tbm
// Passe o arquivo gerado por parametro e depois remova o ns2 abertura e fechamento
public void ajustaXml(File file) throws Exception {
FileReader reader = new FileReader(file);
BufferedReader leitor = new BufferedReader(reader);
leitor.read();
String vlr = “”;
StringBuffer vlrFile = new StringBuffer();
String line = leitor.readLine();
while(line != null) {
vlrFile.append( line );
line = leitor.readLine();
}
vlr = vlrFile.toString();
// aqui acontece a gambi… temporariamente resolve o problema
if (vlr.indexOf(“ns2:”) > -1) {
vlr = vlr.replaceAll(“ns2:”, “”);
}
if (vlr.indexOf(“:ns2″) > -1) {
vlr = vlr.replaceAll(“:ns2″, “”);
}
leitor.close();
reader.close();
FileWriter writer = new FileWriter(file);
PrintWriter saida = new PrintWriter(writer);
saida.print( “<” + vlr);
writer.close();
saida.close();
}
Zaqueu
22. mai, 2009
Galera precisava elaborar um trabalho sobre o JAXB mais não tenho nem idéia do que seja isso e os arquivos que achei na internet estão todos em inglês. Alguém pode me dar uma mãozinha com um link ou algo do tipo?!
Valew…
saisso
16. jun, 2009
Obrigado pelo post
dcbasso
28. jul, 2009
Tem como resolver o mesmo problema acima com menos gambi…
Tem umas anotacoes nas classes geradas que da problemas… inclusive uma anotacao localizada na package-info.java…
ABRACOS
Mateus Leal
05. nov, 2011
Olá, alguem poderia me passar um tutorial (em portugues de preferencia) de como usar a classe XStrean, estou precisando apenas ler dados em arquivos XML e depois armazenar dinovo nos mesmos arquivos lidos (caso mude algum valor). Obrigado
Fi
19. dez, 2011
Para quem precisar apenas processar um XML e extrair dados diretamente dele, sem transformar em objetos, a melhor biblioteca que eu já vi é a JDOM!
http://www.jdom.org/