bill.reynolds Posted November 13, 2017 Share Posted November 13, 2017 Hi, I'm running into an issue running the following JRXML file. Here's what I'm trying to do - I'd like to pass this report a collection of strings, and then join these strings into a new String parameter using the expression editor. Here is the JRXML file: <?xml version="1.0" encoding="UTF-8"?><!-- Created with Jaspersoft Studio version 6.3.0.final using JasperReports Library version 6.3.0 --><!-- 2017-11-13T15:34:24 --><jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="collection_test" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="4a22e2a3-efb0-425f-a139-0cf337cfec5e"><property name="com.jaspersoft.studio.data.defaultdataadapter" value="One Empty Record"/><parameter name="issue-status-filter" class="java.util.List"/><parameter name="issue-status-filter-clause" class="java.lang.String" isForPrompting="false"><defaultValueExpression><![CDATA[($P{issue-status-filter} == null || $P{issue-status-filter}.isEmpty()) ? "" : ("and status in ('" + String.join("', '", $P{issue-status-filter}) + "')")]]></defaultValueExpression></parameter><queryString><![CDATA[select 1]]></queryString><background><band splitType="Stretch"/></background><detail><band height="125" splitType="Stretch"><textField><reportElement x="65" y="43" width="235" height="30" uuid="4b00b860-c1fd-4ae3-a254-2828e90ca286"/><textFieldExpression><![CDATA["Status Types:" + $P{issue-status-filter-clause}]]></textFieldExpression></textField></band></detail></jasperReport> This report works as expected in JasperStudio. Additionally, it in JasperServer works when I pass it two or more parameters in the report request. However, when I try to pass it a single item in the Collection, it throws a ClassCastException. Here is the relevant request:curl -u superuser:XXXXXX "http://localhost:8080/jasperserver-pro/rest_v2/reports/reports/collection_test.pdf?issue-status-filter=open" -o issue.pdfHere is the resulting stacktracejasperserver_1 | Caused by: java.lang.ClassCastException: java.lang.String cannot be cast to java.util.Listjasperserver_1 | at collection_test_1510604074207_861928.evaluate(collection_test_1510604074207_861928:137)jasperserver_1 | at net.sf.jasperreports.engine.fill.JREvaluator.evaluate(JREvaluator.java:276)jasperserver_1 | ... 17 more From what I can see, it appears that Jasper is internally converting the single-element collection to a String when running on the server, and failing when trying to evaulate the expression.Environment Details:Jasper Server Pro - 6.3.0Jasper Studio - 6.3.0 I also tested against Jasper Server CE 6.4.0, and got the same results. Link to comment Share on other sites More sharing options...
Solution lucianc Posted November 14, 2017 Solution Share Posted November 14, 2017 I assume you don't have an input control defined for the issue-status-filter parameter in the server report unit.The recommended solution is to create a multi valued input control for the parameter. The input control can be either backed by a query (something like select distinct status from ... in your case) or by a static values list (if there's a fixed set of status values).I would also recommeng using $X{IN,status,issue-status-filter} instead of manually constructing the status in (...) clause with String.join. For one, $X{IN} protects you from SQL injection.If for some reason you don't want to create an input control, your only chance is to write the parameter so it works with both single values and collections of values. Something like this: <parameter name="issue-status-filter" class="java.lang.Object" /> <parameter name="issue-status-filter-list" class="java.util.List" isForPrompting="false"> <defaultValueExpression> ($P{issue-status-filter} == null) ? null : (($P{issue-status-filter} instanceof Collection) ? new ArrayList((Collection) $P{issue-status-filter}) : Collections.singletonList($P{issue-status-filter})) </defaultValueExpression> </parameter>[/code]Then you can use issue-status-filter-list for the query. It's not pretty but I don't see any other way.Regards,Lucian Link to comment Share on other sites More sharing options...
bill.reynolds Posted November 14, 2017 Author Share Posted November 14, 2017 Thanks Lucian. I came up with a similar ternary operator earlier this morning - I agree it is a little messy, but I was able to get it to work: <parameter name="issue-status-filter" class="java.lang.Object"/> <parameter name="issue-status-filter-clause" class="java.lang.String" isForPrompting="false"> <defaultValueExpression><![CDATA[$P{issue-status-filter} == null ? "" : $P{issue-status-filter} instanceof java.util.Collection ? ((java.util.Collection<String>)$P{issue-status-filter}).isEmpty() ? "" : "and status in ('" + String.join("', '", ((java.util.Collection<String>)$P{issue-status-filter})) + "')" : $P{issue-status-filter} instanceof java.lang.String ? ((java.lang.String)$P{issue-status-filter}).equals("") ? "" : "and status in ('" + ((java.lang.String)$P{issue-status-filter}).toString() + "')" : "";]]></defaultValueExpression> </parameter> I haven't looked at creating an input control yet, however - if I get some time I'll see if that helps our use case. Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now