Freemarker Reports
Overview
HTML reports generated with freemarker templates
Github: https://github.com/gitorko/project69
Freemarker
We will generate a single html file report using freemarker template and provide a rest url to download the report.
Code
1package com.demo;
2
3import java.io.ByteArrayInputStream;
4import java.io.StringWriter;
5import java.util.Date;
6import java.util.HashMap;
7import java.util.List;
8import java.util.Map;
9import java.util.Random;
10import java.util.stream.Collectors;
11import java.util.stream.IntStream;
12
13import freemarker.template.Configuration;
14import freemarker.template.Template;
15import lombok.extern.slf4j.Slf4j;
16import org.springframework.core.io.InputStreamResource;
17import org.springframework.http.HttpHeaders;
18import org.springframework.http.MediaType;
19import org.springframework.http.ResponseEntity;
20import org.springframework.web.bind.annotation.GetMapping;
21import org.springframework.web.bind.annotation.RestController;
22
23@RestController
24@Slf4j
25public class HomeController {
26
27 @GetMapping("/report")
28 public ResponseEntity<InputStreamResource> getReport() throws Exception {
29 log.info("Generating report!");
30 String htmlReport = this.generateHtmlReport();
31 ByteArrayInputStream bis = new ByteArrayInputStream(htmlReport.getBytes());
32 return ResponseEntity.ok()
33 .contentType(MediaType.APPLICATION_OCTET_STREAM)
34 .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"myreport.htm\"")
35 .body(new InputStreamResource(bis));
36 }
37
38 private String generateHtmlReport() throws Exception {
39 Configuration cfg = new Configuration(Configuration.VERSION_2_3_30);
40 cfg.setClassForTemplateLoading(this.getClass(), "/");
41 cfg.setDefaultEncoding("UTF-8");
42 Template template = cfg.getTemplate("templates/my-report.ftl");
43 List<Employee> employees = getEmployeeData();
44 Map<String, Object> templateData = new HashMap<>();
45 templateData.put("reportTitle", "Company Employee Report");
46 templateData.put("employees", employees);
47 StringWriter out = new StringWriter();
48 template.process(templateData, out);
49 return out.toString();
50 }
51
52 private List<Employee> getEmployeeData() {
53 //Sample Data
54 Random random = new Random();
55 return IntStream.range(0, 150)
56 .mapToObj(i -> Employee.builder()
57 .name("Name " + i)
58 .age(random.nextInt(65 - 20) + 20)
59 .dob(new Date())
60 .salary(40000 + (100000 - 40000) * random.nextDouble())
61 .build())
62 .collect(Collectors.toList());
63 }
64}
1<html>
2
3<head>
4 <title>Employee Report</title>
5 <style>
6 table {
7 font-family: arial, sans-serif;
8 border-collapse: collapse;
9 width: 100%;
10 }
11
12 td,
13 th {
14 border: 1px solid #DDDDDD;
15 text-align: left;
16 padding: 8px;
17 }
18
19 th {
20 background-color: #CCCCCC;
21 }
22
23 p.yellow {
24 color: #FFDC0B;
25 font-weight: bold;
26 }
27
28 p.green {
29 color: #2F8400;
30 font-weight: bold;
31 }
32 </style>
33</head>
34
35<body>
36<h3>${(reportTitle)!"Default Title"}</h3>
37<br/>
38
39<h4>Employee Details</h4>
40<table>
41 <tr>
42 <th>Id</th>
43 <th>Name</th>
44 <th>Age</th>
45 <th>Dob</th>
46 <th>Salary</th>
47 </tr>
48 <#assign empCounter=1>
49 <#list employees as empObj>
50 <tr>
51 <td>${empCounter}</td>
52 <td>
53 <a href="#">${empObj.name}</a>
54 </td>
55 <td>
56 ${empObj.age}
57 </td>
58 <td>
59 ${empObj.dob?date}
60 </td>
61 <td>
62 <#if empObj.salary gt 50000>
63 <p class="green">
64 ${empObj.salary}
65 </p>
66 <#else>
67 <p class="yellow">
68 ${empObj.salary}
69 </p>
70 </#if>
71 </td>
72 </tr>
73 <#assign empCounter=empCounter+1>
74 </#list>
75</table>
76<h2>Total Employees: ${employees?size}</h2>
77</body>
78</html>
Setup
1# Project 69
2
3HTML reports with freemarker
4
5[https://gitorko.github.io/freemarker-reports/](https://gitorko.github.io/freemarker-reports/)
6
7### Version
8
9Check version
10
11```bash
12$java --version
13openjdk version "21.0.3" 2024-04-16 LTS
14```
15
16### Dev
17
18To run the backend in dev mode.
19
20```bash
21./gradlew clean build
22./gradlew bootRun
23```
References
comments powered by Disqus