Introduction
Microservices has almost became the defacto architecture in many current projects, and while you may agree or disagree with the need for microservices, the reality is it is a very common architecture now, especially in modern enterprise applications.
And in many such applications we are usually faced with the need for providing reports to the user, these can be mainly web-based reports like the ones shown in dashboards, or they can be pixel-perfect reports, i.e reports that are expected to be printed by users; bank statements, invoices, salary slips, are all examples of such reports. While using paper-based reports seems obsolete, in many enterprises and government workflows, it is a hard requirement.
The web-based reports are already done via the frontend technology of the application, which will generate some html for showing the data in the end. The web-based reports aims to be interactive, with reactive design for different screen sizes, and it is mainly optimized to run on browsers.
But in the case of printable reports, we usually aim to provide them as PDF files, and they are designed to be printed on certain paper size like A4. The design objectives are different, and so are the optimizations and required features, for example there is usually the need for page breaks, page header and footers with sections like page numbers, page background images, etc.
This means the tools and design priorities and optimizations are different, and usually conflicting. While we can try to generate the report as a simple html page and let the user print it, it is not that simple, and the results are usually sub-optimal, and because browser print functionality handle basic cases, any more complex requirement can lead to a road block.
So, the best option is usually to generate pixel-perfect reports with tools dedicated for that, and there are many tools already available; Birt, Pentaho, Jasper Reports, Crystal reports are all example of such tools. Some tools provides SDK's and libraries that you can use in your application directly, others rely on a dedicated report server for generating the reports. Like everything in technology, each option comes with its pros and cons, but when it comes to printable reports, I believe Jasper reports are on the top of the list.
Why Jasper reports?
Jasper reports is one of the oldest and most-mature report generation libraries in the java eco-system, having several great features such as :
Opensource
It seems at first that money shouldn't be a problem for enterprises, yet, for teams working in enterprises, opensource solutions are usually on the top of the list, while the money can be available for paid solutions, another main factor is ... bearucracy π.
To use a properitary solution, you need to go through a bearucratic limbo in a big organizations, depending on the organization , the process may take months of back-and-forth meetings and procedures, and for technical teamleaders to start such a quest, there have to be some good reasons.
On the otherhand opensource solutions can be used on day 1, as long as the license allows it, this means quick and cheap adoption.
Jasper reports is mainly a java library , which is opensource, therefore, teams can start using it at once, or at least try it in some pilot project. The same goes for the community version of other jasper reports tools like their report designer : Jasper studio, and their report server.
Actively developed
A usual problem with opensource projects is developers abandoning the project. With lack of motivated developers or resources, development can halt after sometime. This can be a problem in enterprise applications because they usually have long lifetime, so, you need tools with long lifetime as well. It is not rare to have a system working for a decade in a big organization, because the business it serves actually doesn't change that much through out the decade.
Jasper reports ecosystem is developed by Tibco, a well-know company, and for more than a decade now, the project has bee active and kicking. Tibco profit model here is to provide opensource version of their tools, while providing additional premium features for a price, which seems to work fine for them till now.
Mature and Feature rich
Jasper reports is almost 2 decades old, so, we can consider it a mature library π. It already provides a variaty of features covering many use cases. Bugs are rare - for me at least -, and it is well optimized.
Reports can have a variaty of datasources, from database queries, to xml and json files. The library supports generating charts, sub-reports, can use custom fonts, and can generate reports as PDF, docx, xlsx, and other formats.
The tooling is also mature. Their WYSIWYG report designer is more than a decade old and is based on eclipse IDE, it is feature rich and simple to use, and it can even have additional features using eclipse plugins like managing git repositories for reports.
Challenges using jasper reports in microservices
So, where is the problem? If we need to use Jasper reports in our microservice application we will just use the library in our services or add the report server to the cluster, right?
Well, it is not always that simple:
Being a java library means it is accessible mainly by applications written in java or other JVM languages. If you have the services built using .Net for example, this option is out.
It is a heavy weight library, adding a lot of dependencies and like 50 MB - IIRC - to the application jar file. Adding a heavy library like that to generate a report or two in a single service is usually an overkill, especially if one of the dependencies may mess with something else.
Generating reports on the microservice itself can be problematic if the reports are complex. If your service has many users who generate reports, then the report generation can eat from the overall performance.
In many cases, the solution is to simply use Jasper report server to handle the report generation for all services, it is battle-proven solution, and will work with any technology via its REST API. The problem is, Jasper report server is not microservices friendly.
Jasper report server is an entire report management system, it comes with its own web report designer, its own dashboard for managing reports, users, access management, database connections, etc. It was meant to run as a standalone central monotlithic solution. It needs its own database to run all this, and needs manual configuration to add the reports to the server.
It was made in the era of the monolith, not microservices. So, if the system needs a lighweight scalable report server just to generate arbitrary reports and nothing else, Jasper report server was not built for that.
Tibco has realized that as well, and therefore they introduced JasperReports IO, a jasper report server that mainly provides a REST API for generating reports.
Unfortunately it is not opensource π.
So, we are now in square one, if we have microservices and need a lightweight opensource report server, what should we use?
I met the same problem with a recent project. We had a simple dotnet service and we needed a good reporting opensource solution. While dotnet had reporting solutions, most were not opensource, and I was familiar with jasper reports, as I already worked with it for several years to produce high quality pixel-perfect reports in Arabic.
The application was deployed as a docker image, so, it made sense to deploy a report server to handle the reports generation in the same cluster.
But even for such a simple scenario, JasperReport server was an overkill. I just needed a lightweight REST API that takes the report as url, generate it and return it back.
As JasperReport IO was licensed, and its features seemed to be an overkill as well, my developer brain decided it is time to just do it myself π.
Introducing Jasper report API !
While this may seem like a shameless promotion ..... well, it is π , but there isn't really much to promote here anyway.
Using Jasper reports API
This is a service that provides a simple API for generating arbitrary reports. Reports design files - jasper's JRXML files - are placed in a directory accessible to the service, and to generate a PDF report we call it like this
http://localhost:8080/report/emp-report.pdf
If we need a docx version of it we call
http://localhost:8080/report/emp-report.docx
Current supported extensions are : pdf, docx, xlsx,html, csv
Report parameters can be provided as Query parameters, similar to JasperReports server.
http://localhost:8080/report/emp-report.pdf?dep_id=1&month=11
The service is just a simple spring boot 3 application, so, it can have all the spring boot goodies: Spring security, spring data, optimized docker images, support for distributed tracing, metrics, logging.
The service will run the reports against the configured datasource for the spring application, so, it currently works against a single database only, and while it can be authenticated using spring security, there is no internal access management for each report, that's out of the scope of simple report service.
Fiddling with the API
The easiest way is to run the service as a docker image. This command will run the service with security disabled, and mounts the reports directory at ./test-reports
. In this example, the service connects to a postgres database to run the reports against it.
docker run -it --tty --rm\
-v ./test-reports:/var/reports\
-e SPRING_PROFILES_ACTIVE=security-off\
-e SPRING_DATASOURCE_URL=jdbc:postgresql://localhost:5432/postgres\
-e SPRING_DATASOURCE_USERNAME=postgres\
-e SPRING_DATASOURCE_PASSWORD=postgres\
-p 8080:8080\
ahmedgalalfathy/jasper-reports-api:0.1
After that you can generate a report by calling
http://localhost:8080/report/<report name>.<extension>
If you need some ready examples to fiddle with, feel free to clone the examples repository. It comes with a complete testing environment with sample reports and database.
If you ran into some problems using this, or have anything in your mind about it , your feedback is very welcomed π.
If you found that useful, give it a thumb up and a star in github, so I can put it in my CV before the next great global depression.
Thanks for reading all this and have a great day!
Top comments (0)