Skip to content

Releases: Jahia/jcr-stats

2_1_3

25 Jun 16:23
95339c5

Choose a tag to compare

JCR Stats 2.1.3

Release date: 2026-06-25 · Requires Jahia 8.2.1.0+

A small admin-UI patch release. The JCR Stats admin page now scrolls vertically
when its content is taller than the screen, and the Saved executions history
is shown above the results. Drop-in upgrade from 2.1.2 — no API, permission, or
data changes.

🐛 Fixed

  • The admin page now scrolls when content exceeds the screen. Jahia's admin
    (moonstone) settings frame is a fixed-height region, so a route must provide its
    own scrolling. The JCR Stats page didn't, so once the results, flamegraph and the
    Saved-executions / Exclusions panels stacked taller than the frame, the bottom was
    clipped with no scrollbar. The page now owns a vertical scrollbar, so nothing is
    ever cut off.

🔧 Changed

  • "Saved executions" moved above the results. The saved-run history now appears
    directly under the controls — above the View (flamegraph / tree / largest /
    diff) section — so past runs are the first thing you reach. The panel still
    disappears entirely when there is no history, and the Exclusions panel stays
    below the results.

✅ Quality

  • Backend: 88 Java unit tests. Frontend: Jest suite green, ESLint clean.
  • End-to-end: 33/33 Cypress tests passing (admin UI, API, permissions). The
    flamegraph viewport test was updated to the new layout — it now asserts the
    flamegraph stays full-width with a usable height inside the scrollable container
    (the flamegraph may extend below the fold on a short window, which is expected now
    that the page scrolls).

Upgrade notes

  • Drop-in from 2.1.2 — no migration. Admin route unchanged
    (/jahia/administration/jcrStats), still gated by the jcrStatsAdmin permission.

2_1_2

25 Jun 15:33
f4b3ffd

Choose a tag to compare

JCR Stats 2.1.2

Release date: 2026-06-25

A usability and robustness release for whole-site analysis: computations no
longer abort on un-representable nodes, long runs can be cancelled, branches can
be excluded, and every run is saved so it can be reopened and compared later.
Also a broad hardening pass across security, accessibility (WCAG 2.2 AAA), and
reliability. Drop-in upgrade from 2.1.x.

Highlights

  • 🌳 Whole-site computations no longer crash on nodes with names that aren't
    valid JCR paths (e.g. external mounts).
  • ⏹️ Cancel a running computation for real — it stops on the server.
  • 🚫 Exclude paths from a computation, persisted in an OSGi config file.
  • 🗂️ Saved executions — every run is auto-saved as JSON; reopen, compare, or
    delete past runs.
  • WCAG 2.2 Level AAA accessibility pass on the admin UI.

Added

Saved executions (server-side JSON history)

Every completed computation is automatically saved as a JSON snapshot in the JCR
(/sites/systemsite/files/jcr-stats/snapshots/), so a past run's flamegraph can
be reopened later — by anyone with the jcrStatsAdmin permission, and across
restarts. A Saved executions panel lists the history (most recent first) with
its date and size, and per-row View (reload into the viewer), Compare
(diff against the current result), and Delete actions. Snapshots are capped
at the 50 most recent (oldest pruned on write). New GraphQL:
jcrStats.snapshots, jcrStats.saveSnapshot, jcrStats.deleteSnapshot.

Path exclusions

Exclude a path — and its whole subtree — from the computation. Click a frame in
the flamegraph and choose Exclude this path; excluded paths are listed with a
Remove control. Exclusions are persisted as an OSGi configuration file
(${karaf.etc}/org.jahia.community.jcrstats.cfg, property
jcrStats.excludedPaths) via a ManagedService, so they survive restarts and
can be hand-edited. New GraphQL: jcrStats.exclusions,
jcrStats.addExclusion(path), jcrStats.removeExclusion(path). Exclusions take
effect on the next computation.

Server-side cancellation

A new jcrStats.cancel mutation and a cancelled flag on jcrStats.status. The
traversal polls a cooperative cancellation flag at the start of every node, so a
running job stops between nodes (never mid-JCR-operation). The Cancel button
now actually stops the server-side job.

Changed

  • "Load data" joins the history — loading a JSON file now also stores it as a
    saved execution (so loaded data is persisted alongside computed runs), and the
    standalone Compare with… button was removed; comparison is driven entirely
    from the Saved executions list.
  • Saved-executions UX — rows show date and size, with per-row Delete and a
    capped, scrollable list; Compare is gated until a current result is loaded.

