Skip to content

Commit

Permalink
Charts native support (#140)
Browse files Browse the repository at this point in the history
  • Loading branch information
melloware authored Oct 21, 2024
1 parent fca0535 commit 38592b0
Show file tree
Hide file tree
Showing 8 changed files with 133 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ void indexTransitiveDependencies(BuildProducer<IndexDependencyBuildItem> index)
index.produce(new IndexDependencyBuildItem("org.apache.xmlgraphics", "batik-css"));
index.produce(new IndexDependencyBuildItem("org.apache.xmlgraphics", "batik-dom"));
index.produce(new IndexDependencyBuildItem("org.apache.xmlgraphics", "batik-gvt"));
index.produce(new IndexDependencyBuildItem("org.apache.xmlgraphics", "batik-il8n"));
index.produce(new IndexDependencyBuildItem("org.apache.xmlgraphics", "batik-svg-dom"));
index.produce(new IndexDependencyBuildItem("org.apache.xmlgraphics", "batik-svggen"));
index.produce(new IndexDependencyBuildItem("org.apache.xmlgraphics", "batik-util"));
}

Expand Down Expand Up @@ -52,8 +54,10 @@ void runtimeBatikInitializedClasses(BuildProducer<RuntimeInitializedPackageBuild
org.apache.batik.ext.awt.image.spi.DefaultBrokenLinkProvider.class.getName(),
org.apache.batik.gvt.CompositeGraphicsNode.class.getPackageName(),
org.apache.batik.gvt.renderer.MacRenderer.class.getPackageName(),
org.apache.batik.script.InterpreterPool.class.getName(),
org.apache.batik.script.jpython.JPythonInterpreter.class.getPackageName(),
org.apache.batik.script.InterpreterPool.class.getName()).toList());
org.apache.batik.svggen.SVGClip.class.getPackageName()
).toList());
//@formatter:on
Log.debugf("Batik Runtime: %s", classes);
classes.stream()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
package io.quarkiverse.jasperreports.deployment;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;

import io.quarkus.deployment.annotations.BuildProducer;
import io.quarkus.deployment.annotations.BuildStep;
import io.quarkus.deployment.builditem.CombinedIndexBuildItem;
import io.quarkus.deployment.builditem.IndexDependencyBuildItem;
import io.quarkus.deployment.builditem.nativeimage.NativeImageResourceBuildItem;
import io.quarkus.deployment.builditem.nativeimage.NativeImageResourceBundleBuildItem;
import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
import io.quarkus.deployment.builditem.nativeimage.RuntimeInitializedPackageBuildItem;
import io.quarkus.logging.Log;

