This is an automated email from the ASF dual-hosted git repository.

luigidemasi pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 98b448794610eae613f80a3c2825d962ba4be367
Author: Luigi De Masi <[email protected]>
AuthorDate: Tue Sep 29 13:13:43 2026 +0200

    CAMEL-25138: Align semantic XML schema order and declaration ownership
    
    Order semantic declarations before routes in the generated schemas and XML
    writer, with schema validation coverage for routes and camel documents.
    Use the supplied source consistently for question ownership, document the
    reserved model: prefix, and remove redundant XML declaration assignments.
    
    Document Java builder ordering and the runtime route dump limitation:
    direct model exports preserve declarations, but runtime dumps omit them.
    Explain the handwritten semantic serializers in the generator templates.
    
    XML resources are parsed during preparse so shared questions exist before
    route initialization. The loader's pending-cache invalidation is retained
    because a failed batch prevents earlier builders from clearing their input;
    retrying must read corrected resources.
    
    Validation: 928 focused tests passed, 2 skipped; full repository clean
    install with tests skipped; generated XML IO and Spring schema validation;
    formatter validation and import-order checks.
    
    Co-authored-by: Codex <[email protected]>
    Signed-off-by: Luigi De Masi <[email protected]>
---
 .../camel/catalog/docs/semantic-language.adoc      | 22 ++++++++++++++++++----
 .../apache/camel/catalog/schemas/camel-spring.xsd  |  2 +-
 .../apache/camel/catalog/schemas/camel-xml-io.xsd  |  2 +-
 .../src/main/docs/semantic-language.adoc           | 22 ++++++++++++++++++----
 .../DefaultSemanticDefinitionConfigurer.java       |  8 ++------
 .../apache/camel/semantic/SemanticQuestions.java   |  8 ++++++--
 .../camel/semantic/SemanticDeclarationDslTest.java | 18 ++++++++++++++++++
 .../org/apache/camel/model/RoutesDefinition.java   |  2 ++
 .../model/app/SemanticDefinitionConfigurer.java    |  5 ++++-
 .../apache/camel/java/out/JavaDslModelWriter.java  |  2 +-
 .../java/org/apache/camel/xml/out/ModelWriter.java |  2 +-
 .../org/apache/camel/xml/out/ModelWriterTest.java  | 22 ++++++++++++++++++++++
 .../src/test/resources/semantic-routes.xml         |  8 ++++----
 .../org/apache/camel/yaml/out/YamlModelWriter.java |  2 +-
 .../camel/dsl/xml/io/XmlRoutesBuilderLoader.java   |  5 +++--
 .../resources/velocity/model-java-dsl-writer.vm    |  1 +
 .../main/resources/velocity/model-yaml-writer.vm   |  1 +
 17 files changed, 104 insertions(+), 28 deletions(-)

diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/semantic-language.adoc
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/semantic-language.adoc
index 955e180b4208..b2dd15c021d4 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/semantic-language.adoc
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/semantic-language.adoc
@@ -121,16 +121,23 @@ public void configure() {
 ----
 
 Declarations are installed after `configure()` completes and before the routes 
are initialized.
-They can appear before or after the routes that reference them. Use 
`.type("boolean")` with
+They can appear before or after the routes that reference them within the same 
builder.
+When adding builders to a running context, add the builder declaring shared 
questions before
+builders whose routes reference them. Use `.type("boolean")` with
 optional `.threshold(0.8)`, `.uncertainty(0.1)` and 
`.uncertaintyPolicy("non-match")` for boolean
 questions. Use `.type("score")` and successive `.level("description")` calls 
for ordered score
 levels. Java applications can also continue to register immutable 
`SemanticQuestion` definitions
 using `SemanticQuestions.get(context).replace(source, questions)`.
 
+Java/XML declarations reserve source keys beginning with `model:`. For a route 
resource, the
+key is `"model:" + resource.getLocation()`; passing this key and an empty map 
to `replace`
+removes that resource's questions. Reloading the resource installs them again. 
Embedded Java
+builders without a resource receive distinct generated source keys.
+
 === XML declarations
 
 With xref:others:java-xml-io-dsl.adoc[XML DSL], place a `semantic` element 
inside the `camel` or
-`routes` document, alongside the routes:
+`routes` document, before the routes to comply with the XML schema:
 
 [source,xml]
 ----
@@ -156,14 +163,21 @@ With xref:others:java-xml-io-dsl.adoc[XML DSL], place a 
`semantic` element insid
 For boolean questions, `threshold`, `uncertainty` and `uncertaintyPolicy` are 
optional question
 attributes. For score questions, replace the named `criterion` elements with 
ordered
 `level` elements, such as 
`<level>Routine</level><level>Urgent</level><level>Critical</level>`.
-XML declarations are loaded before route references are initialized, including 
declarations
-after a route or in another resource loaded together. Reload replaces the 
source's questions;
+XML declarations are loaded before route references are initialized, including 
those in another
+resource loaded together. Reload replaces the source's questions;
 removing its declarations or deleting the resource removes obsolete 
definitions.
 
 Both Java and XML declarations require `camel-semantic` and use the same 
context-wide registry,
 validation, defaults and adapters as YAML. They do not require 
`camel-yaml-dsl`. Their questions
 can also be selected together using `refs:name1,name2`, as described below.
 
+=== Exporting declarations
+
+Direct exports of a `RoutesDefinition` containing semantic declarations 
preserve them, as does
+XML-to-YAML conversion. Runtime route dumps such as 
`camel.main.dumpRoutes=yaml` contain only
+the routes and omit the question declarations. Supply the declarations 
separately before
+reloading those dumps.
+
 === Selected state
 
 A question's optional `state` Simple expression overrides
diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd
index 6275aec27673..e30288e5c989 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd
@@ -12898,7 +12898,6 @@ Description of the template parameter for documentation 
purposes.
     <xs:complexContent>
       <xs:extension base="tns:optionalIdentifiedDefinition">
         <xs:sequence>
-          <xs:element maxOccurs="unbounded" minOccurs="0" ref="tns:route"/>
           <xs:element minOccurs="0" name="semantic" 
type="tns:semanticDefinition">
             <xs:annotation>
               <xs:documentation xml:lang="en">
@@ -12908,6 +12907,7 @@ Named semantic question declarations.
               </xs:documentation>
             </xs:annotation>
           </xs:element>
+          <xs:element maxOccurs="unbounded" minOccurs="0" ref="tns:route"/>
         </xs:sequence>
       </xs:extension>
     </xs:complexContent>
diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-xml-io.xsd
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-xml-io.xsd
index 4dcbfe2ffdd2..63270474b9b6 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-xml-io.xsd
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-xml-io.xsd
@@ -12041,7 +12041,6 @@ Description of the template parameter for documentation 
purposes.
     <xs:complexContent>
       <xs:extension base="tns:optionalIdentifiedDefinition">
         <xs:sequence>
-          <xs:element maxOccurs="unbounded" minOccurs="0" ref="tns:route"/>
           <xs:element minOccurs="0" name="semantic" 
type="tns:semanticDefinition">
             <xs:annotation>
               <xs:documentation xml:lang="en">
@@ -12051,6 +12050,7 @@ Named semantic question declarations.
               </xs:documentation>
             </xs:annotation>
           </xs:element>
+          <xs:element maxOccurs="unbounded" minOccurs="0" ref="tns:route"/>
         </xs:sequence>
       </xs:extension>
     </xs:complexContent>
diff --git 
a/components/camel-ai/camel-semantic/src/main/docs/semantic-language.adoc 
b/components/camel-ai/camel-semantic/src/main/docs/semantic-language.adoc
index 955e180b4208..b2dd15c021d4 100644
--- a/components/camel-ai/camel-semantic/src/main/docs/semantic-language.adoc
+++ b/components/camel-ai/camel-semantic/src/main/docs/semantic-language.adoc
@@ -121,16 +121,23 @@ public void configure() {
 ----
 
 Declarations are installed after `configure()` completes and before the routes 
are initialized.
-They can appear before or after the routes that reference them. Use 
`.type("boolean")` with
+They can appear before or after the routes that reference them within the same 
builder.
+When adding builders to a running context, add the builder declaring shared 
questions before
+builders whose routes reference them. Use `.type("boolean")` with
 optional `.threshold(0.8)`, `.uncertainty(0.1)` and 
`.uncertaintyPolicy("non-match")` for boolean
 questions. Use `.type("score")` and successive `.level("description")` calls 
for ordered score
 levels. Java applications can also continue to register immutable 
`SemanticQuestion` definitions
 using `SemanticQuestions.get(context).replace(source, questions)`.
 
+Java/XML declarations reserve source keys beginning with `model:`. For a route 
resource, the
+key is `"model:" + resource.getLocation()`; passing this key and an empty map 
to `replace`
+removes that resource's questions. Reloading the resource installs them again. 
Embedded Java
+builders without a resource receive distinct generated source keys.
+
 === XML declarations
 
 With xref:others:java-xml-io-dsl.adoc[XML DSL], place a `semantic` element 
inside the `camel` or
-`routes` document, alongside the routes:
+`routes` document, before the routes to comply with the XML schema:
 
 [source,xml]
 ----
@@ -156,14 +163,21 @@ With xref:others:java-xml-io-dsl.adoc[XML DSL], place a 
`semantic` element insid
 For boolean questions, `threshold`, `uncertainty` and `uncertaintyPolicy` are 
optional question
 attributes. For score questions, replace the named `criterion` elements with 
ordered
 `level` elements, such as 
`<level>Routine</level><level>Urgent</level><level>Critical</level>`.
-XML declarations are loaded before route references are initialized, including 
declarations
-after a route or in another resource loaded together. Reload replaces the 
source's questions;
+XML declarations are loaded before route references are initialized, including 
those in another
+resource loaded together. Reload replaces the source's questions;
 removing its declarations or deleting the resource removes obsolete 
definitions.
 
 Both Java and XML declarations require `camel-semantic` and use the same 
context-wide registry,
 validation, defaults and adapters as YAML. They do not require 
`camel-yaml-dsl`. Their questions
 can also be selected together using `refs:name1,name2`, as described below.
 
+=== Exporting declarations
+
+Direct exports of a `RoutesDefinition` containing semantic declarations 
preserve them, as does
+XML-to-YAML conversion. Runtime route dumps such as 
`camel.main.dumpRoutes=yaml` contain only
+the routes and omit the question declarations. Supply the declarations 
separately before
+reloading those dumps.
+
 === Selected state
 
 A question's optional `state` Simple expression overrides
diff --git 
a/components/camel-ai/camel-semantic/src/main/java/org/apache/camel/semantic/DefaultSemanticDefinitionConfigurer.java
 
b/components/camel-ai/camel-semantic/src/main/java/org/apache/camel/semantic/DefaultSemanticDefinitionConfigurer.java
index c6da03a7790b..2d7b34e75374 100644
--- 
a/components/camel-ai/camel-semantic/src/main/java/org/apache/camel/semantic/DefaultSemanticDefinitionConfigurer.java
+++ 
b/components/camel-ai/camel-semantic/src/main/java/org/apache/camel/semantic/DefaultSemanticDefinitionConfigurer.java
@@ -48,12 +48,8 @@ public class DefaultSemanticDefinitionConfigurer implements 
SemanticDefinitionCo
                 }
             }
         }
