Cascading/Dependent Parameters in JS 5.5 using Groovy

1

In Jasperserver 4.1 cascading/dependent parameters (just cascading parameters, not cascading queries input controls) worked fine for us when using either Java or Groovy as the report language. However, after we upgraded to Jasperserver 5.5, the cascading parameters no longer worked when using Groovy. Here's a brief example:

<parameter name="year" class="java.lang.Integer" isForPrompting="true"/>
<parameter name="month" class="java.lang.Integer" isForPrompting="true"/>
<parameter name="endOfMonth" class="java.util.Date" isForPrompting="false">
<defaultValueExpression><![CDATA[((new GregorianCalendar($P{year}, $P{month}, 0)).getTime())]]></defaultValueExpression>
</parameter>
 
Using this in the report yields the following error:
 
Message Error
 
groovy.lang.GroovyRuntimeException: failed to invoke constructor: public java.util.GregorianCalendar(int,int,int) with arguments: [null, null, 0] reason: java.lang.IllegalArgumentException
 
Error Trace
 
groovy.lang.GroovyRuntimeException: failed to invoke constructor: public java.util.GregorianCalendar(int,int,int) with arguments: [null, null, 0] reason: java.lang.IllegalArgumentException at org.codehaus.groovy.reflection.CachedConstructor.createExceptionText(CachedConstructor.java:93) at org.codehaus.groovy.reflection.CachedConstructor.invoke(CachedConstructor.java:81) at org.codehaus.groovy.reflection.CachedConstructor.doConstructorInvoke(CachedConstructor.java:71) at org.codehaus.groovy.runtime.callsite.ConstructorSite.callConstructor(ConstructorSite.java:42) at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallConstructor(CallSiteArray.java:57) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:182) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:198) at cascadingParametersTest_1389993683606_71896.evaluate(calculator_cascadingParametersTest_1389993683606_71896:132) at net.sf.jasperreports.engine.fill.JREvaluator.evaluate(JREvaluator.java:231) at net.sf.jasperreports.engine.fill.JRCalculator.evaluate(JRCalculator.java:591) at net.sf.jasperreports.engine.fill.JRCalculator.evaluate(JRCalculator.java:559) at net.sf.jasperreports.engine.fill.JRFillDataset.setFillParameterValues(JRFillDataset.java:994) at net.sf.jasperreports.engine.fill.JRFillDataset.setParameterValues(JRFillDataset.java:635) at net.sf.jasperreports.engine.fill.JRParameterDefaultValuesEvaluator.evaluateParameterDefaultValues(JRParameterDefaultValuesEvaluator.java:87) at net.sf.jasperreports.engine.fill.JRParameterDefaultValuesEvaluator.evaluateParameterDefaultValues(JRParameterDefaultValuesEvaluator.java:59) at com.jaspersoft.jasperserver.api.engine.jasperreports.service.impl.EngineServiceImpl.getReportInputControlsInformation(EngineServiceImpl.java:2472) at com.jaspersoft.jasperserver.api.engine.jasperreports.service.impl.EngineServiceImpl.getReportInputControlsInformation(EngineServiceImpl.java:2430) at com.jaspersoft.jasperserver.api.engine.jasperreports.service.impl.EngineServiceImpl.getReportInputControlsInformation(EngineServiceImpl.java:2318) at com.jaspersoft.jasperserver.war.action.ReportParametersAction.getControlsInformation(ReportParametersAction.java:612) at com.jaspersoft.jasperserver.war.action.ReportParametersAction.getReportParameterValuesFromRequest(ReportParametersAction.java:450) at com.jaspersoft.jasperserver.war.action.ViewReportAction.executeReport(ViewReportAction.java:495) at com.jaspersoft.jasperserver.war.action.ViewReportAction.runReport(ViewReportAction.java:404) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) at org.springframework.webflow.action.DispatchMethodInvoker.invoke(DispatchMethodInvoker.java:98) at.......
 

We have double checked all the considerations for using cascading parameters, and everything is in order. Maybe something has changed regarding how the report expressions are calculated under the hood for Groovy reports... Does anyone know what is the cause of this and how to solve it?

We've also found that Marianol has used cascading parameters with apparent success in this topic, but we don't know whether that's JS 5.5 or not.

ftama7's picture
15
Joined: Jun 26 2013 - 8:28am
Last seen: 4 years 6 months ago

Yes, ftama7 that should work fine in 5.5. But I'm thinking that it may have something to do on how the execution of the dependant IC are working. I'll try to replicate this.

Can you post a JasperServer Export of the report so I can see the how the parameters are setup? 
Other thing you can try is to check that the default value is getting passed on correctly if you take out the cascading parameters.

 

marianol - 5 years 10 months ago

Here's the export for a test report I made with the same settings as our production reports which present the issue: https://drive.google.com/file/d/0B9GFH6mnvMancF9EUmhPY3FyTFE/edit?usp=sh...

I've previously tested that when using constant values instead of parameters inside the dependent parameter, the expression is evaluated correctly. However, when using the parameters, they're considered as null when calculating the dependent parameter expression.

ftama7 - 5 years 10 months ago

I have also replicated this behavior in a brand new JasperServer 5.5 installation, without any of the custom configurations we have on our production environment. This is quite puzzling, as we considered some of the changes to the JR Database could've been causing the issue.

