Skip to content

CAMEL-25490: camel-yaml-io - dump a top-level onException as top-level, not as a step of every route - #27609

Open
Croway wants to merge 3 commits into
apache:mainfrom
Croway:CAMEL-25490-normalize-onexception
Open

Croway wants to merge 3 commits into
apache:mainfrom
Croway:CAMEL-25490-normalize-onexception

Conversation

@Croway

@Croway Croway commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor

JIRA: https://issues.apache.org/jira/browse/CAMEL-25490

Problem

camel validate normalize turns a valid YAML file with a top-level onException into a file that camel validate yaml rejects: the onException is written as the first step of every route.

- onException:
    exception:
      - java.lang.Exception
    handled:
      constant: "true"
    steps:
      - log:
          message: "Failed: ${exception.message}"
- route:
    id: myRoute
    from:
      uri: timer:tick
      steps:
        - log:
            message: "Hello"

camel validate normalize in.yaml --output=out.yaml (4.22.1) writes the onException under route.from.steps, and then:

$ camel validate yaml out.yaml
	/0/route/from/steps/0: property 'onException' is not defined in the schema and the schema does not allow additional properties

The onException of a routeConfiguration loaded before the routes ends up in the steps of each route as well (and is also dumped in the routeConfiguration).

camel validate yaml and the compact notation warning recommend camel validate normalize, so users and AI agents run it and copy its output over valid routes.

Cause

When a route is prepared (RouteDefinitionHelper.prepareRoute / initOnExceptions), the context scoped onExceptions (top-level ones, those of a RouteBuilder, and those of the route configurations that apply) are added to the outputs of the route with routeScoped=false. LwModelToYAMLDumper.dumpModelAsYaml wrote all the route outputs as steps, but the YAML DSL has no onException among the steps of a route (see CAMEL-25207).

Fix

LwModelToYAMLDumper leaves the context scoped onExceptions out of the route steps, and writes the ones that do not belong to a route configuration once, as top-level onException entries before the routes. Route scoped onExceptions, such as from(...).onException(...) in the Java DSL, are written as before.

Several files normalized into one

camel validate normalize a.yaml b.yaml writes one file: DefaultDumpRoutesStrategy dumped the routes of each source file separately and appended them to the same output file. With the fix above, a top-level onException of b.yaml would then come after the routes of a.yaml, which the YAML DSL loader rejects (onException must be defined before any routes). The second commit changes DefaultDumpRoutesStrategy (camel-core-engine): when the routes are dumped into a single file (dumpRoutesOutput is a file name), the routes of all the files are dumped together, so every top-level onException comes before the first route. This is outside camel-yaml-io because the dumper only sees one group of routes at a time, and the grouping per file is done by the dump strategy; the change is limited to the YAML routes dump, and dumps into a directory still write one file per source file. As the files are merged into one, a top-level onException then applies to the routes of all of them (a single YAML file has no narrower scope for it).

Test

OnExceptionYamlDumpTest (camel-yaml-dsl) loads YAML routes, dumps them as camel.main.dumpRoutes does, and loads the dump back with the YAML DSL JSON schema validation of YamlTestSupport:

  • a top-level onException with two routes, before and after the context is started: dumped once, as top-level, and it still applies to both routes after the reload;
  • a routeConfiguration onException loaded before the route: not dumped in the route;
  • two files, the second with a top-level onException, dumped with DefaultDumpRoutesStrategy into one output file as camel validate normalize does: the onException comes first, and the combined file passes the schema validation and loads both routes.

The tests fail without the fixes and pass with them. The camel-yaml-io and camel-yaml-dsl tests pass, and so do the dump tests of camel-core (DefaultDumpRoutesStrategy*, DumpModel*).

Other top-level elements show related but separate problems with camel validate normalize; they are listed in the JIRA issue and not changed here.

…l, not as a step of every route

When routes are prepared, the context scoped onExceptions (the top-level
onException of a YAML file, the onException of a RouteBuilder, and those
of the route configurations that apply) are added to the outputs of each
route. The YAML dumper wrote them as steps of every route, which the YAML
DSL schema rejects, so camel validate normalize turned a valid file into
an invalid one.

The YAML dumper now leaves the context scoped onExceptions out of the
route steps, and writes those that do not belong to a route configuration
once, as top-level onException entries before the routes.
@github-actions

github-actions Bot commented Oct 9, 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.

@gnodet-bot gnodet-bot 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 fix. Context-scoped onExceptions are correctly separated from route-scoped ones, and the identity-based filtering in doWriteOutputs is the right approach given how prepareRoute injects shared references. One low-severity robustness nit below.

Pre-fix test validation ✅: topLevelOnExceptionIsDumpedAsTopLevel — without the fix, a 2-route setup would produce 3 onException: occurrences (1 top-level + 1 per route), so hasSize(2) would fail. routeConfigurationOnExceptionIsNotDumpedInTheRoutes — the test first asserts the onException was injected into route outputs (proving prepareRoute fired), then asserts the dump omits it; without the fix that assertion fails.

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

@github-actions

github-actions Bot commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor

🧪 CI tested the following changed modules:

  • core/camel-core-engine
  • core/camel-yaml-io
  • dsl/camel-yaml-dsl/camel-yaml-dsl

ℹ️ Dependent modules were not tested because the total number of affected modules exceeded the threshold (50). Use the test-dependents label to force testing all dependents.


🔬 Scalpel shadow comparison — Scalpel: 497 of 704 tested, 27 compile-only — current: 497 all tested

Maveniverse Scalpel detected 497 affected modules (current approach: 497).

Skip-tests mode would test 497 modules (3 direct + 495 downstream), skip tests for 27 (generated code, meta-modules)

