With Salmos Report in Spring boot generate reports in few lines of code

Mostafa Shaeri
Javarevisited
5 min readNov 5, 2021

--

Generating reports from data stored in database has always been one of important part of application development. Along with Report’s title, columns’ header, content direction, styles, fonts and etc., most of times there exist numerical information in the report that should be summarized in the header or footer section of the report. Moreover, Some times we need to export data in different structure or format such as XML, JSON, PDF or other custom structure.

Although the existing libraries like Jasper are so comprehensive and matured, when you need to make simple tiny reports it can be frustrating and somehow confusing to work with its xml based configuration and environment setup. In my last project I looked for a battery included alternative library for Spring that is easy to setup and easy to use, unfortunately I couldn’t find (maybe I didn’t googled well ). I decided to start an open-source project to develop an easy to configure and easy to use library in Spring boot that make quick reports in few lines of codes.

After putting some efforts, I implemented what I had in my mind. Now, Not only it can directly read data from database using SQL query and JDBC data source, but also it can be fed by List of objects (for example list of entity objects retrieved by Hibernate). Until now it can produce Html, xml, pdf and custom format report.

Current Version of the this plugin is 2.1.0 and it can be imported by maven or grade like :

<dependency>
<groupId>io.github.birddevelper</groupId>
<artifactId>salmos-report-spring-boot-starter</artifactId>
<version>2.1.0</version>
</dependency>
implementation 'io.github.birddevelper:salmos-report-spring-boot-starter:2.1.0'

There exist 3 main classes in this plugin to make amazing things for you.

  • HtmlReportMaker : A class that generates HTML table from records retrieved by given sql query or from list of object. You can specify a title for report, the table can be stylized with css classes and you can choose which column should be summarized at last row of the table. You can specify whether you want the table to have index column or not. Moreover you can define a template and use it for your reports :
import io.github.birddevelper.salmos.HtmlReportMaker;
import io.github.birddevelper.salmos.setting.HtmlReportTemplate;
import io.github.birddevelper.salmos.setting.SummaryType;


@Service
public class ReportService {

@Autowired
DataSource dataSource;

public String generateReport() {

// Creating instance of HtmlReportMaker
HtmlReportMaker hrm = new HtmlReportMaker(dataSource);
// specify columns of data that must be summarized in table footer row
hrm.addSummaryColumn("Age", SummaryType.AVERAGE);
hrm.addSummaryColumn("Salary", SummaryType.SUM);

// template specifies the report table appearance
HtmlReportTemplate myTemplate = new HtmlReportTemplate();
myTemplate.setTableCssClass("tblReport");
myTemplate.setEvenRowCssClass("myEvensRow");
myTemplate.setOddRowCssClass("myOddsRow");
myTemplate.setHeaderRowCssClass("myheader");
myTemplate.setRightToLeft(true);
myTemplate.setRowIndexHeader("#");
myTemplate.setRowIndexVisible(true);

hrm.setTemplate(myTemplate);

// summary section numbers decimal point setting
hrm.setSummaryDecimalPrecision(1);

// summary section numbers seperated by comma
hrm.setSummaryCommaSeperatedNumbers(true);

// show row's index
hrm.isRowIndexVisible(true);

// set the query retrieving data from database
hrm.setSqlQuery("select fullname as 'Name', age as 'Age', salary as 'Salary' from chamber limit 0,10");

return hrm.generate();



}
}
  • XmlReportMaker : A class that generates XML document from records retrieved by given sql query or from list of object. With this class you can produce two types of xml. In the RecordColumnAsElementAttribute mode it embeds each field of row in its element tag like this as its attributes:
<students><student id=”1" firstname=”Alex” lastname=”Tailor” 
birthdate=”1980/09/19" />
<student id=”2" firstname=”Alice” lastname=”James” birthdate=”1988/06/22" />
.
.
.
</students>

And in RecordColumnAsElementChild it add each field of row as its child tag, like this :

<students><student >
<id>1</id>
<firstName>Alex</firstName>
<lastName>Tailor</lastName>
<birthdate>1980/09/19</birthdate>
</student>
<student >
<id>1</id>
<firstName>Alice</firstName>
<lastName>James</lastName>
<birthdate>1988/06/22</birthdate>
</student>
.
.
.
</students>

Sample code for xml generator :

