0

When I package my stand-alone-java-application, that compiles, renders and prints Jasper-Reports, in a fat jar with all dependencies, I get the error that the function TEXT – a function used in the report and defined in the net.sf.jasperreports-functions-library is not found.

The method TEXT(Integer, String) is undefined for the type [...]
                value = IF(LEN(TEXT(((java.lang.Integer)parameter_X.getValue()),"#"))==2,"***",REPT("*",6-LEN(TEXT(((java.lang.Integer)parameter_X.getValue()),"#")))) //$JR_EXPR_ID=58$

Other functions from the same library work. When I run the application with gradle run, the function is found and the report can be printed. The library is on my classpath.

There are several similar questions on this site and Stackoverflow, but neither provided answers, that worked for me. In the following, I will explain what I tried:

In my build.gradle-File I defined dependencies to the following libraries:

implementation('net.sf.jasperreports:jasperreports:6.18.1')
implementation('net.sf.jasperreports:jasperreports-functions:6.18.1')

In my java-Files, I created a DesignFile and statically imported the functions into it. I tried two methods:

Method 1 as given in an answer in this thread: Unresolved symbols when compiling jasper report

/*…*/
designFile = JRXmlLoader.load(sourceFile.getAbsolutePath());

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.*");

JasperReport compiledReport = JasperCompileManager.getInstance(ctx).compile(designFile);
/*…*/

Method 2: importing each function on its own

public static String[] textFunctions(){
        return new String[]{"BASE", "CHAR", "CLEAN", "CODE", "CONCATENATE", "DOUBLE_VALUE",
"EXACT", "FIND", /*"FIXED", */"FLOAT_VALUE", "INTEGER_VALUE", "LEFT", "LEN", "LONG_VALUE", 
"LOWER", "LTRIM", "MID", "PROPER", "REPLACE", "REPT", "RIGHT", "RTRIM", "SEARCH", "SUBSTITUTE",
"T", /*"TEXT",*/ "TRIM", "UPPER"};
    }}  
/*…*/
designFile = JRXmlLoader.load(sourceFile.getAbsolutePath());

for (String textFunction : textFunctions()){
            designFile.addImport("static net.sf.jasperreports.functions.standard.TextFunctions." + textFunction);
        }/* similarly for logical functions, numeric functions and datetime functions*/
        }
JasperReport compiledReport = JasperCompileManager.getInstance(ctx).compile(designFile);
/*…*/

As you can see, the function TEXT is commented out. That’s because the program fails at runtime when run with “gradle run”, when I comment it in:

net.sf.jasperreports.engine.JRException: Errors were encountered when compiling report expressions class file:
1. The import net.sf.jasperreports.functions.standard.TextFunctions.TEXT cannot be resolved
import static net.sf.jasperreports.functions.standard.TextFunctions.TEXT;

The same thing is true with most datetime-functions, in fact, only TIME can be imported to the DesignObject without error at runtime

In addition to that, when I type net.sf.jasperreports.functions.standard.TextFunctions. in my IDE, the content-assist shows a list of available functions, yet TEXT is missing. enter image description here

I suspected, that the function is simply missing in the library, but it is there. In the .gradle/cache/modules-2/files-2.1/… directory, there is the jar with the TextFunctions.java, that contains the function TEXT:

enter image description here

When building the FatJar with dependencies, I have a TextFunctions.class-File in it, that contains the TEXT-Function as well. enter image description here

In my jar, there are two jasperreports_extension.properties on the root level: enter image description here

with the smaller one (from the jasperreport-functions-dependency) containing the following lines:

net.sf.jasperreports.extension.registry.factory.functions=net.sf.jasperreports.functions.FunctionsRegistryFactory
net.sf.jasperreports.extension.functions.datetime=net.sf.jasperreports.functions.standard.DateTimeFunctions
net.sf.jasperreports.extension.functions.math=net.sf.jasperreports.functions.standard.MathFunctions, net.sf.jasperreports.functions.standard.LogicalFunctions
net.sf.jasperreports.extension.functions.text=net.sf.jasperreports.functions.standard.TextFunctions 
net.sf.jasperreports.extension.functions.report=net.sf.jasperreports.functions.standard.ReportFunctions 

Funnily enough, commenting out TEXT, running it locally with gradle run, it works without problems. But packaging it and running it with java -jar it fails to find this function. And statically importing this function leads to gradle run failing as well.

What is happening and how can I fix this? I want to distribute my FatJar on a server and run it, but this problems makes it impossible for me.

aggharta
  • 253
  • 1
  • 7
  • When you create a fat jar out of several JasperReports jars you need to make sure that jasperreports_extension.properties resources from the jars get merged into a single resource in the fat jar. https://stackoverflow.com/a/35025718/983559 shows how to do that using https://maven.apache.org/plugins/maven-shade-plugin/ for instance. – dada67 Feb 02 '22 at 08:21
  • In my fatJar, both jasperreports_extension.properties are present. It is not the case that one is overridden by the other like in the link you posted. Is it really needed to merge them in this case? Why are most functions like IF, T and NOT found, and only some are missing if that would be the problem? – aggharta Feb 02 '22 at 09:53
  • Can you confirm that the jasperreports_extension.properties from your jar has all the lines from https://github.com/TIBCOSoftware/jasperreports/blob/master/jasperreports/ext/functions/src/main/resources/jasperreports_extension.properties – dada67 Feb 02 '22 at 11:08
  • @dada67 I edited my question to include a screenshot of the two jasperreports_extension.properties in my jar and the contents of the smaller one, which contains all the lines you referenced. – aggharta Feb 02 '22 at 12:16
  • If you have two entries with the same name in the jar, only one will be loaded. You need to merge them into a single resource in the jar. – dada67 Feb 02 '22 at 12:22

0 Answers0