简体   繁体   English

Java 程序在构建时运行,但不在胖 jar 中

[英]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.我有一个使用 Jasper Reports API 生成 PDF 的 Java 应用程序。 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.它构建得很好,但我必须通过 Netbeans/iReport 插件添加一些字体,以便在导出 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.但是当我构建一个胖 jar(通过 build.xml 中的一些 package-for-store 行)时,报告将不会运行。 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.当我添加字体时,我将它们添加到一个 jar 中,然后将其添加到类路径中。 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 Jaspersoft Studio 创建我的报告 6.0.3
  • Jasperreport Library 6.0.3 Jasperreport 库 6.0.3
  • Arial Unicode MS, font being embedded Arial Unicode MS,嵌入字体
  • Netbeans 8.0.2 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所以,首先我修改了文件jasperreports_extension.properties的JasperReports-6.0.3.jar和包括以下行

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.因为当我建设我的jar文件某种原因出现了从JasperReports的-6.0.3.jar文件jasperreports_extension.properties和一个内部的JasperReports的字体-6.0.3.jar,最后一个将被覆盖之间的冲突。

Now to include my font (Arial Unicode MS) I edited the file /net/sf/jasperreports/fonts/fonts.xml and inserted the following code:现在要包含我的字体(Arial Unicode MS),我编辑了文件/net/sf/jasperreports/fonts/fonts.xml并插入了以下代码:

<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.在此之后,我将我的字体包含在 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.现在这很重要,当您创建 jar 文件时,请确保在 jasperreports-6.0.3.jar 之前提取 jasperreports-fonts-6.0.3.jar。

Here is my build.xml这是我的 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 .有什么解决这对我来说是要追加的内容jasperreports_extension.properties文件中包含jasperreports-6.xxjar到我的自定义jasperreports_extension.properties

The Problem was that the properties file from the jar got overwritten when creating the fat jar.问题是在创建胖 jar 时,jar 中的属性文件被覆盖了。 Obviously JasperReports merges both files at runtime.显然 JasperReports 在运行时合并了两个文件。 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.如果资源在 jar 文件中,您必须编写特殊代码来处理它。 FileInputStreams will not work. FileInputStreams 将不起作用。

@eoinDub: I had a similar problem when loading the report itselfes from the class directory of the fat jar. @eoinDub:从 fat jar 的类目录加载报告本身时,我遇到了类似的问题。 So I used "... getResourceAsStream ()".所以我使用了“... 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.] [实际上我使用了编译的 *.jasper - 我不记得未编译的 *.jrxml 是否也有效。]

        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在我的项目中,我使用 Maven,我注意到在生成 fat .jar 的最后,它抛出了一条消息

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;在网上看到的关于这个问题的资料中,我了解到这个文件在几个库中重复出现,例如:jasperreports 和 jasperfonts; this causes conflicts between them and the Maven ignores them.这会导致它们之间发生冲突,而 Maven 会忽略它们。 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.所以我所做的是将我的自定义jasperreports_extension.properties文件放在第一个 Maven 依赖文件中,以便此文件设置首先使用它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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