简体   繁体   中英

Java program running on build but not in a fat jar

I have a java application that uses the Jasper Reports API to generate a PDF. It builds fine but I had to add in some fonts via Netbeans/iReport plugin in order for them to show up when exporting the PDF. On clean and build it's fine and everything works.

But when I build a fat jar (via a few package-for-store lines in the build.xml) the reports won't run. Running via the Terminal, I get this error (sorry for wall of text):

Exception in thread "AWT-EventQueue-0" java.lang.ExceptionInInitializerError
    at net.sf.jasperreports.engine.fill.JRBaseFiller.<init>(JRBaseFiller.java:124)
    at net.sf.jasperreports.engine.fill.JRVerticalFiller.<init>(JRVerticalFiller.java:89)
    at net.sf.jasperreports.engine.fill.JRVerticalFiller.<init>(JRVerticalFiller.java:104)
    at net.sf.jasperreports.engine.fill.JRVerticalFiller.<init>(JRVerticalFiller.java:62)
    at net.sf.jasperreports.engine.fill.JRFiller.createFiller(JRFiller.java:179)
    at net.sf.jasperreports.engine.fill.JRFiller.fill(JRFiller.java:108)
    at net.sf.jasperreports.engine.JasperFillManager.fill(JasperFillManager.java:668)
    at net.sf.jasperreports.engine.JasperFillManager.fill(JasperFillManager.java:649)
    at net.sf.jasperreports.engine.JasperFillManager.fillReport(JasperFillManager.java:971)
    at ie.orderofmalta.OMFinancialsForm.yTDReportBtnActionPerformed(OMFinancialsForm.java:283)
    at ie.orderofmalta.OMFinancialsForm.access$700(OMFinancialsForm.java:30)
    at ie.orderofmalta.OMFinancialsForm$8.actionPerformed(OMFinancialsForm.java:163)
    at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2018)
    at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2341)
    at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402)
    at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259)
    at javax.swing.AbstractButton.doClick(AbstractButton.java:376)
    at javax.swing.plaf.basic.BasicMenuItemUI.doClick(BasicMenuItemUI.java:833)
    at javax.swing.plaf.basic.BasicMenuItemUI$Handler.mouseReleased(BasicMenuItemUI.java:877)
    at java.awt.Component.processMouseEvent(Component.java:6505)
    at javax.swing.JComponent.processMouseEvent(JComponent.java:3320)
    at java.awt.Component.processEvent(Component.java:6270)
    at java.awt.Container.processEvent(Container.java:2229)
    at java.awt.Component.dispatchEventImpl(Component.java:4861)
    at java.awt.Container.dispatchEventImpl(Container.java:2287)
    at java.awt.Component.dispatchEvent(Component.java:4687)
    at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4832)
    at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4492)
    at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4422)
    at java.awt.Container.dispatchEventImpl(Container.java:2273)
    at java.awt.Window.dispatchEventImpl(Window.java:2719)
    at java.awt.Component.dispatchEvent(Component.java:4687)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:735)
    at java.awt.EventQueue.access$200(EventQueue.java:103)
    at java.awt.EventQueue$3.run(EventQueue.java:694)
    at java.awt.EventQueue$3.run(EventQueue.java:692)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:87)
    at java.awt.EventQueue$4.run(EventQueue.java:708)
    at java.awt.EventQueue$4.run(EventQueue.java:706)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:705)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:242)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:161)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:146)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:138)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:91)
Caused by: net.sf.jasperreports.engine.JRRuntimeException: net.sf.jasperreports.engine.JRException: Input stream not found at : fonts/fontsfamily1406301744789.xml
    at net.sf.jasperreports.engine.fonts.SimpleFontExtensionHelper.loadFontFamilies(SimpleFontExtensionHelper.java:188)
    at net.sf.jasperreports.engine.fonts.FontExtensionsRegistry.getExtensions(FontExtensionsRegistry.java:56)
    at net.sf.jasperreports.extensions.DefaultExtensionsRegistry.getExtensions(DefaultExtensionsRegistry.java:110)
    at net.sf.jasperreports.engine.util.JRStyledTextParser.<clinit>(JRStyledTextParser.java:83)
    ... 50 more
Caused by: net.sf.jasperreports.engine.JRException: Input stream not found at : fonts/fontsfamily1406301744789.xml
    at net.sf.jasperreports.repo.RepositoryUtil.getInputStreamFromLocation(RepositoryUtil.java:159)
    at net.sf.jasperreports.engine.fonts.SimpleFontExtensionHelper.loadFontFamilies(SimpleFontExtensionHelper.java:183)
    ... 53 more

When I added in the fonts, I added them to a jar which I then added to the class path. By the "input stream not found" error I'm guessing this is something to do with those fonts. But everything works fine in the normal clean-and-build process but I can't understand why the fat jar won't work.

Any ideas?

EDIT: Very similar to this Font Extension for barcode in report

I was stuck with this same problem for two days and I could not find anything to help me. I hope this helps anyone facing the same problem.

Here is how I solved the problem.

First of all, the tools being used by me

  • Jaspersoft Studio to create my reports 6.0.3
  • Jasperreport Library 6.0.3
  • Arial Unicode MS, font being embedded
  • Netbeans 8.0.2

So, first I modified the file jasperreports_extension.properties inside of jasperreports-6.0.3.jar and included the following lines

net.sf.jasperreports.extension.registry.factory.simple.font.families=net.sf.jasperreports.engine.fonts.SimpleFontExtensionsRegistryFactory
net.sf.jasperreports.extension.simple.font.families.dejavu=net/sf/jasperreports/fonts/fonts.xml