/**
* A build step class responsible for registering classes related to the JFreeChart library
* for reflection and runtime initialization during the Quarkus build process.
*/
class JFreeChartProcessor extends AbstractJandexProcessor {

@BuildStep
void indexTransitiveDependencies(BuildProducer<IndexDependencyBuildItem> index) {
index.produce(new IndexDependencyBuildItem("net.sf.jasperreports", "jasperreports-chart-customizers"));
index.produce(new IndexDependencyBuildItem("net.sf.jasperreports", "jasperreports-charts"));
index.produce(new IndexDependencyBuildItem("org.jfree", "jfreechart"));
}

@BuildStep
void runtimeChartInitializedClasses(CombinedIndexBuildItem combinedIndex,
BuildProducer<RuntimeInitializedPackageBuildItem> runtimeInitializedPackages) {
//@formatter:off
List<String> classes = new ArrayList<>(
Stream.of(
net.sf.jasperreports.charts.fill.DefaultChartTheme.class.getName(),
net.sf.jasperreports.charts.util.ChartUtil.class.getPackage().getName(),
org.jfree.chart.ChartFactory.class.getName(),
org.jfree.chart.ChartHints.class.getName(),
org.jfree.chart.JFreeChart.class.getName(),
org.jfree.chart.LegendItem.class.getName(),
org.jfree.chart.block.BlockBorder.class.getName(),
org.jfree.chart.plot.DefaultDrawingSupplier.class.getName()
).toList());
classes.addAll(collectSubclasses(combinedIndex, org.jfree.chart.axis.Axis.class.getName()));
classes.addAll(collectSubclasses(combinedIndex, org.jfree.chart.plot.Plot.class.getName()));
classes.addAll(collectSubclasses(combinedIndex, org.jfree.chart.renderer.AbstractRenderer.class.getName()));
classes.addAll(collectSubclasses(combinedIndex, org.jfree.chart.title.Title.class.getName()));
//@formatter:on
Log.debugf("JFreeChart Runtime: %s", classes);
classes.stream()
.map(RuntimeInitializedPackageBuildItem::new)
.forEach(runtimeInitializedPackages::produce);
}

@BuildStep
void registerChartForReflection(BuildProducer<ReflectiveClassBuildItem> reflectiveClass,
CombinedIndexBuildItem combinedIndex) {
final List<String> classNames = new ArrayList<>(
collectSubclasses(combinedIndex, net.sf.jasperreports.charts.base.JRBaseChartDataset.class.getName()));
classNames.addAll(collectClassesInPackage(combinedIndex,
net.sf.jasperreports.charts.util.DrawChartRendererFactory.class.getPackageName()));
classNames.addAll(collectImplementors(combinedIndex, net.sf.jasperreports.charts.JRChart.class.getName()));
classNames.addAll(collectImplementors(combinedIndex, net.sf.jasperreports.charts.JRChartPlot.class.getName()));
classNames.addAll(collectImplementors(combinedIndex, net.sf.jasperreports.charts.JRChartPlot.class.getName()));
classNames.addAll(collectImplementors(combinedIndex, net.sf.jasperreports.charts.JRXySeries.class.getName()));
classNames.addAll(
collectSubclasses(combinedIndex, net.sf.jasperreports.charts.JRAbstractChartCustomizer.class.getName()));

Log.debugf("Chart Reflection: %s", classNames);
// methods and fields
reflectiveClass.produce(
ReflectiveClassBuildItem.builder(classNames.toArray(new String[0])).methods().fields().serialization().build());
}

@BuildStep
void registerChartResources(BuildProducer<NativeImageResourceBuildItem> nativeImageResourceProducer,
BuildProducer<NativeImageResourceBundleBuildItem> resourceBundleBuildItem) {
//@formatter:off
resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("org.jfree.chart.LocalizationBundle"));
resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("org.jfree.chart.LocalizationBundle_ca"));
resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("org.jfree.chart.LocalizationBundle_cs"));
resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("org.jfree.chart.LocalizationBundle_de"));
resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("org.jfree.chart.LocalizationBundle_es"));
resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("org.jfree.chart.LocalizationBundle_fr"));
resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("org.jfree.chart.LocalizationBundle_it"));
resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("org.jfree.chart.LocalizationBundle_ja"));
resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("org.jfree.chart.LocalizationBundle_nl"));
resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("org.jfree.chart.LocalizationBundle_pl"));
resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("org.jfree.chart.LocalizationBundle_pt_BR"));
resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("org.jfree.chart.LocalizationBundle_pt_PT"));
resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("org.jfree.chart.LocalizationBundle_ru"));
resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("org.jfree.chart.LocalizationBundle_xh_CN"));
resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("org.jfree.chart.LocalizationBundle_xh_TW"));

resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("org.jfree.chart.plot.LocalizationBundle"));
resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("org.jfree.chart.plot.LocalizationBundle_ca"));
resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("org.jfree.chart.plot.LocalizationBundle_cs"));
resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("org.jfree.chart.plot.LocalizationBundle_de"));
resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("org.jfree.chart.plot.LocalizationBundle_es"));
resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("org.jfree.chart.plot.LocalizationBundle_fr"));
resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("org.jfree.chart.plot.LocalizationBundle_it"));
resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("org.jfree.chart.plot.LocalizationBundle_ja"));
resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("org.jfree.chart.plot.LocalizationBundle_nl"));
resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("org.jfree.chart.plot.LocalizationBundle_pl"));
resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("org.jfree.chart.plot.LocalizationBundle_pt_PT"));
resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("org.jfree.chart.plot.LocalizationBundle_ru"));
resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("org.jfree.chart.plot.LocalizationBundle_xh_CN"));

resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("org.jfree.chart.ui.LocalizationBundle"));
resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("org.jfree.chart.ui.LocalizationBundle_de"));
resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("org.jfree.chart.ui.LocalizationBundle_es"));
resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("org.jfree.chart.ui.LocalizationBundle_fr"));
resourceBundleBuildItem.produce(new NativeImageResourceBundleBuildItem("org.jfree.chart.ui.LocalizationBundle_pt_PT"));
//@formatter:on
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,6 @@ UberJarMergedResourceBuildItem mergeResource() {
@BuildStep
void indexTransitiveDependencies(BuildProducer<IndexDependencyBuildItem> 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"));
Expand Down Expand Up @@ -223,6 +220,7 @@ void registerForReflection(CombinedIndexBuildItem combinedIndex, BuildProducer<R
classNames.add(java.util.Map.class.getName());
classNames.add(java.util.Set.class.getName());
classNames.add(java.util.TreeMap.class.getName());
classNames.add(java.util.TreeSet.class.getName());
classNames.add(java.util.UUID.class.getName());
classNames.add(java.util.Vector.class.getName());
classNames.addAll(collectImplementors(combinedIndex, java.time.temporal.TemporalAccessor.class.getName()));
Expand All @@ -249,7 +247,6 @@ void runtimeInitializedClasses(CombinedIndexBuildItem combinedIndex,
//@formatter:off
List<String> classes = collectImplementors(combinedIndex, net.sf.jasperreports.extensions.ExtensionsRegistryFactory.class.getName());
classes.addAll(Stream.of(
"java.awt",
"javax.swing",
"javax.swing.plaf.metal",
"javax.swing.text.html",
Expand Down
2 changes: 1 addition & 1 deletion integration-tests/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@
<skipITs>true</skipITs>
<quarkus.native.enabled>true</quarkus.native.enabled>
<quarkus.native.additional-build-args>
--trace-object-instantiation=net.sf.jasperreports.engine.component.DefaultComponentsBundle
--trace-object-instantiation=java.awt.BasicStroke
</quarkus.native.additional-build-args>
</properties>
<build>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,4 @@ public void customize(final JFreeChart freeChart, final JRChart jasperChart) {
new XYBoxAnnotation(startX, 0.0d, endX, yRange.getUpperBound() / 2.0d, new BasicStroke(), green, green));
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.ServerErrorException;
import jakarta.ws.rs.core.HttpHeaders;
import jakarta.ws.rs.core.Response;

import io.quarkus.logging.Log;
Expand All @@ -23,9 +24,12 @@ public class JasperReportChartResource {
@GET
@Path("")
@Produces(ExtendedMediaType.APPLICATION_PDF)
public byte[] pdf() {
public Response pdf() {
try {
return databaseReportService.pdf("CustomChart.jasper");
final Response.ResponseBuilder response = Response.ok(databaseReportService.pdf("CustomChart.jasper"));
response.header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=charts.pdf");
response.header(HttpHeaders.CONTENT_TYPE, ExtendedMediaType.APPLICATION_PDF);
return response.build();
} catch (final JRException | SQLException ex) {
Log.error("Unexpected DB Error", ex);
throw new ServerErrorException(Response.Status.INTERNAL_SERVER_ERROR, ex);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@
import io.quarkus.test.junit.QuarkusIntegrationTest;

@QuarkusIntegrationTest
public class JasperReportChartResourceIT {
public class JasperReportChartResourceIT extends JasperReportChartResourceTest {
// Execute the same tests but in packaged mode.
}
}
4 changes: 0 additions & 4 deletions runtime/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,6 @@
<groupId>net.sf.jasperreports</groupId>
<artifactId>jasperreports-chart-customizers</artifactId>
</dependency>
<dependency>
<groupId>net.sf.jasperreports</groupId>
<artifactId>jasperreports-chart-themes</artifactId>
</dependency>
<dependency>
<groupId>net.sf.jasperreports</groupId>
<artifactId>jasperreports-charts</artifactId>
Expand Down

0 comments on commit 38592b0

Please sign in to comment.