luigidemasi commented on code in PR #27082:
URL: https://github.com/apache/camel/pull/27082#discussion_r4133467679
##########
dsl/camel-xml-io-dsl/src/main/java/org/apache/camel/dsl/xml/io/XmlRoutesBuilderLoader.java:
##########
@@ -95,19 +97,50 @@ public void preParseRoute(Resource resource) throws
Exception {
if (preparseDone.getOrDefault(resource.getLocation(), false)) {
return;
}
- XmlStreamInfo xmlInfo = xmlInfo(resource);
- if (xmlInfo.isValid()) {
- String root = xmlInfo.getRootElementName();
- if ("beans".equals(root) || "blueprint".equals(root) ||
"camel".equals(root)) {
- new XmlModelParser(resource, xmlInfo.getRootElementNamespace())
- .parseBeansDefinition()
- .ifPresent(bd -> {
- registerBeans(resource, bd);
- camelAppCache.put(resource.getLocation(), bd);
- });
+ try {
+ XmlStreamInfo xmlInfo = xmlInfo(resource);
+ if (xmlInfo.isValid()) {
+ String root = xmlInfo.getRootElementName();
+ SemanticDefinition semantic = null;
+ if ("beans".equals(root) || "blueprint".equals(root) ||
"camel".equals(root)) {
+ new XmlModelParser(resource,
xmlInfo.getRootElementNamespace())
+ .parseBeansDefinition()
+ .ifPresent(bd -> {
+ registerBeans(resource, bd);
+ camelAppCache.put(resource.getLocation(), bd);
+ });
+ BeansDefinition app =
camelAppCache.get(resource.getLocation());
+ if (app != null) {
+ semantic = app.getSemantic();
+ }
+ } else if ("routes".equals(root) || "route".equals(root)) {
+ RoutesDefinition routes = new
XmlModelParser(resource(resource), xmlInfo.getRootElementNamespace())
+ .parseRoutesDefinition().orElse(null);
+ if (routes != null) {
+ routesCache.put(resource.getLocation(), routes);
+ semantic = routes.getSemantic();
+ }
+ }
+ SemanticDefinition.configure(getCamelContext(), resource,
resource.getLocation(), semantic);
}
+ preparseDone.put(resource.getLocation(), true);
+ } catch (Exception e) {
+ // A failed batch also prevents builders for earlier resources
from clearing their cached input.
+ resourceCache.clear();
+ xmlInfoCache.clear();
Review Comment:
Keeping the cache clearing as implemented. Earlier resources may also be
corrected before retry, so clearing only the failed resource would reuse stale
input; failedResourceBatchDoesNotReuseEarlierCachedDeclarationsOnRetry covers
that case. Successful configure() calls already clear their own resource
entries, so the remaining caches hold pending input. A transactional rollback
mechanism would add scope without fixing a demonstrated problem here.
_Codex on behalf of [luigidemasi](https://github.com/luigidemasi)._
##########
dsl/camel-xml-io-dsl/src/main/java/org/apache/camel/dsl/xml/io/XmlRoutesBuilderLoader.java:
##########
@@ -95,19 +97,50 @@ public void preParseRoute(Resource resource) throws
Exception {
if (preparseDone.getOrDefault(resource.getLocation(), false)) {
return;
}
- XmlStreamInfo xmlInfo = xmlInfo(resource);
- if (xmlInfo.isValid()) {
- String root = xmlInfo.getRootElementName();
- if ("beans".equals(root) || "blueprint".equals(root) ||
"camel".equals(root)) {
- new XmlModelParser(resource, xmlInfo.getRootElementNamespace())
- .parseBeansDefinition()
- .ifPresent(bd -> {
- registerBeans(resource, bd);
- camelAppCache.put(resource.getLocation(), bd);
- });
+ try {
+ XmlStreamInfo xmlInfo = xmlInfo(resource);
+ if (xmlInfo.isValid()) {
+ String root = xmlInfo.getRootElementName();
+ SemanticDefinition semantic = null;
+ if ("beans".equals(root) || "blueprint".equals(root) ||
"camel".equals(root)) {
+ new XmlModelParser(resource,
xmlInfo.getRootElementNamespace())
+ .parseBeansDefinition()
+ .ifPresent(bd -> {
+ registerBeans(resource, bd);
+ camelAppCache.put(resource.getLocation(), bd);
+ });
Review Comment:
Yes, the parsed RoutesDefinition is cached and reused during configure(),
while the preparse pass registers shared declarations before any co-loaded
routes initialize. The cross-resource declaration test covers that ordering.
The PR description now explains this loader behavior explicitly.
_Codex on behalf of [luigidemasi](https://github.com/luigidemasi)._
##########
components/camel-ai/camel-semantic/src/main/java/org/apache/camel/semantic/DefaultSemanticDefinitionConfigurer.java:
##########
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.semantic;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.model.PropertyDefinition;
+import org.apache.camel.model.app.SemanticDefinition;
+import org.apache.camel.model.app.SemanticDefinitionConfigurer;
+import org.apache.camel.model.app.SemanticQuestionDefinition;
+import org.apache.camel.spi.Resource;
+import org.apache.camel.util.StringHelper;
+
+/** Converts Java/XML declarations to the same immutable questions used by
YAML and programmatic registration. */
+public class DefaultSemanticDefinitionConfigurer implements
SemanticDefinitionConfigurer {
+ @Override
+ public void configure(CamelContext context, Resource resource, String
source, SemanticDefinition definition) {
+ Map<String, SemanticQuestion> questions = new LinkedHashMap<>();
+ if (definition != null) {
+ for (SemanticQuestionDefinition question :
definition.getQuestions()) {
+ String name = question.getName();
+ if (name == null || name.isBlank()) {
+ throw new IllegalArgumentException("Semantic question
requires a nonblank name");
Review Comment:
Added field-specific numeric diagnostics in b6a0e7ed2db9.
NumberFormatException was already caught by the surrounding
IllegalArgumentException handler, which supplied the question name; the message
now also identifies threshold or uncertainty and the invalid value, while
retaining the original cause. Both non-numeric cases are covered by the
invalid-reload test, including preservation of prior definitions and recovery
after corrected input. All 109 semantic tests pass.
_Codex on behalf of [luigidemasi](https://github.com/luigidemasi)._
##########
core/camel-core-model/src/main/java/org/apache/camel/model/app/SemanticQuestionDefinition.java:
##########
@@ -0,0 +1,183 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.model.app;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import jakarta.xml.bind.annotation.XmlAccessType;
+import jakarta.xml.bind.annotation.XmlAccessorType;
+import jakarta.xml.bind.annotation.XmlAttribute;
+import jakarta.xml.bind.annotation.XmlElement;
+import jakarta.xml.bind.annotation.XmlType;
+
+import org.apache.camel.model.PropertyDefinition;
+import org.apache.camel.spi.Metadata;
+
+/** A semantic question with the same fields and policies as a YAML
declaration. */
+@Metadata(label = "configuration")
+@XmlType(name = "semanticQuestionDefinition", propOrder = { "instructions",
"criteria", "levels" })
+@XmlAccessorType(XmlAccessType.FIELD)
+public class SemanticQuestionDefinition {
+ @XmlAttribute(required = true)
+ @Metadata(required = true, description = "The context-wide question name.")
+ private String name;
+ @XmlAttribute(required = true)
+ @Metadata(required = true, enums = "boolean,choice,score", description =
"The question type.")
+ private String type;
+ @XmlAttribute
+ @Metadata(description = "The Simple expression selecting the message
state.")
+ private String state;
+ @XmlAttribute
+ @Metadata(description = "The boolean decision threshold.")
+ private String threshold;
+ @XmlAttribute
+ @Metadata(description = "The boolean uncertainty band.")
+ private String uncertainty;
+ @XmlAttribute
+ @Metadata(enums = "fail,non-match", description = "The boolean uncertainty
policy.")
+ private String uncertaintyPolicy;
+ @XmlElement(required = true)
+ @Metadata(required = true, description = "Instructions describing the
judgment to make.")
+ private String instructions;
+ @XmlElement(name = "criterion")
+ @Metadata(description = "Named choice criteria, or optional true/false
boolean criteria.")
+ private List<PropertyDefinition> criteria = new ArrayList<>();
+ @XmlElement(name = "level")
Review Comment:
Keeping the mutable collections in the declaration model, consistent with
the existing model-builder convention. Conversion to SemanticQuestion
defensively copies criteria and levels into immutable runtime collections, so
evaluation does not retain these mutable model lists.
_Codex on behalf of [luigidemasi](https://github.com/luigidemasi)._
--
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]