Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,29 @@ follow-ups carried over from the v1.6.7 senior review (see
[ROADMAP.md](ROADMAP.md) and the private taskboard). No breaking
changes are planned.

### Fixes

- The two `DocumentSession` registration entry points are now
**fully** interchangeable, not just cache-equivalent.
`session.registry().register(...)` now calls `ensureOpen()`
before mutating, matching the behaviour of
`session.registerNodeDefinition(...)`. Previously
`registry().register(...)` on a closed session silently mutated
the registry and invalidated a closed-session cache (harmless
but semantically odd). After this change both paths throw
`IllegalStateException` on a closed session. (Track J2 — carry-
over polish from the v1.6.7 senior review.)

### Internal

- `NodeRegistry` Javadoc updated to call out the v1.6.7 non-final
relaxation explicitly (Track J4). The class became non-final
in v1.6.7 (Track I3) so `DocumentSession` could install the
auto-invalidating subclass; the change was already binary-
compatible (japicmp classified it as `semver PATCH`). The
Javadoc just makes the rationale discoverable without reading
the CHANGELOG.

### Public API

- `MarkdownInline.append(...)` (the inline-markdown adapter used by
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -913,18 +913,23 @@ private interface PdfRenderingBody<R> {

/**
* Session-owned {@link NodeRegistry} subclass that funnels every
* {@link #register(NodeDefinition)} call through
* {@link DocumentSession#invalidate()}. Without this wrapper, callers
* that mutated the registry directly via {@code session.registry().
* register(...)} would leave the layout cache pointing at a stale
* compile result — the cache invalidation only happened on the
* dedicated {@link DocumentSession#registerNodeDefinition(NodeDefinition)}
* path. Added in v1.6.7 (Track I3) so the two registration entry points
* have identical caching semantics.
* {@link #register(NodeDefinition)} call through both
* {@link DocumentSession#ensureOpen()} and
* {@link DocumentSession#invalidate()}. The two registration entry
* points — {@code session.registry().register(...)} and
* {@link DocumentSession#registerNodeDefinition(NodeDefinition)} —
* are now fully interchangeable: both refuse to mutate a closed
* session and both invalidate the cached compile.
*
* <p>Added in v1.6.7 (Track I3) as cache-invalidation only; the
* {@code ensureOpen()} symmetry landed in v1.6.8 (Track J2) after
* the senior review noted that the two entry points still
* disagreed on closed-session behaviour.</p>
*/
private final class InvalidatingNodeRegistry extends NodeRegistry {
@Override
public <E extends DocumentNode> NodeRegistry register(NodeDefinition<E> definition) {
ensureOpen();
super.register(definition);
invalidate();
return this;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@
* get the same caching semantics as
* {@code session.registerNodeDefinition(...)}.</p>
*
* <p><strong>Non-final since v1.6.7.</strong> The class lost its
* {@code final} modifier in v1.6.7 (Track I3) so {@code DocumentSession}
* could install the auto-invalidating subclass described above. The
* change is binary-compatible (japicmp classifies it as {@code semver
* PATCH}); standalone-registry callers see no behavioural change.</p>
*
* @since 1.6.0
*/
public class NodeRegistry {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -760,6 +760,32 @@ public List<LayoutFragment> emitFragments(PreparedNode<BadgeNode> prepared, Frag
}
}

/**
* Negative-path companion to the I3 positive test above. After
* closing the session, mutating the registry through
* {@code session.registry().register(...)} must throw
* {@link IllegalStateException} — symmetric with
* {@link DocumentSession#registerNodeDefinition(NodeDefinition)},
* which has always thrown on a closed session. Added in v1.6.8
* (Track J2/J3) after the v1.6.7 senior review flagged that the
* two entry points still disagreed on closed-session behaviour.
*/
@Test
void registryRegisterOnClosedSessionThrowsIllegalStateException() {
DocumentSession session = GraphCompose.document()
.pageSize(200, 160)
.margin(DocumentInsets.of(10))
.create();
// Close via try-with-resources is the canonical path; close
// explicitly here so the assertion runs against a closed
// session.
session.close();

assertThatThrownBy(() -> session.registry()
.register(new BadgeNodeDefinition()))
.isInstanceOf(IllegalStateException.class);
}

@Test
@DisabledIfSystemProperty(named = "no.poi", matches = "true",
disabledReason = "Exercises DocxSemanticBackend; skipped under the no-poi profile that excludes poi-ooxml from the test classpath")
Expand Down