PDFPipe

Comparison

A Java alternative to Flying Saucer (xhtmlrenderer)

Flying Saucer (the xhtmlrenderer project) was a popular Java library for converting XHTML to PDF. It works by wrapping iText 2.x, an unmaintained version of iText from before the license changed to AGPL. The library requires well-formed XHTML (not regular HTML), supports only CSS 2.1, and has had no significant development since the early 2010s. PDFPipe accepts any HTML and renders it with a current browser engine from a standard HTTP call.

Comparison

PDFPipeFlying Saucer
Input formatAny HTMLWell-formed XHTML only
CSS supportModern CSS (Flexbox, Grid, variables)CSS 2.1 subset
Underlying libraryNone needediText 2.x (unmaintained LGPL)
Active maintenanceYesNo (last significant release ~2012)
Web fontsAny URLLocal font files only
JavaScriptYesNo
Maven dependencyNoneorg.xhtmlrenderer:flying-saucer-pdf

The XHTML requirement

Flying Saucer requires valid XHTML: every tag must be closed, all attributes must be quoted, and the document must have a valid DOCTYPE and namespace declarations. HTML generated by most template engines (Thymeleaf, Freemarker, JSP) is HTML5, not XHTML. Getting it to parse cleanly in Flying Saucer often means running it through an HTML-to-XHTML converter like JTidy first, adding another dependency and another failure point. PDFPipe accepts any HTML5 markup.

Spring Boot replacement

java
// Spring Boot controller — no extra Maven dependency needed.
@GetMapping(value = "/invoices/{id}.pdf", produces = "application/pdf")
public ResponseEntity<byte[]> invoicePdf(@PathVariable String id) {
    String html = templateEngine.process("invoice", buildContext(id));

    RestTemplate rest = new RestTemplate();
    HttpHeaders headers = new HttpHeaders();
    headers.setBearerAuth(apiKey);
    headers.setContentType(MediaType.APPLICATION_JSON);

    Map<String, Object> body = Map.of(
        "html", html,
        "options", Map.of("format", "A4")
    );

    byte[] pdf = rest.postForObject(
        "https://api.pdfpipe.xyz/v1/pdf",
        new HttpEntity<>(body, headers),
        byte[].class
    );

    return ResponseEntity.ok()
        .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=invoice-" + id + ".pdf")
        .body(pdf);
}

More Java examples on the Spring Boot guide.

See pricing →