[
https://issues.apache.org/jira/browse/CAMEL-24693?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Claus Ibsen updated CAMEL-24693:
--------------------------------
Fix Version/s: 4.23.0
> EIP documentation YAML examples: validate at build time and ship as a per-EIP
> sample set in camel-catalog
> ---------------------------------------------------------------------------------------------------------
>
> Key: CAMEL-24693
> URL: https://issues.apache.org/jira/browse/CAMEL-24693
> Project: Camel
> Issue Type: Improvement
> Components: camel-catalog, documentation
> Reporter: Claus Ibsen
> Assignee: Claus Ibsen
> Priority: Major
> Fix For: 4.23.0
>
>
> h3. Goal
> Turn the YAML examples in the EIP documentation into a validated, per-EIP
> sample set that ships in camel-catalog, so tooling (Camel TUI editor and AI
> panel, camel-jbang-mcp, IDE plugins, Kaoto) can fetch a small, known-good
> YAML DSL sample for any EIP by name. Small local LLMs in particular fail on
> YAML DSL structure (where does onException go, what does a choice look like);
> a fetched sample fixes that class of error.
> h3. What exists
> {core/camel-core-engine/src/main/docs/modules/eips/pages/*.adoc}: 96 pages
> carry {[source,yaml]} blocks, 291 blocks in total, 280 of them complete route
> documents (a top-level list starting with route/from/beans/rest/...). Every
> page has at least one. All are in canonical YAML DSL form after the 2026-06
> audit.
> Checked on 2026-09-11 with {camel validate yaml} (4.23.0-SNAPSHOT): *209 of
> 280 validate, 71 do not.* Sample files are named {<page>-<n>.camel.yaml}
> where n is the block index on the page.
> h3. Proposed pipeline (build time)
> # Extract the {[source,yaml]} blocks from each EIP (and later component) doc
> page.
> # Validate each against the YAML DSL JSON schema.
> # Load each in a scratch CamelContext (parse/reify only, no start) to confirm
> the runtime accepts it.
> # Package the samples that pass both under camel-catalog (for example
> {org/apache/camel/catalog/samples/eips/<eip>-<n>.yaml}) and expose them via a
> {CamelCatalog} API (e.g. {eipSamples(name)}), a camel-jbang-mcp tool and a
> TUI MCP tool.
> # Fail the build (or report) when a doc example fails either check, so doc
> examples stay correct; report schema-versus-runtime disagreements separately,
> they are schema bugs.
> h3. The 71 samples that fail schema validation today
> Some are genuine doc errors (e.g. circuitBreaker: onFallback placed inside
> the circuit breaker steps also fails at runtime; the loadBalancer pages use
> {failoverLoadBalancer: {}} as a step). Many are the schema being stricter
> than the runtime about scalars ({parallelProcessing: "true"} and
> {timePeriodMillis: 10000} both start fine with {camel run}); those are
> tracked in the companion schema issue and the docs should still be normalised
> to the schema's preferred form. The oneOf cases (marshal, unmarshal,
> resequence) need a look at the schema.
> *Scalar type mismatch (schema stricter than runtime; see the companion schema
> issue)* (41):
> {noformat}
> claimCheck-4.camel.yaml:
> /0/route/from/steps/3/setHeader/expression/constant: integer found, string
> expected
> log-8.camel.yaml: /0/route/logMask: string found, boolean expected
> loop-1.camel.yaml:
> /0/route/from/steps/0/loop/expression/constant/expression: integer found,
> string expected
> loop-4.camel.yaml: /0/route/from/steps/0/loop/copy: string found,
> boolean expected
> loop-5.camel.yaml: /0/route/from/steps/0/loop/doWhile: string
> found, boolean expected
> message-history-1.camel.yaml: /0/route/messageHistory: string
> found, boolean expected
> message-history-2.camel.yaml: /0/route/messageHistory: string
> found, boolean expected
> multicast-2.camel.yaml:
> /0/route/from/steps/0/multicast/parallelProcessing: string found, boolean
> expected
> multicast-3.camel.yaml:
> /0/route/from/steps/0/multicast/parallelProcessing: string found, boolean
> expected
> multicast-4.camel.yaml:
> /0/route/from/steps/0/multicast/parallelProcessing: string found, boolean
> expected
> multicast-5.camel.yaml:
> /0/route/from/steps/0/multicast/stopOnException: string found, boolean
> expected
> pollEnrich-1.camel.yaml:
> /0/route/from/steps/0/pollEnrich/timeout: integer found, string expected
> recipientList-4.camel.yaml:
> /0/route/from/steps/0/recipientList/parallelProcessing: string found, boolean
> expected
> recipientList-5.camel.yaml:
> /0/route/from/steps/0/recipientList/stopOnException: string found, boolean
> expected
> recipientList-6.camel.yaml:
> /0/route/from/steps/0/recipientList/ignoreInvalidEndpoints: string found,
> boolean expected
> rollback-2.camel.yaml:
> /0/route/from/steps/0/choice/when/0/steps/0/rollback/markRollbackOnly: string
> found, boolean expected
> routingSlip-2.camel.yaml:
> /0/route/from/steps/0/routingSlip/ignoreInvalidEndpoints: string found,
> boolean expected
> saga-7.camel.yaml: /1/route/from/steps/0/saga/option: object
> found, array expected
> scatter-gather-2.camel.yaml:
> /1/route/from/steps/0/aggregate/completionTimeout: integer found, string
> expected
> split-10.camel.yaml: /0/route/from/steps/0/split/streaming: string
> found, boolean expected
> split-11.camel.yaml: /0/route/from/steps/0/split/streaming: string
> found, boolean expected
> split-12.camel.yaml: /0/route/from/steps/0/split/streaming: string
> found, boolean expected
> split-13.camel.yaml: /0/route/from/steps/0/split/streaming: string
> found, boolean expected
> split-15.camel.yaml: /0/route/from/steps/0/split/group: string
> found, number expected
> split-16.camel.yaml: /0/route/from/steps/0/split/maxFailedRecords:
> string found, number expected
> split-17.camel.yaml: /0/route/from/steps/0/split/errorThreshold:
> string found, number expected
> split-20.camel.yaml: /0/route/from/steps/0/split/stopOnException:
> string found, boolean expected
> split-21.camel.yaml: /0/route/from/steps/1/split/shareUnitOfWork:
> string found, boolean expected
> split-5.camel.yaml: /0/route/from/steps/0/split/parallelProcessing:
> string found, boolean expected
> split-6.camel.yaml: /0/route/from/steps/0/split/parallelProcessing:
> string found, boolean expected
> split-8.camel.yaml: /0/route/from/steps/0/split/streaming: string
> found, boolean expected
> split-9.camel.yaml: /0/route/from/steps/0/split/streaming: string
> found, boolean expected
> throttle-1.camel.yaml:
> /0/route/from/steps/0/throttle/timePeriodMillis: integer found, string
> expected
> throttle-2.camel.yaml:
> /0/route/from/steps/0/throttle/expression/constant/expression: integer found,
> string expected
> throttle-3.camel.yaml:
> /0/route/from/steps/0/throttle/timePeriodMillis: integer found, string
> expected
> throttle-4.camel.yaml:
> /0/route/from/steps/0/throttle/asyncDelayed: string found, boolean expected
> throttle-5.camel.yaml:
> /0/route/from/steps/0/throttle/rejectExecution: string found, boolean expected
> throttle-6.camel.yaml:
> /0/route/from/steps/0/throttle/expression/constant/expression: integer found,
> string expected
> throttle-7.camel.yaml:
> /0/route/from/steps/0/throttle/expression/constant/expression: integer found,
> string expected
> unmarshal-2.camel.yaml:
> /0/route/from/steps/0/unmarshal/allowNullBody: string found, boolean expected
> wireTap-1.camel.yaml:
> /1/route/from/steps/0/delay/expression/constant/expression: integer found,
> string expected
> {{noformat}}
> *Property not in schema (doc example or schema gap; needs a runtime check
> each)* (20):
> {noformat}
> circuitBreaker-1.camel.yaml:
> /0/route/from/steps/0/circuitBreaker/steps/1: property 'onFallback' is not
> defined in the schema and the schema does not allow additional properties
> customLoadBalancer-1.camel.yaml:
> /0/route/from/steps/0/loadBalance/steps/0: property 'customLoadBalancer' is
> not defined in the schema and the schema does not allow additional properties
> doTry-2.camel.yaml:
> /0/route/from/steps/0/doTry/steps/2/doCatch/steps/0: property 'onWhen' is not
> defined in the schema and the schema does not allow additional properties
> failoverLoadBalancer-1.camel.yaml:
> /0/route/from/steps/0/loadBalance/steps/0: property 'failoverLoadBalancer' is
> not defined in the schema and the schema does not allow additional properties
> failoverLoadBalancer-2.camel.yaml:
> /0/route/from/steps/0/loadBalance/steps/0: property 'failoverLoadBalancer' is
> not defined in the schema and the schema does not allow additional properties
> failoverLoadBalancer-3.camel.yaml:
> /0/route/from/steps/0/loadBalance/steps/0: property 'failoverLoadBalancer' is
> not defined in the schema and the schema does not allow additional properties
> failoverLoadBalancer-4.camel.yaml:
> /0/route/from/steps/0/loadBalance/steps/0: property 'failoverLoadBalancer' is
> not defined in the schema and the schema does not allow additional properties
> fault-tolerance-1.camel.yaml:
> /0/route/from/steps/0/circuitBreaker/steps/1: property 'onFallback' is not
> defined in the schema and the schema does not allow additional properties
> fault-tolerance-2.camel.yaml:
> /0/route/from/steps/0/circuitBreaker/steps/0: property
> 'faultToleranceConfiguration' is not defined in the schema and the schema
> does not allow additional properties
> fault-tolerance-3.camel.yaml:
> /0/route/from/steps/1/circuitBreaker: property 'inheritErrorHandler' is not
> defined in the schema and the schema does not allow additional properties
> keyValueRepository-13.camel.yaml: /0/from/steps/0/aggregate:
> property 'strategyRef' is not defined in the schema and the schema does not
> allow additional properties
> randomLoadBalancer-1.camel.yaml:
> /0/route/from/steps/0/loadBalance/steps/0: property 'randomLoadBalancer' is
> not defined in the schema and the schema does not allow additional properties
> resilience4j-1.camel.yaml:
> /0/route/from/steps/0/circuitBreaker/steps/1: property 'onFallback' is not
> defined in the schema and the schema does not allow additional properties
> resilience4j-2.camel.yaml:
> /0/route/from/steps/0/circuitBreaker/steps/0: property
> 'resilience4jConfiguration' is not defined in the schema and the schema does
> not allow additional properties
> resilience4j-3.camel.yaml:
> /0/route/from/steps/0/circuitBreaker/steps/0: property
> 'resilience4jConfiguration' is not defined in the schema and the schema does
> not allow additional properties
> resilience4j-4.camel.yaml: /0/route/from/steps/1/circuitBreaker:
> property 'inheritErrorHandler' is not defined in the schema and the schema
> does not allow additional properties
> roundRobinLoadBalancer-1.camel.yaml:
> /0/route/from/steps/0/loadBalance/steps/0: property 'roundRobinLoadBalancer'
> is not defined in the schema and the schema does not allow additional
> properties
> stickyLoadBalancer-1.camel.yaml:
> /0/route/from/steps/0/loadBalance/steps/0: property 'stickyLoadBalancer' is
> not defined in the schema and the schema does not allow additional properties
> topicLoadBalancer-1.camel.yaml:
> /0/route/from/steps/0/loadBalance/steps/0: property 'topicLoadBalancer' is
> not defined in the schema and the schema does not allow additional properties
> weightedLoadBalancer-1.camel.yaml:
> /0/route/from/steps/0/loadBalance/steps/0: property 'weightedLoadBalancer' is
> not defined in the schema and the schema does not allow additional properties
> {{noformat}}
> *oneOf ambiguity in the schema* (10):
> {noformat}
> marshal-1.camel.yaml: /0/route/from/steps/0/unmarshal: must
> be valid to one and only one schema, but 0 are valid
> resequence-10.camel.yaml: /0/route/from/steps/0/resequence: must
> be valid to one and only one schema, but 2 are valid with indexes '1, 2'
> resequence-11.camel.yaml: /0/route/from/steps/0/resequence: must
> be valid to one and only one schema, but 2 are valid with indexes '1, 2'
> resequence-2.camel.yaml: /0/route/from/steps/0/resequence: must
> be valid to one and only one schema, but 2 are valid with indexes '1, 2'
> resequence-4.camel.yaml: /0/route/from/steps/0/resequence: must
> be valid to one and only one schema, but 2 are valid with indexes '1, 2'
> resequence-5.camel.yaml: /0/route/from/steps/0/resequence: must
> be valid to one and only one schema, but 2 are valid with indexes '1, 2'
> resequence-6.camel.yaml: /0/route/from/steps/0/resequence: must
> be valid to one and only one schema, but 2 are valid with indexes '1, 2'
> resequence-7.camel.yaml: /0/route/from/steps/0/resequence: must
> be valid to one and only one schema, but 2 are valid with indexes '1, 2'
> resequence-9.camel.yaml: /0/route/from/steps/0/resequence: must
> be valid to one and only one schema, but 2 are valid with indexes '1, 2'
> unmarshal-1.camel.yaml: /0/route/from/steps/0/unmarshal: must
> be valid to one and only one schema, but 0 are valid
> {{noformat}}
> h3. Origin
> Found on 2026-09-11 while benchmarking AI-assisted editing in the Camel TUI:
> a local model could not learn YAML DSL structure from the option-level
> catalog docs alone. Related: CAMEL-23774 (recipes catalog), CAMEL-24362 (YAML
> DSL completion model), CAMEL-24692 (simple validator placeholder bug).
--
This message was sent by Atlassian Jira
(v8.20.10#820010)