JasperReports

A Quarkus extension that lets you utilize JasperReports. JasperReports is an open source Java reporting tool that can write to a variety of targets, such as: screen, a printer, into PDF, HTML, Microsoft Excel, RTF, ODT, comma-separated values (CSV), XSL, or XML files.

Installation

If you want to use this extension, you need to add the io.quarkiverse.jasperreports:quarkus-jasperreports extension first to your build file.

For instance, with Maven, add the following dependency to your POM file:

<dependency>
    <groupId>io.quarkiverse.jasperreports</groupId>
    <artifactId>quarkus-jasperreports</artifactId>
    <version>0.0.3</version>
</dependency>

Compiling Reports

Jasper does not recommend compiling .jrxml reports on the fly, but if necessary, it can be done only in JVM mode. This approach will NOT work in native mode, as there is no Java compiler available and the required classes for compilation are missing. The best practice is to use precompiled .jasper files instead.

Compiling .jrxml files will not work in Native mode!

Database Datasource

When utilizing an Agroal Datasource to generate your report, ensure it is not within an active transaction. JasperReports employs threads for sub-reports and various features, and a connection cannot be passed across thread boundaries while in a transaction. Failing to do so will result in the following error: Enlisted connection used without active transaction.

Caused by: java.sql.SQLException: Enlisted connection used without active transaction
2024-07-22T21:24:13.599110173Z  at io.agroal.pool.ConnectionHandler.verifyEnlistment(ConnectionHandler.java:398)
2024-07-22T21:24:13.599149982Z  at io.agroal.pool.wrapper.ConnectionWrapper.getMetaData(ConnectionWrapper.java:452)
2024-07-22T21:24:13.599212173Z  at net.sf.jasperreports.engine.query.OracleProcedureCallHandler.isOracle(OracleProcedureCallHandler.java:72)
2024-07-22T21:24:13.599341106Z  at net.sf.jasperreports.engine.query.JRJdbcQueryExecuter.isProcedureCall(JRJdbcQueryExecuter.java:566)
2024-07-22T21:24:13.599481640Z  at net.sf.jasperreports.engine.query.JRJdbcQueryExecuter.createStatement(JRJdbcQueryExecuter.java:389)
In your service you must use @Transactional(Transactional.TxType.NEVER) above the method that is filling your report.
@Inject
DataSource datasource;

@Transactional(Transactional.TxType.NEVER)
public byte[] text() throws JRException, SQLException {
    JasperPrint jasperPrint = null;
     try (final Connection connection = datasource.getConnection()) {
         params.put(JRParameter.REPORT_CONNECTION, connection);

         jasperPrint = JRFiller.fill(DefaultJasperReportsContext.getInstance(), SimpleJasperReportSource.from(mainReport, null, new SimpleRepositoryResourceContext()), params);
     }
    final JRTextExporter exporter = new JRTextExporter();
    exporter.setExporterInput(new SimpleExporterInput(jasperPrint));
    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
    exporter.setExporterOutput(new SimpleWriterExporterOutput(outputStream));
    exporter.exportReport();
    return outputStream.toByteArray();
}

Native Container

When building native images in Docker using the standard Quarkus Docker configuration files some additional features need to be installed to support fonts. Specifically font information is not included in Red Hat’s ubi-minimal images. To install it simply add these lines to your DockerFile.native file:

FROM registry.access.redhat.com/ubi8/ubi-minimal:8.9

######################### Set up environment for POI ##########################
RUN microdnf update && microdnf install freetype fontconfig && microdnf clean all
######################### Set up environment for POI ##########################

WORKDIR /work/
RUN chown 1001 /work \
    && chmod "g+rwX" /work \
    && chown 1001:root /work
# Shared objects to be dynamically loaded at runtime as needed,
COPY --chown=1001:root target/*.properties target/*.so /work/
COPY --chown=1001:root target/*-runner /work/application
# Permissions fix for Windows
RUN chmod "ugo+x" /work/application
EXPOSE 8080
USER 1001

CMD ["./application", "-Dquarkus.http.host=0.0.0.0"]
Make sure .dockerignore does not exclude .so files!

Read-Only Streaming Service

A JasperReports repository can handle loading all of the resources a report needs, including any referenced subreports. Simply inject the repository, then use it with the fill manager to produce the report.

    @Inject
    ReadOnlyStreamingService repo;

    public JasperPrint fill() throws JRException {
        Map<String, Object> params = new HashMap<>();
        return JasperFillManager.getInstance(repo.getContext()).fillFromRepo("MyReport.jasper", params);
    }

Extension Configuration Reference

Configuration property fixed at build time - All other configuration properties are overridable at runtime

Configuration property

Type

Default

Enable building all report files.

Environment variable: QUARKUS_JASPERREPORTS_BUILD_ENABLE

boolean

true

The path where all source .jrxml and .jrtx files are located.

Environment variable: QUARKUS_JASPERREPORTS_BUILD_SOURCE

path

src/main/jasperreports

The path where compiled reports are located next to compiled classes.

Environment variable: QUARKUS_JASPERREPORTS_BUILD_DESTINATION

path

jasperreports