Hot questions for Using JasperReports in linux

Question:

i'm evaluating JasperReports for report generation. I have some problems with report portability between Windows and Linux. I found a (hacky) solution to make it work cross platform. However i wonder what is the jasperreports-fonts for:

<dependency>
    <groupId>net.sf.jasperreports</groupId>
    <artifactId>jasperreports-fonts</artifactId>
    <version>5.6.1</version>
</dependency>

I see that it contains the DejaVu Sans font but i have no idea how to use this jar (i found nothing on the net) and if this would solve my cross platform soft in an elegant, simple way.

Can you tell me more about this jar?


Answer:

In jasper report (.jrxml file) you can use several fonts for displaying labels/texts. These fonts may not be always available on different platforms/OS. (e.g. There are some MS fonts which are unavailable on linux machines unless you install them manually). So, we bundle the fonts used in jasper report into a jar and make them work irrespective of underlying platform. Additionally, you can include your own (custom created) fonts in fonts extension jar and ship them along with jasper reports. More information is here.

Also there are couple of ways to configure and use this jar. Have a look at this to know one of the easiest way.

Note that if the font used in jrxml is not available in the JVM, it will throw an error while exporting the report as follows:

net.sf.jasperreports.engine.util.JRFontNotFoundException:  
   Font 'Arial' is not available to the JVM.   

This can be solved in 2 ways: 1. Use jasperreport-extension.jar OR 2. Set the property net.sf.jasperreports.awt.ignore.missing.font to true to ignore missing font. e.g. In jrxml, you can set it as follows:

<property name="net.sf.jasperreports.awt.ignore.missing.font" value="true"/>

Question:

I have a huge problem. I was coding an app which is using Jasperreports. Everything was perfectly fine when I was working locally. But then, when I have dockerized my app, when I run the method that should produce an PDF file, I get an error:

Request processing failed; nested exception is net.sf.jasperreports.engine.JRRuntimeException: Error initializing graphic environment.

I have found out that running my app with

-DJava.awt.headless=true

the problem would solve itself. But it is not.

This is how it looks like in the Dockerfile:

ENTRYPOINT [ "java", "-Djava.awt.headless=true", "-jar", "/var/generator/generator-0.0.1-SNAPSHOT.jar" ]

To be sure that I havent forgotten anything, here is the code of the method which is generating the PDF files, maybe there is something wrong there...

The error is coming from this line:

mainReport = JasperFillManager.fillReport(report, invoiceMap, new JREmptyDataSource());

And here is the method:

