You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2026/10/18 07:56:13 UTC
(camel) 01/01: CAMEL-25748: camel-yaml-dsl-validator - the hint for a script file under groovy: resource: keeps the resource: prefix
This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch fix/CAMEL-25748
in repository https://gitbox.apache.org/repos/asf/camel.git
commit 4be2bdcb6ed642bee22d7c15e7ca2eea751e2aca
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Sun Oct 18 09:56:01 2026 +0200
CAMEL-25748: camel-yaml-dsl-validator - the hint for a script file under groovy: resource: keeps the resource: prefix
A model often writes groovy: {resource: "file:x.groovy"}. The hint for a
language text under another key copied the value into expression:, which
gave expression: "file:x.groovy", and Groovy runs that as code. A script
file is loaded with the resource: prefix, so the hint now adds it and says
so. This covers a value under resource: or resourceUri:, and a file:,
classpath: or http(s): value under script:. Inline code and a value that
has the prefix keep the hint as before.
Co-Authored-By: Claude Opus 5.5 (1M context) <no...@anthropic.com>
Claude-Session: https://claude.ai/code/session_01STT6whBgK1AqsSsUKrnE8m
---
.../camel/dsl/yaml/validator/SchemaHints.java | 24 +++++++++++++--
.../QuotingAndOptionPlacementHintTest.java | 35 ++++++++++++++++++++++
2 files changed, 57 insertions(+), 2 deletions(-)
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/SchemaHints.java b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/SchemaHints.java
index 3254ac7cf905..af763a3624be 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/SchemaHints.java
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/SchemaHints.java
@@ -129,6 +129,27 @@ final class SchemaHints {
}
/** The text of a scalar property of the error's node, or the fallback when it is not a scalar. */
+ /** A value that names a script file by its scheme, as resource: loads it. */
+ private static final Pattern SCRIPT_FILE = Pattern.compile("(file|classpath|https?):.+", Pattern.DOTALL);
+
+ /**
+ * Where the text of a language goes, for the text written under another key (groovy: {script: "..."}). A script
+ * file under resource: (groovy: {resource: "file:x.groovy"}) is loaded with the resource: prefix, which the value
+ * often lacks (CAMEL-25748): the expression "file:x.groovy" would run as code.
+ */
+ static String languageTextHint(String language, String property, String value) {
+ String key = property.toLowerCase(Locale.ROOT);
+ String text = value.strip();
+ boolean scriptFile = !text.startsWith("resource:")
+ && (key.contains("resource") || key.startsWith("script") && SCRIPT_FILE.matcher(text).matches());
+ if (scriptFile) {
+ return "a " + language + " script file is loaded in expression: with the resource: prefix, write " + language
+ + ": {expression: \"resource:" + text.replace("\"", "\\\"") + "\"}";
+ }
+ return "the " + language + " text goes in expression:, write " + language + ": {expression: \""
+ + value.replace("\"", "\\\"") + "\"}";
+ }
+
private static String valueOf(Match m, String property, String fallback) {
JsonNode instance = m.error().getInstanceNode();
JsonNode value = instance != null ? instance.get(property) : null;
@@ -596,8 +617,7 @@ final class SchemaHints {
&& m.error().getInstanceNode() != null
&& !m.error().getInstanceNode().has("expression")
&& m.error().getInstanceNode().path(m.unknown()).isTextual(),
- m -> "the " + m.name() + " text goes in expression:, write " + m.name() + ": {expression: \""
- + valueOf(m, m.unknown(), "...").replace("\"", "\\\"") + "\"}"),
+ m -> languageTextHint(m.name(), m.unknown(), valueOf(m, m.unknown(), "..."))),
unknownProperty(null,
m -> YamlValidator.closest(m.unknown(), m.validator().knownProperties(m.schemaLocation())) != null,
m -> "did you mean '"
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/java/org/apache/camel/dsl/yaml/validator/QuotingAndOptionPlacementHintTest.java b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/java/org/apache/camel/dsl/yaml/validator/QuotingAndOptionPlacementHintTest.java
index bb401243e07c..5560ee7dc377 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/java/org/apache/camel/dsl/yaml/validator/QuotingAndOptionPlacementHintTest.java
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/java/org/apache/camel/dsl/yaml/validator/QuotingAndOptionPlacementHintTest.java
@@ -151,6 +151,41 @@ public class QuotingAndOptionPlacementHintTest {
.contains("the simple text goes in expression:, write simple: {expression: \"${body} != null\"}"));
}
+ /** CAMEL-25748: a script file is loaded with the resource: prefix, which the value under resource: often lacks. */
+ @Test
+ public void aScriptFileUnderAnotherKey() {
+ String yaml = """
+ - route:
+ from:
+ uri: timer:x
+ steps:
+ - setBody:
+ expression:
+ groovy:
+ resource: "file:shipment-mapping.groovy"
+ - setHeader:
+ name: sku
+ expression:
+ groovy:
+ script: "classpath:sku.groovy"
+ - setHeader:
+ name: qty
+ expression:
+ groovy:
+ resourceUri: "resource:file:qty.groovy"
+ """;
+ List<String> lines = lines(yaml);
+ assertThat(lines).anySatisfy(m -> assertThat(m)
+ .contains("a groovy script file is loaded in expression: with the resource: prefix,"
+ + " write groovy: {expression: \"resource:file:shipment-mapping.groovy\"}"));
+ assertThat(lines).anySatisfy(m -> assertThat(m)
+ .contains("write groovy: {expression: \"resource:classpath:sku.groovy\"}"));
+ // a value that has the prefix keeps it once
+ assertThat(lines).anySatisfy(m -> assertThat(m)
+ .contains("write groovy: {expression: \"resource:file:qty.groovy\"}"));
+ assertThat(lines).noneSatisfy(m -> assertThat(m).contains("resource:resource:"));
+ }
+
private static List<String> lines(String yaml) {
try {
return YamlValidator.describeAll(yaml, validator.validate(yaml));