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 eb237cd22793894f9a379a9574a4590ca811b5c3 Author: Luigi De Masi <[email protected]> AuthorDate: Tue Sep 29 14:30:32 2026 +0200 CAMEL-25138: Fix semantic XML documentation and numeric diagnostics Use the XML IO namespace for the native XML declaration example so the catalog documentation schema check validates it, and regenerate its mirror. Identify threshold and uncertainty in non-numeric validation errors while preserving the question context and original cause. Cover both fields in the existing invalid-reload tests, including preservation of the previous definitions and recovery after corrected input. Clarify why duplicate discovery of the stateless default configurer is harmless. Validation: 109 semantic tests and 1082 catalog tests passed, including the documentation schema checks. Full 695-module clean install passed with tests skipped. Co-authored-by: Codex <[email protected]> Signed-off-by: Luigi De Masi <[email protected]> --- .../org/apache/camel/catalog/docs/semantic-language.adoc | 2 +- .../camel-semantic/src/main/docs/semantic-language.adoc | 2 +- .../camel/semantic/DefaultSemanticDefinitionConfigurer.java | 12 ++++++++++-- .../apache/camel/semantic/SemanticDeclarationDslTest.java | 4 ++++ .../java/org/apache/camel/model/app/SemanticDefinition.java | 2 ++ 5 files changed, 18 insertions(+), 4 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 b2dd15c021d4..c360bacb879c 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 @@ -141,7 +141,7 @@ With xref:others:java-xml-io-dsl.adoc[XML DSL], place a `semantic` element insid [source,xml] ---- -<camel xmlns="http://camel.apache.org/schema/spring"> +<camel xmlns="http://camel.apache.org/schema/xml-io"> <semantic> <question name="department" type="choice" state="${header.myState}"> <instructions>Which department should handle this message?</instructions> 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 b2dd15c021d4..c360bacb879c 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 @@ -141,7 +141,7 @@ With xref:others:java-xml-io-dsl.adoc[XML DSL], place a `semantic` element insid [source,xml] ---- -<camel xmlns="http://camel.apache.org/schema/spring"> +<camel xmlns="http://camel.apache.org/schema/xml-io"> <semantic> <question name="department" type="choice" state="${header.myState}"> <instructions>Which department should handle this message?</instructions> 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 2d7b34e75374..871f378049fb 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 @@ -72,13 +72,21 @@ public class DefaultSemanticDefinitionConfigurer implements SemanticDefinitionCo return new SemanticQuestion( type, definition.getInstructions(), definition.getState(), criteria, definition.getLevels(), - definition.getThreshold() == null ? 0.5 : Double.parseDouble(definition.getThreshold()), - definition.getUncertainty() == null ? 0 : Double.parseDouble(definition.getUncertainty()), + definition.getThreshold() == null ? 0.5 : parseDouble(definition.getThreshold(), "threshold"), + definition.getUncertainty() == null ? 0 : parseDouble(definition.getUncertainty(), "uncertainty"), definition.getUncertaintyPolicy() == null ? SemanticQuestion.UncertaintyPolicy.FAIL : enumeration(definition.getUncertaintyPolicy(), SemanticQuestion.UncertaintyPolicy.class)); } + private static double parseDouble(String value, String field) { + try { + return Double.parseDouble(value); + } catch (NumberFormatException e) { + throw new IllegalArgumentException(field + " must be a valid number: " + value, e); + } + } + private static <T extends Enum<T>> T enumeration(String value, Class<T> type) { String normalized = StringHelper.asEnumConstantValue(value); for (T constant : type.getEnumConstants()) { 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 54bef6037643..e2b3f13a7f24 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 @@ -192,6 +192,10 @@ class SemanticDeclarationDslTest { "Duplicate semantic criterion"), Arguments.of(question.replace("type=\"boolean\"", "type=\"score\""), "score needs ordered levels"), Arguments.of(question.replace("type=\"boolean\"", "type=\"boolean\" threshold=\"NaN\""), "within [0,1]"), + Arguments.of(question.replace("type=\"boolean\"", "type=\"boolean\" threshold=\"abc\""), + "Invalid semantic question 'q': threshold must be a valid number: abc"), + Arguments.of(question.replace("type=\"boolean\"", "type=\"boolean\" uncertainty=\"abc\""), + "Invalid semantic question 'q': uncertainty must be a valid number: abc"), Arguments.of(question.replace("type=\"boolean\"", "type=\"boolean\" state=\" \""), "state selector must not be blank"), Arguments.of(question.replace("name=\"q\"", "unknown=\"q\""), "Unexpected attribute")); diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/app/SemanticDefinition.java b/core/camel-core-model/src/main/java/org/apache/camel/model/app/SemanticDefinition.java index 66ae92ca2496..ac1f2f50c0dd 100644 --- a/core/camel-core-model/src/main/java/org/apache/camel/model/app/SemanticDefinition.java +++ b/core/camel-core-model/src/main/java/org/apache/camel/model/app/SemanticDefinition.java @@ -62,6 +62,8 @@ public class SemanticDefinition { if (definition == null || definition.getQuestions().isEmpty()) { return; } + // Concurrent discovery may create equivalent instances of the stateless default configurer. + // The semantic module synchronizes access to shared question state. configurer = context.getCamelContextExtension().getDefaultFactoryFinder() .newInstance("semantic-configurer", SemanticDefinitionConfigurer.class) .orElseThrow(() -> new IllegalArgumentException(