ftama7 - 5 years 10 months ago
show 1 more...

Investigating further, I've checked on the source code for the Jasperreports library for some of the classes in the stacktrace that could've cause the issue, namely the JREvaluator, JRCalculator, JRFillDataset and JRParameterDefaultValuesEvaluator classes. After analyzing the code, I found but one minor difference from the JRParametereDefaultValuesEvaluator from version 4.1 that could possibly cause an issue (line 80's logic used to be after lines 82 and 83). I doubted that could be the issue, but I still tested changing that, compiled my library version, and unfortunately yet expectedly, it didn't work.

Anyway, I believe it's more probable for the issue to be in the Groovy evaluators, compilers or generators, as the problem is only present when using Groovy as the report language. Perhaps lucianc may know about something that could potentially cause such behavior, as he's worked on that code not so long ago...

On another note, I also believe some of the unanswered questions on the forum may be related to this apparent bug I've identified. For example:

http://community.jaspersoft.com//questions/822184/dynamic-query-parameter-input-control-not-working-jasperserver-51-ce

(I'm still trying to find again some of the other similar questions)

ftama7 - 5 years 10 months ago

1 Answer:

0

After doing some additional tests with simpler expressions, I have found the problem and a workaround for it. In simple terms, if you want to use a cascading parameter in a Groovy report, you must start the default value expression for that parameter with an element that uses the $P{} notation. For example:

<parameter name="year" class="java.lang.Integer" isForPrompting="true"/>
<parameter name="month" class="java.lang.Integer" isForPrompting="true"/>
<parameter name="endOfMonth" class="java.util.Date" isForPrompting="false">
<defaultValueExpression><![CDATA[((new GregorianCalendar($P{year}, $P{month}, 0)).getTime())]]></defaultValueExpression>
</parameter>
 
In that context, the parameter endOfMonth won't work, as it'll consider the year and month parameters to be null when evaluationg the default value expression, which is a completely different behavior from the 4.0.1 JS version. Alas, this can be circumvented by doing the following instead:
 
<defaultValueExpression><![CDATA[($P{year} != null && $P{month} != null) ? ((new GregorianCalendar($P{year}, $P{month}, 0)).getTime()) : null]]></defaultValueExpression>
 
Apparently, this is the reason why our Groovy reports weren't working after the migration, but Marianol's Groovy report using cascading parameters did work. 
 
 
 
On another note, I tried to further simplify things by defining a tautologic parameter expressions which we always want to execute:
 
<parameter name="isUserAGoat" class="java.lang.Boolean" isForPrompting="false">
<defaultValueExpression><![CDATA[true]]></defaultValueExpression>
</parameter>
<parameter name="endOfMonth" class="java.util.Date" isForPrompting="false">
<defaultValueExpression><![CDATA[$P{isUserAGoat} ? ((new GregorianCalendar($P{year}, $P{month}, 0)).getTime()) : null]]></defaultValueExpression>
</parameter>
 
I expected this to work, but for some reason it didn't. It is as if giving the isUserAGoat a default value messes things up. Afterwards, I tried this:
 
<parameter name="isUserAGoat" class="java.lang.Boolean" isForPrompting="false"/>
<parameter name="endOfMonth" class="java.util.Date" isForPrompting="false">
<defaultValueExpression><![CDATA[$P{isUserAGoat} ? ((new GregorianCalendar($P{year}, $P{month}, 0)).getTime()) : null]]></defaultValueExpression>
</parameter>
 
This works just fine, as long as you define an input control for isUserAGoat and pass "true" as its value, but as we're not goats I tried rewording things like this:
 
<defaultValueExpression><![CDATA[!$P{isUserAGoat} ? ((new GregorianCalendar($P{year}, $P{month}, 0)).getTime()) : null]]></defaultValueExpression>
 
And it turns out that, again, this doesn't work. It seems that the expression must absolutely, positively start with a $P{}, without even a ! before it. To avoid this, I tried the following:
 
<defaultValueExpression><![CDATA[$P{isUserAGoat} ? null : ((new GregorianCalendar($P{year}, $P{month}, 0)).getTime()) ]]></defaultValueExpression>
 
And this doesn't work either. Apparently, the part of the expression you want to use the dependencies in must be right after the ? operator. This can be quite troublesome, as there's less flexibility for writing expressions. Finally, I tried the following:
 
<defaultValueExpression><![CDATA[$P{REPORT_CONTEXT} ? ((new GregorianCalendar($P{year}, $P{month}, 0)).getTime()) : null]]></defaultValueExpression>
 
With this, we needn't assume everyone is a goat anymore. This works because the parameter REPORT_CONTEXT exists as an object, so Groovy will consider it as true when evaluating it in the binary operation performed by the ternary operator. This didn't work when using other of the default parameters like REPORT_PARAMETERS_MAP or JASPER_REPORT, though... and sadly, as intriguing as it is, I can't keep researching this for much longer.
 
All in all, there's some ways to circumvent this issue, like assuming we're all goats (or perhaps creating a isUserNotAGoat parameter), but I believe this strange behavior in the expressions evaluations should be corrected so that things work as expected again.
ftama7's picture
15
Joined: Jun 26 2013 - 8:28am
Last seen: 4 years 6 months ago
Feedback
randomness