Fixed

  • Whole-site traversal no longer aborts on un-listable branches. Descending
    into an external data-source mount whose child name isn't a valid JCR path
    (e.g. a cloud-dumps node named with an ISO-8601 timestamp, where : is the
    namespace-prefix separator) previously raised
    RepositoryException: Invalid path … ':' not valid name character and aborted
    the whole computation. Direct listing now falls back to an escaped
    ISCHILDNODE query, recovering the valid children; only the single
    un-representable node is omitted. The MAX_VISITED_NODES safety cap is
    unchanged.
  • The "Cancel" button now stops the computation instead of only stopping the
    client-side polling.
  • Snapshot list reflects deletes immediately — listing now iterates the
    folder's children directly instead of an index-backed query that lagged behind
    deletions.
  • Review hardening: snapshot/flamegraph writes use a dedicated system session;
    cancellation is classified by exception type; the flamegraph write aborts on a
    failed header/footer; jsonEscape handles lone surrogates; jcr:data reads
    guard multi-valued properties; assorted frontend race fixes (no stale-run result
    applied to a new run; load-as-snapshot failures surfaced).

Accessibility (WCAG 2.2 Level AAA)

Focus is no longer relocated on async completion (only on user-initiated view
changes); reduced-motion fully stops the progress-bar animation; info/success use
role="status" and errors role="alert"; list/icon buttons carry descriptive
accessible names; the flamegraph uses role="img" with the keyboard-accessible
tree-table as its alternative; the progressbar exposes aria-valuemin/max;
delete uses an accessible inline two-step confirm; borders/links meet AAA
contrast; headings reflow at 400% zoom.

Security

  • saveSnapshot validates the uploaded envelope structurally (parsed JSON
    with format = jcr-stats-flamegraph and a tree), not by substring match.
  • deleteSnapshot only deletes within the snapshots folder.
  • Excluded-path validation hardened (absolute, length-capped, segment-scoped
    ./.. rejection, no ReDoS-prone regex).
  • All GraphQL operations remain gated by the jcrStatsAdmin permission; JCR
    traversal uses a privileged system session by design.

Quality

  • Backend: 88 unit tests. Frontend: 108 Jest tests. End-to-end: 33 Cypress tests
    (admin UI, API, permissions) — all green. SonarQube quality gate passing;
    ESLint clean.

Upgrade notes

  • Drop-in from 2.1.x — no API or data migration required. The admin route is
    jcrStats (/jahia/administration/jcrStats).
  • Assign the jcr-stats-administrator role (or the jcrStatsAdmin permission)
    to users who should access the tool.
  • Saved snapshots and generated flamegraph reports accumulate in the JCR under
    /sites/systemsite/files/jcr-stats/ (snapshots are capped at 50; HTML reports
    are not — prune if needed).

Known limitations

  • The computation is a single, server-wide job — concurrent admins share one run.
  • The subtree is held in memory, bounded by the MAX_VISITED_NODES = 5,000,000
    safety cap.
  • The read-only size/nodeCount/tree GraphQL queries run synchronously on the
    request thread (use the async compute/status/result flow for large paths).

Compatibility

  • Requires Jahia 8.2.1.0 or later.

2_1_1

23 Jun 12:49
2bfe414

Choose a tag to compare

JCR Stats 2.1.1

Release date: 2026-06-23

A performance and maintenance release. JCR Stats now traverses the repository
significantly faster on large subtrees, with no change to the analysis output or
the admin UI. Drop-in upgrade from 2.1.0.

Highlights

  • Faster tree traversal — large-subtree computations no longer pay a
    per-node query cost, so deep/wide analyses finish noticeably quicker.
  • 🎯 More accurate — size and node counts now read committed repository state
    instead of possibly-lagging index state.

Improvements

Direct hierarchy traversal

The size computation now walks the JCR hierarchy directly via
JCRNodeWrapper.getNodes() instead of issuing one ISCHILDNODE JCR-SQL2 query per
node. This removes, at every node:

  • a query parse / plan / Lucene-index lookup, and
  • a redundant path re-resolution of each child.

The bigger and deeper the subtree, the larger the speed-up. Results are also more
accurate because traversal reads committed hierarchy state rather than the
query index, which can lag behind recent writes.

via a system property (see Configuration below). The default is the new direct
strategy; no action is required to get the improvement.

Reduced session overhead

session.refresh(false) now runs once at the start of a traversal instead of once
per node — eliminating needless per-node refresh work on a read-only walk.

Configuration

System property Values Default Effect
jcrStats.traversal direct, query direct direct uses getNodes() hierarchy iteration; query restores the legacy per-node ISCHILDNODE JCR-SQL2 strategy.

To A/B compare on the same build, set -DjcrStats.traversal=query in your
JAVA_OPTS / setenv, restart, run the same path, and compare the
INFO log line:

JCR stats computation finished for path in ms ( nodes visited)

Tests

  • Added JcrStatsTraversalTest covering the direct-traversal aggregation logic
    (size roll-up, node count, single-visit guarantee, size-descending child
    ordering) with mocked JCRNodeWrappers.

Upgrade notes

  • Drop-in upgrade from 2.1.0 — no API, permission, configuration, or data
    changes. Public GraphQL operations, the Karaf command, and the admin UI are
    unchanged.
  • The behavior change is internal (how children are fetched during traversal); the
    computed sizes and node counts are equivalent.

Compatibility

  • Requires Jahia 8.2.1.0 or later (unchanged from 2.1.0).

2_1_0

23 Jun 09:55
49ca062

Choose a tag to compare

