JasperReports logo version 7.0.0 Home - Samples - Configuration - Functions - FAQ - API (Javadoc)

JasperReports - HTTP Data Adapter Sample

Shows how the HTTP data adapters can be used to fill reports.

Main Features in This Sample

HTTP Data Adapter

Secondary Features

JSONQL Data Source
XML Data Source

HTTP Data Adapter

Documented by Sanda Zaharia

Description / Goal
How to fill a report using data from an HTTP request returning XML or JSON file.

Since:

Other Samples
/demo/samples/jsonqldatasource
/demo/samples/xmldatasource

Accessing Data over HTTP

An HTTP data adapter is a data file-based data adapter that uses an HttpDataLocation object, in order to gain access to remote data over HTTP and retrieve content that can be mapped to a custom (usually JSONQL or XML) data source.

DataFile-based adapters (such as JsonDataAdapter or XmlDataAdapter) can be converted into HTTP data adapters by declaring their DataFile element of type HttpDataLocation:

<jsonDataAdapter class="net.sf.jasperreports.data.json.JsonDataAdapterImpl">
  <name>JSON Http Data Adapter</name>
  <dataFile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="httpDataLocation">
    ...
  </dataFile>
  ...
</jsonDataAdapter>

or

<xmlDataAdapter class="net.sf.jasperreports.data.xml.XmlDataAdapterImpl">
  <name>XML Http Data Adapter</name>
  <dataFile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="httpDataLocation">
    ...
  </dataFile>
  ...
</xmlDataAdapter>

The HttpDataLocation object encapsulates the following information, related to a given HTTP request:

HTTP Parameter Properties

None of the elements described above (method, url, username, password, urlParameter, body, postParameter or header) are required in an HTTP data adapter.
The only requirement is to have its type declared as httpDataLocation (xsi:type="httpDataLocation").

In case no method element is specified, the default method name depends on the presence/absence of the body element or the postParameter list:

Regarding the other elements (url, username, urlParameter, etc), we can send all this information via the usual report parameters, since data adapters are in fact parameter contributor objects.

The following predefined parameter properties let us configure the HTTP request, and always override the similar information declared in data adapter:

  1. net.sf.jasperreports.http.data.method
    • is specified per dataset or at report parameter level
    • if declared per dataset, its value is mandatory and represents the HTTP request method used by the data adapter
    • if declared at report parameter level, it needs no value and is used to mark the report parameter as HTTP request method provider
    • if this property is specified in various report parameters, only the last one of them will be considered as HTTP request method provider
  2. net.sf.jasperreports.http.data.url
    • is specified per dataset or at report parameter level
    • if declared per dataset, its value is mandatory and represents the base URL used by the HTTP data adapter
    • if declared at report parameter level, it needs no value and is used to mark the report parameter as URL provider for the HTTP request
    • overrides the deprecated parameter PARAMETER_URL
    • if this property is specified in various report parameters, only the last one of them will be considered as the URL provider
  3. net.sf.jasperreports.http.data.username
    • is specified per dataset or at report parameter level
    • if declared per dataset, its value is mandatory and represents the user name to be used in HTTP data adapters with basic authentication.
    • if declared at report parameter level, it needs no value and is used to mark the report parameter as user name provider for the HTTP request
    • overrides the deprecated parameter PARAMETER_USERNAME
    • if this property is specified in various report parameters, only the last one of them will be considered as the user name provider
  4. net.sf.jasperreports.http.data.password
    • is specified per dataset or at report parameter level
    • if declared per dataset, its value is mandatory and represents the user password to be used in HTTP data adapters with basic authentication.
    • if declared at report parameter level, it needs no value and is used to mark the report parameter as user password provider for the HTTP request
    • overrides the deprecated parameter PARAMETER__PASSWORD
    • if this property is specified in various report parameters, only the last one of them will be considered as the user password provider
  5. net.sf.jasperreports.http.data.body
    • is specified per dataset or at report parameter level
    • if declared per dataset, its value is mandatory and represents the HTTP request body
    • if declared at report parameter level, it needs no value and is used to mark the report parameter as HTTP request body provider
    • if this property is specified in various report parameters, only the last one of them will be considered as the request body provider
    • the HTTP request body will be ignored by the GET method
  6. net.sf.jasperreports.http.data.url.parameter
    • is specified at report parameter level
    • if the property has no value, it will be used to mark the report parameter as URL parameter to be appended to the base URL of the HTTP request; the URL parameter will have the same name and value as the report parameter
    • if the property has a given value, its value will be used as name for the related URL parameter; the value of the URL parameter will be the same as the report parameter value
    • overrides the deprecated parameter prefix PARAMETER_PREFIX_URL_PARAMETER
    • if this property is specified in various report parameters, the related URL parameter will be considered as parameter of type array, being sent multiple times
  7. net.sf.jasperreports.http.data.post.parameter
    • is specified at report parameter level
    • if the property has no value, it will be used to mark the report parameter as HTTP request POST parameter; the POST parameter will have the same name and value as the report parameter
    • if the property has a given value, its value will be used as name for the related request POST parameter; the value of the POST parameter will be the same as the report parameter value
    • overrides the deprecated parameter prefix PARAMETER_PREFIX_POST_PARAMETER
    • if this property is specified in various report parameters, the related POST parameter will be considered as parameter of type array, being sent multiple times
    • POST parameters will be ignored by the GET method
    • POST parameters will be ignored if a request body is provided
  8. net.sf.jasperreports.http.data.header
    • is specified at report parameter level
    • if the property has no value, it will be used to mark the report parameter as HTTP request header; the header will have the same name and value as the report parameter
    • if the property has a given value, its value will be used as name for the related request header; the value of the header will be the same as the report parameter value
    • if this property is specified in various report parameters, the related request header will be added multiple times to the request

