Вы находитесь на странице: 1из 11

Como gerar relatrios PDF na

Web com JasperReports


Aprenda a gerar e disponibilizar relatrios PDF na sua
aplicao Web com iReport e JasperReports
Rafael Ponte - Desenvolvedor e instrutor na TriadWorks
December 01, 2015

Todo sistema Web gera algum tipo de relatrio para seus clientes.
Normalmente estes relatrios so gerados no formato PDF devido sua
facilidade na hora de imprim-los. No mundo Java temos algumas
opes de ferramentas para gerao destes relatrios, mas sem dvida a
mais conhecida e utilizada no mercado o JasperReports e sua
ferramenta grfica para desenhar relatrios, o iReport.
Embora seja comum associarmos o iReport como a tecnologia
responsvel por gerar os relatrios no mundo Java, a verdade que ela
apenas a ferramenta grfica que te ajudar a construir e desenharos
relatrios, ela o que chamamos de report designer. Quem de fato gera
e exporta os relatrios para determinado formato o JasperReports, na
qual conhecido como report engine.

Resumindo, usamos o iReport para desenhar o relatrio e gravar sua


definio em um arquivo XML, cuja extenso .jrxml. Depois disso,
via cdigo Java, executamos o JasperReports para compilar este
JRXML, preench-lo com informaes e, por fim, exportar o relatrio
em si. Ao exportar o relatrio voc pode definir em que formato ele ser
gerado, como PDF, HTML, Excel, Word, OpenOffice etc.
A maior dificuldade dos desenvolvedores no com o iReport, pois ele
simples e fcil de aprender, mas sim com a API do JasperReports para
compilar, preencher e exportar o relatrio. Alis, eu falo por mim, pois
sempre tive dificuldades com JasperReports, por esse motivo resolvi
escrever este post para nunca mais esquecer...

Compilando, preenchendo e exportando


o relatrio
Irei focar na gerao do relatrio em si, na API do JasperReports, e no
em como desenh-lo com o iReport. Portanto, vou levar em

considerao que voc desenhou o relatrio e gravou sua definio em


um arquivo JRXML.
IMPORTANTE: A partir da verso 5.5.0 o iReport foi substitudo
pelo Jaspersoft Studio. As verses antigas sero mantidas e atualizadas
somente at o final deste ano de 2015. Portanto, se estiver em um novo
projeto opte pelo Jaspersoft Studio.
Para gerar um relatrio com JasperReports precisamos executar 3
passos essenciais. Os passos so:
1. compilar o JRXML;
2. preencher o relatrio compilado com dados e informaes;
3. exportar para PDF ou outro formato;
Agora que voc j sabe quais os passos tomar, vamos ao trabalho...
Com o JRXML criado, a primeira coisa que precisamos fazer compillo com a API do JasperReports. Para isso, usamos o mtodo
esttico compileReportToFile da classe JasperCompileManager, como
abaixo:
String jrxml = "alunos.jrxml";

String jasper =
JasperCompileManager.compileReportToFile(jrxml);

System.out.println(jasper); // alunos.jasper

O cdigo acima ir compilar o arquivo alunos.jrxml em um


arquivo alunos.jasper no mesmo diretrio do arquivo de origem. Um
arquivo .jasper o relatrio compilado em formato binrio para que o
JasperReports possa preench-lo e export-lo ao final da gerao.
Normalmente s precisamos dele quando a aplicao est em produo.
Com o relatrio compilado, agora temos que preench-lo com dados e
informaes a partir de uma conexo JDBC e parmetros da prpria
aplicao. Esses parmetros normalmente so preenchidos pelo usurio
atravs de um formulrio, como filtros de uma pesquisa. Para isso,
usamos a classe JasperFillManager e seu mtodo fillReport:
Map<String, Object> parametros = new HashMap<>();

parametros.put("curso_id", 2020);
Connection conexao = // obtem uma conexo jdbc...

JasperPrint print =
JasperFillManager.fillReport("alunos.jasper", parametros,
conexao);

Geralmente o mapa de parmetros utilizado dentro do relatrio como


filtros para a consulta SQL ou algum valor esttico como nome da
empresa, por exemplo. Outro detalhe importante que o
mtodofillReport retorna um objeto do tipo JasperPrint, que nada mais
do que o relatrio preenchido de forma genrica, isto , sem formato
definido.
Aps preencher o relatrio ns devemos export-lo para um formato
concreto, como PDF, HTML, Excel, entre outros. Para isso, usamos
classes especiais responsveis por exportar estes relatrios genricos
para determinado formato, elas so chamadas de exporters, ou mais
especificamente JRExporters. Para o nosso caso, exportaremos o
relatrio para PDF, como abaixo:
OutputStream saida = new FileOutputStream("alunos.pdf");

