Package org.apache.jackrabbit.oak.composite

Composition support

This package contains support classes for implementing a composite persistence at the NodeStore level.

Design goals

  1. Transparency of the composition setup. Neither the NodeStores nor the code using a composite NodeStore should be aware of the specific implementation being used.
  2. Persistence-agnosticity. The composition support should be applicable to any conformant NodeStore implementation.
  3. Negligible performance impact. Composition should not add a significat performance overhead.


The main entry point is the CompositeNodeStore, which wraps one or more NodeStore instances. Also of interest are the CompositeNodeState and CompositeNodeBuilder.

These classes maintain internal mappings of the 'native' objects. For instance, if the composite NodeStore holds two MemoryNodeStore instances, then a call to NodeStore.getRoot() will return a composite NodeState backed by two MemoryNodeState instances. Similarly, a call to NodeState.builder() will return a composite NodeBuilder backed by two MemoryNodeState instances.

Using this approach allows us to always keep related NodeStore, NodeState and NodeBuilder instances isolated from other instances.

Open items

1. Brute-force support for oak:mount nodes.

The Mount.getPathFragmentName() method defines a name pattern that can be used by mounted stores to contribute to a patch which is not owned by them. For instance, a mount named apps which owns /libs,/apps can own another subtree anywhere in the repository given that a node named :oak-mount-apps is found.

The current implementation naively queries all stores whenever the child node list is prepared. This is obviously correct but may be slow. CompositionContext.getContributingStores(java.lang.String, java.util.function.Function)