import io.github.birddevelper.salmos.XmlReportMaker;
import io.github.birddevelper.salmos.setting.SummaryType;
import io.github.birddevelper.salmos.setting.XmlReportElementType;
@Service
public class ReportService {

@Autowired
DataSource dataSource;

public String generateXMLReport() {
// Creating instance of XmlReportMaker
XmlReportMaker xrm = new XmlReportMaker(dataSource);

// specify columns of data that must be summarized (they will put in root element as attribute)
xrm.addSummaryColumn("Age", SummaryType.AVERAGE);
xrm.addSummaryColumn("Salary", SummaryType.SUM);

// summary section numbers decimal point setting
xrm.setSummaryDecimalPrecision(0);

xrm.setRootElementName("Persons");
xrm.setChildElementName("person");

// this line set the generator to put row data in attributes of row element
xrm.setXmlReportElementType(XmlReportElementType.RecordColumnAsElementAttribute);

// set the query retrieving data from database
xrm.setSqlQuery("select fullname as 'Name', age as 'Age', salary as 'Salary' from chamber limit 0,10");

return xrm.generate();
}
}
  • GeneralReportMaker : This class generates output in any given structure and format. The report in this class has 3 parts : header, body and footer. You can set a template for body, it repeats for each row in the query result. In header and footer section you can have summary of specified columns with ::[YourColumnName]Summary. Moreover the header, body and footer can be loaded either from a resource file, from InputStream or from pour String :
import org.log.carvan.utils.GeneralReportMaker;
import io.github.birddevelper.salmos.setting.SummaryType;

@Service
public class ReportService {

@Autowired
DataSource dataSource;

public String generateUniversalReport() {

GeneralReportMaker grm = new GeneralReportMaker(dataSource);
// load template from file located in resources
grm.loadTemplateBodyFromFile("templates/salmosTemplates/template1.html");

// set the query retrieving data from database
grm.setSqlQuery("select fullname as 'Name', age as 'Age', salary as 'Salary' from chamber limit 0,10");

// specify columns of data that must be summarized
grm.addSummaryColumn("Age", SummaryType.AVERAGE);
grm.addSummaryColumn("Salary", SummaryType.SUM);

// set footer template with String (to have a column summary in footer, you should use ::[column name]Summary in template
grm.setTemplateFooter("<p ><b> Age Average >> ::AgeSummary ---- Total Salary >> ::SalarySummary </b> </p>");


return grm.generate();


}
}

Generate from list of objects ( for example : hibernate output )

From version 2.0.0+, you can produce report from list of objects such as list of entities fetched by hibernate. In this case the HtmlReportMaker class must be initiated with ObjectFactory. Before we initiate HtmlReportMaker , We should create ObjectFactory and specify fields of entity which we want to show in report and their header caption in HashMap format, in the following example, fieldMap.put(“age”, “Age”), specifies the “age” filed of Student entity to be shown in report with “Age” caption. Then we load the object list in Objectfactory. Finally we initiate HtmlReportMaker with Objectfactory.

import io.github.birddevelper.salmos.XmlReportMaker;
import io.github.birddevelper.salmos.setting.SummaryType;
import io.github.birddevelper.salmos.setting.XmlReportElementType;
import lombok.Getter;
import lombok.Setter;
@Service
public class ReportService {
@Getter
@Setter
public class Student {
private String name;
private int age;
private Date birthDate;
private List<String> skills;

}

@AutoWired
StudentRepository studentRepository;
public String generateHTMLReport() {
List<Student> studentList = studentRepository.findAll();

// Mapping the class fields to report columns (here we want only name and age, the reset of entity fields will be ignored)
Map<String,String> fieldMap = new HashMap<>();
fieldMap.put("name", "Full Name");
fieldMap.put("age", "Age");

// buidling instance of ObjectFactory class
ObjectFactory objectFactory = new ObjectFactory();

// setting mapping fields
objectFactory.setReportFields(fieldMap);
// setting entity lists
objectFactory.loadObjects(studentList);

// building instance of HtmlReportMaker with ObjectFactory as input parameter
HtmlReportMaker htmlReportMaker = new HtmlReportMaker(objectFactory);

// generate report
return htmlReportMaker.generate();
}
}

I hope I can add more features like excel export to make it more usable. don’t hesitate to give a comment.

The project repository on github : https://github.com/birddevelper/salmos-report-spring-boot-starter.

Reference : salmos report — spring boot report generator

--

--