Skip to content

Fluent Java

Use Letter.builder() when Java code assembles the letter. It starts with A4 defaults and offers chains for content, regions, layout and reusable styling. The final result is the same immutable model used by every API.

FluentQuickstart.java
import com.nsdev.lettergenerator.Letter;
import com.nsdev.lettergenerator.LetterPdfGenerator;
import java.nio.file.Files;
import java.nio.file.Path;
/** A complete first letter using the fluent API and engine-provided standard fonts. */
public final class FluentQuickstart {
private FluentQuickstart() {}
public static void main(String[] args) throws Exception {
var letter = Letter.builder().body("Hello from Letter Generator").build();
byte[] pdf = new LetterPdfGenerator().generate(letter);
Files.write(Path.of(args.length == 0 ? "letter.pdf" : args[0]), pdf);
}
}

Download this source or the complete Maven project.

The focused snippets below assume imports for the named public types. The Java API reference lists signatures and overloads; Javadoc provides exact contracts.

var letter = Letter.builder()
.page(PageSize.A4)
.marginsMm(20)
.subject("Account update")
.salutation("Dear Alex,")
.body("Your first paragraph.\nA forced line change.\n\nA second paragraph.")
.body(Letter.PAGE_BREAK, "Content on the next page.")
.table(Table.builder("Item", "Amount").row("Service", "12.50").build())
.signature(TextSignature.of("Customer Services"))
.signaturePlacement(SignaturePlacement.BOTTOM_LAST)
.signatureHeightMm(20)
.footer("Example Company")
.build();

Plain body(...) text distinguishes line changes, blank-line paragraphs and body page breaks. It does not interpret HTML. Use bodyHtml(...) only for the supported markup vocabulary and explicitly supplied assets.

Body calls append; replaceable regions such as header/footer/signature and semantic roles use their documented replacement behavior. First/following-page overloads let you configure stationery variants. Fluent/HTML semantic roles have a conventional order around the body; typed block order is available when you need exact arbitrary sequencing.

Set .theme(companyTheme) for role/named defaults and .component(name, fragment) for document-local fragments. .style(...) applies document overrides. Child/block/run properties can override inherited values, including explicit false/zero values. Builders defer some region compilation until final page/theme settings are known, so a final theme still governs earlier authored region content.

Use themes/components, company stationery and style inheritance.

.block(block) accepts a public typed block; .group(...) and .table(...) support richer content. Canvas.builder(...) helps create a bounded positioned layout. Advanced cells, table policies or columns can use explicit model values while the surrounding letter remains fluent.

Do not place explicit page breaks in tables, fixed/signature regions or indivisible canvases/columns. Keep rules express intent; impossible strict constraints can reject layout instead of shrinking text silently.

var generator = new LetterPdfGenerator();
var result = generator.render(letter);
Files.write(Path.of("letter.pdf"), result.pdfBytes());
int pages = result.pageCount();

build() snapshots the current builder. Subsequent changes do not mutate that document. Builders are mutable and should stay on one thread; generators can be reused concurrently. validate(letter) checks semantic input without layout, while render establishes actual pagination.

Continue with the complete fluent energy letter, pagination, rich tables and diagnostics.