Aprendendo Apache XMLBEANS

No mundo J2EE, o poderoso xml está cada vez mais presente, e sendo representado e utilizado de diversas formas e tecnologias,

  • podendo ser através de web-services,
  • como camada middleware representando entidade comum para comunicação de sistemas;
  • ou mesmo como dados em ambientes de integração;

e é nesse mundo que entra os XMLBEANS.

A idéia XMLBEAN foi desenvolvida pela BEA Systems , sendo utilizada como recurso na maioria de seus produtos; em Setembro de 2003 a tecnologia foi doado para a Apache para ela dar continuidade ao projeto.

Aprendendo XMLBEANS

O XMLBean é uma maneira de representar e manipular dados e documentos em XML através do Java.

O foco principal de um XMLBEAN é um XML Schema ( arquivo XSD ). No arquivo XSD é definido como os dados são representados indicando os seus atributos e também sua tipagem.

A idéia aqui é a mesma de quando você escreve o codigo em um arquivo TLD para criar uma nova TAG JSP.

No TLD você descreve como deve funcionar, "quais são as regras a seguir" ;; e no JSP voce simplesmente utiliza a tag.

É através dos Schemas (XSD) é que os dados serão ?instanciados? e serão representados em arquivos XML.

Pensemos da seguinte maneira:: "O XSD é a classe e o xml é o objeto da classe"

Imagine sua classe Vo chamado Pessoa com os atributos nome e sobrenome:

Mãos a obra, vamos programar:

public class Pessoa{

private String nome;
private String sobrenome;

public String getNome(){
peturn nome;
}

public String getSobrenome(){
return sobrenome;
}

public void setNome(String paramNome){
nome = paramNome;
}

public void setSobrenome(String paramSobrenome){
sobrenome = paramSobrenome;
}
}

Agora vamos criar uma instância da classe Pessoa:

Pessoa pessoa = new Pessoa();
Pessoa.setNome("Fulano");
Pessoa.setSobrenome("de Tal"); 

Quando criamos um objeto de uma determinada classe, especificamente falando de VOs, estamos criando uma estrutura e um comportamento predefinido pela classe, ou seja, através dos códigos acima voce tem o objeto pessoa que está guardando a informação ?Fulano? e ?de Tal? em seus atributos Nome e Sobrenome respectivamente e seguindo exatamente as normas regidas pela sua classe.

Agora faremos a mesma coisa utilizando XMLBEANS.

Definindo sua "Classe"

Quando voce escreve um Vo… voce começa escrevendo a classe com seus atributos e métodos get e set para cada atributo…

É isso que faremos agora…

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema targetNamespace="http://openuri.org/easypo" 
xmlns:po="http://openuri.org/easypo"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified">

<xs:element name="Pessoa">
<xs:complexType>
<xs:sequence>
<xs:element name="nome" type="xs:string"/>
<xs:element name="sobrenome" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>

Credo!!! meu Deus!! O que é isso aí em cima??? Isso aí em cima é um arquivo XSD ( Schema ) nele percebemos a definição do nome da classe ?Pessoa? como um elemento principal e dentro do corpo é definido propriedades ?também elemento? que representa os atributos da nossa classe Pessoa para só depois fechar o elemento principal “Pessoa”.

Não se preocupe com a sintaxe e definição das tags, pois raramente vai criar um xsd na mão a partir do zero. Existem ferramentas para geração do arquivo, o foco aqui é entender a idéia do que é um xsd.

Instanciando um objeto da classe Pessoa

Agora faremos uma instância da nossa classe e atribuiremos informação aos atributos do nosso objeto .

<po:Pessoa xmlns:po="http://openuri.org/easypo">
<po:Pessoa>
<po:nome>Fulano</po:nome>
<po:sobrenome>de Tal</po:sobrenome>
</po:Pessoa>
</po:Pessoa>

Vemos no xml acima que ele segue as normas regidas pelo xsd (“classe”) e que a propriedade ?po:nome? tem o conteúdo ?Fulano? e a propriedade ?po:sobrenome? tem o conteúdo ?de Tal? e ambos estão cobertos pelo emento principal chamado Pessoa.

Acessando atributos do objeto

Da mesma maneira que invoco get e set do meu objeto Vo em Java eu também posso acessar e alterar meu XMLBEAN.

Carregando xml…

PessoaDocument pesDoc = PessoaDocument.Factory.parse(new File("Pessoa.xml"));
Pessoa pes = pesDoc.getPessoa();

Acima temos um objeto principal representando o documento e só através dele é que pegamos o objeto Vo.
… pegando dados

pes.getNome();
pes.getSobrenome();

… alterando dados

pes.setNome( ?ciclano?);

Ei??? é igual ao VO Java??? é fácil assim??? cadê o SAX e o DOM??? Sim meu pequeno gafanhoto é tão fácil quanto.
No Java eu posso dar um new e criar um novo objeto a qualquer momento e em xmlBean como eu faço isso???

