Generate Jasper reports from data streams

In this article I want to show how the new Jasper Protocol Handler in Odysseus can be used to generate reports out of your data stream using the JasperReports reporting engine. The protocol handler is available from my Odysseus Update Site. To install the protocol handler, select the Wrapper Feature in the Install New Software dialog and confirm the installation. After the installation the protocol handler should be instantaneously available and can be used inside the Sender operator.

Jasper report

Now, let us start with a simple example on how to use this protocol handler in an Odysseus query. To do so, we first need a source that produce a synthetic data stream for us. In the example I use the Timer transport handler that pushes periodically the current time into the system. Obviously, you can replace that data stream with any other data stream like the one from a pattern matching operator as used in my article about Odysseus and Arduino.

In the next line I use a map operator to set some values in the stream. Here, I create three attributes, namely, an id, a name, and a value. The id attribute is of type integer, the name is a string, and the value attribute is of type double. The data types are important later for the reporting template.

In the third line this stream is transformed into a report. To do that, I use the Sender operator and configure it to use the Jasper protocol handler for the transformation of the streaming element, for the data I use the default Tuple data handler, and for the transport I use the File transport handler to pipe the resulting report directly into a file. You can also take another transport handler like a TCP transport handler or the HTTP transport handler to push it to some website. You could even go one step further and use the database feature to store the report into a relational database.


input = ACCESS({source='Source',
                options=[['period', '5000']],
                 ['time', 'Timestamp']]

processing = MAP({EXPRESSIONS = [['toInteger(1)','id'],
                                 ['"Paul Smith"','name'],
                 }, input)

output = SENDER({sink='Sink',
                  ['filename', '${ROOT}/report.pdf'],
                }, processing)

The configuration of the Protocol Handler inside the Sender operator is straight forward. All you have to do is set the template. In addition, you can define the two optional options multi and parameter that I will explain later.

Access to stream attributes

To generate a report with Jasper you have to first define a template or design file to use. Inside the design file you will have access to the elements of the stream, but first you have to define your variable at the top of the file first. Here, the data types have to match the data type of the attribute in the schema of the data stream:

After that, the variable can be referenced in the content. Here, we access the variable value inside a textField. The template I’m using here is based on the example template DataSourceReport.jrxml from the Jasper community website.


Single or Multi

The protocol handler provides two modes. In the first mode, the protocol handler generates a report on each streaming element. This mode is basically useful when you want to report specific rare events, e.g., detection of a critical situation. In the second mode, the protocol handler buffers all streaming elements and generates one huge report as soon as the processing is done. This mode is targeted for applications in which the processing is performed for a limited amount of time, either because the source is empty or the query is stopped. The mode can be set by the multi parameter.