To do so, we will be using 3 open-source components:
JobRunr: JobRunr allows to easily schedule and process background jobs using Java 8 lambda’s. It is backed by persistent storage and can process jobs in a parallel and distributed manner. Thanks to the built-in dashboard we have an in-depth overview into all our background jobs.
Spring Data Jpa: If you want to easily access data in a relational database, Spring Data Jpa is here to help. You can create repositories using nothing more than a simple interface
Docx-Stamper: Docx-Stamper allows to easily generate Word (.docx) documents backed by templates
Architecture
During this tutorial, we will generate the weekly salary slip of all of Acme Corp’s employees and email it to them. How? Well, by
creating a recurring job using JobRunr that will run every week - it will get all of Acme Corp’s employees using Spring Data Jpa and for each of these employees schedule a new background job to create the salary slip
each of these background jobs will fetch the Employee and
consume a TimeClockService which gives the amount of hours an employee worked for the given week.
generate a salary slip document using a DocumentGenerationService which will contain the name of the employee and the amount of hour he or she worked. The salary slip document is generated from a Word template and converted to a PDF file.
send an email to the employee with his salary slip using an EmailService.
For building this salary slip service, we use gradle and our build.gradle file is as follows:
Gradle build file
Employee
Since we need to create salary slips for all employees let us start with the Employee class - it is a simple Entity with some fields like firstName, lastName and email.
EmployeeRepository
WorkWeek
Since the salary slip is generated once per week, we need a class representing the amount of time an employee has worked that week - the WorkWeek class. It has some extra fields like the weekNbr and a from and to date which we will use for our generated salary slip document.
TimeClockService
To get a WorkWeek class for a certain employee, we create a TimeClockService which is a Spring Component. As we don’t want to make this tutorial overly complex, here we use a stub which generates some random data. In a real-world application this service would make a REST or SOAP request to another microservice.
We now have all the necessary data to generate our salary slip - except the SalarySlip class itself:
SalarySlip
DocumentGenerationService
The DocumentGenerationService is also a Spring Component and has the responsibility to generate the actual salary slip documents based on a word template. The word template has a lot of placeholders, like ${employee.firstName}, ${employee.lastName} and ${workWeek.workHoursMonday.setScale(2)} that will be replaced by DocxStamper using the given context object - in our case a SalarySlip object. Finally, the Word document with all fields filled in is converted to a PDF document.
EmailService
The EmailService is again a Spring Component and has the responsibility to email the final salary slip word document to the employee - it uses Spring Boot Starter Email and using a MimeMessage created by the JavaMailSender. It has a method called sendSalarySlip with two arguments - the employee class and the path to the salary slip for that employee. Using these argument, we can send both a personalized text email and attach the actual salary slip as an attachment.
The JavaMailSender is a class provided by Spring Boot Starter Mail and configured using a properties file. You can find the properties file here: …
And finally, the SalarySlipService
The SalarySlipService is the last step of the puzzle and wires everything together:
it has the path to the salary slip word template
it uses the other components we already created:
the EmployeeRepository to get all employees from the database
the TimeClockService to get the amount of hours an employee worked
the DocumentGenerationService to create a salary slip from the given Word template
the EmailService to send a personalized email with the salary slip as attachment to the employee
It also two important public methods:
generateAndSendSalarySlip
The method generateAndSendSalarySlip uses the employee id to get the actual employee data, generates the salary slip Word document and sends it via email to the employee. It will be a JobRunr background job and it is called from the method generateAndSendSalarySlipToAllEmployees. We annotate it with the Job annotation to have meaningful names in dashboard of JobRunr.
generateAndSendSalarySlipToAllEmployees
This is our main method that will be scheduled each week - it gets a stream of employee ids and using the BackgroundJob.enqueue method, we create a background job of the generateAndSendSalarySlip method.
The document generation fails because there is not enough disk space? Or the TimeClockService fails for an employee because the external microservice is down? No worries - as JobRunr is fault-tolerant (it will automatically retry failed jobs with an exponential back-off policy), these failing jobs will be retried 10 times automatically.
The complete SalarySlipService is as follows:
Last but not least - our Spring Boot Application
The Spring Boot Application bootstraps our application and has one important piece of code:
In this SpringBootApplication we create some fake employees, define a DataSource (in our case a simple H2 database) and initialize JobRunr using it’s fluent-api.
Time to use our new application!
Once you start the SalarySlipMicroService application, you can open your browser using the url http://localhost:8000 and navigate to the Recurring jobs tab.
To test it, we trigger it now manually. The job is processed and schedules a new job to create the salary slip for each employee. Within 15 seconds the processing of these jobs start and we will see the generated PDF documents in our tmp folder.
We can inspect a Job and see them succeed - if it would fail for some reason, they will be automatically retried.
Conclusion:
JobRunr and Spring Data integrate very well and both are very easy to use. Being able to schedule Java 8 lambda’s and have them run in a background process is a really nice feature of JobRunr.
To convert the Word document to PDF, there is some nasty stuff in the word template (like white text) to have an OK-layout. Docx-Stamper is a great library and depends on Docx4J. Docx4J allows to convert Word documents to PDF but it still requires some work as a couple of hacks were done to get the layout right.