Como criar um Gerador de Relatórios para JasperReport no JSF

Veja neste artigo como criar classes que sejam capazes de gerar qualquer relatório em JSF usando JasperReport.

Gerar relatórios é um processo comum a quase todos os tipos de sistemas, desde simples a complexos. Relatórios são artefatos finais que podem prover ao usuário/cliente uma forma de saber se as informações que estão sendo alimentadas no sistema estão corretas, ou mesmo se o sistema está realizando os procedimentos adequados.

As vezes a maior dificuldade em gerar relatórios na Web não é sua construção, mas o processo para que este seja mostrado ao usuário da forma mais usual possível.

Neste artigo iremos construir classes que serão responsáveis por tornar a geração do nosso relatório o mais simples possível, isso significa que ao criar relatórios não deveremos nos preocupar com a forma que ele será mostrado ao usuário, mas sim se seu conteúdo está correto.

Usaremos uma das bibliotecas mais conhecidas para geração de relatórios, o JasperReport. Esta é inteiramente escrita em Java e pode usar dados provenientes de quase todo tipo de datasource (fonte de dados) que você imaginar. Isso faz dele um dos melhores, se não o melhor, engine de relatórios open source para Java.

Vamos começar criando uma classe Helper chamada ReportHelper, conforme mostra a Listagem 1, que é responsável por realizar o processo principal, ou seja, gerar o relatório e enviar ao navegador.

Listagem 1. ReportHelper

