Skip to content

GraphCompose 2.0

v1.6.6 Breaking

This release includes breaking changes for platform teams planning a safe upgrade.

Published 1mo Build & Package
✓ No known CVEs patched
Read the diff → Tool health → What is this tool? →

✓ No known CVEs patched in this version

Topics

business-documents cv-templates declarative-api document-generation invoice-template java
+12 more
java-17 layout-engine maven pagination pdf pdf-generator pdf-lib pdf-library pdfbox3 report-generation snapshot-testing template-engine

Summary

AI summary

Broad release touches Build, Public API, Engine internals, and docs/api-stability.md.

Full changelog

v1.6.6 — 2026-05-31

First Maven Central release. GraphCompose now ships under
io.github.demchaav:graph-compose:1.6.6 — note the hyphenated
artifactId, chosen for readability ahead of the Central debut. The
release adds publishable sources/javadoc jars, GPG-signed artefacts,
a binary-compatibility gate against v1.6.5, the metadata Maven
Central requires, and a substantial documentation polish for the
maturity / stability / migration story.

Zero breaking changes from v1.6.5. Existing JitPack callers continue
to resolve through the same coordinates (com.github.DemchaAV:GraphCompose:v1.6.5);
existing API surface compiles and runs unchanged (validated by the new
japicmp gate against the v1.6.5 baseline). New: the @Beta
annotation marker, the @since 1.0.0 class-level Javadoc on
entry-point packages, and a curated docs pass (decision guide for
the two template surfaces, examples maturity index, explicit API
stability policy).

Migration from v1.6.5: no code changes required. Swap the
JitPack <dependency> for the Maven Central form
(io.github.demchaav:graph-compose:1.6.6). The legacy JitPack URL
keeps resolving for callers pinned to v1.6.5 and earlier.

