Antes de nada, Feliz año a mis escasos lectores. Últimamente ando enfangado de nuevo con Java y por supuesto, con JasperReport para sacar informes. Con la aplicación que estoy desarrollando actualmente, estoy utilizando Icefaces 3 para JSF, que da muchas facilidades para crear aplicaciones rápidamente y atractivas, tanto visual como funcionalmente. Una de las cualidades de esta versión del framework, esque todo va por AJAX. Esto, al llegar al momento de presentar al usuario los informes creados con JasperReport, supone un problema. Ya que normalmente, nos inmiscuimos en el ciclo de vida de JSF para capturar la respuesta e imprimir nuestro informe, y esto no le sienta muy bien al framework.  Así que tras unas cuantas peleas y cabezazos contra el teclado, he conseguido llegar a una solución. Dicha solución consiste en sacar el informe en otra ventana, fuera del flujo de Icefaces. Y para presentar el informe, utilizo directamente un Servlet para generar la respuesta. Paso a explicar paso a paso.

Lo primero, tenemos en nuestro archivo .xhtml lo siguiente:

<h:commandButton id="pushButtonId12"  actionListener="#{informes.pdfEdificios}"  />

Utilizamos actionListener, para que no haga ningún refresco del contenido. Ahora, el código del método encargado de manejar dicho evento es el siguiente:


public String pdfEdificios(ActionEvent event) throws IOException{
try {
Connection con = edificiosDao.getConnection();
HashMap parameters = new HashMap();
String reportsDirectory = "c:/Users/Usuario/Documents/NetBeansProjects/Proyecto/build/web/";
String jasperName = "report1.jasper";
JasperPrint jasperPrint = UtilReports.generateReport(con, reportsDirectory, jasperName, parameters);
getSessionMap().put("report",jasperPrint);
JavascriptContext.addJavascriptCall(FacesContext.getCurrentInstance(), "window.open('Report', 'myWindow');");
} catch (NamingException ex) {
Logger.getLogger(Informes.class.getName()).log(Level.SEVERE, null, ex);
} catch (SQLException ex) {
Logger.getLogger(Informes.class.getName()).log(Level.SEVERE, null, ex);
} catch (JRException ex) {
Logger.getLogger(Informes.class.getName()).log(Level.SEVERE, null, ex);
} catch (FileNotFoundException ex) {
Logger.getLogger(Informes.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}

En este método, simplemente generamos el informe mediante UtilReports.generateReport(con, reportsDirectory, jasperName, parameters), una vez hecho, guardamosel objeto JasperPrint a la sesión, para poder recuperarlo después en el Servlet.
Hasta este punto, ya tenemos el informe creado y guardado en la sesión, ahora necesitamos abrir el Servlet automáticamente para llevar el informe al usuario. Para ello, Icefaces nos proporciona JavascriptContext, desde el cual podemos añadir código javascript enviado desde el servidor.
Así que mediante JavascriptContext.addJavascriptCall(FacesContext.getCurrentInstance(), “window.open(‘Report’, ‘myWindow’);”); enviamos el código para que se abra una ventana nueva que lleva al servlet Report. Que habremos creado previamente con el siguiente código para manejar la respuesta:

protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
try {
JasperPrint report =(JasperPrint) request.getSession().getAttribute("report");
response.setContentType("application/pdf");
response.setHeader("Content-Disposition", "attachment; filename=" + "report" + ".pdf;");
response.setHeader("Cache-Control", "no-cache");
response.setHeader("Pragma", "no-cache");
response.setDateHeader("Expires", 0);
JRExporter exporter = new JRPdfExporter();
exporter.setParameter(JRExporterParameter.JASPER_PRINT, report);
exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, response.getOutputStream());
exporter.exportReport();
} catch (JRException ex) {
Logger.getLogger(Report.class.getName()).log(Level.SEVERE, null, ex);
}finally{
request.getSession().removeAttribute("report");
}

}

Aquí, recuperamos de la sesión el objeto JasperPrint de nuestro informes y preparamos las cabeceras de la respuesta para indicar el tipo, y utilizamos un exporter para exportar el informe en el formato deseado (normalmente pdf). Por último, es importante poner en el bloque finally, la liberación del objeto de la sesión, para no sobrecargar la memoria del servidor.
Esta es la única forma que he encontrado, de momento, para poder mostrar los informes sin entrar en conflicto con Icefaces. Si alguién tiene una solución mejor, que no dude en comentarlo.

« »