PessoaDocument pesDoc = PessoaDocument.Factory.newInstance();
Pessoa novaPessoa = PessoaDocument.addNewPessoa();

Pronto… agora é só aplicar get e set sobre o objeto novaPessoa… igual voce faria em um objeto Vo comum.

Vantagens e desvantagens

Ei??? Qual é a vantagem do xmlbean sobre o meu Vo java comum???

Bom, acredito que o arquivo xml é muito mais portável que o objeto Vo java type… pois pode ser acessado a qualquer momento e por qualquer aplicação aonde quer que ela esteja; em outro contexto; em outro servidor; em outra rede; em outro continente… aff exagerei!!! rsrrs e também seguindo as regras definidas por voce no seu Schema ( XSD)

Uhnnn ahh legal!!! Intão vou trocar todos os meus VOs por xmlbeans???

O fato de carregar e descarregar arquivo xml e ter SAX e DOM para manipulação xml por traz do framework implica em performance em aplicações, portanto a utilização de xmlbeans é encargo do desenvolvedor viabilizando custo/beneficio e visando também o tamanho de sua aplicação.

Acredito que as reais vantagens no emprego de XMLBEANS é quando voce gostaria que um determinado Vo fique disponível para acesso externo independente de tecnologia e local físico/lógico.

Se você realmente se interessou pela tecnologia, por favor não se atenha a esse texto tabajara, prossiga seus estudos através dos links abaixo!!!

Referências

Pagina Apache XMLBeans - Documentação - Tutoriais - Downloads - Exemplos
http://xmlbeans.apache.org

Eclipse plug-in - geração de arquivos xsd / xml / java ( value objects )
http://sourceforge.net/projects/xmlbeansplug

Eclipse Plug-in geracao de arquivos xsd a partir de java code
http://www.java-x.us

Artigo dev2dev BEA ? XMLBEANS - Getting Started
http://e-docs.bea.com/workshop/docs81/doc/en/workshop/guide/xmlbeans/conGettingStartedwithXMLBeans.html



Gabriel Ishigami Solana
SCJP - Sun Certificied Java Programmer
SCWCD - Sun Certificied Web Components Developer
Linux user #440457
http://counter.li.org

Com que finalidade você está usando os beans gerados com o XML Beans?

Opa! Comecei a trabalhar com a plataforma da BEA…

O pessoal usa bastante como parametro de métodos de WebServices…

Ah! Uma outra coisa bacana é fazer transformação de um XML para outro XML com layouts diferentes…

Abaços!

Inútil para web services se você usa algo como Apache Axis ou outro engine.

Como disse sou novo com a plataforma… não podemos julgar só pelas minhas palavras… vamos na fonte…

http://www.bea.com/

Só um detalhe… o WebLogic… usa o Apache Axis como engine…

:lol:

Até+…

http://fragmental.com.br/wiki/index.php?title=Evitando_VOs_e_BOs

Sim, é possível…criar mais de um objeto pessoa

No exemplo eu criei como simple type…
mas voce pode criar mais uma ramificação… e repetir o pessoa… na hora de transformar em objeto java… vai vir como array

Exemplificando::

Veja que voce tem um element persons: que no corpo da tag dele tem uma sequence de elements person

&lt?xml version=“1.0” encoding=“ISO-8859-1”?&gt
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault=“qualified”>

<xs:element name=“persons”>
<xs:complexType>
<xs:sequence>
<xs:element name=“person” maxOccurs=“unbounded”>
<xs:complexType>
<xs:sequence>
<xs:element name=“full_name” type=“xs:string”/>
<xs:element name=“child_name” type="xs:string"
minOccurs=“0” maxOccurs=“5”/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>

</xs:schema>

o xml desse xsd ficaria algo parecido com isso::

&lt?xml version=“1.0” encoding=“ISO-8859-1”?&gt<persons xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation=“family.xsd”><person>
<full_name>Hege Refsnes</full_name>
<child_name>Cecilie</child_name>
</person><person>
<full_name>Tove Refsnes</full_name>
<child_name>Hege</child_name>
<child_name>Stale</child_name>
<child_name>Jim</child_name>
<child_name>Borge</child_name>
</person><person>
<full_name>Stale Refsnes</full_name>
</person></persons>

Complementando…

Para gerar classes Java a partir do XSD

1- Ajustar variaveis de ambiente

export XMLBEANS_HOME=
export PATH=$PATH:$XMLBEANS_HOME/bin
export CLASSPATH=$XMLBEANS_HOME/lib/xbean.jar:$CLASSPATH

2 - Executar comando scomp para gerar classes

Ex::
scomp -out tutorials\gettingstarted\lib\easypo.jar schemas\easypo\easypo.xsd

primeiro parametro é o local e o nome do jar com as classes
segundo parametro é aonde esta o xsd

como eu faço para cria r o PessoaDocument??

Duas maneiras de se obter o objeto pessoa document.

um eh criando um novo xml… e outro ehh carregando um xml jah existente.

Cria um novo xml.

