Passing in content when generating JasperServer report using the REST API

烂漫一生 提交于 2019-12-03 06:22:45

After several hours spent on research, I think I'm ready to answer my own question.

JasperReports Server ("JRS" below) is fundamentally designed to fetch data by itself. Although it would be possible to force feed JRS with data, I've decided not to.

One of the most obvious drawback of not letting JRS fetch the data itself is that it would no longer be possible to generate reports from the JRS web interface. Integration from other systems also becomes impossible or difficult if the client application is responsible for supplying the data in a predefined format.

In the project I'm working on, we've decided to build a custom JRS DataSource based on the Remote XML DataSource, that invokes the client application's XML API. In other words, the client application requests a report from JRS, and JRS then requests it's data from the client application. The XML API will have to be expanded to cover all of our reporting needs, but that's a good thing in my opinion. Good API coverage will come in handy in the future.

I hope these thoughts helps someone having similar questions.

As you wrote, fetching data is more natural way for JRS. However, I needed to go the opposite way - I POST data to report sitting in JRS repo via a REST call.

I pass XML data in my parameter "xmlDocument" and, by means of a "trick", an executed report can use this XML for further X-path queries.

xmlDocument is just a simple String:

<parameter name="xmlDocument" class="java.lang.String">
    <defaultValueExpression><![CDATA["<?xml version=\"1.0\" encoding=\"UTF-8\"?><documentData></documentData>"]]></defaultValueExpression>
</parameter>

At designing phase I create XML data adapter with XML file that I use for previewing. Note that a new parameter XML_INPUT_STREAM appeared after choosing XML adapter.

Then I publish the report to JRS. During report execution, when the report is not linked to any data source, it reads XML_INPUT_STREAM parameter instead (as fallback data source), that looks as follows:

<parameter name="XML_INPUT_STREAM" class="java.io.InputStream" isForPrompting="false">
    <defaultValueExpression><![CDATA[new java.io.ByteArrayInputStream($P{xmlDocument}.getBytes("UTF-8"))]]></defaultValueExpression>
</parameter>

I wrap "xmlDocument" string to InputStream.

Even if I agree with the answer, witch states that the JasperServer has been built to fetch data by itself, I had still to pass the data trough the rest API because it's the legacy way of my company to build Jasper reports and because we want to use custom Java services to fetch data.

I've found this described above to be the simpliest possible way to do this.

Having this simple custom pojo that you want to pass to the report trough web API:

public class CustomReport {

private String content;

public String getContent() {
    return content;
}

public void setContent(String content) {
    this.content = content;
}

public CustomReport() {
    super();
}

1) Define a custom jasper scriptlet that has to be deployed on the server as a resource related to the report, witch will deserialize the string into the custom pojo object using GSON:

public class CustomScriptlet
    extends JRDefaultScriptlet { public void afterReportInit()
        throws JRScriptletException
{
    Object customSerializedObj = getParameterValue("customSerialized");
    if (customSerializedObj != null)
    {
        String customSerializedStr = customSerializedObj.toString();
        if ((customSerializedStr != null) && (customSerializedStr.length() > 0))
        {
            CustomReport customReport = new Gson().fromJson(customSerializedStr,
                            CustomReport.class);

            setVariableValue("customReport", customReport);
        }
    }
}

2) Use the parameter/variable with the custom scriptlet in jasper server:

<scriptlet name="Scriptlet_1" class="eu.dedalus.jasper.api.scriptlet.CustomScriptlet">
    <scriptletDescription><![CDATA[CustomScriptlet]]></scriptletDescription>
</scriptlet>
<parameter name="customSerialized" class="java.lang.String"/>
<variable name="customReport" class="com.test.CustomReport" calculation="System"/>

3) Invoke the API @ jasperserver/rest_v2/reportExecutions like this:

    "reportUnitUri" : "/report/Custom_report",
"async":"false",
"outputFormat":"pdf",
"parameters" : {
    "reportParameter" : [
        {
            "name": "customReport",
            "value": ["{ \"content\" : \"test content\" } "]
        }
    ]
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!