JSF - Gerar relatório PDF com subreport

10 respostas
dahenz

Bom dia!

Estou quebrando a cabeça para gerar um simples subreport em pdf, utilizando JDBCConnection no relatório pai e no subreport, ao compilar os dois relatórios aparecem tranquilamente no pdf, ao gerar o relatório no java, é mostrado apenas o pai, ou filho. Estou enviando o código de quando é gerado o relatório:

String pathJasper = FacesUtil.getCurrentDirectory()+"/WEB-INF/classes/br/com/vieweb";		
				
   String reportFileName = pathJasper + File.separator + "ComparativoMediaEncomendas.jasper";								
			
   Map<String, String> parametros = new HashMap<String, String>();				
   parametros.put("data_aa", data_aa);
   parametros.put("data_at", data_at);
   parametros.put("data_ma", data_ma);
   parametros.put("regiao_footer", regiao_footer);
   parametros.put("regiao", target);
   parametros.put("usuario", MySQLDAO.getUsuarioLogado());	
   parametros.put("pathSubReport", pathJasper + File.separator + "ResumoComparativoMediaEncomendas.jasper");

   JasperReport report = (JasperReport) JRLoader.loadObject(reportFileName);
				
   JasperPrint print = JasperFillManager.fillReport(report, parametros, jrDS);				
				
   byte[] bytes = JasperExportManager.exportReportToPdf(print);

   FacesContext facesContext = FacesContext.getCurrentInstance();
   HttpServletResponse response = (HttpServletResponse) facesContext.getExternalContext().getResponse();
												 
   response.setContentType("application/pdf");
   response.setContentLength(bytes.length);
   response.setHeader("Content-Disposition","inline; filename=report.pdf"); 
				
   ServletOutputStream ouputStream = response.getOutputStream(); 
				
   ouputStream.write(bytes, 0, bytes.length); 
   ouputStream.flush(); 
   ouputStream.close(); 
				
   facesContext.responseComplete();

O outputStream pode escrever apenas um array de bytes??? É possível eu passar o array de bytes do relatório pai e do subreport?

Obrigado

10 Respostas

maiconramones

Fala ai, cara eu tenho um código muito semelhante ao seu e que funciona normalmente. Sobre o array de bytes eu utilizo passando o array do relatório todo… Teoricamente não interessa se tu vai ter um ou 10 subrelatórios o jasper te retorna o array de bytes que ele gerou.

Se está aparecendo o relatório pai ou relatório filho, creio que isso seja algum erro na hora da montagem do relatório no jasper, um sugestão é verificar se ele não está fechando a tua JDBCConection.

Mas me parece que o erro é na montagem do relatório e não na hora de escrever os bytes.

dahenz

Olá Maicon… acredito que sim… existe uma forma de concatenar um array de bytes??? Vou ver a respeito da connection… Valew

maiconramones

Cara talvez até exista uma maneira de concatenar o array, mas isso não se aplica ao seu caso.

O jasper que tem que te devolver o array pronto e você simplesmente escreve esse array no ouputStream, simples como a OI hehehe

Feito

dahenz

Olá Maicon!!!

Verifiquei se as conexões estão fechando e estavam, então comentei a linha na qual fechava a mesma, aconteceu a mesma coisa, então alterei meu código da seguinte forma:

Map<String, String> parametros = new HashMap<String, String>();				
				parametros.put("data_aa", data_aa);
				parametros.put("data_at", data_at);
				parametros.put("data_ma", data_ma);
				parametros.put("regiao_footer", regiao_footer);
				parametros.put("regiao", target);
				parametros.put("usuario", MySQLDAO.getUsuarioLogado());	
				parametros.put("pathSubReport", pathJasper + File.separator + "ResumoComparativoMediaEncomendas.jasper");

				Map<String, String> parametrosResumo = new HashMap<String, String>();				
				parametros.put("data_aa", data_aa);
				parametros.put("data_at", data_at);
				parametros.put("data_ma", data_ma);				
				
				JasperReport report = (JasperReport) JRLoader.loadObject(reportFileName);
				JasperReport reportResumo = (JasperReport) JRLoader.loadObject(reportResumoFileName);
				
				JasperPrint print = JasperFillManager.fillReport(report, parametros, jrDS);				
				JasperPrint printResumo = JasperFillManager.fillReport(reportResumo, parametrosResumo, jrDS);
				
				byte[] bytes = JasperExportManager.exportReportToPdf(print);
				byte[] bytesResumo = JasperExportManager.exportReportToPdf(printResumo);								

				FacesContext facesContext = FacesContext.getCurrentInstance();
				HttpServletResponse response = (HttpServletResponse) facesContext.getExternalContext().getResponse();
												 
				response.setContentType("application/pdf");
				response.setContentLength(bytes.length);
				response.setHeader("Content-Disposition","inline; filename=report.pdf"); 
				
				ServletOutputStream ouputStream = response.getOutputStream(); 
				
				ouputStream.write(bytes, 0, bytes.length);
				ouputStream.write(bytesResumo, 0, bytesResumo.length);
				ouputStream.flush(); 
				ouputStream.close(); 
				
				facesContext.responseComplete();

Tosco, pois o sistema irá escrever ou um relatório ou outro, então eu pensei na forma na qual tu faz, e pergunto: Você concatena os arrays de bytes???

dahenz

desculpa… vc já tinha respondido… hehe valew

maiconramones

Pois é foi em cima do lance hehehe

Uma sugestão… eu não gosto de usar o jasper para que monte as querys no relatório… eu utilizo JRBeanCollectionDataSource. Neste caso você monta todas as querys e listas na sua aplicação java, evitando o problema do JDBCConnection ser fechada.

Ou uma solução mais tosca ainda… é você passar duas JDBCConnection para seu relatório, não sei se funciona.

dahenz

Bah cara… chega de tosquisse … hahahaha valew vou seguir sua dica… abraço

dahenz

Puts… nem por decreto… estou utilizando JRResultSetDataSource nas duas consultas, pai e subreport, com a mesma conexão passada por parâmetro… psss… hehe só pra ver se funciona meu subreport, e aparece um WARNING em meu console que diz:

The supplied java.sql.Connection object is null.

Bah… alguma dica??? Valew

maiconramones

A minha dica é usar da forma que eu uso, que é usando JRBeanCollectionDataSource, que é mais ou menos assim…

Eu crio uma lista com os beans e seus respectivos dados que devem aparecer na banda detail, os demais dados eu passo tudo via parametro. Sendo assim o relatório não vai executar nenhuma query, ele já vai receber os dados prontos. No caso de haver um subrelatório a forma é mesma, o detalhe é que você só pode passar um JRBbeanCollection por vez, ai vem o pulo do gato, passe uma lista com os dados que devem aparecer no subrelatorio por parametro mesmo, e no subrelatório marque para usar um datasource e como expressão coloque: $P{listaDoSubRelatorio}

PS: Da forma que coloquei acima o relatório não recebe nenhuma conexão JDBC, somente objetos.

dahenz

Certinho Maicon… obrigado!!!

Criado 12 de agosto de 2009
Ultima resposta 13 de ago. de 2009
Respostas 10
Participantes 2