Modules Scalpel would test (497)
  • archetypes ← downstream of org.apache.camel:camel-test-junit6
  • camel-a2a ← downstream of org.apache.camel:camel-test-junit6
  • camel-activemq ← downstream of org.apache.camel:camel-test-infra-core
  • camel-activemq6 ← downstream of org.apache.camel:camel-test-infra-core
  • camel-ai-observability ← downstream of org.apache.camel:camel-test-junit6
  • camel-ai-observability-api ← downstream of org.apache.camel:camel-test-junit6
  • camel-ai-resource ← downstream of org.apache.camel:camel-test-junit6
  • camel-ai-tool ← downstream of org.apache.camel:camel-test-junit6
  • camel-alibaba-eventbridge ← downstream of org.apache.camel:camel-test-junit6
  • camel-alibaba-fc ← downstream of org.apache.camel:camel-test-junit6
  • camel-alibaba-kms ← downstream of org.apache.camel:camel-test-junit6
  • camel-alibaba-mns ← downstream of org.apache.camel:camel-test-junit6
  • camel-alibaba-oss ← downstream of org.apache.camel:camel-test-junit6
  • camel-alibaba-ots ← downstream of org.apache.camel:camel-test-junit6
  • camel-alibaba-sls ← downstream of org.apache.camel:camel-test-junit6
  • camel-alibaba-sms ← downstream of org.apache.camel:camel-test-junit6
  • camel-amqp ← downstream of org.apache.camel:camel-test-junit6
  • camel-api-component-maven-plugin ← downstream of org.apache.camel:camel-core
  • camel-arangodb ← downstream of org.apache.camel:camel-test-junit6
  • camel-archetype-api-component ← downstream of org.apache.camel:camel-test-junit6
  • camel-archetype-component ← downstream of org.apache.camel:camel-test-junit6
  • camel-archetype-dataformat ← downstream of org.apache.camel:camel-test-junit6
  • camel-archetype-java ← downstream of org.apache.camel:camel-test-junit6
  • camel-archetype-main ← downstream of org.apache.camel:camel-test-junit6
  • camel-as2 ← downstream of org.apache.camel:camel-test-junit6
  • camel-as2-api ← downstream of org.apache.camel:camel-test-junit6
  • camel-asn1 ← downstream of org.apache.camel:camel-test-junit6
  • camel-asterisk ← downstream of org.apache.camel:camel-test-junit6
  • camel-atmosphere-websocket ← downstream of org.apache.camel:camel-test-junit6
  • camel-atom ← downstream of org.apache.camel:camel-test-junit6
  • camel-attachments ← downstream of org.apache.camel:camel-test-junit6
  • camel-avro ← downstream of org.apache.camel:camel-test-junit6
  • camel-avro-rpc ← downstream of org.apache.camel:camel-test-junit6
  • camel-aws-bedrock ← downstream of org.apache.camel:camel-jackson
  • camel-aws-cloudtrail ← downstream of org.apache.camel:camel-test-spring-junit6
  • camel-aws-config ← downstream of org.apache.camel:camel-test-junit6
  • camel-aws-parameter-store ← downstream of org.apache.camel:camel-test-spring-junit6
  • camel-aws-secrets-manager ← downstream of org.apache.camel:camel-test-spring-junit6
  • camel-aws-security-hub ← downstream of org.apache.camel:camel-test-spring-junit6
  • camel-aws2-athena ← downstream of org.apache.camel:camel-test-spring-junit6
  • camel-aws2-comprehend ← downstream of org.apache.camel:camel-test-spring-junit6
  • camel-aws2-cw ← downstream of org.apache.camel:camel-test-spring-junit6
  • camel-aws2-ddb ← downstream of org.apache.camel:camel-jackson
  • camel-aws2-ec2 ← downstream of org.apache.camel:camel-test-spring-junit6
  • camel-aws2-ecs ← downstream of org.apache.camel:camel-test-spring-junit6
  • camel-aws2-eks ← downstream of org.apache.camel:camel-test-spring-junit6
  • camel-aws2-eventbridge ← downstream of org.apache.camel:camel-test-spring-junit6
  • camel-aws2-iam ← downstream of org.apache.camel:camel-test-spring-junit6
  • camel-aws2-kinesis ← downstream of org.apache.camel:camel-test-spring-junit6
  • camel-aws2-kms ← downstream of org.apache.camel:camel-test-spring-junit6
  • camel-aws2-lambda ← downstream of org.apache.camel:camel-test-spring-junit6
  • camel-aws2-mq ← downstream of org.apache.camel:camel-test-spring-junit6
  • camel-aws2-msk ← downstream of org.apache.camel:camel-test-spring-junit6
  • camel-aws2-polly ← downstream of org.apache.camel:camel-test-spring-junit6
  • camel-aws2-redshift ← downstream of org.apache.camel:camel-test-spring-junit6
  • camel-aws2-rekognition ← downstream of org.apache.camel:camel-test-spring-junit6
  • camel-aws2-s3 ← downstream of org.apache.camel:camel-test-spring-junit6
  • camel-aws2-s3-vectors ← downstream of org.apache.camel:camel-test-spring-junit6
  • camel-aws2-ses ← downstream of org.apache.camel:camel-test-spring-junit6
  • camel-aws2-sns ← downstream of org.apache.camel:camel-test-spring-junit6
  • camel-aws2-sqs ← downstream of org.apache.camel:camel-test-spring-junit6
  • camel-aws2-step-functions ← downstream of org.apache.camel:camel-test-spring-junit6
  • camel-aws2-sts ← downstream of org.apache.camel:camel-test-spring-junit6
  • camel-aws2-textract ← downstream of org.apache.camel:camel-test-spring-junit6
  • camel-aws2-timestream ← downstream of org.apache.camel:camel-test-spring-junit6
  • camel-aws2-transcribe ← downstream of org.apache.camel:camel-test-junit6
  • camel-aws2-translate ← downstream of org.apache.camel:camel-test-spring-junit6
  • camel-azure-cosmosdb ← downstream of org.apache.camel:camel-test-junit6
  • camel-azure-eventgrid ← downstream of org.apache.camel:camel-test-junit6
  • camel-azure-eventhubs ← downstream of org.apache.camel:camel-test-junit6
  • camel-azure-files ← downstream of org.apache.camel:camel-test-junit6
  • camel-azure-functions ← downstream of org.apache.camel:camel-test-junit6
  • camel-azure-key-vault ← downstream of org.apache.camel:camel-test-junit6
  • camel-azure-schema-registry ← downstream of org.apache.camel:camel-test-junit6
  • camel-azure-servicebus ← downstream of org.apache.camel:camel-test-junit6
  • camel-azure-storage-blob ← downstream of org.apache.camel:camel-test-junit6
  • camel-azure-storage-datalake ← downstream of org.apache.camel:camel-test-junit6
  • camel-azure-storage-queue ← downstream of org.apache.camel:camel-test-junit6
  • camel-barcode ← downstream of org.apache.camel:camel-test-spring-junit6
  • camel-base64 ← downstream of org.apache.camel:camel-test-junit6
  • camel-bean-validator ← downstream of org.apache.camel:camel-test-junit6
  • camel-beanio ← downstream of org.apache.camel:camel-test-spring-junit6
  • camel-bindy ← downstream of org.apache.camel:camel-test-spring-junit6
  • camel-bonita ← downstream of org.apache.camel:camel-test-junit6
  • camel-box ← downstream of org.apache.camel:camel-test-junit6
  • camel-braintree ← downstream of org.apache.camel:camel-test-junit6
  • camel-caffeine ← downstream of org.apache.camel:camel-test-junit6
  • camel-camunda ← downstream of org.apache.camel:camel-test-junit6
  • camel-cassandraql ← downstream of org.apache.camel:camel-test-junit6
  • camel-cbor ← downstream of org.apache.camel:camel-test-spring-junit6
  • camel-chatscript ← downstream of org.apache.camel:camel-test-junit6
  • camel-chunk ← downstream of org.apache.camel:camel-test-junit6
  • camel-cli-connector ← downstream of org.apache.camel:camel-management
  • camel-cli-debug ← downstream of org.apache.camel:camel-cli-connector
  • camel-clickhouse ← downstream of org.apache.camel:camel-test-junit6
  • camel-clickup ← downstream of org.apache.camel:camel-test-junit6
  • camel-cloudevents ← downstream of org.apache.camel:camel-test-junit6
  • camel-cm-sms ← downstream of org.apache.camel:camel-test-spring-junit6
  • camel-coap ← downstream of org.apache.camel:camel-test-junit6
  • camel-cometd ← downstream of org.apache.camel:camel-test-junit6
  • camel-console ← downstream of org.apache.camel:camel-core
  • camel-consul ← downstream of org.apache.camel:camel-file
  • camel-core ← downstream of org.apache.camel:camel-core-engine
  • camel-core-all ← downstream of org.apache.camel:camel-core-engine
  • camel-core-engine ← core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultDumpRoutesStrategy.java
  • camel-core-xml ← downstream of org.apache.camel:camel-core-engine
  • camel-couchbase ← downstream of org.apache.camel:camel-test-junit6
  • camel-couchdb ← downstream of org.apache.camel:camel-test-junit6
  • camel-cron ← downstream of org.apache.camel:camel-test-junit6
  • camel-crypto ← downstream of org.apache.camel:camel-test-spring-junit6
  • camel-crypto-pgp ← downstream of org.apache.camel:camel-test-spring-junit6
  • camel-csv ← downstream of org.apache.camel:camel-main
  • camel-cxf-common ← downstream of org.apache.camel:camel-test-junit6
  • camel-cxf-rest ← downstream of org.apache.camel:camel-test-junit6
  • camel-cxf-soap ← downstream of org.apache.camel:camel-test-junit6
  • camel-cxf-spring-common ← downstream of org.apache.camel:camel-spring-xml
  • camel-cxf-spring-rest ← downstream of org.apache.camel:camel-core-xml
  • camel-cxf-spring-soap ← downstream of org.apache.camel:camel-spring
  • camel-cxf-spring-transport ← downstream of org.apache.camel:camel-test-junit6
  • camel-cxf-transport ← downstream of org.apache.camel:camel-test-junit6
  • camel-cyberark-vault ← downstream of org.apache.camel:camel-test-junit6
  • camel-dapr ← downstream of org.apache.camel:camel-test-junit6
  • camel-datasonnet ← downstream of org.apache.camel:camel-core
  • camel-debezium-common ← downstream of org.apache.camel:camel-test-junit6
  • camel-debezium-db2 ← downstream of org.apache.camel:camel-test-junit6
  • camel-debezium-maven-plugin ← downstream of org.apache.camel:camel-test-junit6
  • camel-debezium-mongodb ← downstream of org.apache.camel:camel-test-junit6
  • camel-debezium-mysql ← downstream of org.apache.camel:camel-test-junit6
  • camel-debezium-oracle ← downstream of org.apache.camel:camel-test-junit6
  • camel-debezium-postgres ← downstream of org.apache.camel:camel-test-junit6
  • camel-debezium-sqlserver ← downstream of org.apache.camel:camel-test-junit6
  • camel-debug ← downstream of org.apache.camel:camel-management
  • camel-dfdl ← downstream of org.apache.camel:camel-test-junit6
  • camel-dhis2 ← downstream of org.apache.camel:camel-test-junit6
  • camel-dhis2-api ← downstream of org.apache.camel:camel-test-junit6
  • camel-dhis2-parent ← downstream of org.apache.camel:camel-test-junit6
  • camel-diagram ← downstream of org.apache.camel:camel-management
  • camel-disruptor ← downstream of org.apache.camel:camel-test-junit6
  • camel-djl ← downstream of org.apache.camel:camel-test-junit6
  • camel-dns ← downstream of org.apache.camel:camel-test-spring-junit6
  • camel-docker ← downstream of org.apache.camel:camel-test-junit6
  • camel-docling ← downstream of org.apache.camel:camel-test-junit6
  • camel-drill ← downstream of org.apache.camel:camel-test-junit6
  • camel-dropbox ← downstream of org.apache.camel:camel-test-junit6
  • camel-dsl-modeline ← downstream of org.apache.camel:camel-test-junit6
  • camel-duckdb ← downstream of org.apache.camel:camel-test-junit6
  • camel-dynamic-router ← downstream of org.apache.camel:camel-management
  • camel-ehcache ← downstream of org.apache.camel:camel-test-junit6
  • camel-elasticsearch ← downstream of org.apache.camel:camel-test-junit6
  • camel-elasticsearch-rest-client ← downstream of org.apache.camel:camel-test-junit6
  • camel-event ← downstream of org.apache.camel:camel-test-junit6
  • camel-exec ← downstream of org.apache.camel:camel-test-spring-junit6
  • camel-fastjson ← downstream of org.apache.camel:camel-test-spring-junit6
  • camel-fhir ← downstream of org.apache.camel:camel-test-junit6
  • camel-file ← downstream of org.apache.camel:camel-core-engine
  • camel-file-watch ← downstream of org.apache.camel:camel-test-spring-junit6
  • camel-flatpack ← downstream of org.apache.camel:camel-core-engine
  • camel-flink ← downstream of org.apache.camel:camel-test-junit6
  • camel-flowable ← downstream of org.apache.camel:camel-test-junit6
  • camel-fop ← downstream of org.apache.camel:camel-test-junit6
  • camel-fory ← downstream of org.apache.camel:camel-test-spring-junit6
  • camel-freemarker ← downstream of org.apache.camel:camel-management
  • camel-ftp ← downstream of org.apache.camel:camel-test-junit6
  • camel-ftp-common ← downstream of org.apache.camel:camel-file
  • camel-geocoder ← downstream of org.apache.camel:camel-test-junit6
  • camel-git ← downstream of org.apache.camel:camel-test-junit6
  • camel-github2 ← downstream of org.apache.camel:camel-test-junit6
  • camel-google-bigquery ← downstream of org.apache.camel:camel-test-junit6
  • camel-google-calendar ← downstream of org.apache.camel:camel-test-junit6
  • camel-google-common ← downstream of org.apache.camel:camel-core
  • camel-google-drive ← downstream of org.apache.camel:camel-file
  • camel-google-firestore ← downstream of org.apache.camel:camel-test-junit6
  • camel-google-functions ← downstream of org.apache.camel:camel-test-junit6
  • camel-google-mail ← downstream of org.apache.camel:camel-test-junit6
  • camel-google-pubsub ← downstream of org.apache.camel:camel-test-junit6
  • camel-google-secret-manager ← downstream of org.apache.camel:camel-test-junit6
  • camel-google-sheets ← downstream of org.apache.camel:camel-test-junit6
  • camel-google-speech-to-text ← downstream of org.apache.camel:camel-test-junit6
  • camel-google-storage ← downstream of org.apache.camel:camel-test-junit6
  • camel-google-text-to-speech ← downstream of org.apache.camel:camel-test-junit6
  • camel-google-vertexai ← downstream of org.apache.camel:camel-test-junit6
  • camel-google-vision ← downstream of org.apache.camel:camel-test-junit6
  • camel-graphql ← downstream of org.apache.camel:camel-test-junit6
  • camel-grok ← downstream of org.apache.camel:camel-test-spring-junit6
  • camel-groovy ← downstream of org.apache.camel:camel-core
  • camel-grpc ← downstream of org.apache.camel:camel-test-junit6
  • camel-gson ← downstream of org.apache.camel:camel-test-spring-junit6
  • camel-hashicorp-vault ← downstream of org.apache.camel:camel-test-junit6
  • camel-hazelcast ← downstream of org.apache.camel:camel-test-spring-junit6
  • camel-hivemq ← downstream of org.apache.camel:camel-test-junit6
  • camel-hl7 ← downstream of org.apache.camel:camel-core-engine
  • camel-http ← downstream of org.apache.camel:camel-file
  • camel-http-base ← downstream of org.apache.camel:camel-test-junit6
  • camel-http-common ← downstream of org.apache.camel:camel-test-junit6
  • camel-huaweicloud-dms ← downstream of org.apache.camel:camel-test-junit6
  • camel-huaweicloud-frs ← downstream of org.apache.camel:camel-test-spring-junit6
  • camel-huaweicloud-functiongraph ← downstream of org.apache.camel:camel-test-junit6
  • camel-huaweicloud-iam ← downstream of org.apache.camel:camel-test-junit6
  • camel-huaweicloud-imagerecognition ← downstream of org.apache.camel:camel-test-spring-junit6
  • camel-huaweicloud-obs ← downstream of org.apache.camel:camel-test-junit6
  • camel-huaweicloud-smn ← downstream of org.apache.camel:camel-test-spring-junit6
  • camel-huggingface ← downstream of org.apache.camel:camel-test-junit6
  • camel-ibm-cos ← downstream of org.apache.camel:camel-test-junit6
  • camel-ibm-secrets-manager ← downstream of org.apache.camel:camel-test-junit6
  • camel-ibm-watson-discovery ← downstream of org.apache.camel:camel-test-junit6
  • camel-ibm-watson-language ← downstream of org.apache.camel:camel-test-junit6
  • camel-ibm-watson-speech-to-text ← downstream of org.apache.camel:camel-test-junit6
  • camel-ibm-watson-text-to-speech ← downstream of org.apache.camel:camel-test-junit6
  • camel-ibm-watsonx-ai ← downstream of org.apache.camel:camel-test-junit6
  • camel-ibm-watsonx-data ← downstream of org.apache.camel:camel-test-junit6
  • camel-ical ← downstream of org.apache.camel:camel-test-junit6
  • camel-iggy ← downstream of org.apache.camel:camel-test-junit6
  • camel-ignite ← downstream of org.apache.camel:camel-test-junit6
  • camel-infinispan ← downstream of org.apache.camel:camel-test-junit6
  • camel-infinispan-common ← downstream of org.apache.camel:camel-test-junit6
  • camel-infinispan-embedded ← downstream of org.apache.camel:camel-test-junit6
  • camel-influxdb ← downstream of org.apache.camel:camel-test-junit6
  • camel-influxdb2 ← downstream of org.apache.camel:camel-test-junit6
  • camel-iso8583 ← downstream of org.apache.camel:camel-jackson
  • camel-jackson ← downstream of org.apache.camel:camel-core-engine
  • camel-jackson-avro ← downstream of org.apache.camel:camel-test-junit6
  • camel-jackson-protobuf ← downstream of org.apache.camel:camel-test-junit6
  • camel-jackson3 ← downstream of org.apache.camel:camel-core-engine
  • camel-jackson3-avro ← downstream of org.apache.camel:camel-test-junit6
  • camel-jackson3-protobuf ← downstream of org.apache.camel:camel-test-junit6
  • camel-jackson3xml ← downstream of org.apache.camel:camel-test-spring-junit6
  • camel-jacksonxml ← downstream of org.apache.camel:camel-test-spring-junit6
  • camel-jactl ← downstream of org.apache.camel:camel-core
  • camel-jandex ← downstream of org.apache.camel:camel-test-junit6
  • camel-jasypt ← downstream of org.apache.camel:camel-test-spring-junit6
  • camel-java-io ← downstream of org.apache.camel:camel-core-engine
  • camel-java-joor-dsl ← downstream of org.apache.camel:camel-rest
  • camel-javascript ← downstream of org.apache.camel:camel-core
  • camel-jaxb ← downstream of org.apache.camel:camel-test-junit6
  • camel-jbang-console ← downstream of org.apache.camel:camel-management
  • camel-jbang-mcp ← downstream of org.apache.camel:camel-yaml-io
  • camel-jbang-plugin-mcp ← downstream of org.apache.camel:camel-jbang-core
  • camel-jbang-plugin-route-parser ← downstream of org.apache.camel:camel-jbang-core
  • camel-jbang-plugin-tui ← downstream of org.apache.camel:camel-test-junit6
  • camel-jbang-plugin-validate ← downstream of org.apache.camel:camel-test-junit6
  • camel-jcache ← downstream of org.apache.camel:camel-test-junit6
  • camel-jcr ← downstream of org.apache.camel:camel-test-junit6
  • camel-jdbc ← downstream of org.apache.camel:camel-test-spring-junit6
  • camel-jetty ← downstream of org.apache.camel:camel-management
  • camel-jetty-common ← downstream of org.apache.camel:camel-jackson
  • camel-jfr ← downstream of org.apache.camel:camel-test-junit6
  • camel-jgroups ← downstream of org.apache.camel:camel-test-junit6
  • camel-jgroups-raft ← downstream of org.apache.camel:camel-test-junit6
  • camel-jira ← downstream of org.apache.camel:camel-file
  • camel-jms ← downstream of org.apache.camel:camel-management
  • camel-jmx ← downstream of org.apache.camel:camel-management
  • camel-jolt ← downstream of org.apache.camel:camel-test-junit6
  • camel-jooq ← downstream of org.apache.camel:camel-test-junit6
  • camel-joor ← downstream of org.apache.camel:camel-core
  • camel-jpa ← downstream of org.apache.camel:camel-test-junit6
  • camel-jq ← downstream of org.apache.camel:camel-core
  • camel-jsch ← downstream of org.apache.camel:camel-test-junit6
  • camel-jslt ← downstream of org.apache.camel:camel-test-junit6
  • camel-json-validator ← downstream of org.apache.camel:camel-test-junit6
  • camel-jsonapi ← downstream of org.apache.camel:camel-test-junit6
  • camel-jsonata ← downstream of org.apache.camel:camel-test-junit6
  • camel-jsonb ← downstream of org.apache.camel:camel-test-spring-junit6
  • camel-jsonpath ← downstream of org.apache.camel:camel-file
  • camel-jsoup ← downstream of org.apache.camel:camel-test-junit6
  • camel-jt400 ← downstream of org.apache.camel:camel-test-junit6
  • camel-jta ← downstream of org.apache.camel:camel-core-engine
  • camel-jte ← downstream of org.apache.camel:camel-test-junit6
  • camel-kafka ← downstream of org.apache.camel:camel-test-junit6
  • camel-kafka-common ← downstream of org.apache.camel:camel-test-junit6
  • camel-kafka-share ← downstream of org.apache.camel:camel-test-junit6
  • camel-kamelet ← downstream of org.apache.camel:camel-management
  • camel-kamelet-main-support ← downstream of org.apache.camel:camel-main
  • camel-keycloak ← downstream of org.apache.camel:camel-test-junit6
  • camel-knative ← downstream of org.apache.camel:camel-test-junit6
  • camel-knative-api ← downstream of org.apache.camel:camel-test-junit6
  • camel-knative-http ← downstream of org.apache.camel:camel-test-junit6
  • camel-kserve ← downstream of org.apache.camel:camel-test-junit6
  • camel-kubernetes ← downstream of org.apache.camel:camel-http
  • camel-kudu ← downstream of org.apache.camel:camel-test-junit6
  • camel-langchain4j-agent ← downstream of org.apache.camel:camel-test-junit6
  • camel-langchain4j-chat ← downstream of org.apache.camel:camel-test-junit6
  • camel-langchain4j-core ← downstream of org.apache.camel:camel-test-junit6
  • camel-langchain4j-embeddings ← downstream of org.apache.camel:camel-test-junit6
  • camel-langchain4j-embeddingstore ← downstream of org.apache.camel:camel-test-junit6
  • camel-langchain4j-ingest ← downstream of org.apache.camel:camel-test-junit6
  • camel-langchain4j-tokenizer ← downstream of org.apache.camel:camel-test-junit6
  • camel-langchain4j-web-search ← downstream of org.apache.camel:camel-test-junit6
  • camel-launcher-container ← downstream of org.apache.camel:camel-launcher
  • camel-ldap ← downstream of org.apache.camel:camel-test-junit6
  • camel-ldif ← downstream of org.apache.camel:camel-test-junit6
  • camel-lra ← downstream of org.apache.camel:camel-core-engine
  • camel-lucene ← downstream of org.apache.camel:camel-test-junit6
  • camel-lumberjack ← downstream of org.apache.camel:camel-test-junit6
  • camel-lzf ← downstream of org.apache.camel:camel-test-junit6
  • camel-mail ← downstream of org.apache.camel:camel-test-spring-junit6
  • camel-mail-microsoft-oauth ← downstream of org.apache.camel:camel-mail
  • camel-main ← downstream of org.apache.camel:camel-core-engine
  • camel-management ← downstream of org.apache.camel:camel-core-engine
  • camel-mapstruct ← downstream of org.apache.camel:camel-test-junit6
  • camel-master ← downstream of org.apache.camel:camel-test-junit6
  • camel-maven-plugin ← downstream of org.apache.camel:camel-core
  • camel-mcp-server ← downstream of org.apache.camel:camel-test-junit6
  • camel-mcp-server-api ← downstream of org.apache.camel:camel-test-junit6
  • camel-mdc ← downstream of org.apache.camel:camel-test-spring-junit6
  • camel-metrics ← downstream of org.apache.camel:camel-management
  • camel-micrometer ← downstream of org.apache.camel:camel-management
  • camel-micrometer-observability ← downstream of org.apache.camel:camel-undertow
  • camel-micrometer-prometheus ← downstream of org.apache.camel:camel-micrometer
  • camel-microprofile-config ← downstream of org.apache.camel:camel-test-junit6
  • camel-microprofile-fault-tolerance ← downstream of org.apache.camel:camel-management
  • camel-microprofile-health ← downstream of org.apache.camel:camel-test-junit6
  • camel-milo ← downstream of org.apache.camel:camel-test-junit6
  • camel-milvus ← downstream of org.apache.camel:camel-test-junit6
  • camel-mina ← downstream of org.apache.camel:camel-test-spring-junit6
  • camel-mina-sftp ← downstream of org.apache.camel:camel-test-junit6
  • camel-minio ← downstream of org.apache.camel:camel-test-spring-junit6
  • camel-mllp ← downstream of org.apache.camel:camel-test-junit6
  • camel-mongodb ← downstream of org.apache.camel:camel-test-junit6
  • camel-mongodb-gridfs ← downstream of org.apache.camel:camel-test-junit6
  • camel-mustache ← downstream of org.apache.camel:camel-test-junit6
  • camel-mvel ← downstream of org.apache.camel:camel-core
  • camel-mybatis ← downstream of org.apache.camel:camel-test-junit6
  • camel-nats ← downstream of org.apache.camel:camel-test-junit6
  • camel-neo4j ← downstream of org.apache.camel:camel-test-junit6
  • camel-netty ← downstream of org.apache.camel:camel-management
  • camel-netty-http ← downstream of org.apache.camel:camel-management
  • camel-oaipmh ← downstream of org.apache.camel:camel-test-spring-junit6
  • camel-oauth ← downstream of org.apache.camel:camel-test-junit6
  • camel-observability-services ← downstream of org.apache.camel:camel-management
  • camel-observation ← downstream of org.apache.camel:camel-test-spring-junit6
  • camel-ocsf ← downstream of org.apache.camel:camel-test-junit6
  • camel-odata ← downstream of org.apache.camel:camel-test-junit6
  • camel-ognl ← downstream of org.apache.camel:camel-core
  • camel-olingo2 ← downstream of org.apache.camel:camel-test-junit6
  • camel-olingo2-api ← downstream of org.apache.camel:camel-test-junit6
  • camel-olingo4 ← downstream of org.apache.camel:camel-test-junit6
  • camel-olingo4-api ← downstream of org.apache.camel:camel-test-junit6
  • camel-once ← downstream of org.apache.camel:camel-test-junit6
  • camel-opa ← downstream of org.apache.camel:camel-test-junit6
  • camel-openai ← downstream of org.apache.camel:camel-file
  • camel-openapi-java ← downstream of org.apache.camel:camel-core-engine
  • camel-openapi-rest-dsl-generator ← downstream of org.apache.camel:camel-core-engine
  • camel-openapi-validator ← downstream of org.apache.camel:camel-test-junit6
  • camel-openfeature ← downstream of org.apache.camel:camel-test-junit6
  • camel-openfga ← downstream of org.apache.camel:camel-test-junit6
  • camel-opensearch ← downstream of org.apache.camel:camel-test-junit6
  • camel-openstack ← downstream of org.apache.camel:camel-test-junit6
  • camel-opentelemetry ← downstream of org.apache.camel:camel-undertow
  • camel-opentelemetry-metrics ← downstream of org.apache.camel:camel-test-spring-junit6
  • camel-opentelemetry2 ← downstream of org.apache.camel:camel-undertow
  • camel-optaplanner ← downstream of org.apache.camel:camel-test-spring-junit6
  • camel-paho ← downstream of org.apache.camel:camel-test-junit6
  • camel-paho-mqtt5 ← downstream of org.apache.camel:camel-test-junit6
  • camel-parquet-avro ← downstream of org.apache.camel:camel-test-junit6
  • camel-pdf ← downstream of org.apache.camel:camel-test-junit6
  • camel-pg-replication-slot ← downstream of org.apache.camel:camel-test-junit6
  • camel-pgevent ← downstream of org.apache.camel:camel-test-junit6
  • camel-pgvector ← downstream of org.apache.camel:camel-test-junit6
  • camel-pinecone ← downstream of org.apache.camel:camel-test-junit6
  • camel-platform-http ← downstream of org.apache.camel:camel-test-junit6
  • camel-platform-http-jolokia ← downstream of org.apache.camel:camel-core
  • camel-platform-http-main ← downstream of org.apache.camel:camel-test-junit6
  • camel-platform-http-vertx ← downstream of org.apache.camel:camel-file
  • camel-plc4x ← downstream of org.apache.camel:camel-test-junit6
  • camel-pqc ← downstream of org.apache.camel:camel-test-junit6
  • camel-printer ← downstream of org.apache.camel:camel-test-junit6
  • camel-protobuf ← downstream of org.apache.camel:camel-test-spring-junit6
  • camel-pubnub ← downstream of org.apache.camel:camel-test-junit6
  • camel-pulsar ← downstream of org.apache.camel:camel-test-junit6
  • camel-python ← downstream of org.apache.camel:camel-core
  • camel-python3 ← downstream of org.apache.camel:camel-core
  • camel-qdrant ← downstream of org.apache.camel:camel-test-junit6
  • camel-quartz ← downstream of org.apache.camel:camel-management
  • camel-quickfix ← downstream of org.apache.camel:camel-test-spring-junit6
  • camel-quickjs ← downstream of org.apache.camel:camel-core
  • camel-reactive-streams ← downstream of org.apache.camel:camel-core-engine
  • camel-reactor ← downstream of org.apache.camel:camel-test-junit6
  • camel-redis ← downstream of org.apache.camel:camel-test-junit6
  • camel-resilience4j ← downstream of org.apache.camel:camel-management
  • camel-resilience4j-micrometer ← downstream of org.apache.camel:camel-management
  • camel-resourceresolver-github ← downstream of org.apache.camel:camel-test-junit6
  • camel-rest ← downstream of org.apache.camel:camel-core-engine
  • camel-rest-openapi ← downstream of org.apache.camel:camel-rest
  • camel-rest-postman ← downstream of org.apache.camel:camel-rest
  • camel-restdsl-openapi-plugin ← downstream of org.apache.camel:camel-core-engine
  • camel-robotframework ← downstream of org.apache.camel:camel-test-junit6
  • camel-rocketmq ← downstream of org.apache.camel:camel-test-junit6
  • camel-rss ← downstream of org.apache.camel:camel-test-junit6
  • camel-rxjava ← downstream of org.apache.camel:camel-test-junit6
  • camel-salesforce ← downstream of org.apache.camel:camel-core-engine
  • camel-salesforce-codegen ← downstream of org.apache.camel:camel-salesforce
  • camel-sap-netweaver ← downstream of org.apache.camel:camel-test-junit6
  • camel-saxon ← downstream of org.apache.camel:camel-core
  • camel-schematron ← downstream of org.apache.camel:camel-test-junit6
  • camel-semantic ← downstream of org.apache.camel:camel-test-junit6
  • camel-servicenow ← downstream of org.apache.camel:camel-test-junit6
  • camel-servicenow-maven-plugin ← downstream of org.apache.camel:camel-core-engine
  • camel-servlet ← downstream of org.apache.camel:camel-management
  • camel-shell ← downstream of org.apache.camel:camel-test-junit5
  • camel-shiro ← downstream of org.apache.camel:camel-test-junit6
  • camel-sjms ← downstream of org.apache.camel:camel-test-junit6
  • camel-sjms2 ← downstream of org.apache.camel:camel-test-junit6
  • camel-slack ← downstream of org.apache.camel:camel-test-junit6
  • camel-smb ← downstream of org.apache.camel:camel-file
  • camel-smooks ← downstream of org.apache.camel:camel-test-junit6
  • camel-smpp ← downstream of org.apache.camel:camel-test-spring-junit6
  • camel-snakeyaml ← downstream of org.apache.camel:camel-test-spring-junit6
  • camel-snmp ← downstream of org.apache.camel:camel-test-junit6
  • camel-soap ← downstream of org.apache.camel:camel-test-junit6
  • camel-solr ← downstream of org.apache.camel:camel-test-junit6
  • camel-spiffe ← downstream of org.apache.camel:camel-test-junit6
  • camel-splunk-hec ← downstream of org.apache.camel:camel-test-junit6
  • camel-spring ← downstream of org.apache.camel:camel-core-engine
  • camel-spring-ai-chat ← downstream of org.apache.camel:camel-test-junit6
  • camel-spring-ai-embeddings ← downstream of org.apache.camel:camel-test-junit6
  • camel-spring-ai-image ← downstream of org.apache.camel:camel-test-junit6
  • camel-spring-ai-vector-store ← downstream of org.apache.camel:camel-test-junit6
  • camel-spring-batch ← downstream of org.apache.camel:camel-test-junit6
  • camel-spring-cloud-config ← downstream of org.apache.camel:camel-test-junit6
  • camel-spring-jdbc ← downstream of org.apache.camel:camel-test-spring-junit6
  • camel-spring-ldap ← downstream of org.apache.camel:camel-test-spring-junit6
  • camel-spring-main ← downstream of org.apache.camel:camel-spring
  • camel-spring-rabbitmq ← downstream of org.apache.camel:camel-http
  • camel-spring-redis ← downstream of org.apache.camel:camel-test-junit6
  • camel-spring-security ← downstream of org.apache.camel:camel-core-engine
  • camel-spring-ws ← downstream of org.apache.camel:camel-spring
  • camel-spring-xml ← downstream of org.apache.camel:camel-core
  • camel-sql ← downstream of org.apache.camel:camel-test-spring-junit6
  • camel-ssh ← downstream of org.apache.camel:camel-test-junit6
  • camel-state-store ← downstream of org.apache.camel:camel-test-main-junit5
  • camel-stax ← downstream of org.apache.camel:camel-core
  • camel-stitch ← downstream of org.apache.camel:camel-test-junit6
  • camel-stream ← downstream of org.apache.camel:camel-test-junit6
  • camel-streamcaching-test ← downstream of org.apache.camel:camel-core
  • camel-stringtemplate ← downstream of org.apache.camel:camel-management
  • camel-stripe ← downstream of org.apache.camel:camel-test-junit6
  • camel-swift ← downstream of org.apache.camel:camel-test-junit6
  • camel-syslog ← downstream of org.apache.camel:camel-test-spring-junit6
  • camel-tahu ← downstream of org.apache.camel:camel-test-junit6
  • camel-tarfile ← downstream of org.apache.camel:camel-file
  • camel-telegram ← downstream of org.apache.camel:camel-test-junit6
  • camel-telemetry ← downstream of org.apache.camel:camel-undertow
  • camel-telemetry-dev ← downstream of org.apache.camel:camel-undertow
  • camel-tensorflow-serving ← downstream of org.apache.camel:camel-test-junit6
  • camel-test-infra-all ← downstream of org.apache.camel:camel-test-infra-artemis
  • camel-test-infra-artemis ← downstream of org.apache.camel:camel-test-junit6
  • camel-test-infra-core ← downstream of org.apache.camel:camel-core
  • camel-test-infra-smb ← downstream of org.apache.camel:camel-test-junit6
  • camel-test-junit5 ← downstream of org.apache.camel:camel-core-engine
  • camel-test-junit6 ← downstream of org.apache.camel:camel-core-engine
  • camel-test-main-junit5 ← downstream of org.apache.camel:camel-yaml-io
  • camel-test-main-junit6 ← downstream of org.apache.camel:camel-yaml-io
  • camel-test-spring-junit5 ← downstream of org.apache.camel:camel-management
  • camel-test-spring-junit6 ← downstream of org.apache.camel:camel-management
  • camel-thrift ← downstream of org.apache.camel:camel-test-spring-junit6
  • camel-thymeleaf ← downstream of org.apache.camel:camel-management
  • camel-tika ← downstream of org.apache.camel:camel-test-spring-junit6
  • camel-toon ← downstream of org.apache.camel:camel-test-junit5
  • camel-tracing ← downstream of org.apache.camel:camel-test-spring-junit6
  • camel-twilio ← downstream of org.apache.camel:camel-test-junit6
  • camel-twitter ← downstream of org.apache.camel:camel-test-junit6
  • camel-typesafe-ai ← downstream of org.apache.camel:camel-test-junit6
  • camel-ubl ← downstream of org.apache.camel:camel-test-junit5
  • camel-undertow ← downstream of org.apache.camel:camel-rest
  • camel-undertow-spring-security ← downstream of org.apache.camel:camel-test-junit6
  • camel-univocity-parsers ← downstream of org.apache.camel:camel-core-xml
  • camel-velocity ← downstream of org.apache.camel:camel-management
  • camel-vertx ← downstream of org.apache.camel:camel-test-junit6
  • camel-vertx-http ← downstream of org.apache.camel:camel-rest
  • camel-vertx-websocket ← downstream of org.apache.camel:camel-test-junit6
  • camel-wasm ← downstream of org.apache.camel:camel-test-junit6
  • camel-weather ← downstream of org.apache.camel:camel-test-junit6
  • camel-weaviate ← downstream of org.apache.camel:camel-test-junit6
  • camel-web3j ← downstream of org.apache.camel:camel-test-junit6
  • camel-webhook ← downstream of org.apache.camel:camel-test-junit6
  • camel-whatsapp ← downstream of org.apache.camel:camel-test-junit6
  • camel-wolf-defender ← downstream of org.apache.camel:camel-test-junit6
  • camel-wordpress ← downstream of org.apache.camel:camel-test-junit6
  • camel-workday ← downstream of org.apache.camel:camel-test-junit6
  • camel-xchange ← downstream of org.apache.camel:camel-test-junit6
  • camel-xj ← downstream of org.apache.camel:camel-test-junit6
  • camel-xml-io-dsl ← downstream of org.apache.camel:camel-core-engine
  • camel-xml-jaxb-dsl ← downstream of org.apache.camel:camel-rest
  • camel-xml-jaxb-dsl-test-definition ← downstream of org.apache.camel:camel-rest
  • camel-xml-jaxb-dsl-test-spring ← downstream of org.apache.camel:camel-rest
  • camel-xmlsecurity ← downstream of org.apache.camel:camel-test-junit6
  • camel-xmpp ← downstream of org.apache.camel:camel-test-junit6
  • camel-xslt-saxon ← downstream of org.apache.camel:camel-spring-xml
  • camel-yaml-dsl-common ← downstream of org.apache.camel:camel-core-engine
  • camel-yaml-dsl-validator ← downstream of org.apache.camel:camel-yaml-io
  • camel-yaml-dsl-validator-maven-plugin ← downstream of org.apache.camel:camel-yaml-dsl-validator
  • camel-yaml-io ← core/camel-yaml-io/src/main/java/org/apache/camel/yaml/LwModelToYAMLDumper.java
  • camel-zendesk ← downstream of org.apache.camel:camel-test-junit6
  • camel-zip-deflater ← downstream of org.apache.camel:camel-test-junit6
  • camel-zipfile ← downstream of org.apache.camel:camel-file
  • camel-zookeeper ← downstream of org.apache.camel:camel-file
  • camel-zookeeper-master ← downstream of org.apache.camel:camel-test-junit6
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-salesforce-maven-plugin
  • 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

