| # AGENTS.md - AI Agent Instructions for Apache Jackrabbit Oak |
| |
| ## Project Overview |
| |
| Apache Jackrabbit Oak is a scalable, high-performance hierarchical content repository |
| implementing the JCR (Java Content Repository) specification. It is a multi-module Maven |
| project with ~47 modules written in Java 11. |
| |
| ## General Guidelines |
| |
| - When working on a specific area, first read the area-specific documentation before |
| making changes (see doc links in the module tables below) |
| - New code must have >80% test coverage. Security modules (`oak-security-spi`, |
| `oak-auth-*`, `oak-authorization-*`) require 100% test coverage |
| - Do not weaken or remove existing test assertions to make the build pass. If a test |
| fails after a change, investigate the root cause. Only modify existing tests when the |
| behavioral change is intentional and explicitly requested |
| - Write self-descriptive, easy-to-read code. Prefer minimal changes — AI tends to add |
| more lines than necessary; aim to be concise |
| - Avoid trivial comments. Only add comments where the logic is complex and not |
| obvious from the code itself |
| - Use feature toggles for non-trivial changes. If the change is a bug fix, the toggle |
| should be enabled by default. If the change introduces a new feature, the toggle should |
| be disabled by default |
| |
| ## Build Commands |
| |
| ```bash |
| # Full build (skip tests for speed) |
| mvn clean install -DskipTests |
| |
| # Fast build (no tests, no coverage) |
| mvn clean install -Pfast |
| |
| # Build a single module (use -DskipTests only for modules you did not change) |
| mvn clean install -pl oak-core -DskipTests |
| |
| # Build a module and its dependencies (use -DskipTests only for unchanged dependencies) |
| mvn clean install -pl oak-core -am -DskipTests |
| |
| # Rebuild a module and all modules that depend on it (use after SPI/API changes) |
| mvn clean install -pl oak-store-spi -amd -DskipTests |
| |
| # Full build with tests |
| mvn clean install |
| |
| # Build with integration tests |
| mvn clean install -PintegrationTesting |
| ``` |
| |
| ## Test Commands |
| |
| ```bash |
| # Run tests for a single module |
| mvn test -pl oak-core |
| |
| # Run a specific test class |
| mvn test -pl oak-core -Dtest=TreeTest |
| |
| # Run a specific test method |
| mvn test -pl oak-core -Dtest=TreeTest#testMethodName |
| |
| # Run integration tests for a module |
| mvn verify -pl oak-store-document -PintegrationTesting |
| |
| # Run with code coverage |
| mvn verify -pl oak-core -Pcoverage -Dskip.coverage=false |
| ``` |
| |
| Always run tests for the modules you modified. Use `-DskipTests` only when building |
| dependencies that you did not change. |
| |
| **Test framework:** JUnit 4 (4.13.1) with Mockito 5.x (loaded as Java agent). |
| Some modules also use EasyMock. Do not introduce JUnit 5 unless explicitly requested. |
| |
| **Test fixtures:** Tests may run against multiple backend fixtures: `SEGMENT_TAR` (default), |
| `DOCUMENT_NS` (MongoDB), `DOCUMENT_RDB`, `SEGMENT_AWS`, `SEGMENT_AZURE`. |
| |
| ## Repository Structure |
| |
| **Note:** Individual submodules may have their own `AGENTS.md` file with module-specific |
| instructions. When working within a particular module, check for and read its `AGENTS.md` |
| before making changes. |
| |
| All modules grouped by area. The **Description** column provides additional context |
| for understanding each module's role. |
| |
| ### API & Core |
| |
| | Module | Purpose | Description | |
| |--------|---------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| |
| | `oak-api` | Public Oak API | Defines `ContentRepository`, `ContentSession`, `Root`, `Tree` and other core interfaces for accessing repository content. See: `oak-api/README.md`, `oak-doc/src/site/markdown/oak_api/error_codes.md` | |
| | `oak-core` | Core repository implementation | MVCC-based transactional content model, node state management, commit handling, and internal kernel. See: `oak-doc/src/site/markdown/archigreat l-model.md` | |
| | `oak-core-spi` | Core SPI interfaces | Service Provider Interfaces for plugins and storage backends (NodeStore, Commit, etc.) | |
| | `oak-commons` | Shared utilities | Common utility classes used across all Oak modules | |
| | `oak-jackrabbit-api` | Jackrabbit API extensions | Additional API beyond the JCR spec (e.g., extended session, security). See: `oak-jackrabbit-api/README.md` | |
| | `oak-jcr` | JCR API binding | Implementation of the javax.jcr (JCR 2.0) specification on top of Oak's content model | |
| | `oak-parent` | Parent POM | Dependency management and shared plugin settings | |
| |
| ### Node Store (Persistence) |
| |
| | Module | Purpose | Description | |
| |--------|---------|-------------| |
| | `oak-store-spi` | Storage SPI | Interfaces and base classes for implementing custom NodeStore backends. See: `oak-doc/src/site/markdown/nodestore/overview.md` | |
| | `oak-store-composite` | Composite NodeStore | Combines multiple NodeStores, allowing different subtrees to be backed by different stores. See: `oak-doc/src/site/markdown/nodestore/compositens.md` | |
| | `oak-store-document` | Document NodeStore | Stores content as documents in MongoDB or relational databases (RDB). Supports clustering, revision management, and branch tracking. See: `oak-doc/src/site/markdown/nodestore/documentmk.md`, `oak-doc/src/site/markdown/nodestore/document/mongo-document-store.md`, `oak-doc/src/site/markdown/nodestore/document/rdb-document-store.md` | |
| | `oak-segment-tar` | Segment/TarMK storage | Immutable segment-based storage using TAR files. Includes online/offline compaction and generational garbage collection. Default for single-instance deployments. See: `oak-doc/src/site/markdown/nodestore/segment/overview.md`, `oak-doc/src/site/markdown/nodestore/segmentmk.md`, `oak-segment-tar/release-howto.md` | |
| | `oak-segment-remote` | Remote segment base | Shared base for cloud segment backends (AWS, Azure) | |
| | `oak-segment-aws` | Segment on AWS S3 | Remote segment store backend storing segments in Amazon S3 | |
| | `oak-segment-azure` | Segment on Azure Blob | Remote segment store backend storing segments in Microsoft Azure Blob Storage. Includes Azurite test support | |
| |
| ### Blob / Binary Storage |
| |
| | Module | Purpose | Description | |
| |--------|---------|-------------| |
| | `oak-blob` | Blob SPI & base | Core interfaces and base classes for BlobStore (binary large object) implementations. See: `oak-blob/README.md`, `oak-doc/src/site/markdown/plugins/blobstore.md` | |
| | `oak-blob-cloud` | Cloud blob base | Common functionality for cloud-based BlobStore providers | |
| | `oak-blob-cloud-azure` | Azure BlobStore | AzureDataStore implementation storing binaries in Azure Blob Storage with direct binary access. See: `oak-doc/src/site/markdown/features/direct-binary-access.md` | |
| | `oak-blob-plugins` | Blob plugins | Additional BlobStore implementations and cloud integration plugins (S3, etc.) | |
| |
| ### Query & Indexing |
| |
| | Module | Purpose | Description | |
| |--------|---------|-------------| |
| | `oak-query-spi` | Query index SPI | Interfaces for implementing custom query index providers. See: `oak-doc/src/site/markdown/query/query-engine.md` | |
| | `oak-search` | Search framework | Higher-level search abstraction and query optimization shared by Lucene and Elastic backends. See: `oak-doc/src/site/markdown/query/query.md`, `oak-doc/src/site/markdown/query/indexing.md`, `oak-doc/src/site/markdown/query/index-management.md` | |
| | `oak-lucene` | Lucene indexing | Embedded Apache Lucene full-text and property indexing with facets, suggestions, spellcheck, and excerpts. See: `oak-doc/src/site/markdown/query/lucene.md`, `oak-doc/src/site/markdown/query/property-index.md`, `oak-doc/src/site/markdown/query/hybrid-index.md` | |
| | `oak-search-elastic` | Elasticsearch indexing | Distributed full-text search and indexing via external Elasticsearch cluster. See: `oak-doc/src/site/markdown/query/elastic.md` | |
| |
| ### Security |
| |
| | Module | Purpose | Description | |
| |--------|---------|-------------| |
| | `oak-security-spi` | Security SPI | Interfaces for authentication and authorization provider plugins. See: `oak-doc/src/site/markdown/security/overview.md`, `oak-doc/src/site/markdown/security/introduction.md` | |
| | `oak-auth-external` | External authentication | Framework for external identity providers (SAML, OAuth, etc.) with user/group synchronization. See: `oak-auth-external/README.md`, `oak-doc/src/site/markdown/security/authentication/external/` | |
| | `oak-auth-ldap` | LDAP authentication | LDAP/Active Directory identity provider with user and group sync. See: `oak-auth-ldap/README.md`, `oak-doc/src/site/markdown/security/authentication/ldap.md` | |
| | `oak-authorization-cug` | Closed User Groups | CUG-based authorization restricting read access to defined groups on subtrees. See: `oak-doc/src/site/markdown/security/authorization/cug.md` | |
| | `oak-authorization-principalbased` | Principal-based authz | Access control evaluated by principal rather than by content path. See: `oak-doc/src/site/markdown/security/authorization/principalbased.md` | |
| |
| ### Tools & CLI |
| |
| | Module | Purpose | Description | |
| |--------|---------|-------------| |
| | `oak-run` | CLI toolbox | Runnable JAR with commands for backup, restore, compaction, debug console, index management, migration, and more. See: `oak-run/README.md`, `oak-doc/src/site/markdown/command_line.md`, `oak-doc/src/site/markdown/features/oak-run-nodestore-connection-options.md` | |
| | `oak-run-commons` | CLI shared code | Base classes shared by oak-run commands | |
| | `oak-run-elastic` | CLI Elastic tools | Elasticsearch-specific oak-run commands | |
| | `oak-upgrade` | Migration tools | Upgrades Jackrabbit 2.x repositories to Oak, including node store migration between backends. See: `oak-doc/src/site/markdown/migration.md` | |
| | `oak-http` | HTTP binding | REST/HTTP server exposing Oak repository operations remotely. See: `oak-http/README.md` | |
| |
| ### Other Modules |
| |
| - **Benchmarks:** `oak-benchmarks`, `oak-benchmarks-lucene`, `oak-benchmarks-elastic` — performance benchmarks. See: `oak-benchmarks/README.md` |
| - **Integration tests:** `oak-it`, `oak-it-osgi` — cross-module and OSGi integration tests |
| - **Examples / training:** `oak-exercise`, `oak-examples`, `oak-pojosr` — learning resources and OSGi test registry |
| - **Documentation:** `oak-doc` (build with `-Pdoc`) — site source at `oak-doc/src/site/markdown/` |
| |
| ## Feature Toggles |
| |
| Oak has a built-in feature toggle mechanism for safely rolling out new behavior at runtime. |
| Toggles are disabled by default and can be enabled without redeployment. |
| |
| **Core API** (in `oak-core-spi`): |
| - `Feature` — wrapper for checking toggle state. Create with `Feature.newFeature(name, whiteboard)`, |
| check with `feature.isEnabled()`, clean up with `feature.close()`. |
| See: `oak-core-spi/src/main/java/org/apache/jackrabbit/oak/spi/toggle/Feature.java` |
| - `FeatureToggle` — the underlying toggle registered on the OSGi Whiteboard. State is managed |
| via `setEnabled(boolean)` using an `AtomicBoolean` (thread-safe). |
| See: `oak-core-spi/src/main/java/org/apache/jackrabbit/oak/spi/toggle/FeatureToggle.java` |
| |
| **Naming convention:** toggle names follow the pattern `FT_OAK-<issue>` or |
| `FT_<DESCRIPTION>_OAK-<issue>` (e.g., `FT_OAK-11949`, `FT_CLASSIC_MOVE_OAK-10147`). |
| |
| **How it works:** |
| 1. A component creates a toggle: `Feature ft = Feature.newFeature("FT_OAK-XXXXX", whiteboard)` |
| 2. The toggle is registered on the Whiteboard for runtime discovery |
| 3. Code checks the toggle: `if (feature != null && feature.isEnabled()) { ... }` |
| 4. Admin tooling can discover and flip toggles via the Whiteboard at runtime |
| |
| **Examples in the codebase:** |
| - Query engine toggles (`FT_OAK-11949`, `FT_OAK-12007`) registered in `oak-core/.../Oak.java` |
| - Document store toggles (throttling, merge lock) in |
| `oak-store-document/.../DocumentNodeStoreBuilder.java` (embedded verification and full GC are |
| controlled only via OSGi `embeddedVerificationEnabled` and `fullGCEnabled`, not runtime toggles) |
| - Some features also support a system property fallback (e.g., `oak.classicMove`) |
| |
| ## Code Conventions |
| |
| ### Style |
| - No wildcard imports (import each class individually) |
| - Follow existing code style in the module you are modifying |
| - OSGi bundle compliance is required - modules produce OSGi bundles |
| - Never use regular expression parsing and find / replace for JSON or XML data |
| |
| ### License Header |
| Every Java file must start with the Apache 2.0 license header. The build enforces this |
| via the Apache RAT plugin. Use this exact header: |
| |
| ```java |
| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| ``` |
| |
| ### Annotations |
| - Use `@NotNull` / `@Nullable` from `org.jetbrains.annotations` for API contracts |
| - Use OSGi annotations (`@Component`, `@Activate`, etc.) for service components |
| |
| ### OSGi exports and baseline |
| - A package is **exported** (and baseline-checked by `maven-bundle-plugin`, `failOnError: true` |
| in `oak-parent`) when it appears in the bundle manifest `Export-Package` — typically via |
| `package-info.java` (`@Version` from `org.osgi.annotation.versioning`) in SPI/API modules, |
| or via an explicit `<Export-Package>` list in the module `pom.xml` (e.g. `oak-core`). |
| - Packages absent from `Export-Package` — including typical `*.impl.*` implementation packages |
| in SPI modules — are bundle-internal even when classes are `public`. |
| - Baseline applies when you change an **exported** package contract, not every `public` class |
| in a bundle module. |
| - To verify exports: inspect `Export-Package` in the module manifest or `target/baseline.xml` |
| after `mvn process-classes bundle:manifest -pl <module>`. |
| |
| ## Git Workflow |
| |
| - **Main branch:** `trunk` (not master/main). Never commit directly to trunk |
| - **Issue tracker:** Apache Jira, project key `OAK` (e.g., OAK-12345) |
| - **Branch naming:** `issue/OAK-<issue_number>` (e.g., `issue/OAK-12345`). If no Jira |
| issue is specified, ask the user what the branch name should be |
| - **Commit message format:** Start with Jira issue key: `OAK-XXXXX: Description of change` |
| - **PR target:** PRs should target `trunk` |
| - All changes must be committed to the issue branch, never directly to trunk |
| - **Code review:** After pushing changes, remind the user to request a review from |
| committers who have previously contributed to the affected modules |
| |
| ## CI |
| |
| - **GitHub Actions:** Runs on PRs and pushes to trunk. Builds with Java 11, runs full |
| test suite with `SEGMENT_TAR` and `DOCUMENT_NS` fixtures. |
| - **Jenkins:** Parallel module testing pipeline. |
| - **SonarCloud:** Code quality analysis runs after build. |
| - **Commit checks:** PR commit messages and branch names are validated automatically. |
| |
| ## Common Pitfalls |
| |
| - Always build `oak-parent` first if dependencies are missing: |
| `mvn install -pl oak-parent -DskipTests` |
| - MongoDB must be running locally (port 27017) for `DOCUMENT_NS` fixture tests |
| - Some modules have long-running integration tests; use `-DskipTests` or `-Pfast` for |
| quick iteration |
| - OSGi baseline checks may fail if you change an **exported** public API (see **OSGi exports |
| and baseline** above) — this is intentional to prevent accidental breaking changes |