PessoaDocument pesDoc = PessoaDocument.Factory.newInstance(); Pessoa novaPessoa = PessoaDocument.addNewPessoa();

carrega o xml existente.

Olá, galera,

Estou tentando usar o xmlBeans para trabalhar com a NFe, mas estou obtendo um problema com o objeto retornado pelo pelo método parse. Todos os objetos (tags) com exceção do objeto raiz, estão vindo null. Os getters estão obedecendo a estrutura definida pelo XSD, porém estão todos null.

o arquivo xsd que estou usando é o leiauteNFe_v2.00.xsd

se alguém pudar ajudar, agradeço :smiley:

public static void main(String[] args) {
		// TODO Auto-generated method stub
		File file = new File("C:\\Files\\NFEXML.xml");
		try{	
						
		    TNfeProc doc = TNfeProc.Factory.parse(file);
		    System.out.println(doc.getProtNFe());
		    System.out.println(doc.getNFe());		    		    
		    System.out.println(doc.getVersao());
		    
		    /* output:
		     * null
		     * null
		     * null
		     */
		}
		catch(XmlException e){
			e.printStackTrace();
		}
		catch(Exception e){
			e.printStackTrace();
		}

	}

Ola Rafael,

Experimente re-gerar as classes java através do xsd, pode ser que voce tenha alterado a estrutura
e não tenha feito isso.

Escrevi esse tutorial a bastante tempo e hoje existe implementação da própria Sun - chama-se JAXB.

É bem simples, somente algumas nomenclaturas mudam. funciona da mesma forma, após escrever o
xsd é necessário rodar um comando para gerar as classes java.

Exemplos…
http://www.oracle.com/technetwork/articles/javase/index-140168.html

Será que seu arquivo.xml que vc esta fazendo o parse esta sem definições de namespace ou com definições incorretas?

Gabiso, estou tentando usar o JAXB:

public static void main(String[] args) {
		// TODO Auto-generated method stub
		try{
			File file = new File("C:\\Files\\NFEXML.xml");
			JAXBContext context = JAXBContext.newInstance("br.inf.portalfiscal.nfe");
			Unmarshaller un = context.createUnmarshaller();						
			TNfeProc nfe = (TNfeProc) un.unmarshal(file);
			
		}
		catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}	
	}

mas na linha 7 estou obtendo o seguinte erro:

javax.xml.bind.UnmarshalException: unexpected element (uri:"http://www.portalfiscal.inf.br/nfe", local:"nfeProc"). Expected elements are (none)
	at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.handleEvent(UnmarshallingContext.java:631)
	at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:236)
	at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:231)
	at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportUnexpectedChildElement(Loader.java:105)
	at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext$DefaultRootLoader.childElement(UnmarshallingContext.java:1038)
	at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext._startElement(UnmarshallingContext.java:467)
	at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.startElement(UnmarshallingContext.java:448)
	at com.sun.xml.internal.bind.v2.runtime.unmarshaller.SAXConnector.startElement(SAXConnector.java:137)
	at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.startElement(AbstractSAXParser.java:501)
	at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.scanStartElement(XMLNSDocumentScannerImpl.java:400)
	at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl$NSContentDriver.scanRootElementHook(XMLNSDocumentScannerImpl.java:626)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:3095)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$PrologDriver.next(XMLDocumentScannerImpl.java:922)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:648)
	at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:140)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:510)
	at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:807)
	at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:737)
	at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:107)
	at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1205)
	at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:522)
	at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:200)
	at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:173)
	at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:137)
	at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:142)
	at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:151)
	at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:169)
	at jaxb_test.C1.main(C1.java:26)

ei gerei todas as classes a partir de todos os esquemas XSD contidos na pasta PL_006g (a mais recente) do portal da NFe (http://www.nfe.fazenda.gov.br/portal/listaConteudo.aspx?tipoConteudo=/fwLvLUSmU8=)

não estou sabendo como corrigir esse erro. Se alguem puder dar alguma dica, ajudaria muito :smiley:

Criei um tutorial bem simples no meu blog ensinando como começar com xmlbeans.

Segue o link: http://robsonp.com/01/2011/xml-com-xmlbeans/

Valeu

Amigos, pensando em um CTe e usando XMLBEANS, vamos supor que no campo e o valor vá como null, quando eu gero o xml as seguintes tags são marcadas no resultado, onde diz que nas tags do exemplo o valor é null.

Gostaria de saber se existe uma maneira de remover estas tags caso elas sejam null, alguma parametrização no XMLBEAN que me permite configura-lo para mostrar ou não!

O ideal seria estas tags não vir no xml remove-las!

<pag> 
      <cnpj xsi:nil="true"/> 
</pag> 

<receb> 
      <cnpj xsi:nil="true"/> 
</receb>

Obrigado!

Shakall acredito que se você tá gerando os Beans a partir do Schema não tem como você deixar de gerar estas tags. Você terá que fazer a verificação pra ver se é null.

Entendi, puts fods vai dar uma trabalheira!