Build reactor — dependencies compiled but only changed modules were tested (3 modules, 36.0s total)

Total reactor time: 36.0s

Module Duration Status
Camel :: YAML DSL 15.7s SUCCESS
Camel :: YAML IO 11.5s SUCCESS
Camel :: Core Engine 8.7s SUCCESS

Top 20 slowest modules:

  • Camel :: YAML DSL (15.7s)
  • Camel :: YAML IO (11.5s)
  • Camel :: Core Engine (8.7s)

⚙️ View full build and test results

…ether when they go into one YAML file

When the routes are dumped into a single file (dumpRoutesOutput is a file,
as camel validate normalize does), the routes of each source file were
dumped separately and appended, so the top-level onException of a second
file came after the routes of the first file, which the YAML DSL loader
rejects. The routes of all the files are now dumped together, so every
top-level onException comes before the first route.
@Croway
Croway requested a review from davsclaus October 9, 2026 08:37

@gnodet-bot gnodet-bot 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.

Reviewed the new YAML dump normalization logic — the approach is clean and the test coverage looks good. One null-safety concern in the newly added helper methods.

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

… a route configuration

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@gnodet-bot gnodet-bot 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.

Re-review after latest commits: both prior findings (null guard in containsInstance) are fully addressed. Deep trace of the context-scoped OE lifecycle confirms the collection, filtering, and top-level emission logic is correct across all paths — started/not-started, route-configuration OEs, and multi-file dump. LGTM.

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

