TIBCOSoftware / jasperreports

JasperReports® - Free Java Reporting Library
https://community.jaspersoft.com/downloads/community-edition/
GNU Lesser General Public License v3.0
1.03k stars 397 forks source link

Custom visualization module not recognized even though its jar is in java path #189

Closed dhombios closed 3 years ago

dhombios commented 3 years ago

When using a report template that contains a Custom Visualization Component from a custom Java application based on JasperReports Library, Jasper raises an exception due to an unknown entity even though the CVC jar has been added to java path (see the attached POM). According to the wiki (https://community.jaspersoft.com/wiki/custom-visualization-component-v60x), this module just requires specifying the path to PhantomJs to be able to use CVC components in JasperReports Server or JasperReports Studio and the JasperReports Library wiki does not contain any additional infomation about its usage (https://community.jaspersoft.com/wiki/jasperreports-library-reference-materials). Therefore, I initially assumed that it did not require any additional configuration

Nevertheless, as the Exception is still being raised, it seems that some undocumented configuration is required to enable the module. I attach below both, the Error and the POM of the project.

I tried asking before in the Answers section of your community website, but it seems to have little activity (https://community.jaspersoft.com/questions/1183536/it-possible-use-custom-visualization-components-jaspersoft-library)

Thanks in advanced

Raised exception:

net.sf.jasperreports.engine.JRRuntimeException: Unknown entity http://www.jaspersoft.com/cvcomponent/component.xsd, not loading.
net.sf.jasperreports.engine.JRRuntimeException: Unknown entity http://www.jaspersoft.com/cvcomponent/component.xsd, not loading.
at net.sf.jasperreports.engine.xml.JRXmlDigester.resolveEntity(JRXmlDigester.java:232)
at com.sun.org.apache.xerces.internal.util.EntityResolverWrapper.resolveEntity(EntityResolverWrapper.java:110)
at com.sun.org.apache.xerces.internal.impl.XMLEntityManager.resolveEntity(XMLEntityManager.java:1081)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaLoader.resolveDocument(XMLSchemaLoader.java:657)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.findSchemaGrammar(XMLSchemaValidator.java:2430)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.handleStartElement(XMLSchemaValidator.java:1767)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.startElement(XMLSchemaValidator.java:740)
at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.scanStartElement(XMLNSDocumentScannerImpl.java:374)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2784)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:602)
at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:112)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:505)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:841)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:770)
at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:141)
at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1213)
at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:643)
at org.apache.commons.digester.Digester.parse(Digester.java:1892)
at net.sf.jasperreports.engine.xml.JRXmlLoader.loadXML(JRXmlLoader.java:299)
at net.sf.jasperreports.engine.xml.JRXmlLoader.loadXML(JRXmlLoader.java:286)
at net.sf.jasperreports.engine.xml.JRXmlLoader.load(JRXmlLoader.java:275)
at net.sf.jasperreports.engine.xml.JRXmlLoader.load(JRXmlLoader.java:220)
at net.sf.jasperreports.engine.xml.JRXmlLoader.load(JRXmlLoader.java:195)
at net.sf.jasperreports.engine.xml.JRXmlLoader.load(JRXmlLoader.java:186)
at net.sf.jasperreports.engine.JasperCompileManager.compile(JasperCompileManager.java:289)
at net.sf.jasperreports.engine.JasperCompileManager.compileReport(JasperCompileManager.java:576)
at com.Dhombios.myreport.Report_generator.publish(Report_generator.java:48)
at com.Dhombios.myreport.CLI.main(CLI.java:98)
Report generation failed

POM dependencies section (JasperReports Library version 6.16):

<dependencies>
<!-- https://mvnrepository.com/artifact/net.sf.jasperreports/jasperreports -->
<dependency>
<groupId>net.sf.jasperreports</groupId>
<artifactId>jasperreports</artifactId>
<version>6.16.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/net.sf.jasperreports/jasperreports-cu... -->
<dependency>
<groupId>net.sf.jasperreports</groupId>
<artifactId>jasperreports-custom-visualization</artifactId>
<version>6.16.0</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.apache.poi/poi -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>5.0.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.0.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.30</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.30</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-collections4 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.4</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-simple -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.30</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<scope>test</scope>
<version>2.44.0</version>
</dependency>
<dependency>
<groupId>com.opera</groupId>
<artifactId>operadriver</artifactId>
<scope>test</scope>
<version>1.5</version>
<exclusions>
<exclusion>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-remote-driver</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
<version>4.11</version>
</dependency>
</dependencies>
dadza commented 3 years ago

Can you put these lines somewhere in your code and post here the output? Feel free to use any logging framework instead of System.out

ClassLoader jrClassLoader = JasperCompileManager.class.getClassLoader();
System.out.println("CVC XSD at " + jrClassLoader.getResource("net/sf/jasperreports/customvisualization/component.xsd"));
for (Enumeration<URL> jrExtensions = jrClassLoader.getResources("jasperreports_extension.properties"); jrExtensions.hasMoreElements(); ) {
    System.out.println("JR extension at " + jrExtensions.nextElement());
}
dhombios commented 3 years ago

