Olá, nesse artigo vou falar sobre geração de relatórios com IReport a partir de dados que já estão na memória (objetos DTO) em vez de fazer uma consulta SQL direta no Jasper. Para isso, utilizamos o JRBeanCollectionDataSource.
Vamos ver primeiro as dependencias do POM:
<!-- Core do Jasper -->
<dependency>
<groupId>net.sf.jasperreports</groupId>
<artifactId>jasperreports</artifactId>
<version>5.6.0</version>
</dependency>
<!-- Necessário para ler os campos do DTO -->
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.4</version>
</dependency>
<!-- Motor de exportação PDF (Jasper 5.6 usa essa versão) -->
<dependency>
<groupId>com.lowagie</groupId>
<artifactId>itext</artifactId>
<version>2.1.7</version>
</dependency>
O IReport gera dois arquivos:
.jrxml: É o seu arquivo de edição (código-fonte XML). É onde você desenha no iReport.
.jasper: É o arquivo compilado. Dica: Sempre coloque o .jasper na pasta de recursos (src/main/resources) do seu projeto Java para que a aplicação o encontre facilmente.
Configurando o iReport para reconhecer o DTO:
Para que os campos apareçam no designer:
- Vá em Tools -> Options -> iReport -> Classpath e adicione a pasta target/classes do seu projeto.
- No Report Inspector, clique com o botão direito em Fields -> Add Field.
- O nome do campo deve ser idêntico ao atributo da classe Java (ex: se no Java é private String nomeCliente, no iReport o campo deve se chamar nomeCliente).
Como lidar com Logos e Backgrounds
No ambiente Java EE, o relatório não sabe "onde ele está" a menos que você diga. Para usar caminhos como images/logo.png direto no .jrxml, faça o seguinte:
No iReport (Designer) crie um parâmetro chamado IMAGENS_DIR (tipo String). No campo da imagem, use a expressão:
$P{IMAGENS_DIR} + "logo.png"
No Java você extrai o caminho da pasta de relatórios dinamicamente:
// Obtém o caminho físico da pasta de relatórios dentro do seu WAR
String pathRelatorios = getServletContext().getRealPath("/WEB-INF/imagens/");
Map<String, Object> parametros = new HashMap<>();
// Passa esse caminho base para o Jasper
parametros.put("IMAGENS_DIR", pathRelatorios + File.separator);
Outra opção é usando o InputStream, passá-la como um InputStream via parâmetro.
No iReport:
- Vá em Parameters -> Add Parameter. Nomeie como LOGO_IMG.
- Mude a Parameter Class para java.io.InputStream.
- Arraste um elemento de Image para o relatório. No campo Image Expression, digite: $P{LOGO_IMG}.
No Java carregue a imagem da sua pasta de recursos (src/main/resources/images/logo.png) e envie para o Jasper:
InputStream logo = this.getClass().getResourceAsStream("/images/logo.png");
parametros.put("LOGO_IMG", logo);
O Código Java de geração do Relatório
Aqui está o restante do código Java para a geração do relatório:
// Centralizando a lógica de criação do JasperPrint
private JasperPrint prepararRelatorio(List<MeuDTO> listaDados, Map<String, Object> parametros) throws JRException {
// Carrega o arquivo compilado dos resources
InputStream relatorioStream = this.getClass().getResourceAsStream("/relatorios/meu_arquivo.jasper");
// Transforma a lista de objetos no DataSource do Jasper
JRBeanCollectionDataSource ds = new JRBeanCollectionDataSource(listaDados);
// Gere os parametros necessários
Aqui você pega o caminho relativo da imagem por exemplo
// Une o layout (.jasper) + Parâmetros + Dados (DTOs)
return JasperFillManager.fillReport(relatorioStream, parametros, ds);
}
// Método para enviar ao navegador
public void emitirRelatorio(HttpServletResponse response, List<MeuDTO> lista, boolean baixar) {
try {
JasperPrint jp = prepararRelatorio(lista, new HashMap<>());
// Define o tipo de saída (PDF)
response.setContentType("application/pdf");
// Define se abre no navegador ou faz download
String modo = baixar ? "attachment" : "inline";
response.setHeader("Content-Disposition", modo + "; filename=\"relatorio.pdf\"");
// Escreve o PDF na resposta HTTP
JasperExportManager.exportReportToPdfStream(jp, response.getOutputStream());
response.getOutputStream().flush();
response.getOutputStream().close();
} catch (Exception e) {
e.printStackTrace();
}
}
Dica: Se usarem uma versão do Java muito nova (Java 17+), o Jasper 5.6 pode precisar de flags extras no servidor (--add-opens), pois ele é uma ferramenta antiga que acessa classes internas do Java.
Nenhum comentário:
Postar um comentário