Skip to content

Commit

Permalink
Barcode4J and QRCode support
Browse files Browse the repository at this point in the history
  • Loading branch information
melloware committed Oct 16, 2024
1 parent 004bbf5 commit 3310295
Show file tree
Hide file tree
Showing 13 changed files with 315 additions and 27 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
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.IndexDependencyBuildItem;
import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
import io.quarkus.deployment.builditem.nativeimage.RuntimeInitializedPackageBuildItem;
import io.quarkus.logging.Log;

/**
* Register Barcode4J and ZXING barcode libraries.
*/
public class BarcodeProcessor {

@BuildStep
void indexTransitiveDependencies(BuildProducer<IndexDependencyBuildItem> index) {
index.produce(new IndexDependencyBuildItem("net.sf.barcode4j", "barcode4j"));
index.produce(new IndexDependencyBuildItem("com.google.zxing", "core"));
}

@BuildStep
void runtimeBarcodeInitializedClasses(BuildProducer<RuntimeInitializedPackageBuildItem> runtimeInitializedPackages) {
//@formatter:off
List<String> classes = new ArrayList<>(
Stream.of(org.krysalis.barcode4j.output.bitmap.BitmapEncoderRegistry.class.getName(),
net.sf.jasperreports.barcode4j.Barcode4JExtensionsRegistryFactory.class.getName()
).toList());
//@formatter:on
Log.debugf("Barcode4J Runtime: %s", classes);
classes.stream()
.map(RuntimeInitializedPackageBuildItem::new)
.forEach(runtimeInitializedPackages::produce);
}

@BuildStep
void registerBatikForReflection(BuildProducer<ReflectiveClassBuildItem> reflectiveClass) {
final List<String> classNames = new ArrayList<>();
classNames.add("javax.imageio.ImageIO");
classNames.add(org.krysalis.barcode4j.output.bitmap.ImageIOBitmapEncoder.class.getName());

Log.debugf("Barcode4J Reflection: %s", classNames);
// methods and fields
reflectiveClass.produce(
ReflectiveClassBuildItem.builder(classNames.toArray(new String[0])).methods().fields().build());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ void registerForReflection(CombinedIndexBuildItem combinedIndex, BuildProducer<R
classNames.addAll(collectClassesInPackage(combinedIndex, net.sf.jasperreports.data.xmla.XmlaDataAdapterImpl.class.getPackageName()));
classNames.addAll(collectClassesInPackage(combinedIndex, net.sf.jasperreports.engine.JasperReport.class.getPackageName()));
classNames.addAll(collectClassesInPackage(combinedIndex, net.sf.jasperreports.engine.base.ElementStore.class.getPackageName()));
//classNames.addAll(collectClassesInPackage(combinedIndex, net.sf.jasperreports.engine.component.DefaultComponentsBundle.class.getPackageName()));
classNames.addAll(collectClassesInPackage(combinedIndex, net.sf.jasperreports.engine.design.JRDesignQuery.class.getPackageName()));
classNames.addAll(collectClassesInPackage(combinedIndex, net.sf.jasperreports.engine.export.DefaultExporterFilterFactory.class.getPackageName()));
classNames.addAll(collectClassesInPackage(combinedIndex, net.sf.jasperreports.engine.export.ExporterNature.class.getPackageName()));
Expand Down
2 changes: 1 addition & 1 deletion integration-tests/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@
<skipITs>true</skipITs>
<quarkus.native.enabled>true</quarkus.native.enabled>
<quarkus.native.additional-build-args>
--trace-object-instantiation=org.openxmlformats.schemas.wordprocessingml.x2006.main.STZoom$Enum
--trace-object-instantiation=net.sf.jasperreports.engine.component.DefaultComponentsBundle
</quarkus.native.additional-build-args>
</properties>
<build>
Expand Down
136 changes: 136 additions & 0 deletions integration-tests/src/main/jasperreports/Barcode4JReport.jrxml
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
<jasperReport name="Barcode4JReport" language="java" pageWidth="595" pageHeight="842" columnWidth="515" leftMargin="40" rightMargin="40" topMargin="50" bottomMargin="50" uuid="432a7055-07f0-43d2-8d4c-00337bfe4d0a">
<style name="Barcode" fontName="DejaVu Sans" fontSize="10.0"/>
<title height="742">
<element kind="line" uuid="f980135d-c40f-42a7-93cd-d9d82925d5e2" x="0" y="0" width="515" height="1"/>
<element kind="staticText" uuid="df70158b-7d84-4c11-ae3e-a7bd238bcf3f" x="0" y="10" width="515" height="30" fontSize="22.0" hTextAlign="Center">
<text><![CDATA[Barcode Sample]]></text>
</element>
<element kind="textField" uuid="50f14e7a-b548-4a5d-9395-a387ea2e7e81" x="0" y="50" width="515" height="20" fontSize="12.0" hTextAlign="Center">
<expression><![CDATA["This sample uses Barcode4J Version 2.0"]]></expression>
</element>
<element kind="textField" uuid="55317c38-260d-4fb5-8c73-693d6425c411" x="0" y="70" width="515" height="20" fontSize="12.0" linkType="Reference" hTextAlign="Center">
<expression><![CDATA["http://barcode4j.sourceforge.net/"]]></expression>
<hyperlinkReferenceExpression><![CDATA["http://barcode4j.sourceforge.net/"]]></hyperlinkReferenceExpression>
</element>
<element kind="staticText" uuid="e3c8aa4c-a571-4288-b6ab-9eca96752649" x="0" y="100" width="100" height="30" style="Barcode">
<text><![CDATA[Code 128]]></text>
</element>
<element kind="component" uuid="17dc8c86-0d9c-4542-b153-71844a13bfe5" x="130" y="100" width="200" height="30" style="Barcode">
<component kind="barcode4j:Code128" moduleWidth="1.0">
<codeExpression><![CDATA["0123456789"]]></codeExpression>
</component>
</element>
<element kind="staticText" uuid="038aa527-7c7f-48b5-9547-7ba91470754c" x="0" y="135" width="100" height="30" style="Barcode">
<text><![CDATA[Codabar]]></text>
</element>
<element kind="component" uuid="a8dd7541-3d7d-44fc-9281-2bf0bd7ff556" x="130" y="135" width="200" height="30" style="Barcode">
<component kind="barcode4j:Codabar" moduleWidth="1.2" textPosition="none" wideFactor="4.0">
<codeExpression><![CDATA["01234567890"]]></codeExpression>
</component>
</element>
<element kind="staticText" uuid="e819db15-0b87-47b8-8474-cbe17cc7a37a" x="0" y="170" width="100" height="40" style="Barcode">
<text><![CDATA[DataMatrix]]></text>
</element>
<element kind="component" uuid="3955570e-f418-4cf2-9a94-cbed633f8e68" x="130" y="170" width="70" height="40" style="Barcode">
<component kind="barcode4j:DataMatrix" moduleWidth="4.0">
<codeExpression><![CDATA["JasperReports"]]></codeExpression>
</component>
</element>
<element kind="staticText" uuid="079dc326-5af1-4979-927c-3d9d75bfe21b" x="0" y="215" width="100" height="30" style="Barcode">
<text><![CDATA[EAN-128]]></text>
</element>
<element kind="component" uuid="d5a009ab-4cd5-401e-96c8-9ba64b1fc8e9" x="130" y="215" width="250" height="30" style="Barcode">
<component kind="barcode4j:EAN128" moduleWidth="1.4" checksumMode="check">
<codeExpression><![CDATA["0101234567890128"]]></codeExpression>
</component>
</element>
<element kind="staticText" uuid="63b7698e-e4a1-4fff-9ea0-a9772dd5b2c4" x="0" y="250" width="100" height="30" style="Barcode">
<text><![CDATA[Code39]]></text>
</element>
<element kind="component" uuid="7fc9f508-28ba-4b6e-bf7d-2e5e39b98ed8" x="130" y="250" width="400" height="30" style="Barcode">
<component kind="barcode4j:Code39">
<codeExpression><![CDATA["0123456789"]]></codeExpression>
</component>
</element>
<element kind="staticText" uuid="8ca7d2e2-c66f-4c25-ab3d-2fb15453b8b0" x="0" y="285" width="100" height="30" style="Barcode">
<text><![CDATA[USPS Intelligent Mail]]></text>
</element>
<element kind="component" uuid="8fdd4d61-26b7-4a0e-b569-18d70d929c10" x="130" y="285" width="400" height="30" style="Barcode">
<component kind="barcode4j:USPSIntelligentMail" ascenderHeight="8.0" trackHeight="10.0">
<codeExpression><![CDATA["00040123456200800001987654321"]]></codeExpression>
</component>
</element>
<element kind="staticText" uuid="df0b440d-9a4f-49ea-aa1d-c860c2ad3911" x="0" y="320" width="100" height="30" style="Barcode">
<text><![CDATA[Royal Mail Customer]]></text>
</element>
<element kind="component" uuid="4d2d0a42-1318-4873-8572-3cca99ebde50" x="130" y="320" width="400" height="30" style="Barcode">
<component kind="barcode4j:RoyalMailCustomer" ascenderHeight="8.0" intercharGapWidth="2.5" trackHeight="10.0">
<codeExpression><![CDATA["0123456789"]]></codeExpression>
</component>
</element>
<element kind="staticText" uuid="dc520315-36de-4535-9d40-2dc5b96e07bc" x="0" y="355" width="100" height="30" style="Barcode">
<text><![CDATA[Interleaved 2 of 5]]></text>
</element>
<element kind="component" uuid="26bab176-29df-4677-ba6a-e8df79eea8e1" x="130" y="355" width="400" height="30" style="Barcode">
<component kind="barcode4j:Interleaved2Of5">
<codeExpression><![CDATA["0123456789"]]></codeExpression>
</component>
</element>
<element kind="staticText" uuid="ddcf57ba-86e5-4b2c-8293-89cc3c044890" x="0" y="390" width="100" height="30" style="Barcode">
<text><![CDATA[UPC-A]]></text>
</element>
<element kind="component" uuid="234c47ef-0149-43aa-9595-44eb81a2bd54" x="130" y="390" width="400" height="30" style="Barcode">
<component kind="barcode4j:UPCA">
<codeExpression><![CDATA["01234567890"]]></codeExpression>
</component>
</element>
<element kind="staticText" uuid="1ee2c6c4-54d0-4bae-af20-03970939c63c" x="0" y="425" width="100" height="30" style="Barcode">
<text><![CDATA[UPC-E]]></text>
</element>
<element kind="component" uuid="51b4da4c-b93b-4757-9f6e-8757a6716ea1" x="130" y="425" width="400" height="30" style="Barcode">
<component kind="barcode4j:UPCE">
<codeExpression><![CDATA["01234133"]]></codeExpression>
</component>
</element>
<element kind="staticText" uuid="2cb2f39b-a468-4d35-9047-2066f52aec84" x="0" y="460" width="100" height="30" style="Barcode">
<text><![CDATA[EAN-13]]></text>
</element>
<element kind="component" uuid="35e15c85-135e-4e4a-ada4-3caab948d304" x="130" y="460" width="400" height="30" style="Barcode">
<component kind="barcode4j:EAN13">
<codeExpression><![CDATA["012345678901"]]></codeExpression>
</component>
</element>
<element kind="staticText" uuid="9399924d-03f6-4825-adfd-0a51cca77964" x="0" y="495" width="100" height="30" style="Barcode">
<text><![CDATA[EAN-8]]></text>
</element>
<element kind="component" uuid="00eb6f75-bdf7-408a-ba56-f76ecca2f8e6" x="130" y="495" width="400" height="30" style="Barcode">
<component kind="barcode4j:EAN8">
<codeExpression><![CDATA["01234565"]]></codeExpression>
</component>
</element>
<element kind="staticText" uuid="6ffb2cc2-63fd-4754-b8c3-48828cca8ab1" x="0" y="530" width="100" height="20" style="Barcode">
<text><![CDATA[POSTNET]]></text>
</element>
<element kind="component" uuid="16fee5fe-1e0f-4f56-b240-64a2ff904744" x="130" y="530" width="400" height="20" style="Barcode">
<component kind="barcode4j:POSTNET" shortBarHeight="10.0" checksumMode="add">
<codeExpression><![CDATA["01234"]]></codeExpression>
</component>
</element>
<element kind="staticText" uuid="c1127dd1-6cde-483c-8b1c-927b5fd285a3" x="0" y="555" width="100" height="30" style="Barcode">
<text><![CDATA[PDF417]]></text>
</element>
<element kind="component" uuid="f8257c9c-cc13-40f4-8c1e-b2dda037fb3d" x="130" y="555" width="400" height="30" style="Barcode">
<component kind="barcode4j:PDF417" moduleWidth="4.0">
<codeExpression><![CDATA["JasperReports"]]></codeExpression>
</component>
</element>
<element kind="staticText" uuid="c1127dd1-6cde-483c-8b1c-927b5fd285a3" x="0" y="600" width="100" height="80" style="Barcode">
<text><![CDATA[QRCode]]></text>
</element>
<element kind="component" uuid="f8257c9c-cc13-40f4-8c1e-b2dda037fb3d" mode="Opaque" x="130" y="600" width="400" height="80" forecolor="#0000FF" backcolor="#FFFF00" style="Barcode">
<component kind="barcode4j:QRCode" margin="2" errorCorrectionLevel="M">
<codeExpression><![CDATA["http://barcode4j.sourceforge.net/"]]></codeExpression>
</component>
</element>
</title>
</jasperReport>
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package io.quarkiverse.jasperreports.it;

import java.io.ByteArrayOutputStream;
import java.util.HashMap;

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.core.HttpHeaders;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;

import org.eclipse.microprofile.openapi.annotations.media.Content;
import org.eclipse.microprofile.openapi.annotations.responses.APIResponse;

import io.quarkiverse.jasperreports.repository.ReadOnlyStreamingService;
import io.quarkus.logging.Log;
import net.sf.jasperreports.engine.JREmptyDataSource;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;

@Path("jasper/barcode4j")
@ApplicationScoped
@Produces(MediaType.APPLICATION_OCTET_STREAM)
public class JasperReportsBarcode4JResource extends AbstractJasperResource {

private static final String TEST_REPORT_NAME = "Barcode4JReport.jasper";

@Inject
ReadOnlyStreamingService repo;

@APIResponse(responseCode = "200", description = "Fetch a report with barcodes", content = @Content(mediaType = ExtendedMediaType.APPLICATION_PDF))
@GET
@Path("/pdf")
@Produces({ ExtendedMediaType.APPLICATION_PDF })
public Response pdf() throws JRException {
final long start = System.currentTimeMillis();
JasperPrint jasperPrint = JasperFillManager.getInstance(repo.getContext()).fillFromRepo(TEST_REPORT_NAME,
new HashMap<>(), new JREmptyDataSource());

ByteArrayOutputStream outputStream = exportPdf(jasperPrint);
Log.infof("PDF creation time : %s", (System.currentTimeMillis() - start));

final Response.ResponseBuilder response = Response.ok(outputStream.toByteArray());
response.header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=barcode4j.pdf");
response.header(HttpHeaders.CONTENT_TYPE, ExtendedMediaType.APPLICATION_PDF);
return response.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import java.util.Set;

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.ServerErrorException;
Expand All @@ -35,6 +36,7 @@
import org.eclipse.microprofile.openapi.annotations.media.Schema;
import org.eclipse.microprofile.openapi.annotations.responses.APIResponse;

import io.quarkiverse.jasperreports.repository.ReadOnlyStreamingService;
import io.quarkus.logging.Log;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperFillManager;
Expand All @@ -46,7 +48,10 @@
@ApplicationScoped
public class JasperReportsCsvResource extends AbstractJasperResource {

private static final String TEST_DS_NAME = "CsvDataSourceReport";
private static final String TEST_REPORT_NAME = "CsvDataSourceReport.jasper";

@Inject
ReadOnlyStreamingService repo;

@GET
@Path("ds")
Expand All @@ -68,12 +73,8 @@ public Response datasource() {
// dataSource.setUseFirstRowAsHeader(true);
dataSource.setColumnNames(columnNames);

JasperFillManager.fillReportToFile("target/classes/jasperreports/" + TEST_DS_NAME + ".jasper", parameters,
dataSource);
Log.infof("Report : CsvDataSourceReport.jasper. Filling time : %d", (System.currentTimeMillis() - start));

JasperPrint jasperPrint = (JasperPrint) JRLoader
.loadObject(JRLoader.getLocationInputStream("target/classes/jasperreports/" + TEST_DS_NAME + ".jrprint"));
JasperPrint jasperPrint = JasperFillManager.getInstance(repo.getContext()).fillFromRepo(TEST_REPORT_NAME,
parameters, dataSource);
ByteArrayOutputStream outputStream = exportCsv(jasperPrint);

Log.infof("CSV creation time : %s", (System.currentTimeMillis() - start));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import java.util.Map;

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
Expand All @@ -35,21 +36,25 @@
import org.eclipse.microprofile.openapi.annotations.media.Schema;
import org.eclipse.microprofile.openapi.annotations.responses.APIResponse;

import io.quarkiverse.jasperreports.repository.ReadOnlyStreamingService;
import io.quarkus.logging.Log;
import net.sf.jasperreports.engine.JREmptyDataSource;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRParameter;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.util.JRLoader;
import net.sf.jasperreports.json.query.JsonQueryExecuterFactory;

@Path("/jasper/json/")
@ApplicationScoped
@Produces(MediaType.APPLICATION_OCTET_STREAM)
public class JasperReportsJsonResource extends AbstractJasperResource {

private static final String TEST_JSON_REPORT_NAME = "JsonCustomersReport";
private static final String TEST_JSONQL_REPORT_NAME = "NorthwindOrdersReport";
private static final String TEST_JSON_REPORT_NAME = "JsonCustomersReport.jasper";
private static final String TEST_JSONQL_REPORT_NAME = "NorthwindOrdersReport.jasper";

@Inject
ReadOnlyStreamingService repo;

@GET
@Path("ds")
Expand All @@ -73,14 +78,8 @@ public Response jsonqlDatasource() {
protected Response fillToCsv(String reportFile, Map<String, Object> params) {
try {
long start = System.currentTimeMillis();

JasperFillManager.fillReportToFile("target/classes/jasperreports/" + reportFile + ".jasper", params);
Log.infof("Report : %s.jasper. Filling time : %d", reportFile, (System.currentTimeMillis() - start));

JasperPrint jasperPrint = (JasperPrint) JRLoader
.loadObject(
JRLoader.getLocationInputStream(
"target/classes/jasperreports/" + reportFile + ".jrprint"));
JasperPrint jasperPrint = JasperFillManager.getInstance(repo.getContext()).fillFromRepo(reportFile,
params, new JREmptyDataSource());
ByteArrayOutputStream outputStream = exportCsv(jasperPrint);

Log.infof("CSV creation time : %s", (System.currentTimeMillis() - start));
Expand Down
Loading

0 comments on commit 3310295

Please sign in to comment.