JRExporter exporter = new JRPdfExporter();


exporter.setParameter(JRExporterParameter.JASPER_PRINT,
print);
exporter.setParameter(JRExporterParameter.OUTPUT_STREAM,
saida);

exporter.exportReport(); // gera o relatrio no fluxo de


sada

Repare que o arquivo PDF final ser gerado na sada que indicamos,
nesse caso num FileOutputStream com o nome alunos.pdf.
Para facilitar a compreenso, vamos juntar todo o cdigo em um bloco
um pouco mais organizado, como a seguir:
String jrxml = "alunos.jrxml";

Map<String, Object> parametros = new HashMap<>();


Connection conexao = new
ConnectionFactory().getConnection();
OutputStream saida = new FileOutputStream("alunos.pdf");

// compila jrxml em um arquivo .jasper


String jasper =
JasperCompileManager.compileReportToFile(jrxml);

// preenche relatorio
JasperPrint print = JasperFillManager.fillReport(jasper,
parametros, conexao);

// exporta para pdf


JRExporter exporter = new JRPdfExporter();
exporter.setParameter(JRExporterParameter.JASPER_PRINT,
print);
exporter.setParameter(JRExporterParameter.OUTPUT_STREAM,
saida);
exporter.exportReport();

Embora o JasperReports j tenham alguns bons anos de mercado ele


ainda possui uma documentao fraca e com poucos exemplos prticos,
em especial a API de exporters. De qualquer forma, ela melhorou na
sua verso 6.x:
JRPdfExporter exporter = new JRPdfExporter();
exporter.setExporterInput(new SimpleExporterInput(print));
exporter.setExporterOutput(outpuStream);

SimplePdfExporterConfiguration conf = new


SimplePdfExporterConfiguration();
exporter.setConfiguration(conf);

exporter.exportReport();

Com essa nova API voc tem a possibilidade de fazer ajustes finos no
PDF de maneira mais simples, como ajustar fontes, layout, verso do
formato exportado, criptografia, permisses, idioma e muito mais.
Caso queira o relatrio em outro formato, como Excel, basta mudar o
cdigo responsvel pela exportao do arquivo.

Encapsulando em uma classe


