Spring MVC Reportes con DynamicReports

En el tutorial Spring MVC JasperReports aprendimos a generar vistas (PDF, HTML, XLS, etc.) con la librería de reportes antes mencionada, en este post veremos como generar los reportes sin necesidad de utilizar las plantillas JRXML, el diseño del reporte será creado programáticamente con la biblioteca DynamicJasper diseñada para tal propósito, lo aprendido se puede aplicar a otras librerías similares como, DynamicReports por ejemplo.

Lo primero, como siempre, es agregar las dependencias para poder utilizar la librería DynamicJasper.

<!-- Dynamic Jasper -->
<dependency>
    <groupId>ar.com.fdvs</groupId>
    <artifactId>DynamicJasper</artifactId>
    <version>5.0.10</version>
</dependency>

<!-- Excel XLS View -->
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>3.14</version>
</dependency>

La segunda dependencia es opcional, la añadimos solo si deseamos generar vistas Excel XLS.

Nuestra configuración queda del siguiente modo, definimos dos ViewResolver uno para las vistas JSP y otro para los reportes.

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = {
    "carmelo.spring.controller",
    "carmelo.spring.service"})
public class WebAppConfig {

    @Bean
    public ViewResolver reportViewResolver() {
        JasperReportsViewResolver resolver = new JasperReportsViewResolver();
        resolver.setViewNames("*_DynamicReport");
        resolver.setViewClass(DynamicReportView.class);
        resolver.setOrder(1);
        return resolver;
    }

    @Bean
    public ViewResolver jspViewResolver() {
        InternalResourceViewResolver resolver = new InternalResourceViewResolver();
        resolver.setPrefix("/WEB-INF/views/");
        resolver.setSuffix(".jsp");
        resolver.setOrder(2);
        return resolver;
    }
}

El JasperReportsViewResolver ya lo usamos en el tutorial Spring MVC con JasperReports, setViewNames("*_DynamicReport") estable el nombre de las vistas que manejaremos con este ViewResolver, en este ejemplo todas la vistas cuyo nombre termine en _DynamicReport.

La clase DynamicReportView la crearemos nosotros, esta es nuestra implementación, la cual será la encargada de generar las vistas, para facilitar nuestro trabajo de programación extenderemos la clase JasperReportsMultiFormatView.

public class DynamicReportView extends JasperReportsMultiFormatView {

    @Override
    protected JasperReport loadReport() {
        return null;
    }

    @Override
    protected JasperPrint fillReport(Map<String, Object> model) throws Exception {

        JRDataSource ds = new JRBeanCollectionDataSource((Collection<?>) model.get("datasource"));
        ReportGenerator rg = (ReportGenerator) model.get("generator");
        
        JasperReport jr = rg.generateReport(model);
        JasperPrint jp = JasperFillManager.fillReport(jr, model, ds);
        
        return jp;
    }
 
}

El método loadReport() carga el archivo .jrxml o .jasper pero ya no lo necesitamos, el método fillReport(Map model) lo usaremos para generar el reporte, usando el modelo le pasaremos la fuente de datos y un objeto ReportGenerator que se define de la siguiente manera.

import java.util.Map;
import net.sf.jasperreports.engine.JasperReport;

public interface ReportGenerator {
    JasperReport generateReport(Map params);
}

Usando esta interface indicaremos cual será el método encargado de generar el reporte.

En nuestro controlador debemos agregar los atributos necesarios al modelo, datasource, generator y format, adicionalmente agregamos cualquier otros parámetro para el reporte.

@Controller
public class CustomerController {

    @Autowired
    private CustomerService customerService;

    @RequestMapping("/report/{fmt}")
    public String report(@PathVariable("fmt") String format, Model model) {

        model.addAttribute("format", format);
        model.addAttribute("datasource", customerService.findAll());
        model.addAttribute("generator", (ReportGenerator) this::customerReport);

        return "customer_DynamicReport";
    }

    private JasperReport customerReport(Map params) {
        try {
            FastReportBuilder drb = new FastReportBuilder();
            drb
                    .addColumn("ID", "ID", Integer.class.getName(), 10)
                    .addColumn("FIRSTNAME", "FIRSTNAME", String.class.getName(), 50)
                    .addColumn("LASTNAME", "LASTNAME", String.class.getName(), 50)
                    .addColumn("STREET", "STREET", String.class.getName(), 50)
                    .addColumn("CITY", "CITY", String.class.getName(), 50)
                    .setTitle("Primer informe con Dynamic Jasper")
                    .setPrintBackgroundOnOddRows(true)
                    .setUseFullPageWidth(true);

            return DynamicJasperHelper.generateJasperReport(
                    drb.build(), new ClassicLayoutManager(), params);

        } catch (ColumnBuilderException | ClassNotFoundException | JRException ex) {
            Logger.getLogger(CustomerController.class.getName()).log(Level.SEVERE, null, ex);
            return null;
        }
    }
}

El método customerReport(Map model) es el encargado de generar el reporte usando la librería DynamicJasper dependiendo de tu proyecto aquí deberán agregar o quitar elementos del diseño del reporte, se puede utilizar cualquier otra librería.

Spring MVC con DynamicReports

El formato de salida de la vistas esta definido en una variable en la URL:

  • Excel: localhost:8084/dynamicjasper/report/xls
  • PDF: localhost:8084/dynamicjasper/report/pdf
  • CSV: localhost:8084/dynamicjasper/report/csv

Es todo por ahora nos vemos en la próxima.

Comentarios

Entradas populares de este blog

Conectar SQL Server con Java

Conociendo la clase cv::Mat de OpenCV

Entrenar OpenCV en Detección de Objetos

Procesamiento de imágenes en OpenCV

Acceso a la webcam con OpenCV