How to debug jasper reports?

Solution for How to debug jasper reports?
is Given Below:

Currently i am working on my first reports using iReport for design. Under certain conditions jasper gets stuck in some kind of infinte loop / recursive call. Jasper’s logs following repeatedly:

[...]
12-04-10 10:29:59,222 DEBUG s.engine.fill.JRVerticalFiller|Fill 1207280802: page footer
12-04-10 10:29:59,222 DEBUG ports.engine.fill.JRBaseFiller|Fill 1207280802: adding page 38849
12-04-10 10:29:59,222 DEBUG ts.engine.fill.JRFillSubreport|Fill 1207280802: resuming 849817670
12-04-10 10:29:59,222 DEBUG e.fill.JRThreadSubreportRunner|Fill 849817670: notifying to continue
12-04-10 10:29:59,222 DEBUG e.fill.JRThreadSubreportRunner|Fill 849817670: waiting for fill result
12-04-10 10:29:59,222 DEBUG e.fill.JRThreadSubreportRunner|Fill 849817670: notified to continue
12-04-10 10:29:59,222 DEBUG ports.engine.fill.JRBaseFiller|Fill 849817670: suspeding subreport runner
12-04-10 10:29:59,222 DEBUG e.fill.JRThreadSubreportRunner|Fill 849817670: notifying on suspend
12-04-10 10:29:59,222 DEBUG e.fill.JRThreadSubreportRunner|Fill 849817670: waiting to continue
12-04-10 10:29:59,222 DEBUG e.fill.JRThreadSubreportRunner|Fill 849817670: notified of fill result
12-04-10 10:29:59,222 DEBUG ts.engine.fill.JRFillSubreport|Fill 1207280802: subreport 849817670 to continue
[...]

This sequence is logged repeatedly with identical filler ids. I have difficulties with interpreting those debug logs. Apart from solving the concrete problem i am interested in strategies to debug jasper reports. So, how do you debug reports?

You can use the log4j.properties to get some additional information from iReport. The below steps were provided to me by Jasper support to help me see what SQL was being generated by a report with several sub reports and dynamic SQL being passed between them.

  1. Create a log4j.properties file (place it under ireport/etc), with the
    contents as follows:

    #############################################
    log4j.appender.fileout=org.apache.log4j.RollingFileAppender
    log4j.appender.fileout.File=C:/tmp/iReport.log
    log4j.appender.fileout.MaxFileSize=1024KB
    log4j.appender.fileout.MaxBackupIndex=1
    log4j.appender.fileout.layout=org.apache.log4j.PatternLayout
    log4j.appender.fileout.layout.conversionPattern=%d{ABSOLUTE} %5p
    %c{1},%t:%L - %m%n
    log4j.rootLogger=warn, fileout
    log4j.logger.net.sf.jasperreports.engine.query=debug
    #############################################
    

    With the above, the output log will be in the iReport.log in the c:/tmp
    folder.

  2. Edit ireport/etc/ireportpro.conf and add the following contents in the
    default_options parameter:

    -J-Dlog4j.configuration=file:/E:/Server/Server451/ireport/etc/log4j.properties
    

    So it becomes:

    default_options="-J-Xms24m -J-Xmx512m
    
    -J-Dorg.netbeans.ProxyClassLoader.level=1000 -J-XX:MaxPermSize=256m
    -J-Dlog4j.configuration=file:/E:/Server/Server451/ireport/etc/log4j.properties"
    

    Please pay attention to the above directory, you will need to adjust it to
    your own specific directory of iReport installation.

  3. Restart iReport and execute reports, the generated SQL will then be
    output in iReport.log.

You can use te class below to create an “expression logger” which you can then use in the report to see variable values, and when they are evaluated or used.

First, you need to create a logger and put it in the report parameters map in your Java code which starts the report:

String loggerName = "jasper.report." + reportName;
Logger logger = LoggerFactory.getLogger(loggerName);
reportParameters.put("log", new JasperLogger(logger));

In the report, create a new parameter log with the type of the class below. Now, when you have to evaluate an expression (like a “Print When Expression”), wrap it:

$P{log}.debug("printWhen for text field ...: {}", ...original expression...)

Here is the code for the class:

import org.slf4j.Logger;

/** A wrapper for a SLF4J logger which allows to log expressions as they are evaluated. */
public class JasperLogger {

    private Logger delegate;

    public JasperLogger(Logger delegate) {
        this.delegate = delegate;
    }

    public <T> T debug(String message, T value) {
        delegate.debug(message, value);
        return value;
    }

    public <T> T info(String message, T value) {
        delegate.info(message, value);
        return value;
    }

    public <T> T error(String message, T value) {
        delegate.error(message, value);
        return value;
    }
}

For Jasperreports version 7.5, this is the configuration file you have to set:

vim /opt/tomcat/webapps/jasperserver/WEB-INF/log4j2.properties

logger.net_sf_jasperreports_engine_query_JRJdbcQueryExecuter.name=net.sf.jasperreports.engine.query.JRJdbcQueryExecuter
logger.net_sf_jasperreports_engine_query_JRJdbcQueryExecuter.level=debug

This way you will have the queries executed and the parameters substituted:

[...]
FROM t
GROUP BY trunc(local_date, 'DD')
ORDER BY trunc(local_date, 'DD') DESC
2021-09-23T12:06:57,495 DEBUG JRJdbcQueryExecuter,pool-5-thread-1:586 - Parameter #1 (USU_WEB of type java.lang.String): FOO
2021-09-23T12:06:57,501 DEBUG JRJdbcQueryExecuter,pool-5-thread-1:586 - Parameter #2 (START_DATETIME of type java.lang.String): 2021-09-13 00:00:00
2021-09-23T12:06:57,501 DEBUG JRJdbcQueryExecuter,pool-5-thread-1:586 - Parameter #3 (END_DATETIME of type java.lang.String): 2021-09-24 00:00:00
2021-09-23T12:06:57,501 DEBUG JRJdbcQueryExecuter,pool-5-thread-1:586 - Parameter #4 (USU_WEB of type java.lang.String): FOO