-        if (resource != null) {
-            // A YAML loader can register its own declarations from the same 
resource before its RouteBuilder runs.
-            SemanticQuestions.get(context).replace("model:" + 
resource.getLocation(), resource, questions);
-        } else {
-            SemanticQuestions.get(context).replace(source, questions);
-        }
+        // A YAML loader can register its own declarations from the same 
resource before its RouteBuilder runs.
+        SemanticQuestions.get(context).replace("model:" + source, resource, 
questions);
     }
 
     private static SemanticQuestion question(SemanticQuestionDefinition 
definition) {
diff --git 
a/components/camel-ai/camel-semantic/src/main/java/org/apache/camel/semantic/SemanticQuestions.java
 
b/components/camel-ai/camel-semantic/src/main/java/org/apache/camel/semantic/SemanticQuestions.java
index 5597e348ad5c..cccc22e48ae6 100644
--- 
a/components/camel-ai/camel-semantic/src/main/java/org/apache/camel/semantic/SemanticQuestions.java
+++ 
b/components/camel-ai/camel-semantic/src/main/java/org/apache/camel/semantic/SemanticQuestions.java
@@ -43,7 +43,11 @@ public final class SemanticQuestions {
         }
     }
 
-    /** Replace all definitions from one source; an empty map removes obsolete 
declarations. */
+    /**
+     * Replace all definitions from one source; an empty map removes obsolete 
declarations. Java/XML declarations
+     * reserve the {@code model:} prefix. Resource declarations use {@code 
model:} followed by
+     * {@link Resource#getLocation()}, while embedded Java builders use unique 
generated source keys.
+     */
     public synchronized void replace(String source, Map<String, 
SemanticQuestion> definitions) {
         Map<String, SemanticQuestion> replacement = new HashMap<>();
         sources.forEach((location, entries) -> {
@@ -76,7 +80,7 @@ public final class SemanticQuestions {
     synchronized void replace(String location, Resource source, Map<String, 
SemanticQuestion> definitions) {
         removeDeletedResources();
         replace(location, definitions);
-        if (!definitions.isEmpty() && "file".equals(source.getScheme())) {
+        if (source != null && !definitions.isEmpty() && 
"file".equals(source.getScheme())) {
             resources.put(location, source);
         }
     }
diff --git 
a/components/camel-ai/camel-semantic/src/test/java/org/apache/camel/semantic/SemanticDeclarationDslTest.java
 
b/components/camel-ai/camel-semantic/src/test/java/org/apache/camel/semantic/SemanticDeclarationDslTest.java
index 79b3ca75e1b6..54bef6037643 100644
--- 
a/components/camel-ai/camel-semantic/src/test/java/org/apache/camel/semantic/SemanticDeclarationDslTest.java
+++ 
b/components/camel-ai/camel-semantic/src/test/java/org/apache/camel/semantic/SemanticDeclarationDslTest.java
@@ -223,6 +223,24 @@ class SemanticDeclarationDslTest {
         assertThat(states).isEmpty();
     }
 
+    @ParameterizedTest
+    @ValueSource(booleans = { false, true })
+    void 
declarationSourceCanBeReplacedAndRemovedIndependentlyOfItsResource(boolean 
trackResource) {
+        Resource resource = trackResource ? 
ResourceHelper.fromString("questions.xml", "") : null;
+        SemanticDefinition definition = new SemanticDefinition();
+        definition.question("first").type("boolean").instructions("Valid?");
+        SemanticDefinition.configure(context, resource, "declared-source", 
definition);
+        SemanticDefinition replacement = new SemanticDefinition();
+        
replacement.question("second").type("boolean").instructions("Updated?");
+        SemanticDefinition.configure(context, resource, "declared-source", 
replacement);
+        SemanticQuestions questions = SemanticQuestions.get(context);
+        assertThatThrownBy(() -> 
questions.get("first")).hasMessageContaining("Unknown");
+        assertThat(questions.get("second")).isNotNull();
+        questions.replace("model:declared-source", Map.of());
+        assertThatThrownBy(() -> 
questions.get("second")).hasMessageContaining("Unknown");
+        assertThat(states).isEmpty();
+    }
+
     @Test
     void embeddedBuilderInstancesOwnSeparateDeclarations() throws Exception {
         class Questions extends RouteBuilder {
diff --git 
a/core/camel-core-model/src/main/java/org/apache/camel/model/RoutesDefinition.java
 
b/core/camel-core-model/src/main/java/org/apache/camel/model/RoutesDefinition.java
index 9ca2b1b5b630..f1ae6086fb01 100644
--- 
a/core/camel-core-model/src/main/java/org/apache/camel/model/RoutesDefinition.java
+++ 
b/core/camel-core-model/src/main/java/org/apache/camel/model/RoutesDefinition.java
@@ -27,6 +27,7 @@ import jakarta.xml.bind.annotation.XmlElement;
 import jakarta.xml.bind.annotation.XmlElementRef;
 import jakarta.xml.bind.annotation.XmlRootElement;
 import jakarta.xml.bind.annotation.XmlTransient;
+import jakarta.xml.bind.annotation.XmlType;
 
 import org.apache.camel.CamelContext;
 import org.apache.camel.Endpoint;
@@ -50,6 +51,7 @@ import static 
org.apache.camel.model.RouteDefinitionHelper.routesByIdOrPattern;
  */
 @Metadata(label = "configuration", description = "Container for a collection 
of route definitions")
 @XmlRootElement(name = "routes")
+@XmlType(propOrder = { "semantic", "routes" })
 @XmlAccessorType(XmlAccessType.FIELD)
 public class RoutesDefinition extends 
OptionalIdentifiedDefinition<RoutesDefinition>
         implements RouteContainer, ResourceAware {
diff --git 
a/core/camel-core-model/src/main/java/org/apache/camel/model/app/SemanticDefinitionConfigurer.java
 
b/core/camel-core-model/src/main/java/org/apache/camel/model/app/SemanticDefinitionConfigurer.java
index 141ba19a9323..49977893df9d 100644
--- 
a/core/camel-core-model/src/main/java/org/apache/camel/model/app/SemanticDefinitionConfigurer.java
+++ 
b/core/camel-core-model/src/main/java/org/apache/camel/model/app/SemanticDefinitionConfigurer.java
@@ -21,6 +21,9 @@ import org.apache.camel.spi.Resource;
 
 /** Installs semantic declarations using the optional semantic language 
module. */
 public interface SemanticDefinitionConfigurer {
-    /** Replace the questions belonging to this source, including removing 
obsolete declarations. */
+    /**
+     * Replace the questions belonging to this source, including removing 
obsolete declarations. The source identifies
+     * the owner independently of the optional resource used to track deletion.
+     */
     void configure(CamelContext context, Resource resource, String source, 
SemanticDefinition definition);
 }
diff --git 
a/core/camel-java-io/src/generated/java/org/apache/camel/java/out/JavaDslModelWriter.java
 
b/core/camel-java-io/src/generated/java/org/apache/camel/java/out/JavaDslModelWriter.java
index 42843438f19a..6fd7e0ef9456 100644
--- 
a/core/camel-java-io/src/generated/java/org/apache/camel/java/out/JavaDslModelWriter.java
+++ 
b/core/camel-java-io/src/generated/java/org/apache/camel/java/out/JavaDslModelWriter.java
@@ -2473,8 +2473,8 @@ public class JavaDslModelWriter extends 
JavaDslModelWriterSupport {
     }
     protected void doWriteRoutesDefinition(StringBuilder sb, RoutesDefinition 
def) {
         doWriteOptionalIdentifiedDefinitionAttributes(sb, def);
-        doWriteChildList(sb, "routes", def.getRoutes(), 
this::doWriteRouteDefinitionRef);
         doWriteChildElement(sb, "semantic", def.getSemantic(), 
this::doWriteSemanticDefinition);
+        doWriteChildList(sb, "routes", def.getRoutes(), 
this::doWriteRouteDefinitionRef);
     }
     protected void doWriteRoutingSlipDefinition(StringBuilder sb, 
RoutingSlipDefinition<?> def) {
         doWriteProcessorDefinitionAttributes(sb, def);
diff --git 
a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/out/ModelWriter.java
 
b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/out/ModelWriter.java
index de883785f771..d6a50e2a08bf 100644
--- 
a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/out/ModelWriter.java
+++ 
b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/out/ModelWriter.java
@@ -1684,8 +1684,8 @@ public class ModelWriter extends BaseWriter {
     protected void doWriteRoutesDefinition(String name, RoutesDefinition def) 
throws IOException {
         startElement(name);
         doWriteOptionalIdentifiedDefinitionAttributes(def);
-        doWriteList(null, null, def.getRoutes(), 
this::doWriteRouteDefinitionRef);
         doWriteElement("semantic", def.getSemantic(), 
this::doWriteSemanticDefinition);
+        doWriteList(null, null, def.getRoutes(), 
this::doWriteRouteDefinitionRef);
         endElement(name);
     }
     protected void doWriteRoutingSlipDefinition(String name, 
RoutingSlipDefinition<?> def) throws IOException {
diff --git 
a/core/camel-xml-io/src/test/java/org/apache/camel/xml/out/ModelWriterTest.java 
b/core/camel-xml-io/src/test/java/org/apache/camel/xml/out/ModelWriterTest.java
index d1f86d704e60..8760bdd91848 100644
--- 
a/core/camel-xml-io/src/test/java/org/apache/camel/xml/out/ModelWriterTest.java
+++ 
b/core/camel-xml-io/src/test/java/org/apache/camel/xml/out/ModelWriterTest.java
@@ -37,6 +37,10 @@ import java.util.stream.Stream;
 
 import jakarta.xml.bind.annotation.XmlTransient;
 
+import javax.xml.XMLConstants;
+import javax.xml.transform.stream.StreamSource;
+import javax.xml.validation.SchemaFactory;
+
 import org.w3c.dom.Element;
 
 import org.apache.camel.model.RouteTemplatesDefinition;
@@ -51,6 +55,7 @@ import org.junit.jupiter.api.DisplayName;
 import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.Arguments;
 import org.junit.jupiter.params.provider.MethodSource;
+import org.junit.jupiter.params.provider.ValueSource;
 import org.xmlunit.assertj3.XmlAssert;
 import org.xmlunit.diff.DefaultNodeMatcher;
 import org.xmlunit.diff.ElementSelectors;
@@ -68,6 +73,23 @@ public class ModelWriterTest {
 
     private static final Map<Field, Boolean> TRANSIENT = new 
ConcurrentHashMap<>();
 
+    @ParameterizedTest
+    @ValueSource(strings = { "routes", "camel" })
+    void semanticDeclarationsBeforeRoutesConformToTheSchema(String root) 
throws Exception {
+        String xml = """
+                <%s xmlns="http://camel.apache.org/schema/spring";>
+                  <semantic>
+                    <question name="valid" 
type="boolean"><instructions>Valid?</instructions></question>
+                  </semantic>
+                  <route><from uri="direct:input"/><to 
uri="mock:output"/></route>
+                </%s>
+                """.formatted(root, root);
+        // The build changes the generated schema's namespace to xml-io after 
the test phase.
+        SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI)
+                .newSchema(getClass().getResource("/camel-xml-io.xsd"))
+                .newValidator().validate(new StreamSource(new 
StringReader(xml)));
+    }
+
     @ParameterizedTest
     @MethodSource("routes")
     @DisplayName("Test xml roundtrip for <routes>")
diff --git a/core/camel-xml-io/src/test/resources/semantic-routes.xml 
b/core/camel-xml-io/src/test/resources/semantic-routes.xml
index 1dc074d6871d..061c9cda2e9f 100644
--- a/core/camel-xml-io/src/test/resources/semantic-routes.xml
+++ b/core/camel-xml-io/src/test/resources/semantic-routes.xml
@@ -18,10 +18,6 @@
 
 -->
 <routes xmlns="http://camel.apache.org/schema/xml-io";>
-  <route id="semantic">
-    <from uri="direct:semantic"/>
-    <setBody><language language="semantic">ref:department</language></setBody>
-  </route>
   <semantic>
     <question name="urgent" type="boolean" state="${header.myState}" 
threshold="0.8" uncertainty="0.1" uncertaintyPolicy="non-match">
       <instructions>Is this urgent?</instructions>
@@ -40,4 +36,8 @@
       <level>Critical</level>
     </question>
   </semantic>
+  <route id="semantic">
+    <from uri="direct:semantic"/>
+    <setBody><language language="semantic">ref:department</language></setBody>
+  </route>
 </routes>
diff --git 
a/core/camel-yaml-io/src/generated/java/org/apache/camel/yaml/out/YamlModelWriter.java
 
b/core/camel-yaml-io/src/generated/java/org/apache/camel/yaml/out/YamlModelWriter.java
index 694a6c389454..2ee4afc192f7 100644
--- 
a/core/camel-yaml-io/src/generated/java/org/apache/camel/yaml/out/YamlModelWriter.java
+++ 
b/core/camel-yaml-io/src/generated/java/org/apache/camel/yaml/out/YamlModelWriter.java
@@ -1680,8 +1680,8 @@ public class YamlModelWriter extends 
YamlModelWriterSupport {
     protected JsonObject doWriteRoutesDefinition(RoutesDefinition def) {
         JsonObject jo = new JsonObject();
         doWriteOptionalIdentifiedDefinitionAttributes(jo, def);
-        doWriteChildList(jo, "routes", "routes", def.getRoutes(), 
this::doWriteRouteDefinition);
         doWriteChildElement(jo, "semantic", def.getSemantic(), 
this::doWriteSemanticDefinition);
+        doWriteChildList(jo, "routes", "routes", def.getRoutes(), 
this::doWriteRouteDefinition);
         return jo;
     }
     protected JsonObject doWriteRoutingSlipDefinition(RoutingSlipDefinition<?> 
def) {
diff --git 
a/dsl/camel-xml-io-dsl/src/main/java/org/apache/camel/dsl/xml/io/XmlRoutesBuilderLoader.java
 
b/dsl/camel-xml-io-dsl/src/main/java/org/apache/camel/dsl/xml/io/XmlRoutesBuilderLoader.java
index 8a44717b268a..a945d754496f 100644
--- 
a/dsl/camel-xml-io-dsl/src/main/java/org/apache/camel/dsl/xml/io/XmlRoutesBuilderLoader.java
+++ 
b/dsl/camel-xml-io-dsl/src/main/java/org/apache/camel/dsl/xml/io/XmlRoutesBuilderLoader.java
@@ -340,7 +340,6 @@ public class XmlRoutesBuilderLoader extends 
RouteBuilderLoaderSupport {
                     CamelContextAware.trySetCamelContext(def, 
getCamelContext());
                     def.setResource(getResource());
                     def.setRoutes(app.getRoutes());
-                    def.setSemantic(app.getSemantic());
                     addRoutes(def);
                 }
             }
@@ -367,7 +366,9 @@ public class XmlRoutesBuilderLoader extends 
RouteBuilderLoaderSupport {
             }
 
             private void addRoutes(RoutesDefinition routes) {
-                getRouteCollection().setSemantic(routes.getSemantic());
+                if (routes.getSemantic() != null) {
+                    getRouteCollection().setSemantic(routes.getSemantic());
+                }
                 // xml routes must be prepared in the same way java-dsl (via 
RoutesDefinition)
                 // so create a copy and use the fluent builder to add the route
                 for (RouteDefinition route : routes.getRoutes()) {
diff --git 
a/tooling/maven/camel-package-maven-plugin/src/main/resources/velocity/model-java-dsl-writer.vm
 
b/tooling/maven/camel-package-maven-plugin/src/main/resources/velocity/model-java-dsl-writer.vm
index f195b5d3fbe1..6d9a89ca0632 100644
--- 
a/tooling/maven/camel-package-maven-plugin/src/main/resources/velocity/model-java-dsl-writer.vm
+++ 
b/tooling/maven/camel-package-maven-plugin/src/main/resources/velocity/model-java-dsl-writer.vm
@@ -89,6 +89,7 @@ public class JavaDslModelWriter extends 
JavaDslModelWriterSupport {
     #if( $clazz.simpleName == "OptionalIdentifiedDefinition" )
         #set( $foo = $elementRefs.add($clazz) )
     #end
+## Semantic declaration writers are hand-written in JavaDslModelWriterSupport.
     #if( !$mojo.getXmlEnum($clazz) && !$clazz.isInterface()
         && $clazz.simpleName != "SemanticDefinition" && $clazz.simpleName != 
"SemanticQuestionDefinition" )
         #set( $hasDerived = false )
diff --git 
a/tooling/maven/camel-package-maven-plugin/src/main/resources/velocity/model-yaml-writer.vm
 
b/tooling/maven/camel-package-maven-plugin/src/main/resources/velocity/model-yaml-writer.vm
index 57b48a55174b..09047eaed9bb 100644
--- 
a/tooling/maven/camel-package-maven-plugin/src/main/resources/velocity/model-yaml-writer.vm
+++ 
b/tooling/maven/camel-package-maven-plugin/src/main/resources/velocity/model-yaml-writer.vm
@@ -83,6 +83,7 @@ public class YamlModelWriter extends YamlModelWriterSupport {
     #if( $clazz.simpleName == "OptionalIdentifiedDefinition" )
         #set( $foo = $elementRefs.add($clazz) )
     #end
+## Semantic declaration writers are hand-written in YamlModelWriterSupport.
     #if( !$mojo.getXmlEnum($clazz) && !$clazz.isInterface()
         && $clazz.simpleName != "SemanticDefinition" && $clazz.simpleName != 
"SemanticQuestionDefinition" )
         #set( $hasDerived = false )

Reply via email to