Build

  • Binary-compatibility gate against v1.6.5 (japicmp profile,
    Track E1). The new binary-compat CI job builds the artifact on every
    pull request and diffs it against com.github.DemchaAV:GraphCompose:v1.6.5
    pulled from JitPack. Binary-incompatible modifications to the public
    surface fail the build; source-incompatible changes are reported only
    (phased policy, will tighten after the 1.6.6 cut). Run locally with
    ./mvnw -DskipTests -P japicmp verify -pl .; HTML/MD/XML reports
    land in target/japicmp/. JitPack repository is scoped to the
    japicmp profile, so downstream consumers do not inherit it.
  • Maven Central publish workflow (Track D4). New
    .github/workflows/publish.yml fires
    on the same v* tag push that triggers the existing
    release.yml. It re-runs mvnw verify at the tagged commit, imports
    the GPG key (Track D2) into the runner keyring, writes the
    <server id="central"> credentials block into ~/.m2/settings.xml
    via actions/setup-java@v5, then invokes
    ./mvnw -P release -Dgpg.skip=false deploy — the
    central-publishing-maven-plugin (Track D3) uploads to Central and
    blocks until Sonatype's validator responds. Hyphenated tags
    (-rc, -alpha, -beta, -snapshot) are explicitly skipped — those
    ship only to JitPack and the GitHub Release pre-release surface.
    A workflow_dispatch input lets the maintainer re-publish an
    existing tag without re-cutting it if Central had a transient
    validator hiccup. The workflow is dormant until four GitHub repo
    secrets are wired: MAVEN_GPG_PRIVATE_KEY, MAVEN_GPG_PASSPHRASE,
    CENTRAL_USERNAME, CENTRAL_TOKEN.
  • docs/contributing/release-process.md updated with the
    end-to-end Maven Central runbook (Track D4 docs). New § 2.C
    "One-time Maven Central setup (maintainer)" walks through GPG key
    generation, keyserver upload, Sonatype account / namespace
    verification, Central user-token generation, the four GitHub
    secrets, and the release-candidate dry-run strategy. § 2.B
    post-release checklist gains a new step 9 for the Central publish
    alongside the existing JitPack step.
  • Hosted Javadocs via javadoc.io (Track H3). README's
    distribution-status note now points callers at
    javadoc.io/doc/io.github.demchaav/graph-compose,
    which auto-mirrors any artefact published to Maven Central within
    minutes — no separate hosting infrastructure required. The note
    also pins Maven Central as the going-forward primary distribution
    starting v1.6.6 (JitPack stays available alongside for existing
    callers). The full Central install snippet ("Central as primary,
    JitPack as fallback") lands in the v1.6.6 release-prep PR after the
    first Central publish proves the pipeline end-to-end.
  • central-publishing-maven-plugin in the release profile
    (Track D3). Adds Sonatype's central-publishing-maven-plugin 0.7.0
    to the existing release profile as a packaging extension. Replaces
    the legacy nexus-staging-maven-plugin + manual staging-repository
    workflow with a single deploy call. Configuration:
    publishingServerId=central (matches the <server id="central">
    entry the publish workflow writes from CENTRAL_USERNAME /
    CENTRAL_TOKEN secrets), autoPublish=false (validation gate before
    the artefact goes live — flips to true once we're confident
    post-D4), waitUntil=validated (the build waits for Sonatype's
    validator so any rejection surfaces in the workflow run, not a
    silent stuck upload). Requires the io.github.demchaav namespace to
    be verified on central.sonatype.com (one-time human step via
    GitHub auth or DNS TXT record). The plugin loads inert until D4's
    workflow provides the credentials.
  • GPG signing in the release profile (Track D2). Adds
    maven-gpg-plugin 3.2.7 to the existing release profile, binding
    to the verify phase to sign main / sources / javadoc / pom
    artefacts — Maven Central rejects unsigned uploads. Off by
    default
    : a new property <gpg.skip>true</gpg.skip> keeps local
    mvn -P release package runs working without a configured GPG key.
    The publish workflow (Track D4) flips it explicitly with
    -Dgpg.skip=false once the MAVEN_GPG_PRIVATE_KEY and
    MAVEN_GPG_PASSPHRASE secrets are wired. gpgArguments declares
    --pinentry-mode loopback so non-interactive CI runs accept the
    passphrase from -Dgpg.passphrase / MAVEN_GPG_PASSPHRASE without
    needing a TTY for gpg-agent.
  • release Maven profile with sources + javadoc jars (Track D1).
    Activated with -P release, attaches *-sources.jar and
    *-javadoc.jar to the package phase via the standard
    maven-source-plugin (3.3.1) and maven-javadoc-plugin (3.12.0)
    configurations Maven Central requires. The Javadoc plugin runs with
    doclint=none and failOnError=false so Lombok-generated members
    and @Internal engine surface don't block a publish; warnings are
    surfaced quietly. Default mvnw verify still does not pay the
    ~30 s of extra packaging — the profile is off by default and turned
    on by cut-release.ps1 (once Track D3's central-publishing plugin
    lands) and the publish workflow (Track D4).
  • SCM block canonicalised in pom.xml (Track D1 polish). The
    Central metadata validator is strict about the <scm> block:
    <connection> now uses scm:git:https://… (HTTPS, not the legacy
    git:// transport) and <developerConnection> now uses
    scm:git:ssh://[email protected]/… (the canonical SSH URL with the
    git@ user, not the older ssh://github.com:… form). Matches the
    shape every Central artefact's POM carries.
  • New benchmarks/README.md (Track B1). Honest framing for the
    manual benchmark layer ahead of the Maven Central debut: explicitly
    positions the harness as a smoke / diff / endurance tool — not a
    JMH-grade benchmark — and tells callers when not to use it
    (publishable performance claims, architectural decisions,
    cross-library comparisons that read too much into a single number).
    Documents the file-by-file role of each runner / report tool, the
    exact CI smoke invocation, and a "How to read a report" cheat sheet.
    Cross-links the planned JMH chain (Track C, B3 → B6 in 1.7.0) so a
    reader knows what's coming and how to identify "rigorous"
    measurements when they arrive.
  • Class-level @since 1.0.0 Javadoc on the public entry-point
    surface
    (Track H1). 26 public types in the canonical user-reached
    packages (com.demcha.compose.GraphCompose, com.demcha.compose.document.api.{DocumentSession, DocumentPageSize, PageBackgroundFill},
    com.demcha.compose.document.dsl.{DocumentDsl, RichText, Transformable} plus all 19 DSL builders)
    now carry class-level @since 1.0.0 Javadoc tags so callers can see
    the introduction version at IDE quick-doc / generated Javadoc time
    without trawling CHANGELOG history. New guard test
    PublicApiSinceTagCoverageTest source-scans the three entry-point
    roots and fails the build if a new public top-level type lands
    without a class-level @since tag; internal/ sub-packages are
    excluded by convention (InternalAnnotationCoverageTest covers those).
    Method-level @since backfill for the ~380 public methods in these
    packages is intentionally out of scope here and tracked separately.
  • maven-enforcer-plugin gate (Track E2). Binds three rules to the
    validate phase so the build refuses to start when a precondition is
    broken: requireJavaVersion (≥ 17 — the declared baseline, catches
    accidental JDK 11 / 15 attempts), requireMavenVersion (≥ 3.8.0 —
    the oldest version the planned central-publishing pipeline supports),
    and requirePluginVersions (every plugin must declare an explicit
    non-LATEST / non-RELEASE / non-SNAPSHOT version — the
    generalisation of the PR-7.1 exec-plugin drift lesson).
    Default-lifecycle plugins (clean / install / site / resources /
    deploy) are now pinned in a new <pluginManagement> block so
    requirePluginVersions has nothing to flag. Minimums and versions
    live in <properties> (enforcer.requireMavenVersion,
    enforcer.requireJavaVersion, maven.enforcer.plugin.version).
  • Parallel-session stress test (Track I2). New
    DocumentSessionParallelStressTest drives 32 independent
    DocumentSession instances on a fixed-size thread pool through 4
    iterations and asserts (a) all parallel renders produce a layout-graph
    signature byte-equal to the sequential baseline — exercising the
    shared font registry, glyph cache, built-in node definitions, and
    shape-outline cache for race conditions; (b) every PDF output starts
    with the %PDF magic, is at least 256 bytes, and has size variance
    under 256 bytes across threads (catching corruption or rare
    non-determinism without locking exact byte counts that timestamps
    could drift). 128 + 128 = 256 renders complete in ~1.6 s locally, so
    the test does not bloat CI. The contract is that each
    DocumentSession is single-threaded but the process-wide machinery
    handles concurrent independent sessions safely; this test pins that.
  • no-poi Maven profile + CI job (Track I1). The poi-ooxml
    dependency is declared <optional>true</optional> so callers that
    render only PDFs don't pay the ~10 MB POI footprint; this PR adds a
    regression gate that proves it. Running ./mvnw -P no-poi test -pl .
    excludes poi-ooxml (and its poi / poi-ooxml-lite transitives)
    from the surefire test classpath and sets the system property
    no.poi=true. DOCX-specific tests (DocxSemanticBackendTest and the
    one DOCX export in DocumentSessionTest) now carry
    @DisabledIfSystemProperty(named = "no.poi", matches = "true") and
    skip cleanly. The rest of the canonical suite (1029 tests, 4 skipped
    under -P no-poi) runs green without POI on the classpath. A new
    no-poi-suite CI job exercises the profile on every pull request.

Public API

  • New @Beta annotation (Track H2). Companion to the existing
    @Internal
    marker:
    com.demcha.compose.document.api.Beta
    signals an Extension SPI or Experimental surface — a
    deliberately-exposed seam library users can implement or call, but
    whose shape may still evolve between minor releases per the
    API stability policy § 1. First application:
    com.demcha.compose.document.layout.NodeDefinition
    — the canonical custom-node-type seam, carved out of the otherwise
    @Internal document.layout package. New
    BetaAnnotationDocumentationTest pins the annotation's retention /
    target / @Documented-ness / source-Javadoc contract in the same
    shape InternalAnnotationDocumentationTest already pins for
    @Internal. Additional Extension SPI surfaces (render-handler
    interfaces, fragment-payload interfaces) will gain the marker
    incrementally as their contract solidifies.

Documentation

  • New flagship example: EngineShowcase + regenerated
    assets/readme/repository_showcase_render.png hero image
    ahead of
    the Maven Central debut. A presentation audit before v1.6.6 flagged
    that the existing hero PDF was a dated single-page render and the
    GitHub Pages showcase had 20 broken asset paths (CV v2 migration
    added -v2 suffixes that docs/index.html never picked up). Fixed
    in three commits: (a) docs/index.html path repair so every CV /
    cover-letter preview resolves; (b) new flagship
    examples/.../flagships/EngineShowcase.java renders a single-page
    cinematic brand promo — a navy + electric-orange composition with a
    rounded clip-frame hero (semantic-graph → polished-PDFs visual
    metaphor), a magazine-headline lockup ("Documents as code. /
    Cinematic by default."), three KPI cards (Templates v2 · 1,033
    tests · v1.6.6 Maven Central), a three-column capability grid
    (Semantic DSL · Deterministic Layout · Cinematic Themes), and a
    footer brand stripe — exercising ShapeContainerNode +
    ClipPolicy.CLIP_PATH for the hero frame, classpath-loaded image
    embedding (examples/src/main/resources/engine-hero.png),
    softPanel(...) + accentLeft(...) decorators on V2 sections, and
    mixed serif/sans typography; (c) page 1 rasterised to
    assets/readme/repository_showcase_render.png via the new persistent
    helper com.demcha.examples.support.PdfPageRasterizer (PDFBox-based,
    no external Ghostscript / ImageMagick dependency). The hero now
    reads as the engine's brand register rather than a Lorem-ipsum
    template render.
  • docs/architecture/package-map.md updated alongside H2. A new
    intro paragraph documents the stability-marker convention (Stable
    default; engine packages are package-level @Internal; individual
    Extension SPI seams carved out of @Internal packages carry
    @Beta), and the document.layout row calls out NodeDefinition
    as the current @Beta seam.
  • docs/api-stability.md revised alongside H2 — @Beta annotation
    reference cells in §1 are no longer hedged as "pending"; the
    associated quote block lists both annotations side-by-side with the
    guard tests that pin them.

Engine internals (no behaviour change)

  • RowSlots helper extracted from LayoutCompiler and
    NodeDefinitionSupport. The defence-in-depth IllegalArgumentException
    guard added in v1.6.5 (PR-7.3) for the row weights / children size
    mismatch lived as duplicated inline code at both engine call sites
    with no direct test — a future refactor could have silently deleted
    either copy. The validation now lives in
    com.demcha.compose.document.layout.RowSlots#validateWeightsMatchChildren
    (package-private), with RowSlotsTest driving it directly. Error
    message is unchanged. GraphCompose.DocumentBuilder#pageBackgrounds(...)
    Javadoc now spells out the empty-list-clears semantics in prose, not
    only in the @param line.

Documentation

  • New decision guide: docs/templates/which-template-system.md
    (Track G1). The repo ships two parallel canonical template surfaces —
    cv.presets.* (the "classic" v1.6 rebuild) and cv.v2.presets.* (the
    layered architecture, recommended) — under confusingly similar names.
    The new page pins the terminology once, gives a status matrix
    (Recommended / Supported / Legacy / Internal) for every template
    surface and the canonical DSL, walks a decision tree for new code, and
    provides a preset-by-preset migration table from classic to
    layered plus a 1.x → 2.0 deprecation inventory naming every type
    scheduled for removal. CanonicalSurfaceGuardTest allowlist updated
    so the deprecation-inventory section's literal mentions of
    GraphCompose.pdf(...), PdfComposer, etc. don't trip the
    legacy-token scan (same allowlist class as the v1.5 → v1.6 migration
    log already in there).
  • examples/README.md reorganised by maturity (Track G2). The
    gallery section was grouped by the GraphCompose release that
    introduced each example (Built-in templates / Cinematic v1.5 /
    v1.5 feature showcases / v1.6 feature showcases / Public-API
    surface / Production patterns / Operational documents) — useful
    history for maintainers, less useful for someone landing on the
    examples folder for the first time. The gallery now categorises
    by maturity / intent: 🚀 Start here, 🧱 Core DSL,
    📋 Templates recommended, 🔧 Advanced SPI, 🗄️ Legacy.
    All 26 examples retained their anchor IDs, so existing deep links
    continue to resolve; only the gallery index is restructured. A
    maturity legend introduces the five tiers and links to
    docs/templates/which-template-system.md for the V1 → V2 path that
    the Legacy tier points at.
  • New API stability policy: docs/api-stability.md
    (Track G3). User-facing companion to
    ADR-0003: pins
    the four stability tiers (Stable, Extension SPI, Internal,
    Experimental) with what each one promises in patch / minor /
    major releases, the sealed-hierarchy permit-list policy (additive
    variants must degrade gracefully without default-branch failures),
    the deprecation window (≥ 1 minor release with @Deprecated, removed
    in next major), a per-package tier-lookup table for the canonical
    surface plus the legacy packages headed for 2.0 removal, and an
    "anti-policy" section (no pixel-stable PDFs, no bit-stable artefact
    bytes, no sealed-permit exhaustiveness across minor releases for
    Stable hierarchies). CanonicalSurfaceGuardTest allowlist extended
    so the page can name com.demcha.templates.* / com.demcha.compose.v2.*
    and the legacy pdf(Path) factory in the package-tier and
    deprecation-example sections.

Weekly OSS security release digest.

The CVE patches and breaking changes that affected production tools this week. One email, every Sunday.

No spam, unsubscribe anytime.

Share this release

Track GraphCompose 2.0

Get notified when new releases ship.

Sign up free

About GraphCompose 2.0

All releases →

Related context

Related tools

Earlier breaking changes

  • v2.0.0 Package rename: layered template packages dropped `.v2` suffix; update imports.
  • v2.0.0 Removed dormant ECS engine internals (EntityManager, SystemECS, Entity components, render pipeline).
  • v2.0.0 Removed linkOptions() accessor; use linkTarget() and ExternalLinkTarget.options().
  • v2.0.0 Removed PDF‑typed document‑chrome overloads on DocumentSession; use backend‑neutral metadata/watermark/protect/header/footer.
  • v2.0.0 Removed DSL name-aliases DocumentSession.builder() and DocumentDsl.text(); use builder() and paragraph().

Beta — feedback welcome: [email protected]