public byte[] generateInvoicePDF(Invoice invoice) {

    /* Map to fill in main JasperReport */
    Map<String, Object> invoiceMap = new HashMap<String, Object>();
    invoiceMap.put("FIRST_NAME", invoice.getFirstName());
    invoiceMap.put("LAST_NAME", invoice.getLastName());
    invoiceMap.put("REGON", invoice.getRegon());
    invoiceMap.put("NIP", invoice.getNip());
    invoiceMap.put("BUSINESS_NAME", invoice.getBusinessName());
    invoiceMap.put("BUSINESS_LOCATION", invoice.getBusinessLocation());
    invoiceMap.put("ORDER_DATE", invoice.getOrderDate());
    invoiceMap.put("RECEPTION_DATE", invoice.getReceptionDate());
    invoiceMap.put("CONTRACT_DATE", invoice.getContractDate());
    invoiceMap.put("CONTRACTOR_COMMENT", invoice.getContractorComment());
    invoiceMap.put("INVOICE_NUMBER", invoice.getInvoiceNumber());
    invoiceMap.put("INVOICE_ISSUE_DATE", invoice.getInvoiceIssueDate());

    JasperPrint mainReport;
    JasperPrint tableReport;
    try {
        InputStream invoiceJasper = InvoiceGeneratorServiceImpl.class.getResourceAsStream("/invoices/invoice.jrxml");
        InputStream taskTableJasper = InvoiceGeneratorServiceImpl.class.getResourceAsStream("/invoices/invoice_sub.jrxml");
        JasperDesign mainReportDesign = JRXmlLoader.load(invoiceJasper);
        JasperDesign tableReportDesign = JRXmlLoader.load(taskTableJasper);
        JasperReport report = JasperCompileManager.compileReport(mainReportDesign);
        JasperReport table = JasperCompileManager.compileReport(tableReportDesign);

        /* List to hold Items */
        List<InvoiceTask> taskList = new ArrayList<>();

        /* Add Items to List */
        taskList.addAll(invoice.getInvoiceTasks());

        /* Convert List to JRBeanCollectionDataSource */
        JRBeanCollectionDataSource itemsJRBean = new JRBeanCollectionDataSource(taskList);

        /* Map to hold Jasper report Parameters */
        Map<String, Object> taskListMap = new HashMap<String, Object>();
        taskListMap.put("TasksDataSource", itemsJRBean);
        taskListMap.put("ADDITIONAL_COSTS", invoice.getAdditionalCosts());

        mainReport = JasperFillManager.fillReport(report, invoiceMap, new JREmptyDataSource());
        tableReport = JasperFillManager.fillReport(table, taskListMap, new JREmptyDataSource());
        List<JasperPrint> printList = new ArrayList<>();
        printList.add(mainReport);
        printList.add(tableReport);

        JRPdfExporter exporter = new JRPdfExporter();
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        exporter.setExporterInput(SimpleExporterInput.getInstance(printList)); //Set as export input my list with JasperPrint s
        exporter.setExporterOutput(new SimpleOutputStreamExporterOutput(byteArrayOutputStream));
        SimplePdfExporterConfiguration configuration = new SimplePdfExporterConfiguration();
        configuration.setCreatingBatchModeBookmarks(true); //add this so your bookmarks work, you may set other parameters
        exporter.setConfiguration(configuration);
        exporter.exportReport();

        return byteArrayOutputStream.toByteArray();
    } catch (JRException e) {
        e.printStackTrace();
    }

    return new byte[0];
}

And a little bit more of the stack trace:

2019-04-24 08:43:57.338 ERROR 1 --- [io-8080-exec-10] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is net.sf.jasperreports.engine.JRRuntimeException: Error initializing graphic environment.] with root cause

