Hay dos formas que utilicé para realizar un reporte con DataSource de Hibenate. La primera (la que explico detalladamente a continuación) es con una Hibernate connection directa y la otra es enviando el mismo List que retorna el query, hacia el reporte.
El proceso de generación de un reporte con una Hibernate Connection es el siguiente:
Se debe crear un archivo .jrxml (de la familia de xml basado en el dtd de JasperReport). Esto lo hará iReport. Lo podemos encontrar en http://jasperforge.org -> [iReport -> Download].
Al abrirlo nos mostrará un entorno para la fabricación de un reporte
Aquí tenemos que configurar algunas cosas:
Ruta de los programas para visualizar el reporte: Options -> Settings -> External Programs.
Options -> settings -> Compiler . Activamos aquí, sino la carpeta donde están los binarios se nos llenará de archivos temporales
Options -> Classpath : Esto en muy importante ya que le indicaremos donde tiene que buscar los recursos.
Aquí se deben agregar las carpetas donde se encuentra todos los archivos de mapeo, los java, además del driver manager jdbc de postgres
Luego definimos el data source del reporte: Data -> Connections/Data Sources y creamos un HibernateConnection.
Listo. Para comenzar crearemos un reporte con el asistente e ingresamos el hql.
Seguimos click click click .. En :Build -> [ pdf | html | xls | etc] seleccionamos el tipo de reporte
Para ver final mente el reporte: Build -> Execute (with a active connection). Al guardarlo veremos lo ha hecho en un archivo jrxml.
Podemos apreciar la estructura del reporte:
Title : Título del reporte. Lo pone solo en la primera página del reporte
PageHeader : Pié de página superior. Aquí podría ir el nombre del usuario que lanzó e reporte.
ColumnHeader : Nombre de la columna. Se repite en todas las páginas.
Detail : Detalle. No dejar aquí objetos, ej. un gráfico, por que puede repetirse (todo el obj.)
ColumnFooter : Algún detalle al final de la columna. ej. Suma total.
PageFooter : Pié de página. número de hoja, hora, etc
LastPageFooter : Este pié de pagina solo va en la última página
Summary : Este espacio va entre el ColumnFooter y PageFooter. y se repite en todas las págs.
Luego podremos personalizar el diseño del reporte. Lo principal se encuentra aquí:
Fields: estas son las columnas que nos trajo la consulta
Nota: para modificar la consulta: Data -> Report query. No podemos hacer consultas con join fetch, pero podemos agregar las columnas que faltan, navegando por el árbol de relaciones que aparece al lado y pinchar en Add Selecte
Variables: Son variables generadas por el propio iReport. ej el número de página, número de columna, etc.
Parameters: estos parámetros son enviados desde el proyecto hacia el reporte. ej. si queremos que en el PageHeader aparezca el nombre del proceso de postulación, creamos un parámetro (en iReport) ej. procesoPostulacion de tipo java.lang.String y en el código se lo enviamos así:
Map parameters = new HashMap();
parameters.put("procesoPostulacion", procesoPost);
Con el jrxml dentro del proyecto nos queda agregar las siguientes librerías al mismo:
iReport.jar
itext-2.0.0.jar
jasperreports-1.3.1.jar
jfreechart-1.0.5
jcommon-1.0.0.jar
poi-2.5.1-final-20040804.jar
Para finalizar la prueba creamos un botón jsp que ejecute un método como el siguiente.
<af:commandbutton id="reporte" text="Reporte" action="#{institucionesBean.reporte}">
<af:setactionlistener from="#{prmGlobal.tipoPdf}" to="#{institucionesBean.tipoReporte}">
public String reporte() {
try{
URL url = this.getClass().getResource("/reportes/instituciones.jrxml");
String jrxml = url.getPath();
Map parameters = new HashMap();
JasperReportsToBrowser.reportConnection(jrxml, parameters, tipoReporte);
}catch(Exception e){
e.printStackTrace();
}
return null;
}
</af:setactionlistener></af:commandbutton>
<af:setActionListener from="#{prmGlobal.tipoPdf}" to="#{institucionesBean.tipoReporte}" />
Este parámetro indica el formato del reporte; hasta el momento está "tipoPdf" y "tipoExcel"
tipoReporte es una variable String de la clase del Backing.
String jrxml = this.getClass().getResource( "/reportes/instituciones.jrxml");
es la ruta completa del jrxml
Map parameters = new HashMap(); con este hasMap agregamos los parámetros que definimos en el jrxml.
JasperReportsToBrowser.reportConnection(jrxml, parameters,tipoReporte);
He creado esta clase y método estático y la he agregado al paquete util, donde se completan los pasos en la generación del reporte y entregarlo a través del navegador. Se le debe pasar cadena que contiene el path completo (del sistema) del archivo jrxml; y el hashMap al que le hemos agregado los parámetros que recibirá el reporte.
Reportes con gráficos.
Para generar reportes con gráficos, hacemos click aquí , luego lo dibujamos en el reporte y lo localizaremos en el summary. Para graficar necesitaremos dos variables, para este ejemplo utilicé instituciones, así que crearé la variable $F{Tipo} que representa los tipos de instituciones (colegio, salud, administrativo, iglesia, etc) y la variable $F{Total}, que contiene el total de cada tipo.
Vamos a ingresar la consulta en Data -> Report Query:
select ti.nombre as Tipo, count(*)as Total
from Institucion i ,Tipoinstitucion ti
where i.tipoinstitucion = ti.codigo
group by ti.nombre
Salimos y vamos a las propiedades del gráfico -> chart -> edit chart properties -> char data -> details e ingresamos las variables.
Guardamos e incorporamos el reporte al proyecto.
El proceso de generación de reporte por medio de un List.
Para este método tenemos que crear un jrxml de la misma forma como se menciono anteriormente, de hecho, podemos utilizar el mismo, la diferencia está en el método.
public String reporte() {
try{
URL url = this.getClass().getResource("/reportes/instituciones.jrxml");
String jrxml = url.getPath();
List list = InstitucionCT.getInstituciones(campoInstitucion,tipoInstitucion,null,codestructuraiasd);
Map parameters = new HashMap();
JasperReportsToBrowser.reportList(jrxml, parameters,list,tipoReporte);
}catch(Exception e){
e.printStackTrace();
}
return null;
}
Como se puede apreciar se envía la misma consulta que se solicita para mostrar el listado, que se aprecia en el ABM de Institución.
JasperReportsToBrowser.reportList(jrxml, parameters, list,tipoReporte);
Este método es el que construye el reporte basado en el listado y lo sirve a través del navegador.
Adjunto la clase JasperReportsToBrowser
/*
* Genera y entrega el reporte a través del browser
* @author Rene Vielma
*
*/
package unach.util;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.sql.Connection;
import java.util.List;
import java.util.Map;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletResponse;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperCompileManager;
import net.sf.jasperreports.engine.JasperExportManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import net.sf.jasperreports.engine.export.JRXlsExporter;
import net.sf.jasperreports.engine.export.JRXlsExporterParameter;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;
import unach.hibernate.SessionFactory;
import unach.util.beans.ParametrosGlobales;
public class JasperReportsToBrowser extends HttpServlet{
public static ParametrosGlobales prmGlobal;
// Methods
/**
* Crea un reporte y lo sirve a través del browser
* @param path
* @param parameters
* @param tipo
* @throws ServletException
* @throws IOException
*/
public static void reportConnection(String path,Map parameters,String tipo) throws ServletException, IOException{
HttpServletResponse response = null;
Session session = null;
Transaction tx = null;
try
{
session = null;
tx = null;
session = SessionFactory.getSession();
tx = session.beginTransaction();
Connection connection = SessionFactory.getSession().connection();
parameters.put("HIBERNATE_SESSION", session);
JasperReport report = JasperCompileManager.compileReport(path);
JasperPrint print = JasperFillManager.fillReport(report,parameters,connection);
ExternalContext ectx = FacesContext.getCurrentInstance().getExternalContext();
response = (HttpServletResponse)ectx.getResponse();
OutputStream out = response.getOutputStream();
if(tipo == prmGlobal.getTipoPdf()){
byte[] bytes = JasperExportManager.exportReportToPdf(print);
response.setHeader("Content-disposition", "attachment; filename=ListadoPDF");
response.setContentType(tipo);
//response.setHeader("Cache-Control", "private");
//response.setHeader("Pragma", "");
response.setContentLength(bytes.length);
out.write(bytes);
out.flush();
out.close();
}
if(tipo == prmGlobal.getTipoExcel()){
ByteArrayOutputStream arrayOutputStream = new ByteArrayOutputStream();
JRXlsExporter exporterXLS = new JRXlsExporter();
exporterXLS.setParameter(JRXlsExporterParameter.JASPER_PRINT, print);
exporterXLS.setParameter(JRXlsExporterParameter.OUTPUT_STREAM, arrayOutputStream);
exporterXLS.setParameter(JRXlsExporterParameter.IS_ONE_PAGE_PER_SHEET, Boolean.FALSE);
exporterXLS.setParameter(JRXlsExporterParameter.IS_DETECT_CELL_TYPE, Boolean.TRUE);
exporterXLS.setParameter(JRXlsExporterParameter.IS_WHITE_PAGE_BACKGROUND, Boolean.FALSE);
exporterXLS.setParameter(JRXlsExporterParameter.IS_REMOVE_EMPTY_SPACE_BETWEEN_ROWS, Boolean.TRUE);
exporterXLS.exportReport();
response.setHeader("Content-disposition", "attachment; filename=ListadoPDF");
response.setContentType("application/vnd.ms-excel");
//response.setHeader("Cache-Control", "private");
//response.setHeader("Pragma", "");
response.setContentLength(arrayOutputStream.toByteArray().length);
out.write(arrayOutputStream.toByteArray());
out.flush();
out.close();
}
FacesContext.getCurrentInstance().responseComplete();
}
catch (JRException e){
// display stack trace in the browser
StringWriter stringWriter = new StringWriter();
PrintWriter printWriter = new PrintWriter(stringWriter);
e.printStackTrace(printWriter);
response.setContentType("text/plain");
response.getOutputStream().print(stringWriter.toString());
}
catch (HibernateException e) {
if (tx != null)
tx.rollback();
throw e;
}
finally {
session.close();
}
}
/**
* Envía el List en el reporte y lo sirve a través del browser
* @param path
* @param parameters
* @param list
* @throws ServletException
* @throws IOException
* @author Rene Vielma
*/
public static void reportList(String path,Map parameters,List list,String tipo) throws ServletException, IOException{
HttpServletResponse response = null;
try{
JRBeanCollectionDataSource ds = new JRBeanCollectionDataSource(list);
JasperReport report = JasperCompileManager.compileReport(path);
JasperPrint print = JasperFillManager.fillReport(report,parameters,ds);
ExternalContext ectx = FacesContext.getCurrentInstance().getExternalContext();
response = (HttpServletResponse)ectx.getResponse();
OutputStream out = response.getOutputStream();
if(tipo == prmGlobal.getTipoPdf()){
byte[] bytes = JasperExportManager.exportReportToPdf(print);
response.setHeader("Content-disposition", "attachment; filename=ListadoPDF");
response.setContentType(tipo);
//response.setHeader("Cache-Control", "private");
//response.setHeader("Pragma", "");
response.setContentLength(bytes.length);
out.write(bytes);
out.flush();
out.close();
}
if(tipo == prmGlobal.getTipoExcel()){
ByteArrayOutputStream arrayOutputStream = new ByteArrayOutputStream();
JRXlsExporter exporterXLS = new JRXlsExporter();
exporterXLS.setParameter(JRXlsExporterParameter.JASPER_PRINT, print);
exporterXLS.setParameter(JRXlsExporterParameter.OUTPUT_STREAM, arrayOutputStream);
exporterXLS.setParameter(JRXlsExporterParameter.IS_ONE_PAGE_PER_SHEET, Boolean.FALSE);
exporterXLS.setParameter(JRXlsExporterParameter.IS_DETECT_CELL_TYPE, Boolean.TRUE);
exporterXLS.setParameter(JRXlsExporterParameter.IS_WHITE_PAGE_BACKGROUND, Boolean.FALSE);
exporterXLS.setParameter(JRXlsExporterParameter.IS_REMOVE_EMPTY_SPACE_BETWEEN_ROWS, Boolean.TRUE);
exporterXLS.exportReport();
response.setHeader("Content-disposition", "attachment; filename=ListadoPDF");
response.setContentType("application/vnd.ms-excel");
//response.setHeader("Cache-Control", "private");
//response.setHeader("Pragma", "");
response.setContentLength(arrayOutputStream.toByteArray().length);
out.write(arrayOutputStream.toByteArray());
out.flush();
out.close();
}
FacesContext.getCurrentInstance().responseComplete();
}
catch (JRException e){
// display stack trace in the browser
StringWriter stringWriter = new StringWriter();
PrintWriter printWriter = new PrintWriter(stringWriter);
e.printStackTrace(printWriter);
response.setContentType("text/plain");
response.getOutputStream().print(stringWriter.toString());
}
}
}