Utils¶
Render FreeMarker templates and convert rendered content to document formats; mark filter DTO fields.
Use TemplateRenderUtil for template rendering and document output, and UserFilterDTO for the filter metadata consumed by the R2DBC utilities. Keep template resources and model data under application control.
| Maven artifact | Packaging | Source project |
|---|---|---|
org.fireflyframework:fireflyframework-utils |
jar |
modules/utils |
Part of Team-wide architecture.
In the onboarding service¶
After accepting an application, the service can render a confirmation template or generate a PDF receipt. Template data and document storage remain application choices.
Add the component¶
Installation and version availability explains source builds and published releases.
<dependency>
<groupId>org.fireflyframework</groupId>
<artifactId>fireflyframework-utils</artifactId>
<version>26.10.20-SNAPSHOT</version>
</dependency>
Quick start¶
The Java examples in this section are API fragments for application code. Use the stated imports and supply the application-owned collaborators described alongside them.
Render a template to HTML¶
Place invoice.ftl under src/main/resources/templates/:
<!-- src/main/resources/templates/invoice.ftl -->
<html><body>
<h1>Invoice for ${customerName}</h1>
<p>Total: ${total}</p>
</body></html>
import org.fireflyframework.utils.template.TemplateRenderUtil;
import java.util.Map;
Map<String, Object> model = Map.of("customerName", "Acme Corp", "total", "1,250.00 EUR");
String html = TemplateRenderUtil.renderTemplateToHtml("invoice.ftl", model);
Render a template straight to PDF bytes¶
byte[] pdf = TemplateRenderUtil.renderTemplateToPdfBytes("invoice.ftl", model);
// e.g. return as a ResponseEntity<byte[]> with Content-Type: application/pdf
Customize the PDF (watermark, encryption, metadata, bookmarks)¶
import org.fireflyframework.utils.template.TemplateRenderUtil.PdfOptions;
import org.fireflyframework.utils.template.TemplateRenderUtil.PdfOptions.PageSize;
PdfOptions options = new PdfOptions()
.withPageSize(PageSize.A4)
.withMargins(36, 36, 36, 36)
.withDefaultFont("DejaVu Sans")
.withFontDirectory("/opt/fonts") // embeds .ttf/.otf found here
.withWatermark("CONFIDENTIAL", 0.3f, 60, 45, "#888888")
.withMetadata("Q1 Invoice", "Billing", "Invoice", "invoice,billing")
.withEncryption("ownerSecret") // owner password, printing/copy allowed
.withBookmark("Summary", "1")
.withChildBookmark("Line Items", "1");
byte[] pdf = TemplateRenderUtil.renderTemplateToPdfBytes("invoice.ftl", model, options);
Render asynchronously¶
import java.util.concurrent.CompletableFuture;
CompletableFuture<byte[]> future =
TemplateRenderUtil.renderTemplateToPdfBytesAsync("invoice.ftl", model);
Render an HTML fragment to an image¶
byte[] png = TemplateRenderUtil.renderHtmlToImage(
"<h1 style='color:#0a6'>Hello</h1>", 800, 400, "png");
Mark a filterable ID on a filter DTO¶
import org.fireflyframework.utils.annotations.FilterableId;
import java.util.UUID;
public class UserFilterDTO {
@FilterableId
private UUID customerId; // included in filters with exact matching, exposed as a query param
private UUID accountId; // excluded from filters (default behaviour for *Id fields)
private String name; // regular field with full filtering capabilities
}
Configuration and wiring¶
This module declares no @ConfigurationProperties class of its own. Use the constructor/port contracts above and the configuration of the host or related core module.
Public API and extension points¶
| Type | Contract and responsibility |
|---|---|
TemplateRenderUtil |
Utility for rendering FreeMarker templates to XHTML, PDF, and images using Flying Saucer. |
FilterableId |
The FilterableId annotation is used to mark ID fields that should be included in filtering operations. |
Related components¶
| Related component | Why it belongs nearby |
|---|---|
| Kernel | Share a consistent exception vocabulary across application, domain, and infrastructure boundaries. |
Build and test¶
Use Java 25. From the repository root, build this component with its required dependencies:
git clone https://github.com/fireflyframework/fireflyframework-jafly.git
cd fireflyframework-jafly
./mvnw -pl :fireflyframework-utils -am verify
./mvnw -pl :fireflyframework-utils -am install
verify runs the selected projects' tests. install makes the current build available in your local Maven repository.
Representative test sources:
Test fixture¶
The testRenderHtmlToImage test demonstrates one concrete behavior. Excerpt from TemplateRenderUtilTest.java. The test class supplies its fixtures and imports.
@Test
void testRenderHtmlToImage() throws Exception {
// Create a simple HTML content
String html = "<html><body><h1 style='color:blue'>Image Test</h1></body></html>";
// Render to image
byte[] imageBytes = TemplateRenderUtil.renderHtmlToImage(html, 400, 200, "png");
// Verify image was created
assertNotNull(imageBytes);
assertTrue(imageBytes.length > 0, "Image should not be empty");
// Verify it's a PNG image by checking the header
byte[] pngHeader = {(byte)0x89, 'P', 'N', 'G'};
byte[] actualHeader = new byte[4];
System.arraycopy(imageBytes, 0, actualHeader, 0, 4);
assertArrayEquals(pngHeader, actualHeader, "Image should be a PNG");
}
Detailed reference¶
Configuration¶
This module has no Spring @ConfigurationProperties and no auto-configuration. There are no firefly.* properties to set in application.yml. TemplateRenderUtil is configured programmatically via its static methods, which apply globally to the utility:
| Method | Purpose | Default |
|---|---|---|
setTemplateCachingEnabled(boolean) |
Enable/disable in-memory template caching | enabled |
setTemplateCacheMaxSize(int) |
Max number of cached compiled templates | 100 |
setAsyncThreadPoolSize(int) |
Size of the async rendering thread pool | max(2, availableProcessors()) |
addSharedVariable(name, value) |
Expose a variable to every template | none |
setTemplatePreProcessor(BiFunction) |
Transform template source before rendering | none |
setTemplatePostProcessor(BiFunction) |
Transform rendered output after rendering | none |
addTemplateLoader(TemplateLoader) |
Register an additional FreeMarker loader | classpath + ./templates |
setTemplateDirectory(String) / setClasspathAndFileTemplateLoaders(...) |
Override where templates are loaded from | classpath:/templates, then ./templates |
Template lookup order with its default configuration: classpath:/templates, then the working-directory ./templates folder, then any custom loaders. FreeMarker defaults: UTF-8 encoding, Locale.US, and a rethrow exception handler.
Call TemplateRenderUtil.shutdownAsyncThreadPool() on application shutdown if you used the async APIs.
Continue the application¶
Use the Notifications Core guide for the next part of this integration. The runnable submission/query service is in Getting started.