Connectors - opencrawling/opencrawling GitHub Wiki

Connectors Reference

OpenCrawling is built around a connector-based architecture. Every step of the pipeline — ingesting content from a source, transforming it via embeddings, and writing it to a destination — is handled by a dedicated connector implementing a well-defined Java interface.


Connector Types

Type Interface Role
Repository Connector RepositoryConnector Scans a content source and emits RepositoryDocument objects as a reactive Flux stream
Output Connector OutputConnector Receives a RepositoryDocument and writes it directly to a destination (sync/direct mode)
Transformation Connector Configured via Admin UI Selects the embedding engine (Ollama, OpenAI, etc.) for the oc-embedding-service

Core Interfaces

RepositoryConnector (in oc-core):

public non-sealed interface RepositoryConnector extends Connector {
    Flux<RepositoryDocument> scan(String basePath);
}

OutputConnector (in oc-core):

public non-sealed interface OutputConnector extends Connector {
    Mono<Void> send(RepositoryDocument document);
}

Both extend Connector which provides getName(), connect(), and disconnect() lifecycle methods.


Repository Connectors

Repository connectors are responsible for discovering and streaming documents from content sources into the pipeline.


📁 FileSystem Repository Connector

Filesystem

Module: oc-filesystem-repository-connector
Class: FileSystemRepositoryConnector
Spring Bean: @Primary — selected by default when no other connector is specified

Description

Recursively scans a local filesystem directory using Java NIO and emits each regular file as a RepositoryDocument. Subdirectory traversal is parallelised using Java 25 Structured Task Scope for high-throughput I/O on deep directory trees.

Configuration

No external configuration properties are required. The path is provided at runtime via the scan(String basePath) call (e.g., from the Admin UI job form or the crawler SCAN_PATH environment variable).

Metadata extracted per document

Metadata key Value
extension File extension (e.g. pdf, txt, docx)
uri file:// URI of the absolute path

Connector type selection

Set the connector type to filesystem in the Admin UI or via the environment variable:

# docker-compose-decoupled.yml
environment:
  CONNECTOR_TYPE: filesystem
  SCAN_PATH: /data

Notes

  • Files are streamed; content is not loaded into memory until processed.
  • The uri is a file:// URI (e.g. file:///data/report.pdf), so no Claim Check Pattern is used — the IngestionConsumer reads directly from the local filesystem path.

🏢 Alfresco Content Services (ACS) Repository Connector

Alfresco Java Spring Boot OIS Compliance

Module: oc-alfresco-repository-connector
Class: AlfrescoRepositoryConnector
Security Mapper: AlfrescoSecurityMapper
Spring Bean: @Component (activated when CONNECTOR_TYPE=alfresco or spring.opencrawling.connector.type=alfresco)
Dedicated Guide: Alfresco Content Services (ACS) Connector

Description

Connects to an Alfresco Content Services (Community or Enterprise) instance via the native Alfresco Core REST API v1 and Alfresco Search REST API v1. Supports dual-mode ingestion:

  1. Hierarchical Folder Tree Traversal: Scans from root (-root-), a specific folder path (e.g. /Company Home/Sites), a Node UUID, or a site document library (siteId), with options to toggle subfolder recursion (includeSubfolders) and exclude specific folders (excludedFolders).
  2. Search API Query Ingestion: Executes declarative AFTS (Alfresco Full Text Search), CMIS SQL, or Lucene queries against /public/search/versions/1/search.

Features zero-trust ACL mapping via AlfrescoSecurityMapper (extracting inherited and locally set permissions for users and GROUP_* authorities), binary content stream size thresholds (maxContentSizeBytes), and metadata-only indexing (includeContentStream=false).

Configuration Properties

Property key Spring property Environment variable Default Description
url spring.opencrawling.connector.alfresco.url ALFRESCO_URL http://localhost:8080/alfresco/api/-default-/public/alfresco/versions/1 Base URL of the Alfresco REST API
username spring.opencrawling.connector.alfresco.username ALFRESCO_USERNAME admin Alfresco username
password spring.opencrawling.connector.alfresco.password ALFRESCO_PASSWORD admin Alfresco password (Basic Auth)
batchSize spring.opencrawling.connector.alfresco.batch-size ALFRESCO_BATCH_SIZE 100 Number of items fetched per API page
crawlMode spring.opencrawling.connector.alfresco.crawl-mode ALFRESCO_CRAWL_MODE folder Ingestion mode: folder or query
queryLanguage spring.opencrawling.connector.alfresco.query-language ALFRESCO_QUERY_LANGUAGE afts Query language: afts, cmis, or lucene
searchQuery spring.opencrawling.connector.alfresco.search-query ALFRESCO_SEARCH_QUERY TYPE:'cm:content' Default query for query crawl mode
rootFolderPath spring.opencrawling.connector.alfresco.root-folder-path ALFRESCO_ROOT_FOLDER_PATH / Default folder path to scan
rootFolderId spring.opencrawling.connector.alfresco.root-folder-id ALFRESCO_ROOT_FOLDER_ID "" Optional starting node UUID
siteId spring.opencrawling.connector.alfresco.site-id ALFRESCO_SITE_ID "" Optional Site ID (auto-targets documentLibrary)
includeSubfolders spring.opencrawling.connector.alfresco.include-subfolders ALFRESCO_INCLUDE_SUBFOLDERS true Recursively traverse child folders
excludedFolders spring.opencrawling.connector.alfresco.excluded-folders ALFRESCO_EXCLUDED_FOLDERS Data Dictionary Comma-separated folder names/paths to skip
includeAcls spring.opencrawling.connector.alfresco.include-acls ALFRESCO_INCLUDE_ACLS true Extract ACE permissions and zero-trust ACLs
includeContentStream spring.opencrawling.connector.alfresco.include-content-stream ALFRESCO_INCLUDE_CONTENT_STREAM true Download binary payload for text extraction
maxContentSizeBytes spring.opencrawling.connector.alfresco.max-content-size-bytes ALFRESCO_MAX_CONTENT_SIZE_BYTES 52428800 Max payload size in bytes (50 MB)
mimeTypeFilter spring.opencrawling.connector.alfresco.mimetype-filter ALFRESCO_MIMETYPE_FILTER "" Comma-separated MIME whitelist (e.g. application/pdf)

Docker Compose example

oc-crawler:
  environment:
    CONNECTOR_TYPE: alfresco
    SCAN_PATH: /Company Home
    ALFRESCO_URL: http://alfresco:8080/alfresco/api/-default-/public/alfresco/versions/1
    ALFRESCO_USERNAME: admin
    ALFRESCO_PASSWORD: admin
    ALFRESCO_CRAWL_MODE: folder
    ALFRESCO_INCLUDE_SUBFOLDERS: "true"
    ALFRESCO_INCLUDE_ACLS: "true"

SCAN_PATH formats

Format Behaviour
(empty) or -root- Scans from the Alfresco repository root
/Company Home/Sites/my-site Scans using a relative path from root
a1b2c3d4-... (UUID) Scans a specific node by its Alfresco Node ID
TYPE:'cm:content' AND PATH:'/app:company_home//*' Executes AFTS query via Search REST API
SELECT * FROM cmis:document WHERE cmis:name LIKE 'Invoice%' Executes CMIS SQL query via Search REST API

Metadata extracted per document

Metadata key Value source
name entry.name from the API response
nodeType entry.nodeType (e.g. cm:content)
mimeType entry.content.mimeType
sizeInBytes entry.content.sizeInBytes
alfresco_node_id Alfresco node UUID
alfresco_parent_id Parent folder UUID
alfresco_aspects Attached aspect names
alfresco_identity_users Comma-separated authorized reader users
alfresco_identity_groups Comma-separated authorized reader groups
alfresco_is_inherited Boolean flag for permission inheritance
cm:title, cm:description, etc. All Alfresco cm:* properties returned via ?include=properties

Claim Check Pattern

Because Alfresco documents are fetched from a remote HTTP server, the connector downloads the content stream and saves it to a local shared directory (/data/claims/) before publishing the reference to Kafka. This decouples the slow HTTP download from the fast Kafka publish step.

Note

The shared /data directory must be volume-mounted and accessible by both the crawler and the consumer containers in the decoupled deployment.

PGVector verification queries

After a crawl job completes, verify ingestion with:

-- Total chunks stored for Alfresco documents
SELECT count(*) FROM vector_store_1024;

-- Inspect content and source URI of stored chunks
SELECT id,
       LEFT(content, 200)     AS preview,
       metadata->>'name'      AS filename,
       metadata->>'mimeType'  AS mime_type,
       metadata->>'uri'       AS source_uri