HTTP Data Service

The information stored in the HttpDataLocation object is collected and processed by the HttpDataServicehttps://jasperreports.sourceforge.net/api/net/sf/jasperreports/dataadapters/http/HttpDataService.html API, which builds a client object to send a specific request over HTTP.

As a result, a data file connection is obtained in the form of an HttpDataConnection object.

This object comes with an InputStream that can be extracted and interpreted as custom data source (usually in JSON or XML format), using the available public methods of the class:

The JSON and XML HTTP Data Adapters

This sample provides 2 examples based on the HTTP data adapter: one of them will process the input in order to get a JSONQL data source, the other will prepare an XML data source by querying the same data.

Following are the 2 data adapter definitions:

<jsonDataAdapter class="net.sf.jasperreports.data.json.JsonDataAdapterImpl">
  <name>JSON Http Data Adapter</name>
  <dataFile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:type="httpDataLocation">
    <method>GET</method>
    <url><![CDATA[https://www.omdbapi.com/?r=json]] ></url>
  </dataFile>
  <useConnection>true</useConnection>
  <timeZone xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:java="http://java.sun.com" xsi:type="java:java.lang.String">Europe/Bucharest</timeZone>
  <locale xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:java="http://java.sun.com" xsi:type="java:java.lang.String">ro_RO</locale>
  <selectExpression></selectExpression>
</jsonDataAdapter>
<xmlDataAdapter class="net.sf.jasperreports.data.xml.XmlDataAdapterImpl">
  <name>XML Http Data Adapter</name>
  <dataFile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:type="httpDataLocation">
    <method>GET</method>
    <url><![CDATA[https://www.omdbapi.com/?r=xml]] ></url>
  </dataFile>
  <useConnection>true</useConnection>
  <timeZone xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:java="http://java.sun.com" xsi:type="java:java.lang.String">Europe/Bucharest</timeZone>
  <locale xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:java="http://java.sun.com" xsi:type="java:java.lang.String">ro_RO</locale>
  <selectExpression></selectExpression>
</xmlDataAdapter>

We can observe that the above data adapters are quite similar:

But:

Now let's take a look into JRXML files provided in this sample, in order to see how the remaining request input is provided via report parameters and properties.

The JRXML files

The JRXML files are found in the reports folder of this JasperReports sample.

Like the above data adapters, they look almost similar, the only differences being related to data adapter type, query language and dataset field properties (because these are also related to the query language).

Each JRXML report:

Following are presented the settings in the JsonHttpDataAdapterReport.jrxml file:

<jasperReport name="JsonHttpDataAdapterReport" language="java" columnCount="3" pageWidth="595" pageHeight="842"
  columnWidth="171" leftMargin="40" rightMargin="40" topMargin="50" bottomMargin="50">
  <property name="net.sf.jasperreports.data.adapter" value="data/JsonHttpDataAdapter.jrdax"/>
  <dataset name="FetchDataset"/>
  <dataset name="MoviesDataset">
    <property name="net.sf.jasperreports.data.adapter" value="data/JsonHttpDataAdapter.jrdax"/>
    <parameter name="page" class="java.lang.Integer">
      <property name="net.sf.jasperreports.http.data.url.parameter"/>
    </parameter>
    <query language="jsonql"><![CDATA[animals]] ></query>
    <field name="name" class="java.lang.String">
      <property name="net.sf.jasperreports.jsonql.field.expression" value="name"/>
    </field>
    <field name="size" class="java.lang.Integer">
      <property name="net.sf.jasperreports.jsonql.field.expression" value="size"/>
    </field>
    <field name="type" class="java.lang.String">
      <property name="net.sf.jasperreports.jsonql.field.expression" value="type"/>
    </field>
    <field name="image" class="java.lang.String">
      <property name="net.sf.jasperreports.jsonql.field.expression" value="image"/>
    </field>
  </dataset>
  <query language="jsonql"/>
  <field name="totalResults" class="java.lang.Integer">
    <property name="net.sf.jasperreports.jsonql.field.expression" value="totalResults"/>
  </field>
  ...
</jasperReport>

Both the main dataset and MoviesDataset require information from JsonHttpDataAdapter.jrdax file via net.sf.jasperreports.data.adapter property.

With these settings, the web service URL will look like:

http://www.omdbapi.com/?r=json

In response the web service will return a JSON object in the following format:

{
  "Search":[
    {"Title":"Aliens","Year":"1986","imdbID":"tt0090605","Type":"movie","Poster":"https://.../...jpg"},
    {"Title":"Cowboys & Aliens","Year":"2011","imdbID":"tt0409847","Type":"movie","Poster":"https://.../...jpg"},
    ...
   ],
  "totalResults":"213",
  "Response":"True"
}

Here we have:

In the main dataset we are interested only in retrieving the "totalResults" number, in order to use it in the page header.
To get it, we declared the report query language as jsonql, and set a related report field named totalResults as follows:

<query language="jsonql">
  <![CDATA[]] >
</query>
<field name="totalResults" class="java.lang.Integer">
  <property name="net.sf.jasperreports.jsonql.field.expression" value="totalResults"/>
</field>

One can observe the associated net.sf.jasperreports.jsonql.field.expression property that links the totalResults field name to the "totalResults" number provided by the JSON object.

MoviesDataset comes with one dataset parameter, related to request URL parameters via properties:

 <parameter name="page" class="java.lang.Integer">
   <property name="net.sf.jasperreports.http.data.url.parameter"/>
 </parameter>

The page parameter adds pagination (each page contains by default 10 results) to the request URL.
The net.sf.jasperreports.http.data.url.parameter property has no value in this case, meaning that the name of the appended URL parameter is also page.
Since there is no default value for this parameter, its value will be provided during report execution at runtime.

With these settings, for the second page of results, the web service URL will look like:

http://www.omdbapi.com/?r=json&page=2

Note: The http://www.omdbapi.com/?r=json& request URL has the same effect as http://www.omdbapi.com/?r=json&page=1

The query language in MovieDataset is also jsonql, but now we perform a JSONQL query on the "Search" array member of the JSON object, in order to retrieve the movie information regarding title, year, movie type and poster:

 <query language="jsonql">
   <![CDATA[Search]] >
 </query>
 <field name="title" class="java.lang.String">
   <property name="net.sf.jasperreports.jsonql.field.expression" value="Title"/>
 </field>
 <field name="year" class="java.lang.Integer">
   <property name="net.sf.jasperreports.jsonql.field.expression" value="Year"/>
 </field>
 <field name="type" class="java.lang.String">
   <property name="net.sf.jasperreports.jsonql.field.expression" value="Type"/>
 </field>
 <field name="poster" class="java.lang.String">
   <property name="net.sf.jasperreports.jsonql.field.expression" value="Poster"/>
 </field>

Here we have parameter properties with case sensitive values.

For instance, the title report field is linked to the "Title" member of the JSON object representing the movie information in the "Search" array.

All these fields are used in a list component that uses the MovieDataset as dataset, based on title and page parameter values:

<jr:list printOrder="Vertical">
  <datasetRun subDataset="MoviesDataset">
    <datasetParameter name="title">
      <datasetParameterExpression><![CDATA[$P{title}]] ></datasetParameterExpression>
    </datasetParameter>
    <datasetParameter name="page">
      <datasetParameterExpression><![CDATA[$V{REPORT_COUNT}]] ></datasetParameterExpression>
    </datasetParameter>
  </datasetRun>
  <jr:listContents height="65" width="170">
    ...
  </jr:listContents>
</jr:list>

The other subdataset in the report (i.e FetchDataset) is used in conjunction with an empty data source, in order to allow paginated results to be rendered page by page during the report execution.

<detail>
  <band height="65" splitType="Stretch">
    <element kind="component" width="170" height="65">
      <component kind="list" printOrder="Vertical">
        <datasetRun subDataset="FetchDataset">
          <dataSourceExpression><![CDATA[new JREmptyDataSource((int)(Math.ceil($F{totalResults} / 10d)))]] ></dataSourceExpression>
        </datasetRun>
        <contents height="65" width="170">
        ...
        </contents>
      </component>
    </element>
  </band>
</detail>

As already stated, the XmlHttpDataAdapterReport.jrxml file looks similar to JsonHttpDataAdapterReport.jrxml file.

Report parameters definitions are the same in both JRXML files. Query languages and dataset field definitions are slightly different.

Following are presented the main differences exposed by XmlHttpDataAdapterReport.jrxml:

<jasperReport name="XmlHttpDataAdapterReport" ...>
<property name="net.sf.jasperreports.data.adapter" value="data/XmlHttpDataAdapter.jrdax"/>
  <subDataset name="FetchDataset">
    <parameter name="title" class="java.lang.String"/>
  </subDataset>
  <subDataset name="MoviesDataset">
    <property name="net.sf.jasperreports.data.adapter" value="data/XmlHttpDataAdapter.jrdax"/>
    <parameter name="title" class="java.lang.String">
      <property name="net.sf.jasperreports.http.data.url.parameter" value="s"/>
    </parameter>
    <parameter name="page" class="java.lang.Integer">
      <property name="net.sf.jasperreports.http.data.url.parameter"/>
    </parameter>
    <query language="xPath">
      <![CDATA[/root/result]] >
    </query>
    <field name="title" class="java.lang.String">
      <property name="net.sf.jasperreports.xpath.field.expression" value="@title"/>
    </field>
    <field name="year" class="java.lang.Integer">
      <property name="net.sf.jasperreports.xpath.field.expression" value="@year"/>
    </field>
    <field name="type" class="java.lang.String">
      <property name="net.sf.jasperreports.xpath.field.expression" value="@type"/>
    </field>
    <field name="poster" class="java.lang.String">
      <property name="net.sf.jasperreports.xpath.field.expression" value="@poster"/>
    </field>
  </subDataset>
  <parameter name="title" class="java.lang.String" evaluationTime="Early">
    <property name="net.sf.jasperreports.http.data.url.parameter" value="s"/>
    <defaultValueExpression><![CDATA["aliens"]] ></defaultValueExpression>
  </parameter>
  <query language="xPath">
    <![CDATA[/root]] >
  </query>
  <field name="totalResults" class="java.lang.Integer">
    <property name="net.sf.jasperreports.xpath.field.expression" value="@totalResults"/>
  </field>
  ...
</jasperReport>

this JRXML file requires information from data/XmlHttpDataAdapter.jrdax data adapter for both main dataset and MoviesDataset.

The response content will be delivered in the following XML format:

<root totalResults="213" response="True">
  <result title="Aliens" year="1986" imdbID="tt0090605" type="movie" poster="https://.../...jpg"/>
  <result title="Cowboys & Aliens" year="2011" imdbID="tt0409847" type="movie" poster="https://.../...jpg"/>
  ...
</root>
<field name="totalResults" class="java.lang.Integer">
  <property name="net.sf.jasperreports.xpath.field.expression" value="@totalResults"/>
</field>

and in MoviesDataset:

<field name="title" class="java.lang.String">
  <property name="net.sf.jasperreports.xpath.field.expression" value="@title"/>
</field>
<field name="year" class="java.lang.Integer">
  <property name="net.sf.jasperreports.xpath.field.expression" value="@year"/>
</field>
<field name="type" class="java.lang.String">
  <property name="net.sf.jasperreports.xpath.field.expression" value="@type"/>
</field>
<field name="poster" class="java.lang.String">
  <property name="net.sf.jasperreports.xpath.field.expression" value="@poster"/>
</field>

Running the Sample

Running the sample requires the Apache Maven library. Make sure that maven is already installed on your system (version 3.6 or later). In a command prompt/terminal window set the current folder to demo/samples/httpdataadapter within the JasperReports source project and run the following command:

> mvn clean compile exec:exec@all

It will generate all supported document types containing the sample report in the demo/samples/httpdataadapter/target/reports directory.




© 2001- Cloud Software Group, Inc. www.jaspersoft.com