DevLearningTools

MODULE 13 · LESSON 12

<cfdocument>

cfdocument in depth: the one PDF-generation tag that runs on both Adobe ColdFusion and Lucee, its attributes, and real, concrete engine differences, Flying Saucer vs classic rendering, font handling, and defaults that don't match cfhtmltopdf's.

New lessons are added one at a time as the course gets built out — a graded quiz for each lesson is still on the way.

The previous lesson's cfhtmltopdf is Adobe-only. cfdocument is the tag that actually runs on both engines, converting everything between its start and end tags into PDF (or, on Adobe, FlashPaper) output, just rendered by a different engine underneath depending on where it runs.

Learning Objectives

After completing this lesson, you'll be able to:

  • Generate a PDF from CFML/HTML content with cfdocument.
  • Configure page format, orientation, and security attributes.
  • Recognize where Lucee's rendering genuinely differs, engine choice, units, and font handling.

One Tag, Two Engines

CFML/HTML Between the Tags

Which Engine?

Adobe's Engine, or Lucee's Classic/Flying Saucer

PDF (or FlashPaper) Output

A Basic Example

Tag Syntax
<cfdocument format="pdf" filename="#getTempDirectory()#mydoc.pdf" overwrite="yes">
    <h1>Hello ColdFusion</h1>
    <p>Generated at: <cfoutput>#timeFormat(now())#</cfoutput></p>
</cfdocument>

cfdocument's Core Attributes

AttributeMeaning
formatpdf or FlashPaper (required)
filenameWhere to save the output; omit it to write to the response stream
pagetypeletter (default), legal, A4, A5, B4, B5, B4-JIS, B5-JIS, or custom
orientationportrait (default) or landscape
encryptionnone (default), 40-bit, or 128-bit
fontembedyes (default), no, or selective
bookmarkEnables PDF bookmarks (default no)
backgroundVisibleWhether background colors/images print (default no)
localurlRetrieve referenced images from local disk instead of over HTTP (default no)
src / srcfileGenerate from an external file instead of the tag body
authUser / authPasswordBasic authentication credentials when fetching a remote src
proxyPortDefaults to 80 when a proxy is configured
overwriteWhether to replace an existing file at filename (default no)
NOTE

pagetype actually defaults to letter on both cfdocument and cfhtmltopdf, they're consistent with each other here, it's still worth setting explicitly rather than relying on either default.

Real Engine Differences on Lucee

AspectDetail
Rendering enginetype="modern" (Flying Saucer, the default) or type="classic" (the older PD4ML-based engine), configurable per-document, or globally via this.pdf.type in Application.cfc
UnitsAdds px and pt alongside in and cm, which Adobe's cfdocument doesn't document
Font handlingThe classic engine references font-family names from pd4fonts.properties; Flying Saucer uses .ttf filenames directly, with case sensitivity applied
Format supportWord and Excel conversion is unavailable in Lucee's cfdocument
PackagingRequires the PDF Extension for Jakarta EE (Lucee 7+), it's no longer bundled by default
NOTE

Switching a document from Lucee's classic engine to Flying Saucer (or the reverse) isn't guaranteed to produce visually identical output, verify existing documents after a migration.

A Real Example: Choosing the Rendering Engine Explicitly (Lucee)

Tag Syntax
<cfdocument format="pdf" type="modern" filename="report.pdf" overwrite="yes">
    <h1>Quarterly Report</h1>
</cfdocument>
Application.cfc (application-wide default)
component {
    this.pdf.type = "modern";
}

Common Beginner Mistakes

Confusing localUrl with a general performance setting

It specifically controls whether referenced images are pulled from local disk instead of over HTTP, it doesn't affect anything else about how the document renders.

Assuming Flying Saucer output looks pixel-identical to the classic engine's

They're genuinely different renderers, an existing document may need visual verification after switching engines.

Forgetting the PDF Extension requirement on Lucee 7+

cfdocument requires the PDF Extension for Jakarta EE to be installed on Lucee 7 and later, it isn't bundled by default anymore.

Referencing a font by its font-family name on Flying Saucer

Flying Saucer expects the actual .ttf filename (case-sensitive), unlike the classic engine's pd4fonts.properties-based font-family names.

Best Practices

  • Set pagetype and orientation explicitly rather than relying on the default, even though cfdocument and cfhtmltopdf do actually agree on letter.
  • Pin the rendering engine explicitly (type or this.pdf.type) on Lucee rather than depending on whatever the current default happens to be.
  • Verify visual output after switching a Lucee document between the classic and Flying Saucer engines.
  • Use localurl when the document references images already on local disk, to avoid unnecessary HTTP round-trips during generation.

Interview Questions

Why is cfdocument the right choice when the exact same code must run on both Adobe ColdFusion and Lucee?

It's the one PDF-generation tag both engines implement, cfhtmltopdf is Adobe-only. The underlying rendering engine differs (Adobe's engine vs Lucee's classic/Flying Saucer), but the tag itself is shared.

What's the real difference between Lucee's classic and Flying Saucer engines?

Flying Saucer is the modern default with full CSS 2.1 support, smaller output, and lower resource use; classic is the older PD4ML-based engine kept for compatibility. They aren't guaranteed to render the same input identically.

Why might referencing a font work on Lucee's classic engine but not on Flying Saucer?

Classic uses font-family names from pd4fonts.properties, Flying Saucer expects the actual .ttf filename, case-sensitively, a different lookup mechanism entirely.

Summary

In this lesson, you generated a PDF with cfdocument, configured page format and security attributes, and covered real engine differences on Lucee: Flying Saucer vs the classic engine, extra unit support, font-handling differences, and the PDF Extension requirement on Lucee 7+.

What's Next?

The next lesson covers cfdocumentitem, cfdocument's sub-tag for page breaks, running headers, and footers.