For some reason when I was building my jar file there was a conflict between the file jasperreports_extension.properties from jasperreports-6.0.3.jar and the one inside jasperreports-fonts-6.0.3.jar and the last one would be overridden.

Now to include my font (Arial Unicode MS) I edited the file /net/sf/jasperreports/fonts/fonts.xml and inserted the following code:

<fontFamily name="Arial Unicode MS">
    <normal>net/sf/jasperreports/fonts/ArialUnicodeMS/ARIALUNI.TTF</normal>
    <pdfEncoding>Identity-H</pdfEncoding>
    <pdfEmbedded>true</pdfEmbedded>
    <exportFonts>
    </exportFonts>
</fontFamily>

After this I included my font inside of jasperreports-fonts-6.0.3.jar.

在此处输入图片说明

Now this is very important, when you are creating your jar file make sure to extract jasperreports-fonts-6.0.3.jar before jasperreports-6.0.3.jar.

Here is my build.xml

<target name="-post-jar">
    <jar jarfile="dist2/Reports.jar">
        <zipfileset src="${dist.jar}" excludes="META-INF/*;*.jar;*.txt;*.html" />
        <zipfileset src="lib/jetty-all-9.0.3.v20130506.jar" excludes="META-INF/*;*.txt;*.html" />

        <zipfileset src="lib/lib/jasperreports-javaflow-6.0.3.jar" excludes="META-INF/*;*.txt;*.html" />
        <zipfileset src="lib/jasperreports-fonts-6.0.3.jar" excludes="META-INF/*;*.txt;*.html" />
        <zipfileset src="lib/jasperreports-6.0.3.jar" excludes="META-INF/*;*.txt;*.html" />

        <zipfileset src="lib/mysql-connector-java-5.1.34-bin.jar" excludes="META-INF/*;*.txt;*.html" />
        <zipfileset src="lib/commons-javaflow-20060411.jar" excludes="META-INF/*;*.txt;*.html" />
        <zipfileset src="lib/servlet-api-2.4.jar" excludes="META-INF/*;*.txt;*.html" />
        <zipfileset src="lib/javax.servlet-3.0.jar" excludes="META-INF/*;*.txt;*.html" />
        <zipfileset src="lib/commons-logging-1.1.1.jar" excludes="META-INF/*;*.txt;*.html" />
        <zipfileset src="lib/commons-collections-3.2.1.jar" excludes="META-INF/*;*.txt;*.html" />
        <zipfileset src="lib/ant-1.7.1.jar" excludes="META-INF/*" />
        <zipfileset src="lib/groovy-all-2.0.1.jar" excludes="META-INF/*" />
        <zipfileset src="lib/commons-digester-2.1.jar" excludes="META-INF/*" />

        <zipfileset src="lib/itextpdf-5.5.0.jar" excludes="META-INF/*" />
        <zipfileset src="lib/itext-pdfa-5.5.0.jar" excludes="META-INF/*" />
        <zipfileset src="lib/apache-commons-lang.jar" excludes="META-INF/*" />
        <zipfileset src="lib/com.lowagie.text-2.1.7.jar" excludes="META-INF/*" />

        <zipfileset src="lib/commons-beanutils-1.9.0.jar" excludes="META-INF/*" />

        <manifest>
              <attribute name="Main-Class" value="Jetty"/>
        </manifest>
    </jar>
</target>

What solved it for me was to append the contents of the jasperreports_extension.properties file contained in the jasperreports-6.xxjar to my custom jasperreports_extension.properties .

The Problem was that the properties file from the jar got overwritten when creating the fat jar. Obviously JasperReports merges both files at runtime. Since the original content is missing, it causes this slightly misleading error.

Caused by: net.sf.jasperreports.engine.JRException: Input stream not found at : fonts/fontsfamily1406301744789.xml at 
net.sf.jasperreports.repo.RepositoryUtil.getInputStreamFromLocation(RepositoryUtil.java:159) at 
net.sf.jasperreports.engine.fonts.SimpleFontExtensionHelper.loadFontFamilies(SimpleFontExtensionHelper.java:183) 
... 53 more

You need to provide a proper input stream to whatever you want to do here. If the resource is inside a jar file you must write special code to handle this. FileInputStreams will not work.

@eoinDub: I had a similar problem when loading the report itselfes from the class directory of the fat jar. So I used "... getResourceAsStream ()". I did something like this (see code below). [Actually I used a compiled *.jasper - I don't remember whether an uncompiled *.jrxml did work, too.]

        JasperReport report = null;

    InputStream is = MyClass.class.getClassLoader().getResourceAsStream(reportName);
    if (FilenameUtils.isExtension(reportName, "jrxml")) {
        JasperDesign jd = JRXmlLoader.load(is);

        report = JasperCompileManager.compileReport(jd);

    } else {
        report = (JasperReport) JRLoader.loadObject(is);
    }

    JRCsvDataSource ds;
    try {
        ds = new JRCsvDataSource(csvName, csvEncoding);
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
        return;
    }

    ds.setUseFirstRowAsHeader(true);
    ds.setFieldDelimiter(csvDelimiter.charAt(0));

    JasperPrint jprint = JasperFillManager.fillReport(report, reportParams, ds);

    try {
        JasperExportManager.exportReportToPdfFile(jprint, outPDF);
    } catch (Exception e) {
        e.printStackTrace();
    }

I was stuck with the same problem. In my project I am using Maven, and I noticed that at the end of generating the fat .jar, it threw a message of

jasperreports_extension.properties already added, skipping

Among what I saw on the web about this problem, I got that this file is repeated in several libraries, such as: jasperreports and jasperfonts; this causes conflicts between them and the Maven ignores them. So what I did was put my custom jasperreports_extension.properties file among the first Maven dependency files, so that this file setting takes it first.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM