AEM 6.5 LTS Integration
AEM 6.5 LTS can mount Oak Chain content into its own repository. The content appears at /oak-chain, read-only, next to /content, /apps and /libs, and it is read live from a validator. Sling, CRXDE and the JCR API see ordinary nodes. Binaries stream from the validator.
This is the supported Oak Chain path for AEM 6.5 LTS: one add-on bundle and an opt-in tool, applied with one restart. No Oak bundle is changed. AEM 6.5 LTS SP3 ships Apache Oak 2.4.0 byte for byte, and the bundle builds against exactly those artifacts.
Status
Demonstrated on AEM 6.5 LTS SP3 (
6.6.3.20260819, Apache Oak 2.4.0, Java 21) against a three-validator cluster in mock mode on one host. Two complete opt-in and opt-out rounds passed every step: 591 of 591 bundles active, exactly one composite registration per boot, no ERROR lines, writes under the mount rejected, global writes working, and the original configuration restored byte for byte. Booting with the validator down, attaching when it came up, an outage after attach, and streaming an external binary were each checked live.Validator garbage collection under a live mount was also run, against a three-validator trunk cluster with short GC intervals. The validator AEM mounts ran two full compactions and released the deleted binaries. Every segment AEM had read for the deleted content was physically reclaimed and answered 404, while 639 reads of current content through AEM all returned the right content and bytes. AEM's own Revision Clean Up then compacted its repository with the mount attached.
Not yet run: publish instances, other LTS service packs, chain-backed mode, several hosts, and sustained load.
Support boundary
Adobe does not support a composite node store on AEM 6.5 LTS with TarMK. This is Oak Chain's opt-in path, built on Apache Oak's own composite store. Opting in means accepting that boundary for the instance; opting out restores the original configuration exactly.
How It Works
AEM's repository runs on Oak's CompositeNodeStore with two parts:
- Global store: your existing TarMK store, opened in place from
crx-quickstart/repository/segmentstore. Content, the datastore, indexes and backups stay where they were. - Read-only mount at
/oak-chain: a view of one validator's segment store over HTTP (/journal.log,/manifest,/segments/{uuid},/api/blob/{id}).
The bundle registers exactly one OSGi service: a NodeStoreProvider with role=composite-mount-oak-chain. In AEM 6.5 LTS the only components that bind that interface filter by role, so it cannot rebind or restart any other store. The Segment Tar classes the mount needs are embedded privately, which keeps every import within what the AEM 6.5 LTS API controller allows.
/oak-chain does not exist yet/oak-chainRequirements
6.6.x), author. Verified on SP3.crx3tar). MongoMK, standby or secondary instances, and custom segment stores are refused.Opt In
Build the bundle. The jar is both the OSGi bundle and the opt-in tool.
git clone https://github.com/somarc/oak-chain-connector.git
cd oak-chain-connector
mvn -f mount/pom.xml install
JAR=$(ls mount/target/oak-chain-connector.mount-*.jar)
Then run four commands against the AEM home, the directory that contains crx-quickstart:
AEM=/opt/aem/author
VALIDATOR=http://validator.example.internal:8090
# 1. Checks only; safe while AEM runs
java -jar $JAR preflight $AEM --validator $VALIDATOR
# 2. Stop AEM, then apply. It refuses unless AEM is stopped.
java -jar $JAR enable $AEM --validator $VALIDATOR
# 3. Start AEM as usual, then confirm the opted-in state
OAKCHAIN_AEM_AUTH=admin:password java -jar $JAR verify $AEM --aem-url http://localhost:4502
# 4. Any time: what is applied, and whether anything drifted
java -jar $JAR status $AEM
If the validator requires a token, put it in an environment variable and pass the variable's name with --token-env. Tokens and passwords never go on the command line. Other options: --mount-path (default /oak-chain), --refresh in seconds (default 5).
What preflight checks
Preflight changes nothing and exits non-zero on any failure. It checks the AEM build and that AEM is stopped, using the TarMK repository lock. It confirms TarMK storage, that no other composite, mount or TAR-persistence configuration exists, and that oak-store-composite and Oak's TarPersistenceService are installed. It resolves every Import-Package of the bundle against this instance's own bundle cache, checks the AEM 6.5 LTS API controller rules, and probes the validator's manifest, journal head and head segment.
What Enable Changes
Enable writes nine files and touches nothing under repository/. Every managed file carries an oakchain.optin marker. Its SHA-256 is recorded in crx-quickstart/oak-chain-opt-in/state.properties, and any file it replaces is first copied to oak-chain-opt-in/backup/.
SegmentNodeStoreServiceTarPersistenceServicerepository/segmentstore in placeSegmentNodeStoreFactory~oakchain-globalMountInfoProviderServiceCompositeNodeStoreServiceenabled=false flag.RevisionCleanupTask~mainrole=composite-global. Without it, daily maintenance finds no revision GC and never compacts the repository.OakChainMountProviderinstall/15/oak-chain-connector.mount.jarRun enable again with new options to change the validator URL or refresh interval. It updates in place and keeps the original backups.
Verify
verify checks the current boot only. It confirms that AEM is up and every bundle is active, the mount bundle is active, and the mount path is served. It also confirms exactly one composite registration, which means the repository did not restart, that the mount connected, that there are no resolution errors, and that Revision Clean Up targets the global store. With --write-probe it also confirms that a write under the mount is rejected while a global write and delete succeed.
verify http://localhost:4502 (opted in)
PASS AEM up login page HTTP 200
PASS Bundles 591 total, 591 active, 0 resolved, 0 installed
PASS Mount bundle com.oakchain.connector.mount Active
PASS Mounted path /oak-chain HTTP 200
PASS Composite registrations this boot 1 (no repository restart)
PASS Mount connected this boot connected to validator
PASS Bundle resolution no resolution errors
PASS ERROR lines this boot 0
PASS Revision Clean Up role role=composite-global (daily maintenance compacts the global store)
RESULT: OK
If the validator was not reachable at boot, Mounted path reports a warning rather than a failure: the mount attaches as soon as the validator answers.
Opt Out
# Stop AEM, then:
java -jar $JAR disable $AEM
# Start AEM, then confirm the original state:
OAKCHAIN_AEM_AUTH=admin:password java -jar $JAR verify $AEM --expect vanilla
Disable restores every replaced file byte for byte and removes everything else enable wrote. On the next start AEM's installer uninstalls the bundle, and the original SegmentNodeStoreService opens the same segmentstore again. If a managed file was edited after enable, disable stops and lists it; --force restores the originals anyway.
Operating Notes
What restarts the repository
AEM binds its node store with static, greedy OSGi references, so some changes restart the whole repository. The opt-in avoids all of them in normal operation. Plan these for a maintenance window:
- Updating, stopping or reconfiguring the mount bundle. The composite depends on it, so the repository restarts once; AEM recovers.
- Changing
MountInfoProviderService. - Installing any other bundle that registers a
SegmentNodeStorePersistence,BlobStoreorNodeStoreservice.
Validator garbage collection
Validators run segment and binary GC by default. The mount follows the validator's journal, so it moves to the compacted head on its next refresh, and reads of current content are unaffected.
A reader that holds one revision for a long time, such as a JCR session that never refreshes or a backed-up observation queue, is safe for one full GC cycle, because validators keep two generations. After that its uncached segments can be gone. When that happens is not fixed: Oak rewrites a segment file only when that saves at least a quarter of it, so deleted content can stay on disk for many cycles. A binary the validator has released answers 404, and reading it through AEM fails.
AEM maintenance
AEM's Revision Clean Up finds the revision GC to run by role. After opt-in the repository's store has the role composite-global, so enable sets that role on the task, and verify checks it. If your code base configures RevisionCleanupTask itself, add role=composite-global there, or daily maintenance stops compacting. Data Store Garbage Collection needs nothing.
Service packs
Opt out, apply the service pack, then run preflight and enable again. Preflight catches import ranges or API controller rules that changed with the new Oak line before AEM restarts.
Security
- The mount is read-only. AEM cannot change chain content, and writes under the mount are refused by Oak.
- The validator's read routes accept the operator token when one is configured; the mount sends it as the raw
Authorizationheader. - Validator HTTP is plain HTTP. Keep it on a private network or behind a TLS-terminating proxy.
Limits
/oak-chain will see it. For timely chain events, use the validator's event stream./oak-chainTroubleshooting
/oak-chain returns 404 after startVALIDATOR/manifest from the AEM host; the mount attaches on its own once it answers.RevisionCleanupTask overrides the one enable wrote. Add role=composite-global to it.disable --force to restore the originals.Next Steps
- Content Consumption - reading chain content outside AEM
- Binary Storage - how binaries are hosted and served
- Segment Store GC - what validators reclaim and when
- Status - what has been demonstrated across Oak Chain