JCR Stats 2.1.0

Release date: 2026-06-23

JCR Stats turns a raw JCR subtree into something you can actually read: an
interactive flamegraph, a sortable tree-table, and a top-largest list — weighted
by storage size or by number of nodes. This release adds a full GraphQL API, an
asynchronous computation model for very large trees, and a redesigned admin UI.

Highlights

  • 📊 Interactive admin UI — flamegraph, tree-table, top-largest, and snapshot
    comparison views, available under Administration → System Health → JCR Statistics.
  • Asynchronous computation — large subtrees are traversed in the background
    with live progress, so requests no longer time out.
  • 🔌 GraphQL API — script and automate the same analysis the UI uses.
  • 🔐 Dedicated permission & role — access is gated by a new jcrStatsAdmin
    permission.

New features

GraphQL API

A new jcrStats namespace on the root Query and Mutation:

  • Queries: size(path), nodeCount(path), tree(path, maxDepth),
    status(), result(maxDepth), reports()
  • Mutations:
    • compute(path) — fire-and-forget asynchronous start
    • computeSize(path, deleteTemporaryFile) — synchronous full flamegraph
  • The node tree is returned recursively with depth limiting to keep payloads small.
  • Every operation requires the jcrStatsAdmin permission.

Asynchronous computation

A single server-wide background job model for large subtree traversal:

  • compute(path) starts one job (no-op if one is already running).
  • status() reports live progress: running flag, elapsed time (ms), visited-node
    count, path, and error state.
  • result(maxDepth) returns the cached tree once computation finishes.
  • The admin UI polls status every 2s and shows an elapsed timer + live node counter.
  • Resume-on-remount: leaving the page and coming back re-attaches to a job
    still in progress.

Admin UI

An interactive space-analysis interface at /jahia/administration/jcrStats:

  • Flamegraph view — click-to-zoom visualization of space usage.
  • Tree-table view — hierarchical breakdown with size, % of total, % of parent,
    and node count; fully keyboard accessible.
  • Largest-items view — sorted top-N space consumers.
  • Comparison view — diff two snapshots to see what changed over time.
  • Snapshot save/load — download the current tree as JSON and reload baselines.
  • jContent deep links — jump straight from a result into the jContent editor
    for the selected node.

Metrics

Weight any analysis by size (bytes) for disk-usage analysis or by number of
nodes
for structure/complexity analysis.

Shared computation engine

A reusable JcrStatsComputer now powers all three entry points — the
jcr-stats:compute-size Karaf command, the GraphQL API, and the admin UI — so they
always produce consistent results.

Improvements

  • Single admin menu entry — the previous two-level JCR Statistics → Compute size
    navigation is collapsed into one clickable JCR Statistics entry under
    System Health.
  • Job logging — the asynchronous computation now logs an INFO line when a job
    starts and when it finishes (with elapsed time and visited-node count), making
    long-running scans easy to follow in the server log.
  • Karaf command refactored to delegate to the shared JcrStatsComputer.

Fixes

  • Defensive node-count traversal cap prevents unbounded memory use on pathologically
    large trees.
  • Hardened JSON-import validation for snapshot upload (strict schema enforcement).

Security & access control

  • New jcrStatsAdmin permission and jcr-stats-administrator role
    (bundling administrationAccess + jcrStatsAdmin, marked privileged). All GraphQL
    operations and the admin UI require jcrStatsAdmin.
  • ⚠️ Privileged traversal: compute(path) and computeSize(path) run under a
    JCR system session, which bypasses node-level read ACLs. Holders of
    jcrStatsAdmin therefore get full-repository structural/size visibility regardless
    of per-node read permissions. This is intentional — administrators need the full
    storage footprint — so treat the jcr-stats-administrator role as granting broad
    read-visibility into the entire JCR tree.
  • Generated flamegraph HTML is safe, non-executable content; path parameters are
    validated and traversal is bounded by a configurable depth limit.

Deprecations

  • Direct use of ComputeSizeCommand for programmatic access is deprecated — use the
    GraphQL API or JcrStatsComputer instead.

Upgrade notes

  • The module's root package was renamed from org.jahia.modules.* to
    org.jahia.community.jcrstats, and the module is now declared as a system
    type module.
  • Assign the jcr-stats-administrator role (or grant the jcrStatsAdmin
    permission) to users who should access the tool — see the security note above.

Compatibility

  • Requires Jahia 8.2.1.0 or later (jahia-modules parent 8.2.1.0).

2_0_0

30 Jul 07:56
e390de8

Choose a tag to compare

Full Changelog: 1_0_2...2_0_0

1_0_2

22 Feb 14:34
abc2be1

Choose a tag to compare

Compatibility with Jahia 7.2.3.0

Correction of a bug where the content was not correctly written

02 Dec 13:21
6388fc8

Choose a tag to compare

1_0_1

[maven-release-plugin] copy for tag 1_0_1

First release :)

02 Dec 13:06
1949c28

Choose a tag to compare

1_0_0

[maven-release-plugin] copy for tag 1_0_0