davsclaus opened a new pull request, #26351:
URL: https://github.com/apache/camel/pull/26351

   Fixes [CAMEL-24694](https://issues.apache.org/jira/browse/CAMEL-24694).
   
   ## Problem
   
   The generated YAML DSL JSON schema types scalar attributes from the model's 
catalog metadata, but the model fields are `String` and the YAML deserializer 
passes the raw text to the setter — Camel converts it (resolving property 
placeholders) when the route starts. The schema is therefore stricter than the 
runtime, and every consumer of it — `camel validate yaml`, the TUI save-time 
validation and its `tui_write_file` / `tui_validate_source` MCP tools, 
camel-jbang-mcp `camel_validate_yaml_dsl`, IDE plugins and Kaoto — refuses 
input that `camel run` accepts.
   
   ```yaml
   - route:
       from:
         uri: timer:tick?period=1000
         steps:
           - split:
               parallelProcessing: "true"   # string found, boolean expected
               tokenize: ","
               steps:
                 - log: "${body}"
   ```
   
   Three shapes are affected: a quoted scalar at a typed attribute, a 
**property placeholder** at a typed attribute (the largest class — 572 EIP 
options are schema `boolean`/`integer`/`number` backed by `String` fields), and 
a bare integer at a `duration` attribute, which the schema emits as `string` 
(27 options).
   
   ## Approach
   
   The schema keeps its real types — Kaoto forms, TUI completion and catalog 
docs rely on them, so no type unions are emitted. The leniency lives in 
`YamlValidator`, and applies in **both** classic and canonical mode (they share 
one `init()`):
   
   1. **`typeLoose(true)`** on `SchemaRegistryConfig` — a quoted scalar that 
parses as the expected type validates. This is a validator-runtime flag only; 
`camelYamlDsl.json` is unchanged. Values that do not parse 
(`parallelProcessing: "yes please"`) are still rejected.
   2. **`isRuntimeAcceptedScalar`** post-filter — drops a `type` error when the 
instance is a property placeholder at a typed attribute, or a number/boolean at 
a string-typed attribute. It keys off `getSchemaNode()` / `getInstanceNode()` 
rather than parsing message text, and follows the existing `filterOneOfNoise` 
pattern in the same class.
   
   Everything else stays strict: unknown properties, structure, enums, and 
strings that do not parse as the expected type.
   
   ## Keeping the runtime honest
   
   The filter is only correct if the runtime really does defer conversion for 
every scalar attribute the schema exposes. Out of ~1660 generated deserializer 
cases, five converted eagerly, so a property placeholder was never resolved for 
them — `Boolean.valueOf("{{flag}}")` silently yields `false`.
   
   Two of the five are reachable from the schema and are ported here to 
`String` fields with `@Metadata(javaType = ...)`, like the rest of the model:
   
   * `ParamDefinition.required` (rest DSL `param`)
   * `RouteTemplateParameterDefinition.required` (`templateParameter`)
   
   Because the metadata still declares `javaType = java.lang.Boolean`, the 
catalog and the schema continue to emit `boolean` — only the deserializer 
changes, from `Boolean.valueOf(val)` to passing the text through. The XML 
parser gains the same placeholder support for free.
   
   The other three are **not reachable from the generated schema**, so the 
leniency cannot affect them, and they are left alone and tracked in 
[CAMEL-24696](https://issues.apache.org/jira/browse/CAMEL-24696):
   
   | attribute | why it is unreachable |
   | --- | --- |
   | `CircuitBreakerDefinition.inheritErrorHandler` | `GenerateYamlSchemaMojo` 
skips `inheritErrorHandler` deliberately |
   | `FailoverLoadBalancerDefinition.inheritErrorHandler` | same |
   | `BeanConstructorDefinition.index` | orphan definition — 
`BeanFactoryDefinition.constructors` is emitted as a free-form `object`, so 
nothing `$ref`s it |
   
   `index` is additionally unportable: it ends up as a `Map<Integer, Object>` 
key ordering the constructor arguments, so a placeholder can never work there.
   
   ## API change
   
   `getRequired()` / `setRequired(...)` on the two definitions above now use 
`String` instead of `Boolean`. The fluent `ParamDefinition.required(Boolean)` 
is unchanged and a `required(String)` overload was added for placeholders. 
`RouteTemplateParameterDefinition.isRequired()` still returns `boolean` but 
does not resolve placeholders — callers with a `CamelContext` should use 
`CamelContextHelper.parseBoolean(...)`, which `DefaultModel` now does. 
Documented in the 4.23 upgrade guide. Routes written in XML, YAML or the Java 
DSL need no change.
   
   ## Testing
   
   New `YamlValidatorScalarLeniencyTest` runs every case against **both** the 
classic and canonical validator:
   
   | case | before | after |
   | --- | --- | --- |
   | `parallelProcessing: "true"` | string found, boolean expected | accepted |
   | `parallelProcessing: "{{myParallel}}"` | string found, boolean expected | 
accepted |
   | `group: "100"` / `errorThreshold: "0.5"` | string found, number expected | 
accepted |
   | `group: "{{myGroup}}"` | string found, number expected | accepted |
   | `timeout: 5000` (duration) | integer found, string expected | accepted |
   | `parallelProcessing: "yes please"` | rejected | **still rejected** |
   | `group: "a lot"` | rejected | **still rejected** |
   | `cheese: true` (unknown property) | rejected | **still rejected** |
   
   Plus two runtime regression tests in `RouteTemplateTest` for the placeholder 
at `templateParameter.required` — the case that previously turned a required 
parameter into an optional one without any error.
   
   Green: full clean build (611 modules), camel-yaml-dsl (412), 
camel-openapi-java (97), camel-core template/rest (163), 
camel-yaml-dsl-validator, camel-xml-io, camel-yaml-io, camel-java-io, 
camel-core-engine.
   
   ---
   _Claude Code on behalf of davsclaus_
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to