[
https://issues.apache.org/jira/browse/CAMEL-24693?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18114633#comment-18114633
]
Claus Ibsen commented on CAMEL-24693:
-------------------------------------
Second half, the sample tool, done on a local branch
(feature/CAMEL-24693-eip-sample-tool, stacked on the CAMEL-24695 feature
branch, not pushed yet):
* camel_catalog_sample(name, limit) on the shared authoring registry, so camel
mcp and camel tui --mcp both offer it. It returns up to 5 validated YAML
samples for an EIP or file entry (camelCase, kebab-case, or a part such as
onFallback -> circuitBreaker), plus where it goes: "top-level entry: a list
item at the same level as route or from, not a step inside a route" (from the
schema's top-level keys) or "a step inside the steps of a route".
* Source: the [source,yaml] blocks of the 117 EIP pages plus rest-dsl,
route-configuration, error-handler, oncompletion, try-catch-finally,
exception-clause, routes and route-template from the user manual. 331 complete
examples (top-level list), 322 pass the YAML DSL validator with the
CAMEL-24692/24694/24697 fixes, 102 names. They ship for now as eip-samples.json
in camel-jbang-core, extracted by a script; the build-time extraction into
camel-catalog described in this issue replaces that.
The 9 examples that still fail validation (all in the user manual, so outside
the EIP doc fixes in #26355):
{noformat}
saga-7: ['option: object found, array expected']
errorHandler-1: ["from: required property 'steps' not found", "route: property
'steps' is not defined in the schema and the schema does not allow additional
properties"]
errorHandler-2: ["property 'onException' is not defined in the schema and the
schema does not allow additional properties", "property 'redeliveryPolicy' is
not defined in the schema and the schema does not allow additional properties"]
onCompletion-1: ["property 'onCompletion' is not defined in the schema and the
schema does not allow additional properties"]
onCompletion-2: ["property 'onCompletion' is not defined in the schema and the
schema does not allow additional properties"]
onCompletion-4: ["property 'onCompletion' is not defined in the schema and the
schema does not allow additional properties"]
onCompletion-6: ["onCompletion: property 'executorServiceRef' is not defined in
the schema and the schema does not allow additional properties"]
route-5: ['unmarshal: must be valid to one and only one schema, but 0 are
valid', "jaxb: required property 'contextPath' not found"]
doTry-2: ["property 'onWhen' is not defined in the schema and the schema does
not allow additional properties"]
{noformat}
Two of those look like schema gaps rather than doc errors: onCompletion inside
a route (route-scoped onCompletion) and onWhen under doCatch.
> 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)