πŸ“œ ⬆️ ⬇️

Open source solution for reporting automation

Developers of sites and mobile applications often need to control the preparation of PDF pages for printing or sending them to customers by mail.

PDF files have full control over the display of text and graphics on the page. Unfortunately, libraries for generating dynamically populating PDF files are not included in the standard tools of PHP, JS (Web), Java or Swift (Android and iOS, respectively). In this article I want to tell you about the open source solution for generating PDF files.


')
JasperReports is an open source Java library for generating dynamically populated files. It has many tools for creating complex reporting forms, including in PDF format, but other formats are also available: RTF, DOCX, HTML, XLS, XLS, CSV and XML. In other words, it is enough to develop one form, make one layout - and it will be possible to export it to any of the above formats.

There are also good libraries, such as PDFLib (commercial version) for PHP and its open source version of PDFLib-Lite. True, the library is quite expensive, and the lite version is distributed only in the source code, and when it is installed in the development environment, this limitation can become a problem.

PDFbox is another open source Java library for working with PDF documents. It allows you to create new PDF documents, manage existing documents with the ability to extract content from them. But it does not have a UI (User Interface), unlike JasperReports.

I think JasperReports is especially useful in large projects related to reporting and not only in PDF format. It has everything you need to implement it in your project: simple creation of complex reporting forms, UI for convenient layout, server application and simple integration with the front.

In the article I will cover the following topics:


To start using JasperReports in your project, you need to download two applications: JaspersoftStudio - hereinafter we will call it the working environment - and JasperServer - we will call the server application .

JaspersoftStudio is an Eclipse-based development environment with a built-in JasperReports Java library where dynamic or static PDF files are developed: for example, tickets, receipts, contracts, analytical charts and others.

JasperServer is a server application where files are deployed and stored from JaspersoftStudio. They can be accessed from a mobile or web application. JasperServer has a UI, with it you can view reports, create accounts for different users and give them appropriate access. You can also configure mailing list to email (Scheduler).

Set up the working environment and server application


You can download and install applications using the links above. After the setup of two applications, it is necessary to establish a connection from the working environment to the server application.

Servers β†’ Create JasperReports Server Connection β†’ Specify the preferred server name, URL , username and password. Click Test Connection to verify that the connection to the server is established. If you see Successful - go further.



Create a dynamically populating PDF and publish it


We installed the development environment, the server and established a connection between them. Now let's create a primitive dynamically populating PDF file, which when it is launched (generated) will take data from PostgreSQL, and install it on a server application.

First of all, you should fasten the data source (in our case, PostgreSQL) to the working environment, from where the PDF will take data. Then let's get started on developing our first PDF file.

Data Adapters β†’ Create Data Adapter β†’ Database JDBS Connection and specify the connection data:

  1. JDBC Driver - PostgreSQL (org.postgresql.Driver). If there is no driver for your DBMS, you can install the necessary driver in the Driver Classpath tab.
  2. JDBC URL - it consists of their host, port and database name.
  3. Username and password - log pass from your DBMS account.



We click on the already familiar Test button and upon successful connection (Successful) with the database - Finish .

From this database, the PDF will be populated in the production environment. Since we are planning to deploy our first PDF file to the server as well, let's screw the same data source to the server application:

Data Sources β†’ Add Resource β†’ Data Source and repeat everything from the point above.

Now you are ready to create the PDF. Sources in JasperReports are stored in the JRXML format - this is XML with wired tags and attributes that the JasperReports API works with.

Click File β†’ New β†’ Jasper Report β†’ Blank A4 β†’ Specify the name of the JRXML file β†’ Finish .



After creating a new project, you will see the following picture:



Seven different blocks - each block has its own behavior that is different from the others. You can read more about this in the documentation . By clicking on Source you can see the structure of these blocks:

<?xml version="1.0" encoding="UTF-8"?> <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="Example" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="ae9517f6-ff0b-41bb-a8dc-82196190e940"> <queryString> <![CDATA[]]> </queryString> <background> <band splitType="Stretch"/> </background> <title> <band height="79" splitType="Stretch"/> </title> <pageHeader> <band height="35" splitType="Stretch"/> </pageHeader> <columnHeader> <band height="61" splitType="Stretch"/> </columnHeader> <detail> <band height="125" splitType="Stretch"/> </detail> <columnFooter> <band height="45" splitType="Stretch"/> </columnFooter> <pageFooter> <band height="54" splitType="Stretch"/> </pageFooter> <summary> <band height="42" splitType="Stretch"/> </summary> </jasperReport> 

So, let's remove five extra blocks and leave only two: Title and Detail. The Delete button (Windows) or Backspace (OS X) will help us with this.

Now add two elements. There are two ways to add a new element: register the container in the XML structure ( Source button) or drag the desired element from the upper right Pallette window - Static Text, where there will be field names and Text Field, inside which we will fill in the variable fields pulled from the database:

 <?xml version="1.0" encoding="UTF-8"?> <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="Example" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="ae9517f6-ff0b-41bb-a8dc-82196190e940"> <queryString> <![CDATA[]]> </queryString> <background> <band splitType="Stretch"/> </background> <title> <band height="30" splitType="Stretch"> <staticText> <reportElement x="0" y="0" width="100" height="30" uuid="7b697ed9-f52a-483c-965e-f0b2dc6130c1"/> <text> <![CDATA[Static Text]]> </text> </staticText> </band> </title> <detail> <band height="169" splitType="Stretch"> <textField> <reportElement x="0" y="0" width="100" height="20" uuid="41002e0b-ddb2-4e4b-a049-10810ab51208"/> <textFieldExpression> <![CDATA["Text Field"]]> </textFieldExpression> </textField> </band> </detail> </jasperReport> 