java.lang.NullPointerException: null
    at sun.awt.FontConfiguration.getVersion(FontConfiguration.java:1264) ~[na:1.8.0_201]
    at sun.awt.FontConfiguration.readFontConfigFile(FontConfiguration.java:219) ~[na:1.8.0_201]
    at sun.awt.FontConfiguration.init(FontConfiguration.java:107) ~[na:1.8.0_201]
    at sun.awt.X11FontManager.createFontConfiguration(X11FontManager.java:774) ~[na:1.8.0_201]
    at sun.font.SunFontManager$2.run(SunFontManager.java:431) ~[na:1.8.0_201]
    at java.security.AccessController.doPrivileged(Native Method) ~[na:1.8.0_201]
    at sun.font.SunFontManager.<init>(SunFontManager.java:376) ~[na:1.8.0_201]
    at sun.awt.FcFontManager.<init>(FcFontManager.java:35) ~[na:1.8.0_201]
    at sun.awt.X11FontManager.<init>(X11FontManager.java:57) ~[na:1.8.0_201]
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[na:1.8.0_201]
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) ~[na:1.8.0_201]
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[na:1.8.0_201]
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423) ~[na:1.8.0_201]
    at java.lang.Class.newInstance(Class.java:442) ~[na:1.8.0_201]
    at sun.font.FontManagerFactory$1.run(FontManagerFactory.java:83) ~[na:1.8.0_201]
    at java.security.AccessController.doPrivileged(Native Method) ~[na:1.8.0_201]
    at sun.font.FontManagerFactory.getInstance(FontManagerFactory.java:74) ~[na:1.8.0_201]
    at sun.java2d.SunGraphicsEnvironment.getFontManagerForSGE(SunGraphicsEnvironment.java:201) ~[na:1.8.0_201]
    at sun.java2d.SunGraphicsEnvironment.getAvailableFontFamilyNames(SunGraphicsEnvironment.java:235) ~[na:1.8.0_201]
    at sun.java2d.SunGraphicsEnvironment.getAvailableFontFamilyNames(SunGraphicsEnvironment.java:263) ~[na:1.8.0_201]
    at sun.java2d.HeadlessGraphicsEnvironment.getAvailableFontFamilyNames(HeadlessGraphicsEnvironment.java:94) ~[na:1.8.0_201]
    at net.sf.jasperreports.engine.util.JRGraphEnvInitializer.initializeGraphEnv(JRGraphEnvInitializer.java:58) ~[jasperreports-6.7.1.jar!/:6.7.1]
    at net.sf.jasperreports.engine.fill.BaseReportFiller.<init>(BaseReportFiller.java:136) ~[jasperreports-6.7.1.jar!/:6.7.1]
    at net.sf.jasperreports.engine.fill.JRBaseFiller.<init>(JRBaseFiller.java:273) ~[jasperreports-6.7.1.jar!/:6.7.1]
    at net.sf.jasperreports.engine.fill.JRVerticalFiller.<init>(JRVerticalFiller.java:79) ~[jasperreports-6.7.1.jar!/:6.7.1]
    at net.sf.jasperreports.engine.fill.JRFiller.createBandReportFiller(JRFiller.java:251) ~[jasperreports-6.7.1.jar!/:6.7.1]
    at net.sf.jasperreports.engine.fill.JRFiller.createReportFiller(JRFiller.java:272) ~[jasperreports-6.7.1.jar!/:6.7.1]
    at net.sf.jasperreports.engine.fill.JRFiller.fill(JRFiller.java:156) ~[jasperreports-6.7.1.jar!/:6.7.1]
    at net.sf.jasperreports.engine.fill.JRFiller.fill(JRFiller.java:145) ~[jasperreports-6.7.1.jar!/:6.7.1]
    at net.sf.jasperreports.engine.JasperFillManager.fill(JasperFillManager.java:758) ~[jasperreports-6.7.1.jar!/:6.7.1]
    at net.sf.jasperreports.engine.JasperFillManager.fillReport(JasperFillManager.java:1074) ~[jasperreports-6.7.1.jar!/:6.7.1]
    at com.generator.service.impl.InvoiceGeneratorServiceImpl.generateInvoicePDF(InvoiceGeneratorServiceImpl.java:68) ~[classes!/:na]
    at com.generator.rest.ContractorController.getPdf(ContractorController.java:165) ~[classes!/:na]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_201]

Answer:

This looks like an issue with a missing font.

If you happen to be using Alpine then you might be seeing issue #73, which has the same relevant stack trace. According to that issue, installing the ttf-dejavu package should fix your problem.

Add this to your dockerfile:

RUN apk add ttf-dejavu

Question:

I try to format a Date in Jasper Reports and it works with Windows but not with Linux. With Linux the resulting text is truncated.

Code:

JRXML:

<parameter name="timestamp" class="java.util.Date"/>
[...]
<textField>
    <reportElement x="0" y="0" width="50" height="16" uuid="0007846a-26f1-457a-a198-67a2f7c8417c">
        <property name="local_mesure_unitwidth" value="pixel"/>
        <property name="com.jaspersoft.studio.unit.width" value="px"/>
        <property name="local_mesure_unitx" value="pixel"/>
        <property name="com.jaspersoft.studio.unit.x" value="px"/>
        <property name="local_mesure_unity" value="pixel"/>
        <property name="com.jaspersoft.studio.unit.y" value="px"/>
        <property name="local_mesure_unitheight" value="pixel"/>
        <property name="com.jaspersoft.studio.unit.height" value="px"/>
    </reportElement>
    <box padding="2"/>
    <textElement textAlignment="Left" verticalAlignment="Top">
        <font size="8" pdfFontName="Helvetica" pdfEncoding="Cp1250" isPdfEmbedded="true"/>
    </textElement>
    <textFieldExpression><![CDATA[DATEFORMAT($P{timestamp},"dd.MM HH:mm")]]></textFieldExpression>
</textField>

Maven dependencies:

<dependency>
    <groupId>net.sf.jasperreports</groupId>
    <artifactId>jasperreports</artifactId>
    <version>5.6.0</version>
</dependency>
<dependency>
    <groupId>net.sf.jasperreports</groupId>
    <artifactId>jasperreports-functions</artifactId>
    <version>5.6.0</version>