FROM vector_store_1024
ORDER BY id
LIMIT 10;

-- Semantic similarity search
SELECT id,
       LEFT(content, 300)    AS preview,
       metadata->>'name'     AS filename,
       1 - (embedding <=> (
           SELECT embedding FROM vector_store_1024 LIMIT 1
       ))                    AS similarity
FROM vector_store_1024
ORDER BY similarity DESC
LIMIT 5;

🧊 Apache Iceberg Repository Connector

Apache Iceberg

Module: oc-iceberg-repository-connector
Class: IcebergRepositoryConnector
Spring Bean: @Component (activated when CONNECTOR_TYPE=iceberg)

Description

Connects to an Apache Iceberg table catalog and scans structured data tables, emitting each Iceberg Record as a JSON-serialized RepositoryDocument. Supports REST, Hive Metastore, Hadoop, AWS Glue, and in-memory catalog backends. File scan tasks are parallelized using Java 25 Structured Task Scope for high-throughput Parquet file reading.

Each record is serialized to JSON and treated as a document, making Iceberg data lakes a first-class ingestion source for RAG pipelines. This connector reads Parquet data files directly from the catalog's underlying storage (local FS, S3, GCS, ADLS, etc.).

Configuration Properties (Admin UI / connectors.json)

Property key Default Description
catalogType in-memory Catalog backend type: rest, hive, hadoop, glue, or in-memory
catalogUri (empty) URI of the catalog server (required for rest and hive types)
warehouse tmp/iceberg-warehouse Warehouse root path (local path, s3://, gs://, abfs://, etc.)
idColumn (empty) Optional column name to use as the document ID. Falls back to Iceberg identifier fields, then SHA-256 of JSON content

Catalog Types

catalogType Implementation Required catalogUri
rest RESTCatalog REST catalog server URL (e.g. http://localhost:8181)
hive HiveCatalog Hive Metastore Thrift URI (e.g. thrift://hive:9083)
hadoop HadoopCatalog Not required — uses warehouse path directly
glue GlueCatalog (via reflection) Not required — uses AWS SDK credentials chain
in-memory InMemoryCatalog Not required — ephemeral, for testing only

🔄 Flowable Repository Connector

Flowable

Module: oc-flowable-repository-connector
Class: FlowableRepositoryConnector
Security Mapper: FlowableSecurityMapper
Spring Bean: @Component (activated when CONNECTOR_TYPE=flowable or spring.opencrawling.connector.type=flowable)
Dedicated Guide: Flowable Repository Connector

Description

Connects to a Flowable BPMN Engine REST service (/history/historic-process-instances) to crawl completed and active historic workflow executions, structure process details, extract BPMN variables (/history/historic-variable-instances), and resolve runtime/historic identity links (/history/historic-process-instances/{id}/identitylinks).

Process instances are emitted as standard RepositoryDocument instances containing structured JSON summaries (definition key, business key, start/end timestamps, duration, and user ID), entity reference links, and fine-grained SecurityConfig permissions.

The connector supports two zero-trust architectural models:

  1. Collocated DB Pattern (pgvector on Flowable PostgreSQL): Entity references (flowable_proc_inst_id, flowable_scope_id, flowable_scope_type) are stamped to allow query-time SQL EXISTS subqueries against native ACT_RU_IDENTITYLINK and ACT_HI_IDENTITYLINK tables, eliminating distributed transaction lag without chunk-level row multiplication.
  2. Distributed DB Pattern (External Vector DBs): Extracts user and candidate group identity links into standard OIS security_allowed_read metadata fields for pre-filtering in Qdrant, Milvus, OpenSearch, and Vespa.

Batch scanning and variable resolution are parallelized using Java 25 Structured Task Scope and Virtual Threads (Thread.ofVirtual()).

Configuration Properties (Admin UI / connectors.json)

Property key Spring Property Key Default Description
url spring.opencrawling.connector.flowable.url http://localhost:8080/flowable-rest/service Flowable REST API endpoint
username spring.opencrawling.connector.flowable.username admin Basic auth username
password spring.opencrawling.connector.flowable.password test Basic auth password
batchSize spring.opencrawling.connector.flowable.batch-size 100 Number of process instances per page
processDefinitionKey spring.opencrawling.connector.flowable.process-definition-key "" Optional process definition key filter
includeVariables spring.opencrawling.connector.flowable.include-variables true Extract historic BPMN process variables
includeAcls spring.opencrawling.connector.flowable.include-acls true Extract identity links and map to SecurityConfig
scope spring.opencrawling.connector.flowable.scope all Filter by state: all, completed, or active

SCAN_PATH format

Format Behaviour
(empty) or / Scans all historic process instances
invoice-process Scans process instances matching process definition key invoice-process

Metadata extracted per process instance

Metadata key Description
processDefinitionId Flowable Process Definition ID (e.g. invoice-process:2:98765)
processDefinitionKey Flowable Process Definition Key (e.g. invoice-process)
businessKey Workflow business key (e.g. INV-2026-001)
startUserId User ID that started the process instance
startTime Workflow execution start timestamp
endTime Workflow completion timestamp
durationInMillis Workflow execution duration in milliseconds
flowable_proc_inst_id Flowable Process Instance ID for collocated entity linking
flowable_scope_id Flowable Scope ID (processInstanceId)
flowable_scope_type Flowable Scope Type ("processInstance")
flowable_identity_users List of authorized user IDs resolved from identity links
flowable_identity_groups List of authorized candidate group IDs resolved from identity links
flowable_var_<varName> Dynamically mapped historical BPMN process variable value

Repository Document Structure Example

{
  "id": "proc-1234",
  "uri": "flowable://process-instances/proc-1234",
  "action": "UPSERT",
  "metadata": {
    "mimeType": ["application/json"],
    "processDefinitionId": ["invoice-process:2:98765"],
    "processDefinitionKey": ["invoice-process"],
    "businessKey": ["INV-2026-001"],
    "startUserId": ["finance_agent_1"],
    "startTime": ["2026-07-23T08:00:00Z"],
    "endTime": ["2026-07-23T08:15:00Z"],
    "durationInMillis": ["900000"],
    "flowable_proc_inst_id": ["proc-1234"],
    "flowable_process_instance_id": ["proc-1234"],
    "flowable_scope_id": ["proc-1234"],
    "flowable_scope_type": ["processInstance"],
    "flowable_identity_users": ["finance_agent_1"],
    "flowable_identity_groups": ["finance_managers"],
    "flowable_var_totalAmount": ["250.50"],
    "flowable_var_customerName": ["ACME Corp"]
  },
  "security": {
    "inheritanceEnabled": false,
    "permissions": [
      {"identity": "finance_agent_1", "identityType": "user", "access": "read"},
      {"identity": "finance_managers", "identityType": "group", "access": "read"}
    ]
  }
}

⚡ Camunda Repository Connector

Camunda

Module: oc-camunda-repository-connector
Class: CamundaRepositoryConnector
Security Mapper: CamundaSecurityMapper
Spring Bean: @Component (activated when CONNECTOR_TYPE=camunda or spring.opencrawling.connector.type=camunda)
Dedicated Guide: Camunda Repository Connector

Description

Connects to a Camunda Platform 7 REST Engine (/engine-rest/history/process-instance) to crawl historic workflow executions, process instance details, historical BPMN process variables (/history/variable-instance), and historic identity link authorizations (/history/identity-link-log).

Process instances are emitted as standard RepositoryDocument instances containing structured JSON summaries (definition key, business key, start/end timestamps, duration, and start user ID), entity reference links, and fine-grained SecurityConfig permissions.

The connector supports two zero-trust architectural models:

  1. Collocated DB Pattern (pgvector on Camunda PostgreSQL): Entity references (camunda_proc_inst_id, camunda_scope_id, camunda_scope_type) are stamped to allow query-time SQL EXISTS subqueries against native ACT_RU_IDENTITYLINK and ACT_HI_IDENTITYLINK tables, eliminating distributed transaction lag without chunk-level row multiplication.
  2. Distributed DB Pattern (External Vector DBs): Extracts user and candidate group identity links into standard OIS security_allowed_read metadata fields for pre-filtering in Qdrant, Milvus, OpenSearch, and Vespa.

Batch scanning and variable resolution are parallelized using Java 25 Structured Task Scope and Virtual Threads (Thread.ofVirtual()).

Configuration Properties (Admin UI / connectors.json)

Property key Spring Property Key Default Description
url spring.opencrawling.connector.camunda.url http://localhost:8080/engine-rest Camunda REST API endpoint
username spring.opencrawling.connector.camunda.username demo Basic auth username
password spring.opencrawling.connector.camunda.password demo Basic auth password
batchSize spring.opencrawling.connector.camunda.batch-size 100 Number of process instances per page
processDefinitionKey spring.opencrawling.connector.camunda.process-definition-key "" Optional process definition key filter
includeVariables spring.opencrawling.connector.camunda.include-variables true Extract historic BPMN process variables
includeAcls spring.opencrawling.connector.camunda.include-acls true Extract identity links and map to SecurityConfig
scope spring.opencrawling.connector.camunda.scope all Filter by state: all, completed, or active

SCAN_PATH format

Format Behaviour
(empty) or / Scans all historic process instances
order-process Scans process instances matching process definition key order-process

Metadata extracted per process instance

Metadata key Description
processDefinitionId Camunda Process Definition ID (e.g. order-process:1:1001)
processDefinitionKey Camunda Process Definition Key (e.g. order-process)
businessKey Workflow business key (e.g. ORD-2026-999)
startUserId User ID that started the process instance
startTime Workflow execution start timestamp
endTime Workflow completion timestamp
durationInMillis Workflow execution duration in milliseconds
tenantId Multi-tenant identifier (if applicable)
camunda_proc_inst_id Native Process Instance ID for collocated DB joins
camunda_scope_id Engine scope identifier for entity-level authorization
camunda_scope_type Scope type identifier (processInstance)
camunda_identity_users List of allowed user identities
camunda_identity_groups List of allowed group identities
camunda_var_<varName> Dynamically mapped historical BPMN process variable value

Repository Document Structure Example

{
  "id": "proc-9988",
  "uri": "camunda://process-instances/proc-9988",
  "action": "UPSERT",
  "metadata": {
    "mimeType": ["application/json"],
    "processDefinitionId": ["order-process:1:1001"],
    "processDefinitionKey": ["order-process"],
    "businessKey": ["ORD-2026-999"],
    "startUserId": ["sales_rep_42"],
    "startTime": ["2026-07-24T10:00:00Z"],
    "endTime": ["2026-07-24T10:05:00Z"],
    "durationInMillis": ["300000"],
    "tenantId": ["tenant-alpha"],
    "camunda_proc_inst_id": ["proc-9988"],
    "camunda_process_instance_id": ["proc-9988"],
    "camunda_scope_id": ["proc-9988"],
    "camunda_scope_type": ["processInstance"],
    "camunda_identity_users": ["sales_rep_42", "approver_1"],
    "camunda_identity_groups": ["finance-managers"],
    "camunda_var_orderAmount": ["1500.00"],
    "camunda_var_approvalStatus": ["APPROVED"]
  },
  "security": {
    "inheritanceEnabled": false,
    "permissions": [
      {"identity": "sales_rep_42", "identityType": "user", "access": "read"},
      {"identity": "approver_1", "identityType": "user", "access": "read"},
      {"identity": "finance-managers", "identityType": "group", "access": "read"}
    ]
  }
}

SCAN_PATH format

The basePath argument to scan() is an Iceberg table identifier in the format <namespace>.<table>:

Format Example Description
namespace.table analytics.events Scans the events table in the analytics namespace
db.schema.table prod.dbo.orders Three-part identifier (catalog-specific)

Metadata extracted per document

Metadata key Value
All Iceberg record columns Included as metadata entries (column name → string value)
mimeType Always application/json
sizeInBytes Size of the JSON-serialized record in bytes
uri iceberg://<table-name>/<document-id>

The document ID is resolved in order of priority:

  1. The column specified in idColumn config property
  2. Iceberg table's declared identifier fields
  3. SHA-256 hash of the JSON record content (fallback)

Docker Compose example (with Iceberg REST Catalog + MinIO)

Use the dedicated compose file provided in the oc-iceberg-repository-connector module to spin up a local Iceberg REST catalog backed by MinIO (S3-compatible object storage):

# oc-iceberg-repository-connector/docker-compose.yml
services:
  minio:
    image: minio/minio:RELEASE.2024-05-10T01-39-19Z
    container_name: minio-iceberg
    environment:
      MINIO_ROOT_USER: admin
      MINIO_ROOT_PASSWORD: password
    ports:
      - "9000:9000"
      - "9001:9001"
    command: ["server", "/data", "--console-address", ":9001"]

  iceberg-rest:
    image: apache/iceberg-rest-fixture:1.5.0
    container_name: iceberg-rest
    ports:
      - "8181:8181"
    environment:
      - AWS_ACCESS_KEY_ID=admin
      - AWS_SECRET_ACCESS_KEY=password
      - AWS_REGION=us-east-1
      - CATALOG_WAREHOUSE=s3://warehouse/
      - CATALOG_IO__IMPL=org.apache.iceberg.aws.s3.S3FileIO
      - CATALOG_S3_ENDPOINT=http://minio:9000
      - CATALOG_S3_PATH_STYLE_ACCESS=true
    depends_on:
      - minio

Then configure the crawler to use this catalog:

oc-crawler:
  environment:
    CONNECTOR_TYPE: iceberg
    SCAN_PATH: analytics.events
    ICEBERG_CATALOG_TYPE: rest
    ICEBERG_CATALOG_URI: http://iceberg-rest:8181
    ICEBERG_WAREHOUSE: s3://warehouse/

Notes

  • The connector does not use the Claim Check Pattern — Iceberg records are serialized to JSON in-process and streamed directly as RepositoryDocument objects. No shared volume is required.
  • The uri field uses an iceberg:// scheme that identifies the source table and record ID.
  • For timestamp-based last-modified detection, the connector inspects well-known column names: last_modified, updated_at, timestamp, and date.
  • AWS Glue catalog requires the iceberg-aws dependency on the classpath and AWS credentials configured via environment variables or instance profile.

🕷️ Apache StormCrawler Repository Connector

Apache StormCrawler Apache Storm Java

Module: oc-stormcrawler-repository-connector (with oc-stormcrawler-bolt)
Class: StormCrawlerRepositoryConnector
Spring Bean: @Component (activated when CONNECTOR_TYPE=stormcrawler)
Dedicated Guide: Apache StormCrawler Repository Connector & OpenCrawling Bolt

Description

Orchestrates, monitors, and streams distributed web crawls using Apache StormCrawler 3.7.0 running on Apache Storm 3.1.0 clusters and Java 25.

The connector interacts with the Apache Storm Nimbus REST API to verify cluster health (/api/v1/cluster/summary) and manage topology states (/api/v1/topology/summary). For distributed worker processing, the accompanying OpenCrawlingBolt intercepts parsed HTML content and deletion status streams (HTTP 404/410), normalising them into Open Ingestion Standard (OIS) UPSERT and DELETE payloads dispatched to OpenCrawling.

High-throughput seed scanning and URL resolution leverage Java 25 Virtual Threads and StructuredTaskScope.

Configuration Properties (Admin UI / connectors.json)

Property key Spring Property Key Default Description
nimbusHost spring.opencrawling.connector.stormcrawler.nimbus-host localhost Apache Storm Nimbus hostname
nimbusPort spring.opencrawling.connector.stormcrawler.nimbus-port 6627 Nimbus Thrift RPC port
nimbusRestUrl spring.opencrawling.connector.stormcrawler.nimbus-rest-url http://localhost:8080 Storm UI / Nimbus REST API base URL
topologyName spring.opencrawling.connector.stormcrawler.topology-name opencrawling-web-crawler Target StormCrawler topology name
seeds spring.opencrawling.connector.stormcrawler.seeds https://docs.example.com Comma-separated seed URLs to crawl
concurrency spring.opencrawling.connector.stormcrawler.concurrency 8 Parallel virtual threads for crawl tasks
delayMs spring.opencrawling.connector.stormcrawler.delay-ms 1000 Politeness delay between requests in milliseconds
ignoreRobotsTxt spring.opencrawling.connector.stormcrawler.ignore-robots-txt false Whether to ignore robots.txt disallow directives
customUserAgent spring.opencrawling.connector.stormcrawler.custom-user-agent OpenCrawling-StormCrawler-Bot/1.0 Custom User-Agent header

Metadata extracted per crawled document

Metadata key Description
title Page <title> extracted from HTML
parse.Content-Type MIME type (e.g. text/html)
http.status HTTP response code (e.g. 200)
canonical.url Canonical URL resolved from <link rel="canonical"> or HTTP headers
content.hash Cryptographic hash (SHA-256 or MD5) for deduplication
uri URL of the crawled web page

Docker Compose Example

# docker-compose-decoupled-with-stormcrawler.yml
services:
  oc-crawler:
    environment:
      CONNECTOR_TYPE: stormcrawler
      STORMCRAWLER_NIMBUS_HOST: storm-nimbus
      STORMCRAWLER_NIMBUS_REST_URL: http://storm-ui:8080
      STORMCRAWLER_TOPOLOGY_NAME: opencrawling-web-crawler
      STORMCRAWLER_SEEDS: https://docs.opencrawling.org

💼 Alfresco Process Services (APS) Repository Connector

Alfresco Process Services Java Spring Boot OIS Compliance MCP

Module: oc-aps-repository-connector
Class: ApsRepositoryConnector (with ApsMcpClient)
Spring Bean: @Component (activated when CONNECTOR_TYPE=aps)
Dedicated Guide: Alfresco Process Services (APS) Repository Connector

Description

Connects to Alfresco Process Services (APS) 26.2 via the Enterprise REST API (/activiti-app/api/enterprise) to crawl historic and active process executions (/historic-process-instances/query), dynamically extract all process variables (/historic-process-instances/{id}/variables), and evaluate user tasks and candidate group authorizations (/tasks/query).

In addition to workflow execution metrics, the connector features Workflow Attachment Ingestion: it discovers documents and text attachments attached at the process instance level or task level (/content/{contentId}/raw), streams them into the Claim-Check store, extracts text with Apache Tika, and links them to the parent workflow with inherited variables and Zero-Trust Access Control Lists (ACLs).

The connector supports two zero-trust architectural models:

  1. Collocated DB Pattern (pgvector on APS PostgreSQL): Entity references (aps_proc_inst_id, aps_scope_id, aps_scope_type) are stamped to allow query-time SQL EXISTS subqueries against native ACT_RU_IDENTITYLINK and ACT_HI_IDENTITYLINK tables, eliminating distributed transaction lag without chunk-level row multiplication.
  2. Distributed DB Pattern (External Vector DBs): Extracts user and candidate group identity links into standard OIS security_allowed_read metadata fields for pre-filtering in Qdrant, Milvus, OpenSearch, and Vespa.

The connector also provides an ApsMcpClient to dynamically discover deployed workflow definitions and schema metadata via the Model Context Protocol (MCP). Batch processing is parallelized using Java 25 Virtual Threads and StructuredTaskScope.

Configuration Properties (Admin UI / connectors.json)

Property key Spring Property Key Default Description
url spring.opencrawling.connector.aps.url http://localhost:8080/activiti-app/api/enterprise Base URL of the APS Enterprise REST API
username spring.opencrawling.connector.aps.username [email protected] APS Basic Auth username
password spring.opencrawling.connector.aps.password admin APS Basic Auth password
batchSize spring.opencrawling.connector.aps.batch-size 100 Process instance page batch size
processDefinitionKey spring.opencrawling.connector.aps.process-definition-key "" Optional process definition key filter
includeVariables spring.opencrawling.connector.aps.include-variables true Ingest process instance variables
includeTasks spring.opencrawling.connector.aps.include-tasks true Ingest user tasks
includeAttachments spring.opencrawling.connector.aps.include-attachments true Ingest workflow attachments & documents
includeAcls spring.opencrawling.connector.aps.include-acls true Extract task assignees and candidate groups into SecurityConfig
tenantId spring.opencrawling.connector.aps.tenant-id "" Optional tenant ID for multi-tenant APS
scope spring.opencrawling.connector.aps.scope all Filter by state: all, active, or completed
mcpEnabled spring.opencrawling.connector.aps.mcp.enabled false Enable dynamic workflow discovery via APS MCP Server
mcpUrl spring.opencrawling.connector.aps.mcp.url "" Optional endpoint URL for the APS MCP Server

SCAN_PATH format

Format Behaviour
(empty) or / Scans all process instances matching configured criteria
invoiceApproval Scans process instances matching process definition key invoiceApproval

Metadata extracted per process instance

Metadata key Description
processDefinitionId Process definition unique ID (e.g. invoiceApproval:2:89201)
processDefinitionKey Process definition key (e.g. invoiceApproval)
processDefinitionName Human-readable workflow name (e.g. Invoice Approval Workflow)
businessKey Workflow business tracking key (e.g. INV-2026-9041)
startUserId User ID that initiated the process
startTime / endTime Workflow execution timestamps
durationInMillis Execution duration in milliseconds
tenantId Multi-tenant identifier (if applicable)
aps_proc_inst_id Native Process Instance ID for collocated DB joins
aps_scope_id Engine scope identifier for entity-level authorization
aps_scope_type Scope type identifier (processInstance)
aps_identity_users List of allowed user identities
aps_identity_groups List of allowed group identities
aps_var_<varName> Dynamically mapped BPMN process variable
aps_task_<taskName>_assignee User task assignee

Docker Compose Example

oc-crawler:
  environment:
    CONNECTOR_TYPE: aps
    SCAN_PATH: /
    APS_URL: http://aps:8080/activiti-app/api/enterprise
    APS_USERNAME: [email protected]
    APS_PASSWORD: admin
    APS_INCLUDE_VARIABLES: "true"
    APS_INCLUDE_TASKS: "true"
    APS_INCLUDE_ATTACHMENTS: "true"

📑 OASIS CMIS Repository Connector

OASIS CMIS Java Spring Boot OIS Compliance Claim Check

Module: oc-cmis-repository-connector
Class: CmisRepositoryConnector
Spring Bean: @Component (activated when CONNECTOR_TYPE=cmis or spring.opencrawling.connector.type=cmis)
Dedicated Guide: OASIS CMIS Repository Connector

Description

Connects to any OASIS CMIS 1.0 / 1.1 compliant Enterprise Content Management (ECM) repository — including Alfresco Content Services, OpenText Documentum, IBM FileNet P8, Apache Chemistry InMemory / FileShare, and Nuxeo — using the high-performance CMIS 1.1 Browser Binding (JSON over HTTP/REST).

Implemented natively with Java 25 HttpClient (zero legacy Apache Chemistry dependencies), the connector parallelizes folder hierarchy scanning, metadata enrichment, and binary content extraction using Java 25 Virtual Threads (StructuredTaskScope).

It supports:

  • Multiple Crawl Modes: Recursive folder traversal (folder), CMIS-SQL relational queries (query), and incremental change log synchronization.
  • Versioning Policies: latest_major (official releases), latest (including minor revisions), or all (complete history).
  • Aspects & Secondary Types: Full extraction of cmis:secondaryObjectTypeIds and arbitrary custom metadata namespaces.
  • Zero-Trust Security: Maps CMIS Access Control Lists (ACLs) and ACEs into OIS SecurityConfig permission rules.
  • Claim Check Stream Pattern: Routes binary streams directly to local disk, Apache Ozone, or AWS S3, passing lightweight URI references to Kafka.

Configuration Properties (Admin UI / connectors.json)

Property key Spring Property Key Default Description
endpointUrl spring.opencrawling.connector.cmis.endpoint-url http://localhost:8080/alfresco/api/-default-/public/cmis/versions/1.1/browser CMIS Browser Binding service endpoint
repositoryId spring.opencrawling.connector.cmis.repository-id "" Target repository ID (auto-discovered if empty)
username spring.opencrawling.connector.cmis.username admin Basic auth username
password spring.opencrawling.connector.cmis.password admin Basic auth password
bindingType spring.opencrawling.connector.cmis.binding-type browser Protocol binding (browser or atompub)
crawlMode spring.opencrawling.connector.cmis.crawl-mode folder Ingestion mode (folder or query)
rootFolderPath spring.opencrawling.connector.cmis.root-folder-path / Root folder path for folder mode
rootFolderId spring.opencrawling.connector.cmis.root-folder-id "" Optional starting folder object ID
includeSubfolders spring.opencrawling.connector.cmis.include-subfolders true Recursively traverse folder hierarchy
excludedFolderPaths spring.opencrawling.connector.cmis.excluded-folder-paths /Sites/trash,/System Comma-separated paths to ignore
cmisQuery spring.opencrawling.connector.cmis.cmis-query SELECT * FROM cmis:document CMIS-SQL query for query mode
versionsMode spring.opencrawling.connector.cmis.versions-mode latest_major Version filter (latest_major, latest, all)
includeContentStream spring.opencrawling.connector.cmis.include-content-stream true Fetch binary content stream for text parsing
maxContentSizeBytes spring.opencrawling.connector.cmis.max-content-size-bytes 52428800 Max content stream size in bytes (50 MB)
includeAcls spring.opencrawling.connector.cmis.include-acls true Map ACEs to OIS security permissions
includeSecondaryTypes spring.opencrawling.connector.cmis.include-secondary-types true Extract secondary object types and aspects
batchSize spring.opencrawling.connector.cmis.batch-size 100 Objects per page request
timeoutSeconds spring.opencrawling.connector.cmis.timeout-seconds 30 HTTP request timeout in seconds

SCAN_PATH formats

Format Behaviour
(empty) or / Starts recursive scan from root folder (/)
/Company Home/Sites/my-site Recursively scans specified repository folder path
SELECT * FROM cmis:document WHERE ... Executes CMIS-SQL query directly in query mode
d9f6a1e0-... (UUID) Targets folder with matching CMIS object ID

Metadata extracted per document

Metadata key Description
name Document title / filename
cmis.objectId Unique CMIS object identifier
cmis.name CMIS document name
cmis.baseTypeId Base type (e.g. cmis:document)
cmis.objectTypeId Specific type definition (e.g. cm:content)
cmis.secondaryObjectTypeIds Applied aspects / secondary types list
cmis.createdBy / cmis.lastModifiedBy Creator and modifier usernames
cmis.creationDate / cmis.lastModificationDate ISO-8601 timestamps
cmis.versionLabel Document version string (e.g. 1.0)
cmis.isLatestVersion / cmis.isLatestMajorVersion Version status flags
cmis.contentStreamLength / cmis.contentStreamMimeType Binary size and MIME type
cmis.path Full repository path
<customProperty> Any custom aspect or schema properties

Docker Compose Example

oc-crawler:
  image: opencrawling/oc-runtime:latest
  environment:
    CONNECTOR_TYPE: cmis
    SCAN_PATH: /Company Home
    CMIS_ENDPOINT_URL: http://alfresco:8080/alfresco/api/-default-/public/cmis/versions/1.1/browser
    CMIS_REPOSITORY_ID: -default-
    CMIS_USERNAME: admin
    CMIS_PASSWORD: admin
    CMIS_CRAWL_MODE: folder
    CMIS_INCLUDE_SUBFOLDERS: "true"
    CMIS_VERSIONS_MODE: latest_major
    CMIS_INCLUDE_ACLS: "true"
    CMIS_INCLUDE_CONTENT_STREAM: "true"

🗄️ Relational Database (JDBC) Repository Connector

JDBC 4.2+ Java Spring Boot HikariCP OIS Compliance Claim Check

Module: oc-jdbc-repository-connector
Class: JdbcRepositoryConnector
Security Mapper: JdbcSecurityMapper
Crawl Mode Enum: JdbcCrawlMode
Spring Bean: @Component (activated when CONNECTOR_TYPE=jdbc or spring.opencrawling.connector.type=jdbc)
Dedicated Guide: Relational Database (JDBC) Connector

Description

Connects natively to any JDBC-compliant Relational Database Management System (RDBMS) — including PostgreSQL, MySQL, MariaDB, Oracle Database, Microsoft SQL Server, IBM DB2, SQLite, DuckDB, H2, and Snowflake — via standard JDBC 4.2+ drivers.

The connector supports dual-path ingestion:

  1. Tabular RAG & Auto-Narrativization: Ingests relational rows from tables, views, or arbitrary SQL queries, introspects schema metadata via getSchema(basePath) to empower Spring AI TemplateGenerationCopilot, and renders rows into cohesive natural-language narrative text (or deterministic Markdown key-values) for embedding.
  2. Binary BLOB / CLOB Streaming via Claim Check: Directly streams database binary columns (BLOB, BYTEA, RAW, CLOB) into the active ClaimCheckStore (Local disk, Apache Ozone, AWS S3) with automated magic byte sniffing (PDF, PNG, JPEG, ZIP, GIF, WEBP) and Apache Tika text/OCR extraction without JVM heap exhaustion.

Built on Java 25 Virtual Threads (StructuredTaskScope) and HikariCP connection pooling, it features multi-table concurrent scanning, engine-specific streaming cursors (PostgreSQL autocommit disabled, MySQL streaming fetch), stateful High-Water Mark (HWM) incremental delta crawling, soft-delete tombstone emission (DocumentAction.DELETE), and zero-trust column-to-ACL security mapping (JdbcSecurityMapper).

Configuration Properties (Admin UI / connectors.json)

Property key Spring Property Key Default Description
url spring.opencrawling.connector.jdbc.url jdbc:h2:mem:opencrawling;DB_CLOSE_DELAY=-1 JDBC connection URL
driverClassName spring.opencrawling.connector.jdbc.driver-class-name "" Fully qualified driver class name (auto-detected if blank)
username spring.opencrawling.connector.jdbc.username sa Database authentication username
password spring.opencrawling.connector.jdbc.password "" Database authentication password
crawlMode spring.opencrawling.connector.jdbc.mode table Ingestion mode (table or query)
tableName spring.opencrawling.connector.jdbc.table-name "" Target table or view name
schemaName spring.opencrawling.connector.jdbc.schema-name "" Target database schema qualifier
primaryKeyColumns spring.opencrawling.connector.jdbc.primary-key-columns id Primary key column name(s), comma-separated
titleColumn spring.opencrawling.connector.jdbc.title-column title Column mapped as document title
excludedColumns spring.opencrawling.connector.jdbc.excluded-columns "" Columns to omit from indexing (e.g. sensitive data)
querySql spring.opencrawling.connector.jdbc.query-sql "" Custom SQL query executed when crawlMode=query
blobColumnName spring.opencrawling.connector.jdbc.blob-column-name "" Binary BLOB column (auto-detected if blank)
fileNameColumn spring.opencrawling.connector.jdbc.file-name-column "" Attachment filename column
mimeTypeColumn spring.opencrawling.connector.jdbc.mime-type-column "" Attachment MIME type column
incrementalEnabled spring.opencrawling.connector.jdbc.incremental-enabled false Enable High-Water Mark incremental crawl
hwmColumn spring.opencrawling.connector.jdbc.hwm-column updated_at High-Water Mark column name
hwmType spring.opencrawling.connector.jdbc.hwm-type timestamp HWM type: timestamp or numeric
softDeleteEnabled spring.opencrawling.connector.jdbc.soft-delete-enabled false Enable soft-delete tombstone emission
softDeleteColumn spring.opencrawling.connector.jdbc.soft-delete-column is_deleted Soft-delete status column
softDeleteValue spring.opencrawling.connector.jdbc.soft-delete-value true Soft-delete matching value
securityEnabled spring.opencrawling.connector.jdbc.security-enabled false Extract column-based zero-trust ACLs
userColumns spring.opencrawling.connector.jdbc.user-columns "" Comma-separated user identity columns
groupColumns spring.opencrawling.connector.jdbc.group-columns "" Comma-separated group/role columns
tenantColumn spring.opencrawling.connector.jdbc.tenant-column "" Column containing tenant identifier
defaultPermission spring.opencrawling.connector.jdbc.default-permission read Default permission for mapped identities
fetchSize spring.opencrawling.connector.jdbc.fetch-size 1000 Server-side JDBC cursor fetch size
batchSize spring.opencrawling.connector.jdbc.batch-size 100 Structured concurrency batch size
multiTableParallelEnabled spring.opencrawling.connector.jdbc.multi-table-parallel-enabled true Enable parallel multi-table scanning
narrativizationTemplate spring.opencrawling.connector.jdbc.narrativization-template "" Optional Mustache template for tabular rows

SCAN_PATH formats

Format Behaviour
support_tickets Crawls table support_tickets in table mode
crm.customers Crawls table customers within schema crm
customers,orders,invoices Concurrently scans all three tables in parallel via StructuredTaskScope
SELECT * FROM tickets WHERE ... Executes custom SQL query directly in query mode
(empty) Uses configured tableName or querySql

Metadata extracted per document

Metadata key Description
table_name Source database table or query identifier
primary_key Primary key value
title / name Record display title
is_tabular Flag set to true for structured relational rows
is_blob Flag set to true for binary attachments
is_image Flag set to true when binary matches image magic bytes
media_type Record type (tabular, image, etc.)
mimeType Sniffed or mapped MIME type
tenant_id Mapped tenant identifier
<columnName> Strongly typed column values

Docker Compose Example

oc-crawler:
  image: opencrawling/oc-runtime:latest
  environment:
    CONNECTOR_TYPE: jdbc
    SCAN_PATH: support_tickets
    JDBC_URL: jdbc:postgresql://postgres-source:5432/crm_prod
    JDBC_DRIVER_CLASS_NAME: org.postgresql.Driver
    JDBC_USERNAME: crm_reader
    JDBC_PASSWORD: crm_password
    JDBC_TABLE_NAME: support_tickets
    JDBC_PRIMARY_KEY_COLUMNS: id
    JDBC_TITLE_COLUMN: title
    JDBC_SECURITY_ENABLED: "true"
    JDBC_USER_COLUMNS: owner_id
    JDBC_GROUP_COLUMNS: department_id
    JDBC_SOFT_DELETE_ENABLED: "true"
    JDBC_SOFT_DELETE_COLUMN: is_deleted
    JDBC_SOFT_DELETE_VALUE: "true"

Output Connectors

Output connectors receive a RepositoryDocument and persist it directly (bypassing Kafka — used in the direct/standalone execution mode).


🗄️ Vector Output Connector

PostgreSQL pgvector

Module: oc-vector-output-connector
Class: VectorOutputConnector
Spring Bean: @Component

Description

Parses document content using Apache Tika (with full parser support for PDF, Word, PowerPoint, Excel, HTML, plain text, and more), splits the extracted text into overlapping chunks, generates embeddings by calling the configured embedding model, and writes the resulting vectors to PGVector (PostgreSQL with the pgvector extension).

This connector is used in the direct output mode (where the crawler and vectorisation happen in the same JVM process). In the decoupled mode, the equivalent pipeline is executed across three separate microservices: oc-ingestion-consumer, oc-embedding-service, and oc-runtime (VectorStoreWriterConsumer).

Configuration Properties

Property Default Description
spring.ai.vectorstore.pgvector.url — JDBC URL of the PGVector database
spring.ai.vectorstore.pgvector.username — Database username
spring.ai.vectorstore.pgvector.password — Database password
spring.ai.vectorstore.pgvector.initialize-schema true Auto-creates the vector_store tables on startup
spring.ai.vectorstore.pgvector.dimensions 1536 Default vector dimensions (must match the embedding model)

Vector Store Tables

The connector maintains four separate tables to support different embedding model dimension sizes simultaneously:

Table Dimensions Typical model
vector_store 1536 (default) OpenAI text-embedding-3-small
vector_store_384 384 all-minilm (Ollama)
vector_store_768 768 nomic-embed-text (Ollama)
vector_store_1024 1024 mxbai-embed-large (Ollama)

The correct table is selected automatically based on the length of the embedding vector returned by the model.

Text parsing

Apache Tika's AutoDetectParser handles format detection and extraction. If parsing fails for a specific file (e.g., a FreeMarker .ftl template mistakenly detected as RSS/XML), the connector logs a warning and falls back to reading the file as UTF-8 plain text.


🍃 Milvus Output Connector

Milvus

Module: oc-milvus-output-connector
Class: MilvusOutputConnector
Spring Bean: @Component (activated when spring.opencrawling.output.type=milvus)

Description

Persists precomputed vector embeddings and text chunks directly into a Milvus vector database collection. It supports standard index types (e.g., HNSW), custom metric types (e.g., COSINE), and user token authentication.

In the decoupled architecture, MilvusStoreWriterConsumer consumes embedded chunks from the Kafka opencrawling-embedded topic and saves them using this connector.

Configuration Properties

Property Default Description
SPRING_OPENCRAWLING_OUTPUT_MILVUS_URI http://localhost:19530 URI/Host endpoint of the Milvus standalone instance
SPRING_OPENCRAWLING_OUTPUT_MILVUS_TOKEN root:Milvus Authentication token or username:password
SPRING_OPENCRAWLING_OUTPUT_MILVUS_COLLECTION_NAME enterprise_kb Target Milvus collection name
SPRING_OPENCRAWLING_OUTPUT_MILVUS_VECTOR_FIELD_NAME embeddings Name of the field containing the vector embeddings
SPRING_OPENCRAWLING_OUTPUT_MILVUS_DIMENSIONS 1024 Vector dimension size (e.g., 1024 for mxbai-embed-large)

🔍 OpenSearch 2.x Output Connector

OpenSearch

Module: oc-opensearch2-output-connector
Class: OpenSearch2OutputConnector
Spring Bean: @Component (activated when spring.opencrawling.output.type=opensearch2)

Description

Persists precomputed vector embeddings and text chunks directly into an OpenSearch 2.x instance or cluster. On startup, the connector checks for the existence of the target index and automatically initializes it with k-NN HNSW settings and cosine similarity. It relocates internal org.opensearch classes under a shaded packaging boundary (org.opencrawling.shaded.opensearch2) to avoid classpath namespace conflicts with OpenSearch 3.x.

It also contains built-in connection retries (up to 10 attempts, sleeping 3 seconds between attempts) to gracefully handle container orchestration startup delays.

Configuration Properties

Property Default Description
spring.opencrawling.output.opensearch2.uris http://localhost:9200 URIs of the OpenSearch 2.x nodes (comma-separated)
spring.opencrawling.output.opensearch2.username admin Username for basic authentication
spring.opencrawling.output.opensearch2.password admin Password for basic authentication
spring.opencrawling.output.opensearch2.index-name enterprise_kb Target index name
spring.opencrawling.output.opensearch2.dimensions 1024 Vector dimension size (e.g., 1024 for mxbai-embed-large)

🔍 OpenSearch 3.x Output Connector

OpenSearch

Module: oc-opensearch3-output-connector
Class: OpenSearch3OutputConnector
Spring Bean: @Component (activated when spring.opencrawling.output.type=opensearch3)

Description

Persists precomputed vector embeddings and text chunks directly into an OpenSearch 3.x instance. Similar to the 2.x connector, it automatically checks and boots up the target index using k-NN settings on startup. It includes built-in connection retries (up to 10 attempts, sleeping 3 seconds between attempts) to gracefully wait for OpenSearch containers to become healthy during multi-container orchestration.

Configuration Properties

Property Default Description
spring.opencrawling.output.opensearch3.uris http://localhost:9200 URIs of the OpenSearch 3.x nodes (comma-separated)
spring.opencrawling.output.opensearch3.username admin Username for basic authentication
spring.opencrawling.output.opensearch3.password admin Password for basic authentication
spring.opencrawling.output.opensearch3.index-name enterprise_kb Target index name
spring.opencrawling.output.opensearch3.dimensions 1024 Vector dimension size (e.g., 1024 for mxbai-embed-large)

⚡ Qdrant Output Connector

Qdrant

Module: oc-qdrant-output-connector
Class: QdrantOutputConnector
Spring Bean: @Component (activated when spring.opencrawling.output.type=qdrant)

Description

Persists precomputed vector embeddings and text chunks directly into a Qdrant vector database collection (self-hosted or Qdrant Cloud). It utilizes Qdrant's high-performance gRPC Java Client (io.qdrant:client) for low-latency batch upserts of PointStruct objects.

Upon initialization via QdrantCollectionInitializer, it automatically verifies or provisions the target Qdrant collection with configured vector parameters (dimensions, Cosine/Dot/Euclid distance metrics) and creates KEYWORD payload indexes for security ACL fields (security_allowed_read, security_denied_read). This allows sub-millisecond ACL pre-filtering during similarity search in McpVectorServer.

In the decoupled architecture, QdrantStoreWriterConsumer consumes embedded chunks from the Kafka opencrawling-embedded topic and persists them into Qdrant.

Configuration Properties

Property Default Description
spring.opencrawling.output.qdrant.host localhost Hostname of the Qdrant instance
spring.opencrawling.output.qdrant.port 6334 gRPC port (6334 by default, REST on 6333)
spring.opencrawling.output.qdrant.api-key "" Optional API key for Qdrant Cloud or Enterprise authentication
spring.opencrawling.output.qdrant.collection-name enterprise_kb Target Qdrant collection name
spring.opencrawling.output.qdrant.dimensions 1024 Vector dimension size (e.g. 1024 for mxbai-embed-large)
spring.opencrawling.output.qdrant.distance COSINE Vector distance metric (COSINE, DOT, EUCLID)
spring.opencrawling.output.qdrant.quantization NONE Quantization type (NONE, SCALAR, BINARY)
spring.opencrawling.output.qdrant.use-tls false Enable TLS for secure gRPC connection
spring.opencrawling.output.qdrant.batch-size 500 Point batch size for vector upsert operations

🚀 Vespa Output Connector

Vespa

Module: oc-vespa-output-connector
Class: VespaOutputConnector
Spring Bean: @Component (activated when spring.opencrawling.output.type=vespa)

Description

Persists precomputed vector embeddings and text chunks directly into Vespa, Yahoo's open-source big data serving engine combining ANN vector search with BM25 lexical ranking.

Document chunks and embeddings are fed using the official com.yahoo.vespa:vespa-feed-client HTTP/2 client into Vespa document types with full support for Open Ingestion Standard (OIS) ACL pre-filtering, dynamic multi-dimension vector routing, mTLS security, and Admin UI Model Insights.

Key Features & Architecture

  1. Document/v1 feeding via official HTTP/2 client: Both VespaOutputConnector.send() (direct SPI path) and VespaStoreWriterConsumer (decoupled Kafka writer for opencrawling-embedded) stream document chunks using vespa-feed-client, which manages HTTP/2 multiplexed connection pools, dynamic throttling, and automatic retries for transient 429/503 responses.
  2. Dynamic Multi-Dimension Routing: VespaDocumentMapper.resolveDocumentType() inspects each chunk's actual vector dimension and dynamically routes it to a dimension-specific Vespa document type:
    • 384 dimensions $\rightarrow$ opencrawling_chunk_384 (e.g. all-minilm)
    • 768 dimensions $\rightarrow$ opencrawling_chunk_768 (e.g. nomic-embed-text)
    • 1024 dimensions $\rightarrow$ opencrawling_chunk_1024 (e.g. mxbai-embed-large)
    • Any other dimension $\rightarrow$ Fallback to the configured default document type (opencrawling_chunk). This allows mixing embedding models across jobs without changing configuration or redeploying schemas.
  3. ACL-Aware Security Indexing: Each document carries security_allowed_read, security_denied_read, and security_inheritance fields derived from the OIS security model, enabling exact permission filtering.
  4. Structured Schema Safety: Dynamic metadata fields are consolidated into a single metadata_json blob to conform strictly to Vespa's strongly typed schema requirements.
  5. Admin UI Model Insights & Deployment: Backed by /api/vespa/* REST endpoints (VespaInsightsService / VespaInsightsController), providing live engine health (/api/vespa/health), per-document-type chunk counts (/api/vespa/document-counts), hybrid/BM25 query testing (/api/vespa/query), and one-click bundled schema deployment (/api/vespa/deploy/bundled).
  6. Vespa-Native Secure MCP Server: VespaMcpVectorServer exposes vespaSecureVectorSearch (hybrid BM25 + vector similarity ranking), vespaGetDocumentContent, and vespaListAccessibleSources over SSE/HTTP, pushing ACL security_denied_read checks into Vespa YQL queries while maintaining Java-level OIS re-checking.

Configuration Properties

All properties are bound under spring.opencrawling.output.vespa.*:

Property Default Description
spring.opencrawling.output.vespa.endpoint http://localhost:8080 Vespa container Document/Search API endpoint
spring.opencrawling.output.vespa.namespace opencrawling Vespa Document ID namespace
spring.opencrawling.output.vespa.document-type opencrawling_chunk Default document type used when embedding length is not 384, 768, or 1024
spring.opencrawling.output.vespa.dimensions 1024 Fallback vector dimension matching default document type's tensor schema
spring.opencrawling.output.vespa.timeout-seconds 30 Startup connectivity check timeout in seconds
spring.opencrawling.output.vespa.tls-enabled false Enable mTLS client certificate authentication (Vespa Cloud)
spring.opencrawling.output.vespa.tls-certificate (none) Path to client certificate PEM file
spring.opencrawling.output.vespa.tls-private-key (none) Path to client private key PEM file
spring.opencrawling.output.vespa.tls-ca-certificates (none) Path to CA certificates PEM file

Document Schema Example

{
  "fields": {
    "chunk_id": "doc-123_a1b2c3",
    "text": "Enterprise search chunk content...",
    "uri": "file:///data/report.pdf",
    "acl": "finance",
    "lastModified": "2026-08-01T10:00:00Z",
    "security_inheritance": true,
    "security_allowed_read": ["user1", "finance-group"],
    "security_denied_read": ["external-contractor"],
    "metadata_json": "{\"title\":[\"Q3 Financial Report\"],\"mimeType\":[\"application/pdf\"]}",
    "embedding": { "values": [0.0123, -0.0456, 0.0891] }
  }
}

Execution & Test Scripts

# Spin up Vespa with bundled schema auto-deploy via Docker Compose
docker compose -f oc-vespa-output-connector/docker/docker-compose.yml up -d

# Standalone connector smoke test (feeds chunks & asserts dynamic routing + ACLs)
./scripts/test-vespa-connector.sh

# Decoupled Kafka pipeline test with Vespa
./scripts/test-vespa-decoupled.sh

☀️ Apache Solr Output Connector

Apache Solr

Module: oc-solr-output-connector
Class: SolrOutputConnector
Spring Bean: @Component (activated when spring.opencrawling.output.type=solr)

Description

Persists precomputed vector embeddings and document text chunks into Apache Solr (v10.x / v9.x) using SolrJ 10 native JDK HTTP Client (HttpJdkSolrClient for standalone, CloudSolrClient for SolrCloud mode).

Document chunks are indexed using Solr's solr.DenseVectorField with customizable HNSW graph parameters (hnswMaxConnections, hnswBeamWidth, similarityFunction). It features dynamic REST schema auto-provisioning (SolrCollectionInitializer), Solr 10 vector quantization (scalar, binary), efSearch query tuning, OIS zero-trust ACL security fields, and decoupled Kafka writer consumer execution (SolrStoreWriterConsumer).

For full configuration reference, schema details, and queries, see the Apache Solr Output Connector Wiki Page.

Configuration Properties

All properties are bound under spring.opencrawling.output.solr.*:

Property Default Description
spring.opencrawling.output.solr.mode standalone Solr deployment mode: standalone or cloud
spring.opencrawling.output.solr.url http://localhost:8983/solr Base HTTP URL of standalone Solr instance
spring.opencrawling.output.solr.zk-host localhost:2181 ZooKeeper connection string for SolrCloud mode
spring.opencrawling.output.solr.collection enterprise_kb Target Solr collection / core name
spring.opencrawling.output.solr.dimensions 1024 Vector embedding dimension size
spring.opencrawling.output.solr.similarity cosine Similarity metric: cosine, dot_product, or euclidean
spring.opencrawling.output.solr.vector-encoding FLOAT32 Solr 10 vector encoding: FLOAT32 or BYTE
spring.opencrawling.output.solr.quantization none Solr 10 quantization: none, scalar, or binary
spring.opencrawling.output.solr.hnsw-max-connections 16 HNSW graph max connections ($M$)
spring.opencrawling.output.solr.hnsw-beam-width 100 HNSW graph beam width ($efConstruction$)
spring.opencrawling.output.solr.ef-search 100 Solr 10 efSearch query precision parameter
spring.opencrawling.output.solr.commit-within-ms 1000 Soft-commit latency limit in milliseconds

Execution & Test Scripts

# Spin up standalone Solr 10.x container via Docker Compose
docker compose -f oc-solr-output-connector/docker/docker-compose.yml up -d

# Decoupled Kafka pipeline test with Solr 10
./scripts/test-solr-decoupled.sh

💫 Luxir Output Connector

Luxir

Module: oc-luxir-output-connector
Class: LuxirOutputConnector
Spring Bean: @Component (activated when spring.opencrawling.output.type=luxir)

Description

Persists precomputed vector embeddings, document text chunks, and metadata into Luxir using its native HTTP JSON API.

Document chunks are indexed using Luxir's dynamic schema type conventions (_t, _s, _ss, _v, _vs) and dense vector fields with customizable metrics (cosine, l2, ip). Zero-Trust ACL inheritance is mapped to string (security_inheritance_s: "true"/"false") for seamless dynamic schema indexing. Features include automatic collection creation and vector schema provisioning (LuxirCollectionInitializer), OIS v1.1 tombstone deletion handling (delete_ids), zero-trust ACL security tokens, Admin UI integration, and decoupled Kafka writer consumer execution (LuxirStoreWriterConsumer).

For full configuration reference, schema details, and queries, see the Luxir Output Connector Wiki Page.

Configuration Properties

All properties are bound under spring.opencrawling.output.luxir.*:

Property Default Description
spring.opencrawling.output.luxir.endpoint http://localhost:9400 HTTP endpoint URL of the Luxir instance
spring.opencrawling.output.luxir.collection opencrawling Target Luxir collection name
spring.opencrawling.output.luxir.vector-field embedding_v Vector field name in Luxir (_v suffix convention)
spring.opencrawling.output.luxir.dimensions 1024 Vector dimensionality (matches default mxbai-embed-large model)
spring.opencrawling.output.luxir.similarity cosine Distance metric: cosine, l2, or ip
spring.opencrawling.output.luxir.auto-commit true Whether to automatically commit index updates
spring.opencrawling.output.luxir.commit-within-ms 1000 Soft-commit window in milliseconds
spring.opencrawling.output.luxir.timeout-seconds 30 HTTP connection and socket timeout in seconds

Execution & Test Scripts

# Spin up standalone Luxir container via Docker Compose
docker compose -f oc-luxir-output-connector/docker/docker-compose.yml up -d

# Decoupled Kafka pipeline test with Luxir
./scripts/test-luxir-decoupled.sh

🌊 Apache SeaTunnel Output Connector

SeaTunnel

Module: oc-seatunnel-output-connector
Class: SeaTunnelOutputConnector
Spring Bean: @Component (activated when spring.opencrawling.output.type=seatunnel)

Description

Integrates Apache SeaTunnel (v2.3.13) into OpenCrawling as a distributed data integration engine and fan-out orchestrator. It enables high-throughput document crawling, text extraction, token chunking, zero-trust ACL security mapping, and dense vector embeddings to fan out directly into Apache SeaTunnel pipelines powered by the Zeta Engine, Apache Flink, or Apache Spark.

Through SeaTunnel, OpenCrawling streams can be routed to over 100+ destination sinks simultaneously (ClickHouse, Milvus, Apache Iceberg, StarRocks, Qdrant, Elasticsearch, etc.). Features automated HOCON DAG synthesis (SeaTunnelJobConfigBuilder), Zeta Engine REST API v2 orchestration (SeaTunnelRestClient), OIS v1.1 tombstone deletion handling (-D / RowKind.DELETE), stock SeaTunnel cluster compatibility without requiring custom JARs, Admin UI dynamic health checking, and decoupled Kafka writer consumer execution (SeaTunnelStoreWriterConsumer).

For full configuration reference, schema details, and queries, see the Apache SeaTunnel Output Connector Wiki Page.

Configuration Properties

All properties are bound under spring.opencrawling.output.seatunnel.*:

Property Default Description
spring.opencrawling.output.seatunnel.rest-url http://localhost:8080 HTTP endpoint URL of the SeaTunnel Zeta master REST API (typically mapped to port 8088 or 8080)
spring.opencrawling.output.seatunnel.job-name opencrawling_ingestion_pipeline SeaTunnel job name identifier
spring.opencrawling.output.seatunnel.job-mode STREAMING Execution mode: STREAMING or BATCH
spring.opencrawling.output.seatunnel.checkpoint-interval-ms 5000 State checkpoint interval in milliseconds
spring.opencrawling.output.seatunnel.parallelism 4 Execution parallelism degree across Zeta workers
spring.opencrawling.output.seatunnel.kafka-bootstrap-servers localhost:9092 Kafka broker bootstrap servers for the intermediate fan-out topic
spring.opencrawling.output.seatunnel.kafka-topic opencrawling-embedded Topic containing embedded document chunks
spring.opencrawling.output.seatunnel.kafka-group-id seatunnel-ingestion-consumer Consumer group ID for the SeaTunnel Kafka source
spring.opencrawling.output.seatunnel.target-sinks console Comma-separated list of target SeaTunnel sinks (e.g. console, clickhouse, milvus, qdrant, iceberg)
spring.opencrawling.output.seatunnel.dimensions 1024 Vector dimensionality (matches default mxbai-embed-large)
spring.opencrawling.output.seatunnel.auto-submit-job true Automatically submit the generated HOCON DAG to SeaTunnel on connector startup
spring.opencrawling.output.seatunnel.timeout-seconds 30 HTTP connection and socket timeout in seconds

Execution & Test Scripts

# Spin up standalone Apache SeaTunnel Zeta cluster via Docker Compose
docker compose -f oc-seatunnel-output-connector/docker/docker-compose.yml up -d

# Decoupled Kafka pipeline test with Apache SeaTunnel
./scripts/test-seatunnel-decoupled.sh

📦 Apache Ozone Output Connector (Migration Mode)

Ozone

Module: oc-ozone-output-connector
Class: org.opencrawling.ozone.OzoneOutputConnector (decoupled writer: OzoneMigrationWriterConsumer)
Spring Bean: @Component (activated when spring.opencrawling.output.type=ozone)

Description

Migrates enterprise content bit for bit into Apache Ozone volumes and buckets. It runs only in Migration Mode (opencrawling.pipeline.mode=migration, or pipelineMode: migration per job): Tika extraction, chunking and embeddings are skipped. A job that uses this output in RAG mode is rejected with HTTP 409.

Each UPSERT writes the original binary (SHA-256 computed while streaming), a <key>.ois.json sidecar with metadata, Zero-Trust ACLs and contentRef, and an internal index entry. DELETE removes them (DELETE_KEY) or also writes .tombstones/<key>.ois.json (ARCHIVE_TOMBSTONE). There are two transports: NATIVE (Ozone RPC, the default and about 30% faster) and S3G (S3 Gateway, with parallel multipart uploads for large objects).

For architecture, object layout, tuning and measurements, see the Apache Ozone Output Connector Wiki Page.

Configuration Properties

All properties are bound under spring.opencrawling.output.ozone.*:

Property Default Description
client-type NATIVE NATIVE (ofs/RPC) or S3G (S3 Gateway HTTP)
volume / bucket opencrawling / migration Target volume and bucket (the Admin UI form suggests s3v / migration)
om-host / om-port localhost / 9862 Ozone Manager RPC endpoint (NATIVE)
s3-endpoint http://localhost:9878 S3 Gateway endpoint (S3G)
access-key / secret-key any / any S3 Gateway credentials
auto-create-bucket true Create the volume/bucket if missing
key-strategy HIERARCHICAL HIERARCHICAL (from the relative path) or FLAT (sanitized document id)
sidecar-suffix .ois.json Suffix of the OIS metadata sidecar
tombstone-action DELETE_KEY DELETE_KEY or ARCHIVE_TOMBSTONE
allow-in-memory-fallback false For testing only. When false, an unreachable OM fails the connector.
consumer-group opencrawling-ozone-migration-group Dedicated Kafka consumer group of the decoupled writer
consumer-concurrency 3 Writer threads (effective parallelism = min(threads, topic partitions))
multipart-threshold / multipart-part-size / multipart-concurrency 256MB / 16MB / 4 S3G multipart uploads (0 threshold = disabled)

Related: spring.opencrawling.kafka.topic.partitions (3) and spring.opencrawling.crawler.concurrency (4). See the Configuration Guide.

Execution & Test Scripts

# Migration mode unit + live checks
./scripts/test-ozone-migration.sh

# Decoupled migration: source Ozone (claim check) -> Kafka -> writer -> target Ozone
./scripts/test-ozone-migration-decoupled.sh

# Same, over the S3 transports
OUTPUT_OZONE_CLIENT_TYPE=S3G CLAIM_CHECK_OZONE_CLIENT_TYPE=S3 ./scripts/test-ozone-migration-decoupled.sh

Transformation Connectors (Embedding Engines)

Transformation connectors are not Java classes but named configurations stored in connectors.json and managed via the Admin UI. They define which embedding engine and model the oc-embedding-service should use when processing chunks from Kafka.

Supported Engines

Ollama (local)

Runs a local embedding model via the Ollama server. No API key required.

Config key Example value Description
engine ollama Engine type identifier
model mxbai-embed-large Ollama model name (must be pre-pulled)
baseUrl http://localhost:11434 Ollama server base URL

Recommended models by dimension:

Model Dimensions Pull command
mxbai-embed-large 1024 ollama pull mxbai-embed-large
nomic-embed-text 768 ollama pull nomic-embed-text
all-minilm 384 ollama pull all-minilm

OpenAI

Uses the OpenAI Embeddings API. Requires an API key.

Config key Example value Description
engine openai Engine type identifier
model text-embedding-3-small OpenAI model name
apiKey sk-... OpenAI API key

Adding a New Connector

To implement a custom Repository Connector:

  1. Create a new Maven module (e.g. oc-s3-repository-connector).
  2. Add oc-core as a dependency.
  3. Implement RepositoryConnector:
@Component
public class S3RepositoryConnector implements RepositoryConnector {

    @Override
    public String getName() { return "S3Connector"; }

    @Override
    public void connect() throws Exception { /* initialise S3 client */ }

    @Override
    public void disconnect() throws Exception { /* shutdown */ }

    @Override
    public Flux<RepositoryDocument> scan(String basePath) {
        return Flux.create(sink -> {
            // list S3 objects under basePath prefix
            // for each object: sink.next(new RepositoryDocument(...))
            sink.complete();
        });
    }
}
  1. Add the module to the root pom.xml and to oc-runtime's dependencies.
  2. Register it in docker-compose-decoupled.yml with CONNECTOR_TYPE: s3.

See Repository Connector Execution Modes for how connectors are wired into the runtime.

⚠️ **GitHub.com Fallback** ⚠️