From f6a2fc669476b3a4e4510956ac158ad506a76016 Mon Sep 17 00:00:00 2001 From: Nathan Erwin <3226831+nderwin@users.noreply.github.com> Date: Mon, 21 Oct 2024 10:40:03 -0400 Subject: [PATCH] chart customization example (#139) * added the charting dependencies * index the transitive dependencies for the above * a little refactor to the database report service to make it usable by multiple endpoints * added an example report with a chart customizer to add a green box to the bottom half of the chart * added an endpoint to expose the chart report as a PDF document * added unit and integration tests for the chart endpoint Signed-off-by:Nathan Erwin --- .../deployment/JasperReportsProcessor.java | 7 +++- .../src/main/jasperreports/CustomChart.jrxml | 38 +++++++++++++++++++ .../jasperreports/it/ChartCustomizer.java | 33 ++++++++++++++++ .../it/DatabaseReportService.java | 23 +++++++---- .../it/JasperReportChartResource.java | 35 +++++++++++++++++ .../it/JasperReportsDatabaseResource.java | 4 +- .../it/JasperReportChartResourceIT.java | 8 ++++ .../it/JasperReportChartResourceTest.java | 26 +++++++++++++ pom.xml | 15 ++++++++ runtime/pom.xml | 12 ++++++ 10 files changed, 192 insertions(+), 9 deletions(-) create mode 100644 integration-tests/src/main/jasperreports/CustomChart.jrxml create mode 100644 integration-tests/src/main/java/io/quarkiverse/jasperreports/it/ChartCustomizer.java create mode 100644 integration-tests/src/main/java/io/quarkiverse/jasperreports/it/JasperReportChartResource.java create mode 100644 integration-tests/src/test/java/io/quarkiverse/jasperreports/it/JasperReportChartResourceIT.java create mode 100644 integration-tests/src/test/java/io/quarkiverse/jasperreports/it/JasperReportChartResourceTest.java diff --git a/deployment/src/main/java/io/quarkiverse/jasperreports/deployment/JasperReportsProcessor.java b/deployment/src/main/java/io/quarkiverse/jasperreports/deployment/JasperReportsProcessor.java index b699750..da686f7 100644 --- a/deployment/src/main/java/io/quarkiverse/jasperreports/deployment/JasperReportsProcessor.java +++ b/deployment/src/main/java/io/quarkiverse/jasperreports/deployment/JasperReportsProcessor.java @@ -105,6 +105,9 @@ UberJarMergedResourceBuildItem mergeResource() { @BuildStep void indexTransitiveDependencies(BuildProducer index) { index.produce(new IndexDependencyBuildItem("net.sf.jasperreports", "jasperreports")); + index.produce(new IndexDependencyBuildItem("net.sf.jasperreports", "jasperreports-charts")); + index.produce(new IndexDependencyBuildItem("net.sf.jasperreports", "jasperreports-chart-customizers")); + index.produce(new IndexDependencyBuildItem("net.sf.jasperreports", "jasperreports-chart-themes")); index.produce(new IndexDependencyBuildItem("net.sf.jasperreports", "jasperreports-data-adapters")); index.produce(new IndexDependencyBuildItem("net.sf.jasperreports", "jasperreports-excel-poi")); index.produce(new IndexDependencyBuildItem("net.sf.jasperreports", "jasperreports-jdt")); @@ -245,7 +248,9 @@ void runtimeInitializedClasses(CombinedIndexBuildItem combinedIndex, BuildProducer runtimeInitializedPackages) { //@formatter:off List classes = collectImplementors(combinedIndex, net.sf.jasperreports.extensions.ExtensionsRegistryFactory.class.getName()); - classes.addAll(Stream.of("javax.swing", + classes.addAll(Stream.of( + "java.awt", + "javax.swing", "javax.swing.plaf.metal", "javax.swing.text.html", "javax.swing.text.rtf", diff --git a/integration-tests/src/main/jasperreports/CustomChart.jrxml b/integration-tests/src/main/jasperreports/CustomChart.jrxml new file mode 100644 index 0000000..0b06f5d --- /dev/null +++ b/integration-tests/src/main/jasperreports/CustomChart.jrxml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/integration-tests/src/main/java/io/quarkiverse/jasperreports/it/ChartCustomizer.java b/integration-tests/src/main/java/io/quarkiverse/jasperreports/it/ChartCustomizer.java new file mode 100644 index 0000000..bef9b6c --- /dev/null +++ b/integration-tests/src/main/java/io/quarkiverse/jasperreports/it/ChartCustomizer.java @@ -0,0 +1,33 @@ +package io.quarkiverse.jasperreports.it; + +import java.awt.BasicStroke; +import java.awt.Color; + +import org.jfree.chart.JFreeChart; +import org.jfree.chart.annotations.XYBoxAnnotation; +import org.jfree.chart.plot.XYPlot; +import org.jfree.chart.renderer.xy.XYItemRenderer; +import org.jfree.data.Range; + +import net.sf.jasperreports.charts.JRAbstractChartCustomizer; +import net.sf.jasperreports.charts.JRChart; + +public class ChartCustomizer extends JRAbstractChartCustomizer { + + @Override + public void customize(final JFreeChart freeChart, final JRChart jasperChart) { + final XYPlot plot = freeChart.getXYPlot(); + final XYItemRenderer renderer = plot.getRenderer(); + final Range range = renderer.findDomainBounds(plot.getDataset()); + final Range yRange = plot.getDataRange(plot.getRangeAxis()); + + final double startX = range.getLowerBound() - 1.0d; + final double endX = range.getUpperBound() + 1.0d; + + final Color green = new Color(0, 192, 0, 64); + + renderer.addAnnotation( + new XYBoxAnnotation(startX, 0.0d, endX, yRange.getUpperBound() / 2.0d, new BasicStroke(), green, green)); + } + +} diff --git a/integration-tests/src/main/java/io/quarkiverse/jasperreports/it/DatabaseReportService.java b/integration-tests/src/main/java/io/quarkiverse/jasperreports/it/DatabaseReportService.java index 9c8d4f0..6192af0 100644 --- a/integration-tests/src/main/java/io/quarkiverse/jasperreports/it/DatabaseReportService.java +++ b/integration-tests/src/main/java/io/quarkiverse/jasperreports/it/DatabaseReportService.java @@ -22,23 +22,22 @@ import net.sf.jasperreports.engine.SimpleReportContext; import net.sf.jasperreports.engine.export.JRTextExporter; import net.sf.jasperreports.export.SimpleExporterInput; +import net.sf.jasperreports.export.SimpleOutputStreamExporterOutput; import net.sf.jasperreports.export.SimpleWriterExporterOutput; +import net.sf.jasperreports.pdf.JRPdfExporter; @ApplicationScoped @Transactional(Transactional.TxType.NEVER) public class DatabaseReportService extends AbstractJasperResource { - private static final String TEST_REPORT_NAME = "DbDatasourceMain.jasper"; - @Inject ReadOnlyStreamingService repo; @Inject DataSource datasource; - @Transactional(Transactional.TxType.NEVER) - public byte[] text() throws JRException, SQLException { - final JasperPrint jasperPrint = fill(); + public byte[] text(final String reportName) throws JRException, SQLException { + final JasperPrint jasperPrint = fill(reportName); final JRTextExporter exporter = new JRTextExporter(); exporter.setExporterInput(new SimpleExporterInput(jasperPrint)); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); @@ -47,7 +46,17 @@ public byte[] text() throws JRException, SQLException { return outputStream.toByteArray(); } - private JasperPrint fill() throws JRException, SQLException { + public byte[] pdf(final String reportName) throws JRException, SQLException { + final JasperPrint jasperPrint = fill(reportName); + final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + final JRPdfExporter exporter = new JRPdfExporter(); + exporter.setExporterInput(new SimpleExporterInput(jasperPrint)); + exporter.setExporterOutput(new SimpleOutputStreamExporterOutput(outputStream)); + exporter.exportReport(); + return outputStream.toByteArray(); + } + + private JasperPrint fill(final String reportName) throws JRException, SQLException { final ReportContext reportContext = new SimpleReportContext(); final Map params = new HashMap<>(); @@ -55,7 +64,7 @@ private JasperPrint fill() throws JRException, SQLException { params.put(JRParameter.REPORT_CONTEXT, reportContext); try (final Connection connection = datasource.getConnection()) { - return JasperFillManager.getInstance(repo.getContext()).fillFromRepo(TEST_REPORT_NAME, params, connection); + return JasperFillManager.getInstance(repo.getContext()).fillFromRepo(reportName, params, connection); } } diff --git a/integration-tests/src/main/java/io/quarkiverse/jasperreports/it/JasperReportChartResource.java b/integration-tests/src/main/java/io/quarkiverse/jasperreports/it/JasperReportChartResource.java new file mode 100644 index 0000000..cf6d32b --- /dev/null +++ b/integration-tests/src/main/java/io/quarkiverse/jasperreports/it/JasperReportChartResource.java @@ -0,0 +1,35 @@ +package io.quarkiverse.jasperreports.it; + +import java.sql.SQLException; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.ServerErrorException; +import jakarta.ws.rs.core.Response; + +import io.quarkus.logging.Log; +import net.sf.jasperreports.engine.JRException; + +@Path("jasper/chart") +@ApplicationScoped +public class JasperReportChartResource { + + @Inject + DatabaseReportService databaseReportService; + + @GET + @Path("") + @Produces(ExtendedMediaType.APPLICATION_PDF) + public byte[] pdf() { + try { + return databaseReportService.pdf("CustomChart.jasper"); + } catch (final JRException | SQLException ex) { + Log.error("Unexpected DB Error", ex); + throw new ServerErrorException(Response.Status.INTERNAL_SERVER_ERROR, ex); + } + } + +} diff --git a/integration-tests/src/main/java/io/quarkiverse/jasperreports/it/JasperReportsDatabaseResource.java b/integration-tests/src/main/java/io/quarkiverse/jasperreports/it/JasperReportsDatabaseResource.java index 34b9a7f..57ed880 100644 --- a/integration-tests/src/main/java/io/quarkiverse/jasperreports/it/JasperReportsDatabaseResource.java +++ b/integration-tests/src/main/java/io/quarkiverse/jasperreports/it/JasperReportsDatabaseResource.java @@ -34,6 +34,8 @@ @ApplicationScoped public class JasperReportsDatabaseResource extends AbstractJasperResource { + private static final String TEST_REPORT_NAME = "DbDatasourceMain.jasper"; + @Inject DatabaseReportService databaseReportService; @@ -48,7 +50,7 @@ public String entities() { @Produces(MediaType.TEXT_PLAIN) public String text() { try { - return new String(databaseReportService.text()); + return new String(databaseReportService.text(TEST_REPORT_NAME)); } catch (final JRException | SQLException ex) { Log.error("Unexpected DB Error", ex); throw new ServerErrorException(Response.Status.INTERNAL_SERVER_ERROR, ex); diff --git a/integration-tests/src/test/java/io/quarkiverse/jasperreports/it/JasperReportChartResourceIT.java b/integration-tests/src/test/java/io/quarkiverse/jasperreports/it/JasperReportChartResourceIT.java new file mode 100644 index 0000000..9dc9aff --- /dev/null +++ b/integration-tests/src/test/java/io/quarkiverse/jasperreports/it/JasperReportChartResourceIT.java @@ -0,0 +1,8 @@ +package io.quarkiverse.jasperreports.it; + +import io.quarkus.test.junit.QuarkusIntegrationTest; + +@QuarkusIntegrationTest +public class JasperReportChartResourceIT { + // Execute the same tests but in packaged mode. +} diff --git a/integration-tests/src/test/java/io/quarkiverse/jasperreports/it/JasperReportChartResourceTest.java b/integration-tests/src/test/java/io/quarkiverse/jasperreports/it/JasperReportChartResourceTest.java new file mode 100644 index 0000000..c825ff1 --- /dev/null +++ b/integration-tests/src/test/java/io/quarkiverse/jasperreports/it/JasperReportChartResourceTest.java @@ -0,0 +1,26 @@ +package io.quarkiverse.jasperreports.it; + +import static io.restassured.RestAssured.given; +import static org.hamcrest.Matchers.greaterThan; +import static org.hamcrest.Matchers.notNullValue; + +import jakarta.ws.rs.core.HttpHeaders; + +import org.junit.jupiter.api.Test; + +import io.quarkus.test.junit.QuarkusTest; + +@QuarkusTest +public class JasperReportChartResourceTest { + + @Test + public void testPdfExport() { + given() + .when().get("/jasper/chart") + .then() + .statusCode(200) + .header(HttpHeaders.CONTENT_LENGTH, Integer::parseInt, greaterThan(0)) + .body(notNullValue()); + } + +} diff --git a/pom.xml b/pom.xml index 343f70e..6114286 100644 --- a/pom.xml +++ b/pom.xml @@ -69,6 +69,21 @@ jasperreports ${version.jasperreports} + + net.sf.jasperreports + jasperreports-chart-customizers + ${version.jasperreports} + + + net.sf.jasperreports + jasperreports-chart-themes + ${version.jasperreports} + + + net.sf.jasperreports + jasperreports-charts + ${version.jasperreports} + net.sf.jasperreports jasperreports-jdt diff --git a/runtime/pom.xml b/runtime/pom.xml index b92d8f4..5dcd90b 100644 --- a/runtime/pom.xml +++ b/runtime/pom.xml @@ -38,6 +38,18 @@ + + net.sf.jasperreports + jasperreports-chart-customizers + + + net.sf.jasperreports + jasperreports-chart-themes + + + net.sf.jasperreports + jasperreports-charts + net.sf.jasperreports jasperreports-fonts