1

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.*;
vezult
  • 5,185
  • 25
  • 41
  • CONCATENATE where did you find this function/method?, is it yours? – Petter Friberg Apr 27 '16 at 19:01
  • @PetterFriberg: This is a function in the jasperreport-functions-6.2.1.jar supplied by JasperSoft. Specifically in `net.sf.jasperreports.functions.standard.TextFunctions` – vezult Apr 27 '16 at 20:40

3 Answers3

2

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.

dada67
  • 4,723
  • 17
  • 19
0

I do not get the same result as you using jasperreports-6.2.1.jar and jasperreports-functions-6.2.1.jar, compiling with jre 1.8.0_77 (also with jre1.7)

My report java file has this method in it:

public java.lang.String CONCATENATE(java.lang.String...  arg0)
{
    return getFunctionSupport(net.sf.jasperreports.functions.standard.TextFunctions.class).CONCATENATE(arg0);
}

and the function call works correctly (note that I have not added any imports in jrxml file, nor modified the jasperreports_extension.properties in any way)

So you need to check again that the libraries in class path and that you have not messed with the jasperreports_extension.properties

vezult
  • 5,185
  • 25
  • 41
Petter Friberg
  • 21,252
  • 9
  • 60
  • 109
  • As I said originally, the jasperreports-functions-6.2.1.jar file **is** in my classpath. I have not modified `jasperreports_extension.properties`. – vezult Apr 28 '16 at 13:36
  • I have test since I was curious about the function and as you can see the generate java file is not similar to yours (and it works), you see how the CONCATENATE method is generated inside of the java report file. What JRE are you using? how are you compiling the report? – Petter Friberg Apr 28 '16 at 13:39
  • It seems possible that we are compiling the jasper report itself differently. I was able to get it to work by explicitly adding imports to the `JasperDesign` object. – vezult Apr 28 '16 at 13:43
  • What compiler are you using? jtd-compiler? or the ecj? – Petter Friberg Apr 28 '16 at 13:45
  • @vezult, then you test adding them directly to the jrxml as well, however you have something strange going on while compiling – Petter Friberg Apr 28 '16 at 13:52
0

In order to make these functions available when compiling a jasper report, load the jrxml into a DesignObject and explicitly add the necessary imports:

JRXmlLoader loader = new JRXmlLoader(new SimpleJasperReportsContext(), new Digester());
JasperDesign designFile = loader.load(fileName + ".jrxml");
String destinationFile = fileName + ".jasper";

// Ensure that custom functions are available when compiling reports.
designFile.addImport("static net.sf.jasperreports.functions.standard.TextFunctions.*");
designFile.addImport("static net.sf.jasperreports.functions.standard.MathFunctions.*");
designFile.addImport("static net.sf.jasperreports.functions.standard.DateTimeFunctions.*");
designFile.addImport("static net.sf.jasperreports.functions.standard.LogicalFunctions.*");

JasperCompileManager.compileReportToFile(designFile, destinationFile);

It is important to use a static import. If the static keyword is not used, the methods are not imported directly into the current namespace, as required by the generated java code.

Using this approach, no modification of the jasper report itself is needed.

vezult
  • 5,185
  • 25
  • 41