@davsclaus davsclaus 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.

Thanks @Croway, this is a careful fix with a good write-up, and the round-trip test with schema validation is exactly the right way to pin it. The single-file case reported in CAMEL-25490 looks correct to me:

  • Filtering by identity is safe: RoutesDefinition.prepareRoute adds the OnExceptionDefinition instances of the RouteBuilder and of the route configurations themselves to each route (oe.addAll(g.getOnExceptions())), as design/cross-cutting-binding.adoc also notes ("the lists are new, the definitions are not").
  • routeScoped defaults to true, so route scoped and not-yet-prepared onExceptions are still written as steps.

A few points, none blocking on their own; the first one is a design question worth settling before the backport (#27610) follows:

  1. Several files into one output widens the scope of a top-level onException (inline on DefaultDumpRoutesStrategy). camel validate normalize always writes one file, also for the documented --output normalized/ routes/*.yaml, so the normalized output now changes the error handling of the routes of the other files without telling the user.

  2. Upgrade guide. This changes what YAML route dumps look like (camel.main.dumpRoutes=yaml, JMX dumpRouteAsYaml / dumpRoutesAsYaml, the route-dump dev console) and how dumpRoutesOutput=<file> groups the routes. camel-4x-upgrade-guide-4_23.adoc already has a Route dumps as YAML and Java section (CAMEL-25255) where a short paragraph would fit, for example: a top-level onException (of a YAML file or a RouteBuilder) is written once as a top-level onException before the routes instead of as a step of every route; the onException of a route configuration is no longer written in the routes; when the routes are dumped into one file, the routes of all the source files are dumped together, so a top-level onException applies to all of them when the dump is loaded. If the backport also gets a note for 4.22.2, it goes into camel-4x-upgrade-guide-4_22.adoc on main.

  3. Per-route YAML views (inline on LwModelToYAMLDumper): question about the JMX / dev console / TUI output, and a missing test for the single-route path.

  4. Test YAML (inline): canonical form for the new test input, and an assertion that makes the scope change in the multi-file test explicit.

  5. Attribution (CLAUDE.md, "Attribution"): the last commit carries a Co-Authored-By: Claude trailer and the replies are signed as Claude Code, but the PR description has no AI attribution line; please add one, and keep the Co-Authored-By trailer in the squash commit (the first two commits do not have it).

CI: only the three changed modules were tested (dependents skipped, over the threshold). I looked at the YAML dump tests of camel-core, camel-management, camel-console, camel-kamelet, camel-jbang and camel-yaml-dsl-validator: none dumps a prepared route with a context scoped onException, so I do not expect breakage there.


Claude Code on behalf of @davsclaus. This is a rules-and-conventions review; it does not replace CodeRabbit, Sourcery or SonarCloud.

This review was generated by an AI agent and may contain inaccuracies. Please verify all suggestions before applying.

}
Resource res = route.getResource();
if (res == null) {
if (res == null || outputFileName != null) {

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.

Scope change when several files are dumped into one file. A top-level onException in a YAML file applies only to the routes of that file (YamlRoutesBuilderLoader adds it to the RoutesDefinition of that file). With the routes of all the files dumped together, it is written once at the top and, when the output is loaded, applies to the routes of every file:

  • b.yaml with handled: true for java.lang.Exception now also swallows the errors of the routes of a.yaml;
  • if a.yaml and b.yaml both handle java.lang.Exception, both end up at the top with the same ExceptionPolicyKey (no route id, same class, no onWhen), and ErrorHandlerSupport.addExceptionPolicy keeps the last one, so the routes of a.yaml silently get the handler of b.yaml.

Before this PR the multi-file output failed the schema, but each copy stayed in the routes of its own file. The PR description mentions the wider scope, but nothing tells the user, and camel validate normalize always writes one file (also for the documented --output normalized/ routes/*.yaml). Some options, not necessarily all:

  • a WARN when routes of more than one resource are merged into one file and one of them has a top-level onException (it then applies to the routes of the other files);
  • a follow-up so that camel validate normalize with several files and an output directory writes one file per input file (dumpRoutesOutput as a directory already dumps one file per resource), which keeps the scope exactly;
  • the upgrade-guide note mentioned in the review body.

Smaller point on the same line: with outputFileName != null every route goes under dummy, so a dump into a file with dumpRoutesLog=true (the default) no longer logs the Source: foo.yaml header, even when all the routes come from one file. Merging into one group only when the routes come from more than one resource would keep the single-file case as it was.


List<JsonObject> roots = new ArrayList<>();
try {
for (OnExceptionDefinition oe : topLevel) {

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.

Question: for a single RouteDefinition (JMX ManagedRoute.dumpRouteAsYaml, the route-dump dev console, the TUI source view in YAML) the dump now starts with the top-level onException items before the - route:, and the onException of a route configuration is no longer shown at all, while the XML dump of the same route still shows it inside the route. That looks like the right trade-off for valid YAML, but is it intended for these views? This branch (definition instanceof RouteDefinition) has no test; a small assertion on dumpModelAsYaml(context, context.getRouteDefinition("first"), ...) would pin it.

// the combined dump is valid for the YAML DSL schema and loads
context.removeRouteDefinitions(List.copyOf(context.getRouteDefinitions()));
loadRoutes(yaml);
assertThat(context.getRouteDefinitions()).hasSize(2);

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.

If the wider scope stays, asserting it makes it explicit that the onException of the second file now applies to the route of the first file too:

Suggested change
assertThat(context.getRouteDefinitions()).hasSize(2);
assertThat(context.getRouteDefinitions()).hasSize(2);
// the top-level onException of the second file now applies to the route of the first file as well
assertThat(context.getRouteDefinition("first").getOutputs().get(0)).isInstanceOf(OnExceptionDefinition.class);

Comment on lines +45 to +46
handled:
constant: "true"

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.

Nit: new tests should use the canonical YAML DSL form rather than the classic shorthand (the same applies to lines 92-93 and 129-130):

Suggested change
handled:
constant: "true"
handled:
constant:
expression: "true"

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.

4 participants