When I attempt to compile a jrxml file created in jasper studio v6.2.0, using the jasperreports 6.2.1 library, I get the following errors:
net.sf.jasperreports.engine.JRException: Errors were encountered when compiling report expressions class file:
/home/david_clymer/Development/VistaShare/OutcomeTracker/HUD329902_1461778704578_563528.java:477: error: cannot find symbol
value = CONCATENATE(((java.lang.String)field_ns058Agency_Physical_City.getValue()),",",((java.lang.String)field_ns058Agency_Physical_State.getValue())," ",((java.lang.String)field_ns058Agency_Ph
ysical_Zip.getValue())); //$JR_EXPR_ID=40$
^
symbol: method CONCATENATE(String,String,String,String,String)
location: class HUD329902_1461778704578_563528
...
9 errors
.
at net.sf.jasperreports.engine.design.JRAbstractCompiler.compileReport(JRAbstractCompiler.java:215)
at net.sf.jasperreports.engine.JasperCompileManager.compile(JasperCompileManager.java:357)
at net.sf.jasperreports.engine.JasperCompileManager.compileToFile(JasperCompileManager.java:273)
at net.sf.jasperreports.engine.JasperCompileManager.compileToFile(JasperCompileManager.java:232)
at net.sf.jasperreports.engine.JasperCompileManager.compileReportToFile(JasperCompileManager.java:542)
at RunReport.compileReport(RunReport.java:80)
at RunReport.main(RunReport.java:192)
How do I ensure that these functions are imported and available?
This is the debugging I've done so far:
According to my googling, this results from the absence of jasperreports-functions-6.2.1.jar
in the java classpath. However, in my case it most definitely is in the classpath, and testing shows that its classes are accessible, but the methods are not:
// Imports without error
import net.sf.jasperreports.functions.standard.TextFunctions;
public class Foo {
public static void main(String[] args) {
// Cannot resolve symbol INTEGER_VALUE
Object foo = TextFunctions.INTEGER_VALUE;
}
}
Decompiling the relevant class shows that the method is indeed there:
david_clymer@zapazoid:~/Development/VistaShare/OutcomeTracker/jasperreports/lib/tmp$ jar -xf ../jasperreports-functions-6.2.1.jar
david_clymer@zapazoid:~/Development/VistaShare/OutcomeTracker/jasperreports/lib/tmp$ java -jar ../../../procyon-decompiler-0.5.30.jar net/sf/jasperreports/functions/standard/TextFunctions.class |grep -A 7 INTEGER_VALUE
@Function("INTEGER_VALUE")
@FunctionParameters({ @FunctionParameter("textNumber") })
public static Integer INTEGER_VALUE(final String textNumber) {
if (textNumber == null) {
logNullTextString();
return null;
}
return Integer.parseInt(textNumber);
}
david_clymer@zapazoid:~/Development/VistaShare/OutcomeTracker/jasperreports/lib/tmp$ grep TextFunctions jasperreports_extension.properties
net.sf.jasperreports.extension.functions.text=net.sf.jasperreports.functions.standard.TextFunctions
I'm not really a java programmer, so maybe I'm doing something stupid. I just don't know how to reference the methods properly so that I can be sure that they should work.
Update: using a static import:
import static net.sf.jasperreports.functions.standard.TextFunctions.*
Allows those functions to be imported into the current namespace.
So, back to the original issue. If set net.sf.jasperreports.compiler.keep.java.file=true
in jasperreports.properties
and attempt to compile the report, I can examine the java file that jasper produces from the jrxml. I find that this file does not seem to import the necessary functions (INTEGER_VALUE
, CONCATENATE
, etc). The only imports it contains are:
/*
* Generated by JasperReports - 4/27/16 2:27 PM
*/
import net.sf.jasperreports.engine.*;
import net.sf.jasperreports.engine.fill.*;
import net.sf.jasperreports.functions.standard.TextFunctions.*;
import java.util.*;
import java.math.*;
import java.text.*;
import java.io.*;
import java.net.*;
symbol: method CONCATENATE(String,String,String,String,String)
The problem seems to be that the Java compiler is not able to resolve varargs calls, the method is defined as CONCATENATE(String ...strings).
Add an ecj jar to your application's classpath (for instance the one from http://repo1.maven.org/maven2/org/eclipse/jdt/core/compiler/ecj/4.3.1/), that's usually safer than relying on the JDK compiler.