As chances so que seu sistema ter que gerar inmeros relatrios para
satisfazer a necessidade do cliente. Dessa forma, se o nmero de
relatrios cresce, o cdigo para ger-los tambm cresce. neste
momento que voc deve tomar cuidado ou voc acabar com muita
duplicao de cdigo.
Para evitar cair nesse armadilha, importante isolarmos o cdigo da API
do JasperReports em uma classe com uma responsabilidade bem
definida: gerar os relatrios da aplicao. Esta classe encapsular os
detalhes da API e nos prover alguns mtodos com uma assinatura mais
simples de usar. Esta classe ser nosso gerador de relatrio e seu cdigo
poderia ser algo a semelhante a este aqui:
public class GeradorDeRelatorios {

private Connection conexao;

public GeradorDeRelatorios(Connection conexao) {


this.conexao = conexao;
}

public void geraPdf(String jrxml,


Map<String, Object> parametros, OutputStream saida)
{

try {

// compila jrxml em memoria


JasperReport jasper =
JasperCompileManager.compileReport(jrxml);

// preenche relatorio
JasperPrint print =
JasperFillManager.fillReport(jasper, parametros,
this.conexao);

// exporta para pdf


JRExporter exporter = new JRPdfExporter();
exporter.setParameter(JRExporterParameter.JASPER_PRINT,
print);
exporter.setParameter(JRExporterParameter.OUTPUT_STREAM,
saida);

exporter.exportReport();

} catch (Exception e) {
throw new RuntimeException("Erro ao gerar
relatrio", e);
}
}
}

O cdigo acima no difere do que vimos anteriormente, exceto que em


vez de compilar o arquivo .jrxml em um arquivo fsico .jasper ns
estamos compilando-o na memria, dessa forma no temos que nos
preocupar onde ele ser gerado ou como mant-lo sincronizado durante o
desenvolvimento:

// compila jrxml em memoria


JasperReport jasper =
JasperCompileManager.compileReport(jrxml);

Costumo seguir esta abordagem em meus projetos pois no me preocupo


em pr-compilar os JRXMLs e empacot-los dentro do .war. No fim
tenho apenas os .jrxml na aplicao, nada de .jasper!
Por fim, para usar nossa classe bastaria um cdigo como este:
GeradorDeRelatorios gerador = new
GeradorDeRelatorios(conexao);
gerador.geraPdf("c:\alunos.jrxml", parametros, saida);

Bem melhor, no ?

Gerando relatrio na Web


Uma das dvidas mais frequentes em listas de discusso e fruns sobre
como gerar relatrios em PDF numa aplicao Web. Gerar o relatrio
ns j sabemos, acabamos de fazer mais acima. O que nos falta
disponibilizar o relatrio para download, dessa forma o usurio pode
baix-lo.
Em qualquer aplicao Web para disponibilizar o arquivo PDF para
download ser preciso escrever o seu contedo na resposta do protocolo
HTTP. Escrever o contedo do relatrio no response muito simples,
basicamente precisamos obter o fluxo de sada do response e pass-lo
para nosso gerador. O cdigo abaixo exemplifica bem o que estou
dizendo:
HttpServletResponse response = // obtm o response do seu
framework mvc
OutputStream saida = response.getOutpuStream();

GeradorDeRelatorios gerador = new


GeradorDeRelatorios(conexao);
gerador.geraPdf("c:\alunos.jrxml", parametros, saida);

Pronto! Este cdigo suficiente para enviar o PDF para o browser


independente do framework MVC que voc esteja usando. Por exemplo,

se levarmos esse cdigo para dentro de uma Servlet teramos algo bem
prximo disso:
@WebServlet("/relatorios/alunos")
public class RelatorioDeAlunosServlet extends HttpServlet {

public void doGet(HttpServletRequest request,


HttpServletResponse response) {

// acha jrxml dentro da aplicao


ServletContext contexto =
request.getServletContext();
String jrxml =
contexto.getRealPath("/relatorios/alunos.jrxml");

// prepara parmetros
Map<String, Object> parametros = new HashMap<>();
parametros.put("curso",
request.getParameter("curso_id"));

// abre conexo com o banco


Connection conexao = new
ConnectionFactory().getConnection();

// gera relatrio
GeradorDeRelatorios gerador = new
GeradorDeRelatorios(conexao);
gerador.geraPdf(jrxml, parametros,
response.getOutpuStream());

conexao.close(); // no esquea de fechar a conexo


}

O relatrio ser gerado e exibido diretamente na janela do navegador.


Caso queira forar o download do PDF voc precisar escrever um
pouco mais de cdigo a fim de definir os cabealhos HTTP da resposta.
Um detalhe importante que no cdigo acima estamos buscando o
JRXML de forma dinmica dentro da aplicao. Isso se faz necessrio
pois normalmente os .jrxml esto dentro raiz da aplicao Web e no
em um local especfico no sistemas de arquivos. O trecho de cdigo na
qual estou falando este:
ServletContext contexto = request.getServletContext();
String jrxml =
contexto.getRealPath("/relatorios/alunos.jrxml");

Perceba que o cdigo est simples por questes de didtica, porm sua
responsabilidade garantir que a conexo ser fechada num bloco trycatch-finally, assim voc evita problemas de vazamento de conexo na
sua aplicao.

E as libs?
No adianta mostrar s o cdigo, n? Precisamos saber quais as
bibliotecas (JARs) necessrios para rodar nosso cdigo com
JasperReports. Basicamente voc precisar dos seguintes JARs dentro do
seu projeto:
o
o
o
o
o
o
o
o

jasperreports-5.x.x.jar
iText-2.x.x.jar (necessria para gerar o PDF em si)
jfreechart-1.x.x.jar (necessria se voc quiser gerar grficos e
charts)
jcommon-1.x.x.jar (necessria se voc quiser gerar grficos e
charts)
commons-beanutils-1.x.x.jar
commons-collections-3.x.x.jar
commons-digester-2.x.jar
commons-logging-1.x.jar

Para no se confundir com as verses dos JARs, eu recomendo voc


copiar todas as bibliotecas acima do iReport (diretrio lib de instalao)
que voc esteja usando para desenhar seus relatrios, dessa maneira voc

garante a compatibilidade da engine de gerao do iReport com sua


aplicao Web.
Ou caso voc use Maven:
<dependency>
<groupId>net.sf.jasperreports</groupId>
<artifactId>jasperreports</artifactId>
<version>5.5.0</version>
</dependency>

As bibliotecas listadas so para gerar relatrios em PDF, outros formatos


podem requerer mais alguns JARs.

Вам также может понравиться