Thanks for your help Dadza:

CVC XSD at jar:file:/D:/Dhom/Documents/Projects/Myreport/Test5/Myreport.jar!/net/sf/jasperreports/customvisualization/component.xsd
JR extension at jar:file:/D:/Dhom/Documents/Projects/Myreport/Test5/Myreport.jar!/jasperreports_extension.properties

Additionally, since I posted the issue on github I found a jasperReports library user manual (https://community.jaspersoft.com/sites/default/files/docs/jasperreports-ultimate-guide-3v2_0.pdf) which seems a bit outdated but provides a guide on using CVC from java (page 285). I was going to try following it just in case it's instructions for using extensions can still be used in newer jasperReports versions, even though it is quite probable that many things have changed since 2011

dadza commented 3 years ago

I get it that you have something in your project that creates an uber jar from all the dependencies.

When you do that, you need to take specific care of jasperreports_extension.properties jar resources, which are used by JasperReports to load extensions. See a solution at https://stackoverflow.com/a/35025718

dhombios commented 3 years ago

Thanks, now it detects the extension. I'm going to document it on the community wiki, so future users don't open a similar issue to this one if they need a fat jar However, I still get an error due to not having specified the path to PhantomJs (see below), yet I cannot access the variable that contains it, at least in jasperStudio (com.jaspersoft.jasperreports.components.customvisualization.phantomjs.executable.path), as jvm is unable to find it:

3514 [main] ERROR net.sf.jasperreports.customvisualization.export.CVElementImageProvider - Generating image for Custom Visualization element element77923161343435128113206065653047908829 failed. net.sf.jasperreports.engine.JRRuntimeException: Chrome and/or PhantomJS not properly configured for server side rendering at net.sf.jasperreports.customvisualization.export.CVElementDefaultImageDataProvider.getImageData(CVElementDefaultImageDataProvider.java:75) at net.sf.jasperreports.customvisualization.export.CVElementImageProvider.createRenderable(CVElementImageProvider.java:134) at net.sf.jasperreports.customvisualization.export.CVElementImageProvider.getImage(CVElementImageProvider.java:86) at net.sf.jasperreports.customvisualization.export.CVElementPdfHandler.exportElement(CVElementPdfHandler.java:58) at net.sf.jasperreports.engine.export.JRPdfExporter.exportGenericElement(JRPdfExporter.java:4141) at net.sf.jasperreports.engine.export.JRPdfExporter.exportElements(JRPdfExporter.java:1290) at net.sf.jasperreports.engine.export.JRPdfExporter.exportPage(JRPdfExporter.java:1210) at net.sf.jasperreports.engine.export.JRPdfExporter.exportReportToStream(JRPdfExporter.java:1074) at net.sf.jasperreports.engine.export.JRPdfExporter.exportReport(JRPdfExporter.java:691) at net.sf.jasperreports.engine.JasperExportManager.exportToPdfFile(JasperExportManager.java:155) at net.sf.jasperreports.engine.JasperExportManager.exportReportToPdfFile(JasperExportManager.java:503) at com.Dhombios.myreport.Report_generator.publish(Report_generator.java:82) at com.Dhombios.myreport.CLI.main(CLI.java:99)

dadza commented 3 years ago

The recommended property to set for PhantomJS is net.sf.jasperreports.phantomjs.executable.path

Also see net.sf.jasperreports.chrome.enabled and net.sf.jasperreports.chrome.executable.path, you can use Chromium/Chrome instead of PhantomJS (which is no longer being developed/maintained).

dhombios commented 3 years ago

Thanks again! As soon as I solve some problems related to UTF-8 encoding (€ is being shown in the exported report instead of €) I'll update the wiki with a complete tutorial on using both, Chrome and PhantomJS

dadza commented 3 years ago

That might be a bug because this line doesn't explicitly encode to UTF-8. Therefore if the default character encoding of the JVM is not UTF-8, the data can get corrupted.

Can you test if starting your application with -Dfile.encoding=UTF-8 makes a difference?

dhombios commented 3 years ago

Yes, that solved it. A workaround can be found here: https://stackoverflow.com/a/14987992/15974273 , which consists in adding the following lines at the start of the main function:

System.setProperty("file.encoding","UTF-8");
Field charset = Charset.class.getDeclaredField("defaultCharset");
charset.setAccessible(true);
charset.set(null,null);

On the other hand, I'm having yet another problem, as the text shown in the CVC component needs to be shown aligned with the top of the viewport, but the hanging dominant-baseline and alignment-baseline attributes get ignored. It seems that, sometimes, it might be solved by changing the display attribute of the svg to block (https://stackoverflow.com/q/21099192/15974273), yet it does not work in this case. However, they work when the report is exported to html and opened with the same chromium executable that I have bundled with the application

Edit 20/5/2021 20:46: A workaround for solving this is to set the dy property of the text to 0.75em, but the resulting top margin might change if several texts with different font sizes are used

dadza commented 3 years ago

Log an issue for the UTF-8 problem, we need to fix the code to properly create the HTML no matter the default charset.