</dependency>

Java:

private byte[] createPdf() {

    try {
        InputStream is = getClass().getResourceAsStream("MyReport.jasper");
        JasperReport jasperReport = (JasperReport) JRLoader.loadObject(is);
        Map<String, Object> parameters = new HashMap<String, Object>();
        parameters.put("timestamp", new Date());
        JRDataSource jrDataSource = new JRBeanCollectionDataSource(new Vector(), false);
        JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, parameters, jrDataSource);
        byte[] pdf = JasperExportManager.exportReportToPdf(jasperPrint);
        return pdf;
    } catch (JRException e) {
        throw new RuntimeException("Could not create PDF.", e);
    }
}
Results:

Result with Windows:

Result with Linux:

PDF properties:

Both generated PDF files have the same font properties in Acrobat Reader for Windows:

As you can see, the font is not embedded. (Second font "Helvetica" disappears if I add dependency jasperreports-fonts and remove attributes pdfFontName, pdfEncodingand isPdfEmbedded).

Research:

I read:

  • PDF generated with jasperreport not showing well on Linux but yes on Mac, could the os be related?
  • http://community.jaspersoft.com/questions/527138/pdf-text-truncated-linux-fine-windows
  • http://community.jaspersoft.com/questions/803503/why-text-filed-value-will-be-truncated-if-application-running-linux

and the solution seems to be to embed the font, but it doesn't work.

I use font "Helvetica" which is one of the default fonts and that's the reason, see Wikipedia:

These fonts, or suitable substitute fonts with the same metrics, must always be available in all PDF readers and so need not be embedded in a PDF

and https://stackoverflow.com/a/27345103/5277820:

If you use these fonts in iText, iText will ignore the embedded parameter, because it is safe to assume that Adobe Reader and other viewers can render these fonts correctly.

Question:

Why have the same font different widths with Windows and Linux? Or why is the text truncating and/or line wrapping different?


Answer:

To calculate the font-metrics correctly, the font needs to be available to the java virtual macchine.

See this historical question: Font is not available to the JVM with Jasper Reports, that show various solution to the old error launched

However the correct solution with jasper-reports is to use font-extensions

If you use the distributed jasperreports-font.jar it contains these fonts:

DejaVu SansDejaVu SerifDejaVu Sans Mono

You need to use one of these in font name example fontName="DejaVu Sans", there is no automatic mapping to other fonts, the jar physically contains only these .ttf and no other (open jar and verify for different version of jasper-reports).

Hence only font installed on the pc or included in font-extension are available for the JVM.

If you need other fonts, the best solution is to generate your own font-extension including a valid .ttf font this can be done from within the IDE.

Question:

  1. i have used jasper-reports 3.*
  2. my application-server is jboss
  3. OS is windows : every things is ok and generated pdf shown correctly

but the problem is: 1. when OS is Linux : generated pdf is empty

caused by : 1.maybe for fonts not exist!!

i have tried these ways : 1.copy all necessary fonts in my application's class path 2.install all necessary fonts on Linux machine 3.copy all necessary fonts in JRE/lib/fonts

but problem still not resolved ...

any help will be appriciated?


Answer:

if your Linux using OpenJDK , this is the problem , OpenJDK has problem with regular fonts and some graphical charts , to resolve problem install " sun/Oracle jdk " , all issue will be done

Question:

I am working on jasper reports to produce PDF file.

I have problem that is Font format exception when I run program which generates PDF on linux OS machine. I have used Times new roman font format for jasper file and linux OS does not support Times new roman, can anyone suggest me common font format for linux and windows OS to create jasper file .


Answer:

Java defines the following five logical font families:

  • Dialog
  • DialogInput
  • Monospaced
  • Serif
  • SansSerif

This means that these fonts are always available in java runtime, however they are not actual font libraries but mapped by java to some font installed on system. Hence using any of these font will not cause any error in java.

However, you are exporting to pdf that instead have what is called Standard Type 1 fonts as you can see there is no match and iText (the lib creating the pdf) will use if not defined the default font Helvetica.

The conclusion is that while using a logical font, which would not throw an errors this could lead to report inconsistency in pdf (using another font).

The solution in jasper-reports is to use font-extensions