From df6bde315e89b226affcce53b93ef1236f298062 Mon Sep 17 00:00:00 2001 From: DemchaAV Date: Mon, 6 Jul 2026 02:54:17 +0100 Subject: [PATCH] docs: add the 2.0 module migration guide and modularization ADR Document the completed module split for consumers and record the decision. - ADR 0016 captures the multi-module packaging decision: the split into a lean graph-compose-core plus render backends and templates, the ServiceLoader backend seam, lockstep versioning, and the back-compat wrapper that keeps graph-compose rendering PDF out of the box. - A new migration guide (docs/migration/v2.0.0-modules.md) walks a consumer through the dependency change: PDF callers are unchanged, lean consumers use graph-compose-core, templates become opt-in, and MissingBackendException is the lean-core signal. - Flip the api-stability section 3 ledger's single-jar-packaging row from planned to landed and correct it to the shipped topology. --- docs/adr/0016-multi-module-packaging.md | 87 +++++++++++++++++++++++++ docs/api-stability.md | 2 +- docs/migration/v2.0.0-modules.md | 87 +++++++++++++++++++++++++ 3 files changed, 175 insertions(+), 1 deletion(-) create mode 100644 docs/adr/0016-multi-module-packaging.md create mode 100644 docs/migration/v2.0.0-modules.md diff --git a/docs/adr/0016-multi-module-packaging.md b/docs/adr/0016-multi-module-packaging.md new file mode 100644 index 00000000..61d735aa --- /dev/null +++ b/docs/adr/0016-multi-module-packaging.md @@ -0,0 +1,87 @@ +# ADR 0016 — Multi-module packaging (lean core + render backends + templates) + +- **Status:** Accepted +- **Date:** 2026-07-06 +- **Authors:** Artem Demchyshyn + +## Context + +Through the 1.x line GraphCompose shipped as a single published jar, +`io.github.demchaav:graph-compose`. That one artifact bundled the engine, the +PDFBox render backend (plus PDFBox and zxing), the Apache POI semantic backend, +and the built-in template families. A consumer who only wanted the engine — or +who intended to bring their own render backend — still pulled the entire set, +and an engine patch republished everything. + +The [API-stability ledger](../api-stability.md#3-deprecation-window) tracked this +as a **Stable** packaging commitment we intended to change in the next major: the +single-jar shape could not be split in a minor without breaking every existing +coordinate. + +Two forces shaped the split: + +- **Consumer-side leanness is the benefit, not release-side flexibility.** The + goal is a small dependency tree for engine-only / bring-your-own-backend + consumers. Versioning stays **lockstep** — a patch republishes the whole train + — so the split never promises independent per-module releases. +- **PDF back-compatibility is non-negotiable.** Every existing caller depends on + `graph-compose` and calls `…buildPdf()`. Upgrading to 2.0 must not make a bare + `graph-compose` stop rendering PDF. + +## Decision + +Split the single jar into per-concern Maven modules, versioned in lockstep, with +render backends discovered at runtime through a `ServiceLoader` SPI. + +**Coordinates:** + +- **`graph-compose-core`** — the lean engine: the `DocumentSession` authoring API, + the canonical DSL / nodes / style / layout, chart / svg / markdown / barcode, and + the `FixedLayoutBackendProvider` / `FontMetricsProvider` SPI seams. Depends only on + `slf4j-api` + `flexmark`. Rendering nothing until a backend is on the classpath — + it throws `MissingBackendException` (naming the artifact to add) if asked to build a + PDF without one. +- **`graph-compose-render-pdf`** — the entire PDFBox backend (`document.backend.fixed.pdf.**` + and the `engine.render.pdf.**` tree), PDFBox, and zxing. Registers the PDF + `FixedLayoutBackendProvider` / `FontMetricsProvider` via `META-INF/services`. +- **`graph-compose`** — kept as a coordinate, but now an **empty jar-wrapper** over + `graph-compose-core` + `graph-compose-render-pdf`. So a 1.x caller who upgrades keeps + rendering PDF with no code and no dependency change. Packaging stays `jar` (not `pom`) + so existing `` declarations need no ``. +- **`graph-compose-render-docx`** / **`graph-compose-render-pptx`** — the POI semantic + backends, split apart so a DOCX consumer does not pull the PPTX skeleton (and neither + pulls into the engine). +- **`graph-compose-templates`** — the built-in CV / cover-letter / invoice / proposal + presets. Pure authoring over the canonical DSL, so it depends only on + `graph-compose-core`. **Opt-in:** the `graph-compose` wrapper does not bundle it. +- **`graph-compose-testing`** — the consumer testing support (`LayoutSnapshotAssertions`, + `PdfVisualRegression`). +- **`graph-compose-bundle`** — the batteries-included aggregate: the default PDF stack + (via the wrapper) + templates + the independently-versioned `graph-compose-fonts` and + `graph-compose-emoji` companions. Office backends are not bundled. + +The engine sources stay at the repository root and only the **root coordinate** is +renamed `graph-compose` → `graph-compose-core`; the new wrapper is a small module. The +default coordinate `graph-compose` therefore continues to mean "PDF out of the box". + +No JPMS: modules carry an `Automatic-Module-Name` only, so a split package across +test-scope jars stays legal on the classpath. + +## Consequences + +- **Engine-only / bring-your-own-backend consumers get a lean tree** — depend on + `graph-compose-core` and pull neither PDFBox, POI, zxing, nor the templates. +- **Existing PDF callers are unaffected** — `graph-compose` still renders PDF out of the + box; no code change on upgrade. +- **Templates-via-`graph-compose` consumers break** — a caller that reached a preset + through the 1.x single jar must now add `graph-compose-templates` (or + `graph-compose-bundle`). This is the one accepted source break; PDF compatibility took + priority. See the [modules migration guide](../migration/v2.0.0-modules.md). +- **Lockstep versioning, not independent releases** — every 2.0 coordinate shares the + engine version; a patch republishes the train. `graph-compose-fonts` / + `graph-compose-emoji` keep their own lines (they change rarely). +- **A `MissingBackendException` is now the "why won't it render" signal** for a lean + `graph-compose-core`, replacing the pre-split assumption that the backend is always present. +- The legacy `Entity`-Component-System render pipeline moves into `graph-compose-render-pdf` + rather than being deleted; it is dead on the canonical path but still exercised by + test scaffolding, so its removal is deferred beyond 2.0. diff --git a/docs/api-stability.md b/docs/api-stability.md index 6460e280..5decdd5d 100644 --- a/docs/api-stability.md +++ b/docs/api-stability.md @@ -181,7 +181,7 @@ window starts, and its `Status` flips to `deprecated 1.x`. | Element | Tier now | Status | Why the 1.x shape is a compromise | 2.0 action | ADR | Issue | |---|---|---|---|---|---|---| | `DocumentSession.pageMargins(List)` / `PageMarginRule` | Stable | planned | Per-page margins resolve a block's content width by the page it *begins* on (the engine measures each block once, before pagination). A margin that changes the content width therefore does not re-wrap a block mid-flow across a page boundary. | Revisit a page-aware per-line/per-fragment width model so a block can re-wrap when it crosses a margin boundary, if demand warrants. | — | — | -| `io.github.demchaav:graph-compose` single-jar packaging | Stable | planned | The one published jar bundles the engine, the PDFBox render backend, the POI semantic backend, zxing, and the template families, so an engine-only or bring-your-own-backend consumer still pulls all of them. | Split into a lean `graph-compose` core plus sibling artifacts — `graph-compose-render-pdf`, `graph-compose-render-docx`, `graph-compose-templates`, `graph-compose-testing` — with render backends discovered via a `ServiceLoader` SPI. `graph-compose` keeps its coordinate but no longer contains the PDF backend or templates; add `graph-compose-render-pdf` (or the batteries-included `graph-compose-bundle`) to keep PDF output. | — | — | +| `io.github.demchaav:graph-compose` single-jar packaging | Stable | **landed 2.0** | The one published jar bundled the engine, the PDFBox render backend, the POI semantic backend, zxing, and the template families, so an engine-only or bring-your-own-backend consumer still pulled all of them. | **Done in 2.0.** Split into per-concern lockstep modules, render backends discovered via a `ServiceLoader` SPI. The root coordinate is renamed `graph-compose-core` (the lean engine); `graph-compose` is kept as a back-compat wrapper over `graph-compose-core` + `graph-compose-render-pdf`, so it still renders PDF out of the box. Templates are opt-in (`graph-compose-templates`); DOCX / PPTX ship in `graph-compose-render-docx` / `-render-pptx`. Migration: [modules guide](migration/v2.0.0-modules.md). | [ADR 0016](adr/0016-multi-module-packaging.md) | — | --- diff --git a/docs/migration/v2.0.0-modules.md b/docs/migration/v2.0.0-modules.md new file mode 100644 index 00000000..ce3ba195 --- /dev/null +++ b/docs/migration/v2.0.0-modules.md @@ -0,0 +1,87 @@ +# Migrating to 2.0 — the module split + +GraphCompose 2.0 splits the single `graph-compose` jar into per-concern modules so an +engine-only consumer no longer pulls PDFBox, POI, zxing, and the template families. This +guide covers the **dependency** change. For API-level removals (retired classes, the +`.v2` package rename, `BusinessTheme`), see the [`### Removed` / `### Public API` sections +of the changelog](../../CHANGELOG.md); the rationale is [ADR 0016](../adr/0016-multi-module-packaging.md). + +## TL;DR — rendering PDF? Nothing changes + +`graph-compose` is still the drop-in default. It is now an empty wrapper over +`graph-compose-core` + `graph-compose-render-pdf`, so a 1.x caller who bumps the version +keeps rendering PDF with **no code and no dependency change**. + +```xml + + io.github.demchaav + graph-compose + 2.0.0 + +``` + +You only need to change your dependencies if you want a **leaner** tree, or if you reached +a **built-in template** through the single jar (see [the one break](#the-one-break-templates)). + +## Which artifact now? + +| You want | Depend on | Change from 1.x | +|---|---|---| +| PDF out of the box (the 1.x behaviour) | `graph-compose` | none — same coordinate | +| Batteries-included (PDF + templates + fonts + emoji) | `graph-compose-bundle` | now also carries templates + emoji | +| A lean engine, bring your own backend | `graph-compose-core` | **new** — the renamed root coordinate | +| Built-in CV / cover-letter / invoice / proposal presets | add `graph-compose-templates` | **new** — opt-in, not in `graph-compose` | +| DOCX export | add `graph-compose-render-docx` | POI is no longer in the engine | +| PPTX export | add `graph-compose-render-pptx` | split out of the DOCX artifact | +| Consumer layout/visual test helpers | add `graph-compose-testing` (test scope) | unchanged coordinate | + +All 2.0 coordinates share the `graph-compose` version. `graph-compose-fonts` and +`graph-compose-emoji` keep their own version lines, as they have since 1.8.0 / 1.9.0. + +## The one break: templates + +The built-in presets (`com.demcha.compose.document.templates.**`) moved into the opt-in +`graph-compose-templates` artifact, and the `graph-compose` wrapper does **not** bundle +them. If your 1.x code called a preset through the single jar — + +```java +ModernInvoice.create(theme).compose(session); // needs graph-compose-templates in 2.0 +``` + +— add the artifact (the package names are unchanged, so imports stay the same): + +```xml + + io.github.demchaav + graph-compose-templates + 2.0.0 + +``` + +Or depend on `graph-compose-bundle`, which includes it. This is the only dependency-level +source break in the split — PDF compatibility was kept as the priority. + +## `MissingBackendException` — the lean-core signal + +`graph-compose-core` on its own renders nothing until a render backend is on the classpath. +Asking it to build a PDF throws `MissingBackendException`, whose message names the artifact +to add: + +``` +No fixed-layout render backend on the classpath: add the +io.github.demchaav:graph-compose-render-pdf artifact (or the +io.github.demchaav:graph-compose-bundle aggregate, or another provider +implementation) to render, rasterize, or measure a document. +``` + +Depend on `graph-compose` (or `graph-compose-bundle`) instead of `graph-compose-core` and +the PDF backend is already present. See the +[troubleshooting entry](../troubleshooting.md#missingbackendexception-when-rendering). + +## Reference + +- [README install matrix](../../README.md#installation) — the same table with copy-paste snippets. +- [ADR 0016 — multi-module packaging](../adr/0016-multi-module-packaging.md) — why the split + is shaped this way, including the back-compat wrapper decision. +- [API stability policy § 3](../api-stability.md#3-deprecation-window) — the packaging entry + in the 2.0 breaking-changes ledger.