A query in the database can be written in the queryString tag or click on the DataSet and Query editor dialog button. After that, a new window will open where you need to select a data source (1), write a query (2) and declare field variables. The Read Fields button (3) will read all fields automatically upon valid request. To view the data, click on the Data preview (4).



Fine! We got four fields of type String, now we can perform almost any manipulation with them. For example, we simply list them out and write a little logic.

We print the names of the required fields in the Static Text elements and place them in the Title container. We will indicate variable fields in the Text Field elements in the Detail container, as they will multiply. Our PDF will display the name, city and email address. In order not to be completely bored, let's write a simple logic in the Text Field element, using the fourth field - the gender of the client, Sex.

We do the following: if the client is a woman, then Mrs. will be added in front of the name, if the man is Mr. To do this, use the Java ternary operator:

 <textFieldExpression> <![CDATA[$F{sex}.equals( "male" )?"Mr. "+$F{name}:"Mrs. "+$F{name}]]> </textFieldExpression> 

By clicking on Preview next to the Source button, you can see the result:



As you can see in the screenshot, the PDF was successfully assembled: it took all the values ​​and applied the logic, correctly putting down Mrs. and Mr.

We will also get the City input parameter so that it is possible to filter data by city. This can be done either by clicking Parameters β†’ Create Parameter in the Outline window, or by adding a new parameter tag with the name and class attributes:

 <parameter name="City" class="java.lang.String"/> 

It remains only to add the parameter to the SQL query:

 SELECT Id, name, sex, city, email FROM users WHERE city = $P{City} 

We pass the value San Francisco to the City parameter (I’ll tell you in the next paragraph how to do this) and click Data Preview to view the result.



PDF was collected by successfully filtering the data. We go further

Since we already have a dynamically filling PDF file, we can upload it to the server for further integration with our front-end applications. To do this, click the Publish Report to JasperReports Server button β†’ double-click to open the server β†’ Select the server folder where to download the PDF (in our case, reports ) β†’ Next β†’ Data Source from Repository β†’ select the data source that was created earlier on the server application β†’ Finish .

Frontend Integration


The JasperReports API includes its own RESTful implementation for client-server interaction - REST v2 . If it does not suit you, you can use a simple object access protocol - SOAP .

We will consider REST v2.

The four main methods for CRUD (Create-Read-Update-Delete) actions are available: GET (get), POST (add, change, delete), PUT (add, replace), DELETE (delete). All detailed information is available in the documentation at the links above.

We will consider the more common and relevant GET method for this article.

 http://<host>:<port>/jasperserver[pro]/rest_v2/reports/path/to/report.<format>?<arguments> 

Above is a synchronous request, with which you can get the output of a file (ready-made PDF) in one request-response (an asynchronous call can be found here ).

I think everything is clear with the host and port, and / reports / path / to / report is the URI of the file that is being called. Since we deployed the source of the PDF file (Example.jrxml) to the reports server folder, the completed version of the URI will be: / reports / reports / Example.

format is a format (in our case, PDF).
arguments are parameters.

Above, we added the City parameter, and we will pass it in the request with the value San Francisco to filter data for this city.

If the call is not from an authorized zone, you need to add two more parameters / attributes: j_username and j_password (log pass for authorization). By default, the username and password on the server is jasperadmin .

Thus, we get the following URL:

 http://localhost:8080/jasperserver/rest_v2/reports/reports/Example.PDF?city=San Francisco&j_username=jasperadmin&j_password=jasperadmin 

So we get an already generated PDF. For example, when you call this URL through the address bar of the browser, the file should download automatically.

You may need to display a PDF image. For example, if the client just wants to view the file, you can show the document in PNG format, if you want to download it, then in PDF.

Using Java as an example using the PDFbox library, we will consider how to generate and pick a PDF file from an external application, and then convert it to PNG.

Below is the PullPDF class with one method that takes a URL as an argument.

 import java.awt.image.BufferedImage; import java.io.BufferedInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.net.URL; import java.util.Base64; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.rendering.ImageType; import org.apache.pdfbox.rendering.PDFRenderer; import org.apache.pdfbox.tools.imageio.ImageIOUtil; public class PullPDF { public String ConvertPDF2PNG(String valuefromParam) throws IOException { BufferedInputStream input_file = new BufferedInputStream(new URL(valuefromParam).openStream()); ByteArrayOutputStream baos = new ByteArrayOutputStream(); try { PDDocument document = PDDocument.load(input_file); PDFRenderer pdfRenderer = new PDFRenderer(document); for (int page = 0; page < document.getNumberOfPages(); ++page) { BufferedImage bim = pdfRenderer.renderImageWithDPI(page, 300, ImageType.RGB); ImageIOUtil.writeImage(bim, "png", baos); baos.flush(); byte[] encodedBytes = Base64.getEncoder().encode(baos.toByteArray()); valuefromParam = new String(encodedBytes); } } catch (Exception e) { } return valuefromParam; } } 

You can get the same result using, for example, the Spring Framework. But I tried to show a universal method that can be applied both on Android and the web when working with Java.

Conclusion


If you want to automate the generation of a simple check for an online store and you have limited time to create it, then I recommend using the native tools of your project or the familiar framework. Since the time spent on installing JasperReports, familiarization with the documentation for the development of more complex reporting forms may not be justified. In other cases, JasperReports is a good open source solution for reporting automation.

Source: https://habr.com/ru/post/461719/


All Articles