1. The Enterprise Replatforming Challenge
While OpenCrawling’s primary RAG mode parses documents via Apache Tika, splits them into semantic chunks, and calculates high-dimensional vector embeddings, content migration demands a completely different approach.
When enterprises migrate tens of millions of records into Alfresco Content Services:
- Original Binaries Must Remain Pristine: CAD models, signed PDF contracts with cryptographic certificates, TIFF archives, and high-resolution media must be transferred bit-for-bit without alteration.
- Hierarchies Must Be Maintained: Source folder trees must be seamlessly translated into Alfresco
cm:foldernodes without duplicating intermediate folders or causing race conditions. - Security & Permissions Must Be Preserved: Access control rules from the source must be translated into Alfresco's native permission model (
Consumer,Contributor,Collaborator,Coordinator). - Missing Authorities Must Not Crash Bulk Ingestion: In legacy systems, orphaned users or decommissioned Active Directory groups frequently linger on documents. If sent directly to Alfresco, the REST API rejects the entire payload with HTTP
400 Bad Requestor404 Not Found.
The oc-alfresco-output-connector was built from the ground up to address each of these challenges with enterprise precision.
2. Migration Mode Fast-Path: Zero Compute Overhead
Operating strictly under opencrawling.pipeline.mode=migration (or per-job pipelineMode: migration), the connector completely bypasses the resource-intensive AI vectorization pipeline:
| Pipeline Stage | RAG Mode (Default) | Alfresco Migration Mode |
|---|---|---|
| Apache Tika Text Extraction | Executed in isolated child JVMs | Bypassed completely (0 CPU cycles) |
| Auto-Narrativization Copilot | Mustache template rendering | Bypassed completely |
| Token Chunking & Splitting | TokenTextSplitter execution | Bypassed completely |
| AI Vector Embeddings | Ollama / OpenAI / HuggingFace | Bypassed completely |
| Payload Target | Vector databases & search engines | Alfresco Content Services REST API v1 |
Strict Fail-Fast Protection: Attempting to run a job targeting the Alfresco output connector in RAG mode is rejected immediately with HTTP 409 Conflict ("AlfrescoOutputConnector only supports MIGRATION mode"), protecting operators from accidental misconfigurations.
3. Hierarchical Path Preservation (cm:folder) & Conflict Handling
The connector features an intelligent path resolution engine that evaluates the relativePath or relative_path metadata emitted by repository connectors (e.g. FileSystem, FileNet, SharePoint):
HIERARCHICAL(Default): Progressively inspects each segment of a nested document path (such asMigratedContent/v1/Legal/2026/Contracts). It checks whether intermediatecm:foldernodes exist via/nodes/{parentId}/childrenand automatically provisions missing parent directories. Resolved node IDs are cached in memory to eliminate redundant REST lookups.FLAT: Ingests all documents directly into the base target folder defined bytargetParentNodeId(e.g.-root-) andtargetPathPrefix.
Duplicate Conflict Resolution
When a node with the same name already exists in the target folder, the connector handles it according to conflictStrategy:
OVERWRITE(Default): Replaces the binary stream viaPUT /nodes/{nodeId}/contentand updates properties in-place. If versioning is enabled (cm:versionableaspect), Alfresco automatically increments the document version.AUTO_RENAME: Generates a timestamp-disambiguated filename before creation to avoid naming collisions.FAIL: Aborts the upload of the duplicate and logs an error in the migration ledger.
4. Zero-Trust Security & Pre-Flight Authority Auditing
One of the most innovative features of the new connector is the AlfrescoAuthorityValidator.
Built on Java 25 Structured Concurrency (StructuredTaskScope) and thread-safe caching, the validator audits user and group authorities against target Alfresco endpoints (/people/{id} and /groups/{id}) to guarantee that only valid principals are submitted in permission payloads.
Authority Validation Modes
IN_FLIGHT(Default): Validates authorities on the fly during document ingestion. Results are cached in a thread-safeConcurrentHashMapso that repeated users/groups across millions of documents incur zero additional network round-trips.PRE_FLIGHT: Executes a parallel pre-crawl audit across all distinct authorities usingStructuredTaskScopebefore content ingestion begins.BOTH: Combines pre-flight discovery with in-flight verification for dynamically discovered identities.DISABLED: Directly submits ACEs without pre-validation.
Built-in Authorities & Role Mapping
Standard Alfresco system authorities are recognized natively without issuing REST calls:
GROUP_EVERYONE, EVERYONE, GUEST, ROLE_ANONYMOUS, ROLE_AUTHENTICATED, ROLE_ADMINISTRATOR, ADMIN.
OIS permissions are mapped to Alfresco roles:
read→Consumerwrite→Contributor/Editordelete→Collaboratoradmin/full_control→Coordinator
The Missing Authority Gap Ledger Report
When missingAuthorityAction=SKIP (default), missing authorities are omitted from the node's permissions so valid ACEs are successfully applied, and the gap is captured in an audit ledger. At the conclusion of the migration, a structured JSON gap report is exported:
{
"timestamp": "2026-11-02T22:00:00.000Z",
"targetUrl": "http://localhost:8081/alfresco",
"missingAuthoritiesCount": 2,
"missingAuthorities": [
{
"authority": "retired_contractor",
"identityType": "user",
"firstEncounteredNode": "doc-legal-001",
"timestamp": "2026-11-02T22:00:01.120Z"
},
{
"authority": "GROUP_LEGACY_FINANCE",
"identityType": "group",
"firstEncounteredNode": "doc-fin-042",
"timestamp": "2026-11-02T22:00:02.450Z"
}
]
}
5. Document Lifecycle Actions & Trashcan Tombstones
Open Ingestion Standard (OIS) document lifecycle actions are fully supported:
UPSERT: Streams binary from Claim Check storage, creates or updatescm:content, sets properties, and synchronizes permissions.DELETE: Resolved viatombstoneAction:MOVE_TO_TRASH(Default): CallsDELETE /nodes/{nodeId}?permanent=false. Moves the document to the Alfresco Trashcan, preserving audit trails and enabling administrative recovery.PERMANENT_DELETE: CallsDELETE /nodes/{nodeId}?permanent=trueto purge the document permanently.
6. Lightweight Search Engine Tuning: noindex by Default
In high-throughput bulk migrations, indexing every document into Apache Solr simultaneously introduces substantial I/O overhead and memory contention. Furthermore, all migration writes and folder lookups execute directly against Alfresco's relational database (PostgreSQL)—meaning no search queries are required during ingestion.
In the decoupled Compose stack (docker-compose-decoupled-with-alfresco.yml):
- Alfresco ACS defaults to
-Dindex.subsystem.name=noindex. - Eliminates
UnknownHostException: solr6connection retries and log spam. - Reduces Alfresco container startup time from ~90s down to ~25–30s.
- Saves ~2 GB RAM on the test/target host.
Enabling Solr 6 on Demand: If full-text search indexing is needed on the target Alfresco instance, simply activate the preconfigured solr6 container using Docker Compose profiles:
export ALFRESCO_INDEX_SUBSYSTEM=solr6
docker compose -f oc-alfresco-output-connector/docker/docker-compose-decoupled-with-alfresco.yml --profile search up -d
7. Configuration Reference
| Property | Default | Description |
|---|---|---|
spring.opencrawling.output.alfresco.url |
http://localhost:8081/alfresco |
Target Alfresco Content Services base REST API URL |
spring.opencrawling.output.alfresco.username |
admin |
Admin / service account username |
spring.opencrawling.output.alfresco.password |
admin |
Admin / service account password |
spring.opencrawling.output.alfresco.target-parent-node-id |
-root- |
Starting folder node UUID or alias (-root-, -my-, -shared-) |
spring.opencrawling.output.alfresco.target-path-prefix |
"" |
Base folder path prefix (e.g. MigratedContent/v1) |
spring.opencrawling.output.alfresco.path-strategy |
HIERARCHICAL |
Folder layout: HIERARCHICAL or FLAT |
spring.opencrawling.output.alfresco.conflict-strategy |
OVERWRITE |
Collision handling: OVERWRITE, AUTO_RENAME, or FAIL |
spring.opencrawling.output.alfresco.sync-permissions |
true |
Replicate Zero-Trust ACLs to target node permissions |
spring.opencrawling.output.alfresco.default-permission-role |
Consumer |
Fallback role when access level is unspecified |
spring.opencrawling.output.alfresco.tombstone-action |
MOVE_TO_TRASH |
Delete lifecycle: MOVE_TO_TRASH or PERMANENT_DELETE |
spring.opencrawling.output.alfresco.validate-authorities |
true |
Enable authority existence validation prior to applying permissions |
spring.opencrawling.output.alfresco.authority-validation-mode |
IN_FLIGHT |
Validation timing: IN_FLIGHT, PRE_FLIGHT, BOTH, DISABLED |
spring.opencrawling.output.alfresco.missing-authority-action |
SKIP |
Action on missing authority: SKIP (omits ACE) or FAIL (aborts document) |
spring.opencrawling.output.alfresco.parallelism |
4 |
Concurrent writer threads for streaming content into Alfresco |
8. Automated Verification & Testing
The complete decoupled migration lifecycle is validated via automated test scripts in the repository:
Unit Test Suite: Run mvn test -pl oc-alfresco-output-connector to verify REST client error handling, authority audit caching, and writer consumer event processing.
Decoupled Pipeline Test: Run ./scripts/test-alfresco-migration-decoupled.sh to test containerized Alfresco ACS 26.1.0, MinIO Claim Check store, Kafka streaming, nested folder hierarchy preservation, bit-for-bit binary validation, Zero-Trust ACL checks, and Trashcan tombstones.
Ready to Power Your Alfresco Replatforming?
Explore the Alfresco Output Connector in our live interactive simulator, consult the detailed documentation on our Wiki, or clone the repository on GitHub.