domingo, 1 de marzo de 2015

Reportes dinámicos con PrimeFaces y JasperReports [Java]

Qué tal, bienvenido a esta nueva publicación, el día de hoy les mostraré como crear reportes dinámicos con Primefaces y JasperReports.

La historia comienza con una necesidad que tenía para mis proyectos de aplicación web, en los cuales tenía que mostrar reportes en ciertas secciones de una pantalla que constantemente cambiarían de información, es decir dependían de ciertos valores para su generación.

La idea inicial era que pudiera ser capaz de mostrar un pdf que a lo largo del ciclo de vida de la aplicación siempre estaría cambiando de forma, por lo que se me vino a la cabeza que podía generar un archivo .pdf y después mostrarlo en pantalla, pero, ¿cómo podría hacer esto?.

Después de investigar un poco me di cuenta que PrimeFaces nos proporciona un componente para mostrar todo tipo de contenidos entre estos un pdf, hablo del Componente Media que hablando en términos más técnicos de programación hace uso de un objeto StreamedContent para renderizar contenidos.

Ahora, la idea había evolucionado, si con el método exportReportToPdfStream de JasperExportManager puedo guardar el pdf generado en un OutputStream entonces este lo podría utilizar para crear un StreamedContent y aquí la prueba:

Country.java


Esta es la clase que utilizaré para mantener la información del reporte, el archivo .jasper ya te imaginarás que el diseño solo consta de 2 columnas id y name.

report.xhtml

Lo siento, solo mostraré lo necesario de este archivo, se conforma de un formulario que contiene un inputText, un commandButton que llama al método generateReport, el commandButton Descargar que llama al método downloadFile, el componente Media y algunas condiciones de renderizado.
Nota: el componente media debe tener en false la propiedad cache, de otra forma te dará un buen dolor de cabeza.

JasperReportUtil.java


La clase de utilería JasperReportUtil contiene 3 métodos:

  • getOutputStreamFromReport que retorna un ByteArrayOutputStream a partir de la lista de elementos que deseas renderizar en tu reporte, algún mapa con parámetros y el path del archivo .jasper,
  • getStreamContentFromOutputStream que retorna un StreamedContent a partir de un objeto ByteArrayOutputStream, una cadena con el tipo de contenido a generar y el nombre del archivo. 
  • getStreamContentReport este método es el camino corto (fusiona los 2 métodos anteriores [lo pensaba utilizar en un caso especial, no necesito explicarlo]).

ReportTestController.java


De esta clase seré breve, los 2 métodos que se llaman son generateReport y downloadFile.

El primero genera datos dummys y haciendo uso de la clase de utilería antes mencionada genera el StreamedContent  para que el componente media lo utilice y muestre el pdf.

El segundo método permite descargar el archivo pdf, observar que PrimeFaces ya provee un componente para descargar pero si intentas guardar el pdf o utilizar el componente FileDownload el archivo se descargar corrupto, desconozco la razón.

Una captura de lo que obtienes:


    Choose :
  • OR
  • To comment
8 comentarios:
Write comentarios
  1. Hola, no he logrando que se pinte en la pantalla, si lo descarga pero no lo renderiza, sabes a que se puede deber esto?

    ResponderEliminar
  2. Muchas gracias, me ha servido para descargarlo

    ResponderEliminar
  3. Hola, es posible tan solo descargar el reporte sin necesidad de generarlo?

    ResponderEliminar
  4. Hola!
    No podía llenar un reporte con una Lista, tenía días con ese problema hasta que encontré tu post, tuve que modificar el JasperUtil y agregar el CollectionDataSource. Muchas gracias :)

    ResponderEliminar
  5. me duelve el siguiente error alguna idea que puede estar pasando?
    SEVERE
    [org.primefaces.application.resource.StreamedContentHandler] (default task-15) Error in streaming dynamic resource. null

    ResponderEliminar