Olá a todos!
Estou desenvolvendo um sistema que precisa fazer parse de uma grande quantidade de XMLs (alguns gigabytes) e então trabalhar com esses dados. Neste cenário, estou enfrentando dois problemas.
Problema 1
O tempo de leitura dos XMLs é impraticável (estamos falando de dias) e, sendo uma aplicação que usa Facelets e Hibernate, bibliotecas como o Picollo não são uma opção (esses frameworks exigem validação dos XMLs). Como os arquivos já foram validados anteriormente, estou optando por uma leitura básica de Strings, mas parece que estou reinventando a roda…
Problema 2
Estou usando o H2SQL, que tem uma boa performance por trabalhar com os dados em memória. No entando, com essa quantidade de dados eu constantemente recebo um OutOfMemory (usei VM’s com até 2Gb de Xmx). Estou pensando em usar o postgresql, mas me pergunto se o cache de primeiro nível do Hibernate não vai manter o uso da memória excessivamente alto. Seria o caso de usar apenas o JDBC?
Agradeço desde já por qualquer sugestão!
Para o problema 1, eu usaria o Saxon para ler e filtrar os XML’s através de consultas XQuery, e o JiBX para converter em objetos Java as seqüências XML retornadas pelo Saxon:
http://saxon.sourceforge.net
http://jibx.sourceforge.net/
Para converter seqüências XML em objetos Java, outra opção é o XStream:
http://xstream.codehaus.org/
Muito obrigado a todos pelas respostas.
Gostei do Jibx e estou montando um projeto para testar a performance dele, mas acho que fiz algo errado pois não consigo fazer o binding dos bytecodes.
Se alguém puder dar uma verificada no meu pom.xml, acho que estou esquecendo de alguma coisa…
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>br.com.technocraft.sinfe</groupId>
<artifactId>sinfe</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>SINFe Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jibx</groupId>
<artifactId>maven-jibx-plugin</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>org.jibx</groupId>
<artifactId>jibx-extras</artifactId>
<version>1.2.3</version>
</dependency>
</dependencies>
<build>
<finalName>sinfe</finalName>
<plugins>
<!-- Compiler plugin enforces Java 1.6 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
<includes>
<include>${maven.build.dir}</include>
</includes>
</configuration>
</plugin>
<!-- Eclipse plugin enforces download of source and JavaDoc jars -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-eclipse-plugin</artifactId>
<configuration>
<wtpversion>2.0</wtpversion>
<downloadSources>true</downloadSources>
<downloadJavadocs>true</downloadJavadocs>
</configuration>
</plugin>
<plugin>
<groupId>org.jibx</groupId>
<artifactId>maven-jibx-plugin</artifactId>
<version>1.2.3</version>
<executions>
<execution>
<id>generate-java-code_from_schema</id>
<goals>
<goal>schema-codegen</goal>
</goals>
<configuration>
<schemaDirectory>src/main/conf</schemaDirectory>
<includeSchema>
<include>*.xsd</include>
</includeSchema>
<options>
<package>br.com.technocraft.sinfe.pojos</package>
</options>
</configuration>
</execution>
<execution>
<id>compile-binding</id>
<goals>
<goal>bind</goal>
</goals>
<configuration>
<bindingDirectory>target/generated-sources</bindingDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Obrigado novamente!
Acredito que o SA http://www.saxproject.org/, seja mais versatil do que o XStream, apesar de ser mais porco.
O XStream já tem tudo meio que pronto.
Falando em XML,
Eu gostaria de ser alguns dados da Google que me retornam um XML eu vi em um SRC da google que ela usa annotations para fazer isso alguem sabe como?
Pelo que eu entendi o Saxon serve para executar xquery, acho que não é exatamente o que eu estou procurando.
Se o jibx conseguir, com uma boa performance (como a página do projeto anuncia), extrair os dados dos XMLs e colocar em POJOs, o meu primeiro problema estará resolvido.
victor: o JiBX e o XStream lêem uma seqüência XML e transformam em objetos Java. Se você tiver um arquivo XML de 20 GB e tentar transformá-lo em objetos Java, é quase certo que a memória vai estourar. O que o Saxon faz por você é filtrar o conteúdo do arquivo XML via sintaxe XQuery, de modo que você só capture as partes do arquivo que interessam (é bem possível que, dos 20 GB do arquivo XML original, você queira apenas 50 MB). A propósito, o desempenho do JiBX é realmente excelente, e eu o recomendo sem reservas.
Ainda não consegui fazer o jibx funcionar com o maven e tudo mais, mas parece uma ótima pedida.
O problema dos arquivos XML é a quantidade não o tamanho de cada um. Cada arquivo é pequeno (em torno de 10k) mas preciso colocá-los todos em uma única base de dados.
Só para vcs terem uma ideia, fazendo a leitura através da própria api do jre (com validação) eu demoro em média 5 segundos para cada 100 arquivos. Se faço a leitura por texto puro, esse tempo cai para 700ms.
Assim q eu tiver a média de tempo com o jibx, eu posto aqui.
a api do jdk, dom me parece ser o que você teria de mais rápido para ler seu xml “como xml”, e não ler o texto em si…
se mesmo com essa você está demorando dias para processar tudo, a unica saida que vejo para você processar mais rápido é você dividir esse xml, em várias partes e startar várias threads para que cada uma processe uma parte, por exemplo:
<seuXml>
<mae>
<filha></filha>
<filha></filha>
<filha></filha>
</mae>
<mae>
<filha></filha>
<filha></filha>
<filha></filha>
</mae>
<mae>
<filha></filha>
<filha></filha>
<filha></filha>
</mae>
</seuXml>
você pode colocar uma thread para separar o conteudo das tags <mae>, em objetos por exemplo se esse for o caso, colocar cada uma das tags mães, seus objetos ou o que for em uma fila e criar um pool de threads que vai pegando os itens da fila e processando… se forem incrementais, uma depender da outra ai você não tem o que fazer… vai demorar mesmo, processar gigas de informação demora… (mesmo desse jeito).
Estou com problemas com o code generator do jibx para Maven, os fontes não estão sendo compilados.
Estou usando o compilador customizado para incluir os fontes gerados:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
<includes>
<include>target/generated-sources</include>
</includes>
</configuration>
</plugin>
A configuração do plugin do jibx está assim:
<configuration>
<schemaDirectory>src/main/conf</schemaDirectory>
<includeSchema>
<include>*.xsd</include>
</includeSchema>
<options>
<package>br.com.exemplo.pojos</package>
</options>
<bindingDirectory>target/generated-sources</bindingDirectory>
<load>true</load>
<validate>true</validate>
<verbose>true</verbose>
<verify>true</verify>
</configuration>
Agradeço se alguém tiver uma dica de o que pode estar errado.
A leitura como texto puro é bem mais rápida porque não faz a validação do XML. Estou tentando o jibx porque ele faz um binding nos binários para acelerar a leitura dos xml, acho que vou conseguir uma boa performance esta maneira.
Pessoal, apenas para postar a resolução, não consegui a performance que eu esperava, por isso coloquei a leitura dos XMLs em uma thread separada, com baixa prioridade, de modo a não comprometer a aplicação.
Estou usando o jaxb para fazer o trabalho sujo.
Obrigado a todos!