Repository navigation
Alfresco Content Services Output Connector
The oc-alfresco-output-connector module migrates enterprise content bit-for-bit from legacy ECM repositories or cloud stores into Alfresco Content Services (ACS) (Community Edition 26.1.0+ or Enterprise). It operates strictly in Migration Mode (opencrawling.pipeline.mode=migration).
While AI and vector output connectors (pgvector, OpenSearch, Solr, Qdrant, Vespa, Luxir) chunk, narrativize, and embed document text for semantic search and LLM context windows, the Alfresco output connector streams raw binary content directly from the Claim Check Store (MinIO / S3 / Local filesystem), reproduces hierarchical folder structures (cm:folder), synchronizes Zero-Trust Access Control Lists (ACLs) with target authorities, updates metadata properties and aspects (cm:versionable, cm:titled), and handles Open Ingestion Standard (OIS) document lifecycle tombstones (such as MOVE_TO_TRASH into the Alfresco Trashcan).
| Dimension |
rag Mode (Default) |
migration Mode |
|---|---|---|
| Primary Purpose | Semantic search, RAG, knowledge retrieval | As-is content migration, repository replatforming, ECM consolidation |
| Document Processing | Tika parsing → chunking → embedding generation | None: original binary is streamed bit-for-bit via Virtual Threads |
| Output Target | Vector databases / search engines | Alfresco Content Services REST API v1 (/nodes) |
| Storage Payload | Text chunks + dense vectors | Raw binary stream (cm:content) + metadata properties + aspects |
| Security & ACLs | Vector metadata payload filters | Target Alfresco permissions (locallySet ACEs on /permissions) |
| Search Engine (Solr) | Active indexing required | Bypassed / noindex by default (direct DB repository writes) |
-
Global Default: Configured via
opencrawling.pipeline.mode(ragormigration, defaultrag). -
Per-Job Override:
JobDTO.pipelineModeallows setting the mode per individual crawl/migration job. -
Fail-Fast Guardrail: Attempting to run a job targeting the Alfresco output connector in
ragmode is rejected immediately with HTTP409 Conflict:IllegalStateException: AlfrescoOutputConnector only supports MIGRATION mode (opencrawling.pipeline.mode=migration). Current mode is RAG. AI narrativization and vector embeddings are not supported by this connector.
| Client / Interface | Configuration |
|---|---|
| CLI |
oc job start --name <name> --connector <conn> --path <path> --mode migrationoc job create --file job.json --mode migration
|
| Admin UI | Select Migration in the Pipeline Mode radio group. Choosing the Alfresco output connector automatically configures Migration Mode. |
| Java Client SDK | JobRequest.builder().pipelineMode("migration").build() |
| REST API | Include "pipelineMode": "migration" in the job payload (POST /api/jobs). |
flowchart LR
R["Repository Connector<br/>(FileNet, SharePoint, CMIS, FS)"] --> C["oc-crawler-service<br/>(parallel lanes)"]
C -- "1. upload binary" --> CC[("Claim Check Store<br/>(S3 / MinIO / Local)")]
C -- "2. publish reference" --> K[["Kafka Topic<br/>opencrawling-documents"]]
K -- "3. consume<br/>opencrawling-alfresco-migration-group" --> W["AlfrescoMigrationWriterConsumer"]
W -- "4. stream binary" --> CC
W -- "5. REST v1: folder + binary + ACLs" --> ACS[("Target Alfresco ACS<br/>(REST API v1)")]
W -- "6. log missing authorities" --> GAP[("Authority Gap Ledger<br/>(JSON Audit Report)")]
| Component | Class / Identification | Description |
|---|---|---|
| Output Connector | org.opencrawling.alfresco.output.AlfrescoOutputConnector |
Core connector managing node resolution, binary streaming, versioning, and tombstone lifecycle actions. |
| Decoupled Writer | org.opencrawling.alfresco.output.messaging.AlfrescoMigrationWriterConsumer |
Decoupled Kafka listener on opencrawling-documents under consumer group opencrawling-alfresco-migration-group. |
| REST Client | org.opencrawling.alfresco.output.client.AlfrescoRestClient |
JDK 25 HTTP client communicating with Alfresco REST API v1 (/nodes, /people, /groups, /deleted-nodes, /probes). |
| Authority Validator | org.opencrawling.alfresco.output.security.AlfrescoAuthorityValidator |
Validates target users and groups using Java 25 Structured Concurrency (StructuredTaskScope), maintaining an in-memory cache and exporting audit ledgers. |
| Configuration | org.opencrawling.alfresco.output.config.AlfrescoOutputProperties |
Strongly-typed Spring @ConfigurationProperties(prefix = "spring.opencrawling.output.alfresco"). |
When documents are ingested into target Alfresco, paths are mapped according to pathStrategy:
Company Home (or targetParentNodeId, e.g. -root-)
└── <targetPathPrefix> (e.g. MigratedContent/v1)
├── <subfolder-1>/ <-- cm:folder
│ └── <subfolder-2>/ <-- cm:folder
│ └── document.pdf <-- cm:content
└── root-document.docx <-- cm:content
-
HIERARCHICAL(Default):- Reads
relativePathorrelative_pathmetadata emitted by the source repository connector (e.g.FileSystemRepositoryConnector,FileNetRepositoryConnector,SharePointRepositoryConnector). - Automatically provisions missing parent folders (
cm:folder) along the path usingPOST /nodes/{parentId}/children. - Caches resolved folder node UUIDs to eliminate redundant REST round-trips.
- Reads
-
FLAT:- Ingests all documents directly into the base target folder defined by
targetParentNodeIdandtargetPathPrefix.
- Ingests all documents directly into the base target folder defined by
When a document with the same name already exists in the target folder:
| Strategy | Behavior |
|---|---|
OVERWRITE (Default) |
Updates the existing node in-place via PUT /nodes/{nodeId}/content and updates properties via PUT /nodes/{nodeId}. Alfresco increments the version (cm:versionable). |
AUTO_RENAME |
Appends a timestamp suffix to the filename before creating a new node (e.g. contract_20261102_153000.pdf). |
FAIL |
Aborts ingestion of the duplicate document and logs a conflict warning in the migration ledger. |
The connector translates Open Ingestion Standard (OIS) permission rules into native Alfresco Access Control Entries (locallySet on POST /nodes/{nodeId}/permissions).
| OIS Access Level | Target Alfresco Role |
|---|---|
read |
Consumer |
write |
Contributor (or Editor) |
delete |
Collaborator |
admin / full_control
|
Coordinator |
| (unmapped) | Configurable via defaultPermissionRole (default Consumer) |
The validator automatically recognizes and preserves standard Alfresco built-in authorities without hitting REST endpoints:
-
GROUP_EVERYONE,EVERYONE GUEST-
ROLE_ANONYMOUS,ROLE_AUTHENTICATED,ROLE_ADMINISTRATOR,ADMIN
In enterprise migrations, source repositories frequently contain orphaned users or deprecated groups that do not exist in the target Alfresco LDAP/Active Directory sync. If unhandled, Alfresco rejects permission payloads with HTTP 400 Bad Request or 404 Not Found.
The connector provides configurable authority validation modes:
Validation Mode (authorityValidationMode) |
Behavior |
|---|---|
IN_FLIGHT (Default) |
Checks authorities during document ingestion. Results are cached in a thread-safe ConcurrentHashMap. Valid authorities are applied; missing authorities are skipped (or failed based on missingAuthorityAction). |
PRE_FLIGHT |
Executes a parallel pre-crawl audit across all distinct authorities using Java 25 StructuredTaskScope. Produces an early gap report before content ingestion begins. |
BOTH |
Executes pre-flight batch audit and verifies dynamic in-flight additions. |
DISABLED |
Directly submits permissions without pre-validation. |
When an authority is missing from target Alfresco:
- If
missingAuthorityAction=SKIP: The missing authority is omitted from the document's permission list so valid permissions are successfully applied, and the gap is recorded. - If
missingAuthorityAction=FAIL: Ingestion of the affected document is aborted with an error.
All omitted or missing authorities are exported to a structured Gap Ledger Report:
{
"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"
}
]
}The connector natively supports Open Ingestion Standard (OIS) lifecycle actions:
-
UPSERT: Downloads binary from Claim Check store, provisions folders, creates/updatescm:contentnode, sets properties and Zero-Trust ACLs. -
DELETE: Resolves target node UUID and executes lifecycle action configured bytombstoneAction:-
MOVE_TO_TRASH(Default): CallsDELETE /nodes/{nodeId}?permanent=false. Moves the item to the Alfresco Trashcan, preserving audit trails and enabling accidental deletion recovery. -
PERMANENT_DELETE: CallsDELETE /nodes/{nodeId}?permanent=true. Purges the node from PostgreSQL and content store immediately.
-
The migration stack is defined in oc-alfresco-output-connector/docker/docker-compose-decoupled-with-alfresco.yml.
In Migration Mode, OpenCrawling exclusively uses direct repository REST endpoints against Alfresco's database (PostgreSQL). No search queries are executed during ingestion.
-
-Dindex.subsystem.name=${ALFRESCO_INDEX_SUBSYSTEM:-noindex}defaults tonoindex. -
Zero Log Spam: Eliminates
UnknownHostException: solr6and connection retry warnings. - Fast Startup: Alfresco container boots in ~25–30s instead of ~90s.
- Resource Efficient: Saves ~2 GB RAM and reduces CPU load during bulk migration.
If search indexing and AFTS queries are needed on the target Alfresco instance, a preconfigured solr6 container is available under Docker Compose profiles ["search", "solr"]:
# Set index subsystem to solr6
export ALFRESCO_INDEX_SUBSYSTEM=solr6
# Start stack with search profile enabled
docker compose -f oc-alfresco-output-connector/docker/docker-compose-decoupled-with-alfresco.yml --profile search up -dspring:
opencrawling:
output:
type: alfresco
alfresco:
enabled: true
url: http://localhost:8081/alfresco
username: admin
password: admin
auth-type: basic # basic | bearer
bearer-token: ""
target-parent-node-id: -root- # -root- | -my- | -shared- | <node-uuid>
target-path-prefix: MigratedContent/v1
path-strategy: HIERARCHICAL # HIERARCHICAL | FLAT
node-type: cm:content
aspects:
- cm:versionable
- cm:titled
conflict-strategy: OVERWRITE # OVERWRITE | AUTO_RENAME | FAIL
sync-permissions: true
default-permission-role: Consumer # Consumer | Contributor | Editor | Collaborator | Coordinator
inheritance-enabled: true
tombstone-action: MOVE_TO_TRASH # MOVE_TO_TRASH | PERMANENT_DELETE
validate-authorities: true
authority-validation-mode: IN_FLIGHT # IN_FLIGHT | PRE_FLIGHT | BOTH | DISABLED
missing-authority-action: SKIP # SKIP | FAIL
authority-gap-report-path: reports/alfresco-authority-gap.json
timeout-seconds: 60
parallelism: 4
opencrawling:
pipeline:
mode: migration # Required for Alfresco output connector| Property | Default | Description |
|---|---|---|
spring.opencrawling.output.alfresco.enabled |
true |
Enables the Alfresco output connector bean. |
spring.opencrawling.output.alfresco.url |
http://localhost:8081/alfresco |
Base REST API URL of target Alfresco instance. |
spring.opencrawling.output.alfresco.username |
admin |
Username for Basic authentication. |
spring.opencrawling.output.alfresco.password |
admin |
Password for Basic authentication. |
spring.opencrawling.output.alfresco.auth-type |
basic |
Authentication mechanism: basic or bearer. |
spring.opencrawling.output.alfresco.bearer-token |
"" |
JWT / Bearer token if auth-type=bearer. |
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 |
"" |
Root folder path prefix under parent node (e.g. MigratedContent/v1). |
spring.opencrawling.output.alfresco.path-strategy |
HIERARCHICAL |
Path layout: HIERARCHICAL (subfolders preserved) or FLAT. |
spring.opencrawling.output.alfresco.node-type |
cm:content |
Alfresco content type for uploaded documents. |
spring.opencrawling.output.alfresco.aspects |
["cm:versionable", "cm:titled"] |
List of Alfresco aspects applied to created nodes. |
spring.opencrawling.output.alfresco.conflict-strategy |
OVERWRITE |
Duplicate handling: OVERWRITE (version bump), AUTO_RENAME, or FAIL. |
spring.opencrawling.output.alfresco.sync-permissions |
true |
Replicate Zero-Trust ACL permissions to target node. |
spring.opencrawling.output.alfresco.default-permission-role |
Consumer |
Target role when source access level is unmapped. |
spring.opencrawling.output.alfresco.inheritance-enabled |
true |
Sets isInheritanceEnabled flag on target node ACL. |
spring.opencrawling.output.alfresco.tombstone-action |
MOVE_TO_TRASH |
Deletion lifecycle: MOVE_TO_TRASH (recoverable) or PERMANENT_DELETE. |
spring.opencrawling.output.alfresco.validate-authorities |
true |
Toggles authority existence validation before applying ACEs. |
spring.opencrawling.output.alfresco.authority-validation-mode |
IN_FLIGHT |
Validation timing: IN_FLIGHT, PRE_FLIGHT, BOTH, or DISABLED. |
spring.opencrawling.output.alfresco.missing-authority-action |
SKIP |
Behavior when authority is absent: SKIP (omits ACE) or FAIL (aborts doc). |
spring.opencrawling.output.alfresco.authority-gap-report-path |
reports/alfresco-authority-gap.json |
Path where missing authority gap ledger report is exported. |
spring.opencrawling.output.alfresco.timeout-seconds |
60 |
HTTP client request timeout in seconds. |
spring.opencrawling.output.alfresco.parallelism |
4 |
Concurrency worker threads for writing into Alfresco. |
In the OpenCrawling Admin UI:
- Output Connectors Catalog: Appears as Alfresco Content Services (Migration Mode only).
-
Connection Checker: Validates endpoint connectivity by probing
/alfresco/api/-default-/public/alfresco/versions/1/probes/-ready-. Distinguishes between HTML responses (such as OpenCrawling Admin UI on port 8080) and true Alfresco REST JSON responses on port 8081, providing clear diagnostic guidance. - Automatic Migration Guardrail: Selecting Alfresco Output automatically configures the job for Migration Mode.
Execute the dedicated unit suite verifying node resolution, authority auditing, and Kafka consumer processing:
mvn test -pl oc-alfresco-output-connectorThe repository includes a decoupled integration test script:
# Run end-to-end integration test
./scripts/test-alfresco-migration-decoupled.sh
# Skip Docker image build if already compiled:
SKIP_BUILD=true ./scripts/test-alfresco-migration-decoupled.shVerifications performed by the test suite:
-
Migration Mode RAG Bypass: Asserts that
vector_storetables in PostgreSQL contain 0 records (text parsing and embeddings were completely bypassed). -
Binary Content Integrity: Downloads the migrated binary from target Alfresco (
GET /nodes/{id}/content) and verifies exact bit-for-bit content match. -
Hierarchical Folder Path Preservation: Confirms that nested subfolder documents (e.g.
subfolder/subfolder-spec.txt) are created undercm:foldernodes matching source directory hierarchies. -
Metadata & Aspects Synchronization: Asserts
cm:contentnode type and checkscm:versionableandcm:titledaspects. -
OIS Document Lifecycle Tombstone: Verifies that a
DELETEtombstone moves the document into the Alfresco Trashcan (GET /deleted-nodes/{id}returns HTTP 200).
- Home
- User & Installation Guide
- Quick Start
- VM & Bare-Metal Distribution Installation
- Local Development & Fast Docker Builds
- User Guide
- Architecture
- Zero-Trust Security & ACL Management
- Document Authorization & OpenFGA
- Document Lifecycle Actions & Tombstones
- Apache Tika 4 Text Extraction
- Configuration Guide
- Connectors Reference
- Alfresco Content Services (ACS) Connector
- Alfresco Process Services (APS) Connector
- Flowable Repository Connector
- Camunda Repository Connector
- OASIS CMIS Repository Connector
- Doxis Repository Connector
- M-Files Repository Connector
- SharePoint Online Repository Connector
- IBM FileNet P8 Repository Connector
- OpenText Documentum Repository Connector
- Hyland OpenArch Integration (Repository, Output & MCP)
- Relational Database (JDBC) Connector
- Apache StormCrawler Repository Connector
- gRPC Push Repository Connector
- Apache Solr Output Connector
- Luxir Output Connector
- Apache SeaTunnel Output Connector
- Apache Ozone Output Connector (Migration Mode)
- AWS S3 Output Connector (Migration Mode)
- Alfresco Content Services Output Connector (Migration Mode)
- Connector Execution Modes
- Model Context Protocol
- Apache Ozone Claim Check Store
- Lakehouse Audit Reporting & Ledger
- AI-Powered Observability (AIOps)
- Auto-Narrativization Copilot
- Maven Connector Archetypes
- Java Client SDK
- OpenCrawling CLI
- OpenAPI Specification & Swagger UI
- gRPC Internal Transport
- Migration Guide (ManifoldCF)
- Integration Test — Decoupled Pipeline
- M-Files Integration Test
- SharePoint Online Integration Test
- IBM FileNet Integration Test
- OpenText Documentum Integration Test
- Hyland OpenArch Integration Test
- Local Docker Build Test
- Root CLI Runner Scripts Test
- Secure MCP Server Integration Test
- Narrativization Integration Test
- Reporting Integration Test
- AWS S3 Migration Integration Test
- Alfresco Migration Integration Test
- OpenFGA Authorization Integration Test