1 import java.io.File; 2 import java.io.FileOutputStream; 3 import java.io.IOException; 4 import java.text.SimpleDateFormat; 5 import java.util.Date; 6 import java.util.HashMap; 7 import java.util.List; 8 import java.util.Map; 9 10 import javax.faces.context.FacesContext; 11 import javax.servlet.http.HttpServletRequest; 12 13 import net.sf.jasperreports.engine.JREmptyDataSource; 14 import net.sf.jasperreports.engine.JRException; 15 import net.sf.jasperreports.engine.JRExporter; 16 import net.sf.jasperreports.engine.JRExporterParameter; 17 import net.sf.jasperreports.engine.JasperFillManager; 18 import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource; 19 import net.sf.jasperreports.engine.export.JRPdfExporter; 20 import net.sf.jasperreports.engine.export.JRXlsExporter; 21 22 import org.primefaces.context.RequestContext; 23 import org.springframework.beans.factory.annotation.Autowired; 24 import org.springframework.stereotype.Component; 25 26 @Component(value = "reportHelper") 27 public class ReportHelper { 28 29 public enum FORMATO_RELATORIO{ 30 XLS, PDF; 31 } 32 33 private String gerarIdReport() { 34 SimpleDateFormat simpleDateFormat = new SimpleDateFormat( 35 "ddMMyyyyhhmmss"); 36 String id = simpleDateFormat.format(new Date()); 37 38 return id; 39 } 40 41 /** 42 * Retorna caminho onde os relatórios (.jasper e .jrxml e tmps) ficam 43 * armazenados 44 * */ 45 private String reportSourcePath() { 46 47 return FacesContext.getCurrentInstance().getExternalContext() 48 .getRealPath("/WEB-INF/report/") 49 + "/"; 50 } 51 52 /** 53 * Retorna o caminho onde os relatórios finais ficam no servidor (ex: .PDF) 54 * */ 55 private String reportFile() { 56 return FacesContext.getCurrentInstance().getExternalContext() 57 .getInitParameter("reportDirectory"); 58 } 59 60 /** 61 * Abrir Janela com Arquivo (PDF, XLS, TXT e etc) 62 * */ 63 public void abrirPoupUp(String fileName) { 64 abrirPoupUp(fileName, null); 65 } 66 67 public void abrirPoupUp(String fileName, String nomeJanela){ 68 HttpServletRequest req = (HttpServletRequest) FacesContext 69 .getCurrentInstance().getExternalContext().getRequest(); 70 String contextPath = req.getContextPath().replace("/", ""); 71 if (nomeJanela == null){ 72 nomeJanela = "Relatório"; 73 } 74 75 RequestContext.getCurrentInstance().execute( 76 "window.open("/" + contextPath + "/report/" + fileName 77 + "",'"+nomeJanela+"','width=800px,height=800px')"); 78 } 79 80 /** 81 * Gera o relatório e retorna o nome do relatório gerado 82 * */ 83 private String gerarRelatorio(String relatorio, 84 List beans, Map<String, Object> params, FORMATO_RELATORIO formatoExportacao) { 85 try { 86 if (params == null) { 87 params = new HashMap<String, Object>(); 88 } 89 90 91 JRBeanCollectionDataSource beanCollectionDataSource = new JRBeanCollectionDataSource( 92 beans); 93 94 String relatorioFormated = relatorio.endsWith(".jasper") ? relatorio 95 : (new StringBuilder()).append(relatorio).append(".jasper") 96 .toString(); 97 net.sf.jasperreports.engine.JasperPrint jasperPrint = null; 98 99 if (beans != null && beans.size() > 0) { 100 jasperPrint = JasperFillManager 101 .fillReport(reportSourcePath() + relatorioFormated, params, 102 beanCollectionDataSource); 103 } else { 104 jasperPrint = JasperFillManager 105 .fillReport(reportSourcePath() + relatorioFormated, params, new JREmptyDataSource()); 106 } 107 108 109 StringBuilder nomeRelatorio = new StringBuilder(); 110 nomeRelatorio.append(reportFile() + relatorio + "_" 111 + gerarIdReport()); 112 113 114 JRExporter exporter = null; 115 116 if (formatoExportacao.equals(FORMATO_RELATORIO.PDF)){ 117 exporter = new JRPdfExporter(); 118 nomeRelatorio.append(".pdf"); 119 }else if (formatoExportacao.equals(FORMATO_RELATORIO.XLS)){ 120 exporter = new JRXlsExporter(); 121 nomeRelatorio.append(".xls"); 122 } 123 124 File fTarget = new File(nomeRelatorio.toString()); 125 126 exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint); 127 exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, 128 new FileOutputStream(fTarget.getAbsolutePath())); 129 exporter.exportReport(); 130 131 return fTarget.getName(); 132 } catch (JRException e) { 133 e.printStackTrace(); 134 return null; 135 } catch (IOException e) { 136 // TODO Auto-generated catch block 137 e.printStackTrace(); 138 return null; 139 } 140 } 141 142 /** 143 * Geração de Relatório em XLS 144 */ 145 public String gerarRelatorioXLS(String relatorio, 146 List beans, Map<String, Object> params){ 147 148 return gerarRelatorio(relatorio, beans, params, FORMATO_RELATORIO.XLS); 149 150 } 151 152 /** 153 * Padrão para Arquivos PDF 154 * */ 155 public String gerarRelatorio(String relatorio, 156 List beans, Map<String, Object> params){ 157 158 return gerarRelatorio(relatorio, beans, params, FORMATO_RELATORIO.PDF); 159 160 } 161 162 }

Primeiramente é importante salientar alguns pontos importantes da nossa classe antes de explicar os blocos de código-fonte importantes:

Além disso, vamos entender como o código se comporta:

Os outros métodos de geração de relatório são apenas sobrecargas do método principal, para possibilitar a chamada ao mesmo de várias formas possíveis.

Temos pronta nossa classe Helper que irá fazer a parte mais difícil, que é gerar o relatório, vamos agora ver a nossa classe que irá tratar do front-end, ou seja, será o Backing Bean responsável por cuidar dos filtros para gerar nosso relatório correto. Observe a Listagem 2.

Listagem 2. ReportItem

1 import javax.faces.application.FacesMessage; 2 import javax.faces.context.FacesContext; 3 4 import br.com.projetoteste.helper.ReportHelper.FORMATO_RELATORIO; 5 6 public abstract class ReportItem { 7 8 private String nome; 9 private String descricao; 10 private String jasperName; 11 12 public ReportItem(String nome, String descricao, String jasperName) { 13 this.nome = nome; 14 this.descricao = descricao; 15 this.jasperName = jasperName; 16 } 17 18 public ReportItem(String descricao) { 19 this.nome = this.getClass().getSimpleName(); 20 this.descricao = descricao; 21 this. jasperName = this.getClass().getSimpleName().toLowerCase(); 22 } 23 24 public abstract void gerarRelatorio(FORMATO_RELATORIO formato); 25 26 public String getNome() { 27 return nome; 28 } 29 30 public void setNome(String nome) { 31 this.nome = nome; 32 } 33 34 public String getDescricao() { 35 return descricao; 36 } 37 38 public void setDescricao(String descricao) { 39 this.descricao = descricao; 40 } 41 42 public String getJasperame() { 43 return jasperName; 44 } 45 46 public void setJasperName(String jasperName) { 47 this. jasperName = jasperName; 48 } 49 50 }

A ideia de criar uma classe ReportItem é para que todos os Backing Beans de relatórios possam estender dela, criando assim uma padronização para a geração de relatórios. Ela é simples, mas eficaz. Vejamos:

Vamos ver agora como usar o nosso ReportItem em conjunto com o ReportHelper. Digamos que nossos relatórios tenham a seguinte nomenclatura: R001, R002 e assim por diante. Então vamos criar um Backing Bean chamado R001, que estende de ReportItem. Isso já caracteriza que nosso Backing Bean é um gerenciador de algum relatório específico, como mostra a Listagem 3.

Listagem 3. R001 extends ReportItem

1 import java.text.SimpleDateFormat; 2 import java.util.Date; 3 import java.util.HashMap; 4 import java.util.List; 5 import java.util.Map; 6 7 import javax.annotation.PostConstruct; 8 import javax.faces.bean.ManagedBean; 9 import javax.faces.bean.ManagedProperty; 10 import javax.faces.bean.ViewScoped; 11 12 13 import br.com.projetoteste.helper.ReportHelper; 14 import br.com.projetoteste.helper.ReportHelper.FORMATO_RELATORIO; 15 import br.com.projetoteste.report.bean.ReportItem; 16 17 @ManagedBean(name = "r001") 18 @ViewScoped 19 public class R001 extends ReportItem { 20 21 22 @ManagedProperty(value = "#") 23 private ReportHelper reportHelper; 24 25 private Date dataInicial, dataFinal; 26 27 @PostConstruct 28 public void init() { 29 dataInicial = new Date(); 30 dataFinal = new Date(); 31 } 32 33 public R001() { 34 super("Listagem de Funcionarios da Empresa"); 35 } 36 37 @Override 38 public void gerarRelatorio(FORMATO_RELATORIO formato) { 39 List<Funcionario> funcionarios = (List<Funcionario>) MeuServico.getListaFuncionario(); 40 Map<String, Object> params = new HashMap<String, Object>(); 41 params.put("titulo", getNome()); 42 43 SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy"); 44 params.put("dataInicial", sdf.format(dataInicial)); 45 params.put("dataFinal", sdf.format(dataFinal)); 46 47 String fileName = reportHelper.gerarRelatorio("r001", funcionarios, params); 48 reportHelper.abrirPoupUp(fileName); 49 50 } 51 52 public void gerarXLS() { 53 gerarRelatorio(FORMATO_RELATORIO.XLS); 54 } 55 56 public void gerarPDF() { 57 gerarRelatorio(FORMATO_RELATORIO.PDF); 58 } 59 60 public ReportHelper getReportHelper() { 61 return reportHelper; 62 } 63 64 public void setReportHelper(ReportHelper reportHelper) { 65 this.reportHelper = reportHelper; 66 } 67 68 public Date getDataInicial() { 69 return dataInicial; 70 } 71 72 public void setDataInicial(Date dataInicial) { 73 this.dataInicial = dataInicial; 74 } 75 76 public Date getDataFinal() { 77 return dataFinal; 78 } 79 80 public void setDataFinal(Date dataFinal) { 81 this.dataFinal = dataFinal; 82 } 83 84 }

Vamos entender o código apresentado:

Agora você pode utilizar o backing bean em qualquer XHTML, fazendo chamada sempre ao actionListener gerarRelatorio().

Com base neste artigo você terá uma estrutura genérica para geração de relatórios em JSF, abstraindo toda a complexidade para a geração do mesmo. A única coisa que você precisará se preocupar é com o filtro do seu relatório e a criação propriamente dita do mesmo.

Espero que tenham gostado e até a próxima.

Ebook exclusivo
Dê um upgrade no início da sua jornada. Crie sua conta grátis e baixe o e-book

Artigos relacionados