Skip to content

camel-docling: honor the operationId URI path segment to select the operation - #26102

Open
Croway wants to merge 1 commit into
apache:mainfrom
Croway:camel-docling-operation-id-dispatch
Open

camel-docling: honor the operationId URI path segment to select the operation#26102
Croway wants to merge 1 commit into
apache:mainfrom
Croway:camel-docling-operation-id-dispatch

Conversation

@Croway

@Croway Croway commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Summary

DoclingEndpoint stores the docling:<operationId> URI path segment (e.g. docling:EXTRACT_STRUCTURED_DATA, matching the component's own documented syntax docling:operationId), but DoclingComponent never applied it to DoclingConfiguration.operation, and DoclingProducer.getOperation() only consults the CamelDoclingOperation header or the configured/default operation (CONVERT_TO_MARKDOWN).

As a result, an endpoint such as:

docling:EXTRACT_STRUCTURED_DATA?useDoclingServe=true&doclingServeUrl=...&outputFormat=json

silently performs CONVERT_TO_MARKDOWN instead - the URI path segment is effectively ignored unless the operation is also passed via the operation query parameter or the CamelDoclingOperation header (the pattern already used by this component's own docs/tests, e.g. docling:convert?operation=CONVERT_TO_MARKDOWN).

I hit this concretely while testing the docling example in camel-spring-boot-examples: a document-metadata-extractor route using docling:EXTRACT_STRUCTURED_DATA?...&outputFormat=json was writing markdown text into .json files (invalid JSON), because it was actually always running CONVERT_TO_MARKDOWN.

  • DoclingComponent.createEndpoint() now parses operationId into a DoclingOperations value and applies it to the endpoint's configuration before setProperties() runs, so an explicit ?operation=... query parameter still takes precedence, and an operationId that isn't a recognized operation name (used as a purely descriptive endpoint id) is silently ignored rather than failing endpoint creation.
  • Added two regression tests in DoclingComponentTest: operationId selecting the operation, and an explicit operation parameter overriding a recognized operationId. (The "unrecognized operationId + explicit operation parameter" case was already covered by the existing testCreateEndpointWithParameters.)

Related, not fixed here: once the operation is dispatched correctly, EXTRACT_STRUCTURED_DATA (and CONVERT_TO_JSON in docling-serve mode) sets the exchange body to a DoclingDocument POJO regardless of outputFormat, and there's no registered type converter to String/bytes for it - callers need to marshal it explicitly (e.g. via camel-jackson) before handing it to a byte-oriented endpoint like file:. Happy to file that as a separate follow-up if useful.

Test plan

  • mvn -o test -Dtest='!*IT' in components/camel-ai/camel-docling - all unit tests pass, including the new regression tests
  • Reproduced against a live docling-serve container via the camel-spring-boot-examples docling example: before the fix, EXTRACT_STRUCTURED_DATA silently ran CONVERT_TO_MARKDOWN; after the fix, it correctly dispatches to structured-data extraction
  • Verified the pre-existing docling:convert?operation=... style (used elsewhere in this component's tests/docs) is unaffected

@github-actions

github-actions Bot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

🌟 Thank you for your contribution to the Apache Camel project! 🌟
🤖 CI automation will test this PR automatically.

🐫 Apache Camel Committers, please review the following items:

  • First-time contributors require MANUAL approval for the GitHub Actions to run
  • You can use the command /component-test (camel-)component-name1 (camel-)component-name2.. to request a test from the test bot although they are normally detected and executed by CI.
  • You can label PRs using skip-tests and test-dependents to fine-tune the checks executed by this PR.
  • Build and test logs are available in the summary page. Only Apache Camel committers have access to the summary.

⚠️ Be careful when sharing logs. Review their contents before sharing them publicly.

…peration

DoclingEndpoint stores the docling:<operationId> URI path segment (e.g.
docling:EXTRACT_STRUCTURED_DATA) but DoclingComponent never applied it to
DoclingConfiguration.operation, and DoclingProducer.getOperation() only
consults the CamelDoclingOperation header or the configured/default
operation (CONVERT_TO_MARKDOWN). As a result, an endpoint like
docling:EXTRACT_STRUCTURED_DATA?useDoclingServe=true&outputFormat=json
silently performed CONVERT_TO_MARKDOWN instead, since the operation was
never set anywhere else - the path segment was purely cosmetic despite the
component's own syntax being documented as "docling:operationId".

DoclingComponent.createEndpoint() now parses the operationId into a
DoclingOperations value and applies it to the endpoint's configuration
before setProperties() runs, so an explicit ?operation=... query parameter
(as already used in this component's own tests and docs) still takes
precedence, and an operationId that isn't a recognized operation name is
silently ignored rather than failing endpoint creation.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Hs6c6LpuL8ZZ3gaSXwt7CS
@Croway
Croway force-pushed the camel-docling-operation-id-dispatch branch from 3174341 to f462af9 Compare September 3, 2026 17:29
@Croway
Croway requested a review from oscerd September 3, 2026 17:29
@github-actions

github-actions Bot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

🧪 CI tested the following changed modules:

  • components/camel-ai/camel-docling

🔬 Scalpel shadow comparison — Scalpel: 9 tested, 27 compile-only — current: 9 all tested

Maveniverse Scalpel detected 36 affected modules (current approach: 9).

⚠️ Modules only in Scalpel (27)
  • apache-camel
  • camel-allcomponents
  • camel-catalog
  • camel-catalog-console
  • camel-catalog-maven
  • camel-catalog-suggest
  • camel-componentdsl
  • camel-endpointdsl
  • camel-endpointdsl-support
  • camel-itest
  • camel-jbang-core
  • camel-jbang-it
  • camel-jbang-main
  • camel-jbang-plugin-edit
  • camel-jbang-plugin-generate
  • camel-jbang-plugin-kubernetes
  • camel-jbang-plugin-test
  • camel-kamelet-main
  • camel-launcher
  • camel-report-maven-plugin
  • camel-route-parser
  • camel-yaml-dsl
  • camel-yaml-dsl-deserializers
  • camel-yaml-dsl-maven-plugin
  • coverage
  • docs
  • dummy-component

Skip-tests mode would test 9 modules (1 direct + 8 downstream), skip tests for 27 (generated code, meta-modules)

Modules Scalpel would test (9)
  • camel-docling
  • camel-jbang-mcp
  • camel-jbang-plugin-mcp
  • camel-jbang-plugin-route-parser
  • camel-jbang-plugin-tui
  • camel-jbang-plugin-validate
  • camel-launcher-container
  • camel-yaml-dsl-validator
  • camel-yaml-dsl-validator-maven-plugin
Modules with tests skipped (27)
  • apache-camel
  • camel-allcomponents
  • camel-catalog
  • camel-catalog-console
  • camel-catalog-maven
  • camel-catalog-suggest
  • camel-componentdsl
  • camel-endpointdsl
  • camel-endpointdsl-support
  • camel-itest
  • camel-jbang-core
  • camel-jbang-it
  • camel-jbang-main
  • camel-jbang-plugin-edit
  • camel-jbang-plugin-generate
  • camel-jbang-plugin-kubernetes
  • camel-jbang-plugin-test
  • camel-kamelet-main
  • camel-launcher
  • camel-report-maven-plugin
  • camel-route-parser
  • camel-yaml-dsl
  • camel-yaml-dsl-deserializers
  • camel-yaml-dsl-maven-plugin
  • coverage
  • docs
  • dummy-component

ℹ️ Shadow mode — Scalpel observes but does not affect test execution. Learn more

⚠️ Some tests are disabled on GitHub Actions (@DisabledIfSystemProperty(named = "ci.env.name")) and require manual verification:

  • components/camel-ai/camel-docling: 6 test(s) disabled on GitHub Actions
All tested modules (36 modules)
  • Camel :: AI :: Docling
  • Camel :: All Components Sync point
  • Camel :: Assembly
  • Camel :: Catalog :: Camel Catalog
  • Camel :: Catalog :: Camel Report Maven Plugin
  • Camel :: Catalog :: Camel Route Parser
  • Camel :: Catalog :: Console
  • Camel :: Catalog :: Dummy Component
  • Camel :: Catalog :: Maven
  • Camel :: Catalog :: Suggest
  • Camel :: Component DSL
  • Camel :: Coverage
  • Camel :: Docs
  • Camel :: Endpoint DSL
  • Camel :: Endpoint DSL :: Support
  • Camel :: Integration Tests
  • Camel :: JBang :: Core
  • Camel :: JBang :: Integration tests
  • Camel :: JBang :: MCP
  • Camel :: JBang :: Main
  • Camel :: JBang :: Plugin :: Edit
  • Camel :: JBang :: Plugin :: Generate
  • Camel :: JBang :: Plugin :: Kubernetes
  • Camel :: JBang :: Plugin :: MCP
  • Camel :: JBang :: Plugin :: Route Parser
  • Camel :: JBang :: Plugin :: TUI
  • Camel :: JBang :: Plugin :: Testing
  • Camel :: JBang :: Plugin :: Validate
  • Camel :: Kamelet Main
  • Camel :: Launcher
  • Camel :: Launcher :: Container
  • Camel :: YAML DSL
  • Camel :: YAML DSL :: Deserializers
  • Camel :: YAML DSL :: Maven Plugins
  • Camel :: YAML DSL :: Validator
  • Camel :: YAML DSL :: Validator Maven Plugin

⚙️ View full build and test results

@gnodet gnodet left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Solid bugfix. The operationId-to-operation wiring is correctly placed before setProperties(), preserving the right precedence chain: header > ?operation= param > operationId path segment > default. The silent IllegalArgumentException catch is the correct choice — failing on unrecognized operationId values would break existing endpoints like docling:convert and docling:process. Test coverage hits the key cases: operationId selecting operation, explicit param overriding a recognized operationId, and pre-existing tests already cover unrecognized operationId with explicit params.

This review was generated by an AI agent, Hermès on behalf of @gnodet.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants