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

davsclaus pushed a commit to branch camel-4.18.x
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/camel-4.18.x by this push:
     new c4d336516dd0 CAMEL-23051: camel-yaml-dsl - CamelYamlParser should 
support property placeholders
c4d336516dd0 is described below

commit c4d336516dd0118edd5aa1f0e77981d4d7e0a313
Author: Claus Ibsen <[email protected]>
AuthorDate: Sun Feb 22 18:03:33 2026 +0100

    CAMEL-23051: camel-yaml-dsl - CamelYamlParser should support property 
placeholders
---
 .../camel/dsl/yaml/validator/CamelYamlParser.java  | 23 ++++++-
 .../dsl/yaml/validator/DummyPropertiesParser.java  | 52 +++++++++++++++
 .../dsl/yaml/validator/DummyTypeConverter.java     | 77 ++++++++++++++++++++++
 .../dsl/yaml/validator/CamelYamlParserTest.java    | 14 ++++
 .../camel/dsl/yaml/validator/YamlParserTest.java   |  2 +
 .../dsl/yaml/validator/YamlValidatorTest.java      | 13 ++++
 .../src/test/resources/bad2.yaml                   | 26 ++++++++
 .../src/test/resources/foo2.yaml                   | 26 ++++++++
 8 files changed, 232 insertions(+), 1 deletion(-)

diff --git 
a/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/CamelYamlParser.java
 
b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/CamelYamlParser.java
index be7b3a4f725b..18f5562d9a88 100644
--- 
a/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/CamelYamlParser.java
+++ 
b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/CamelYamlParser.java
@@ -23,6 +23,8 @@ import java.util.List;
 
 import com.networknt.schema.ValidationMessage;
 import org.apache.camel.CamelContext;
+import org.apache.camel.TypeConverterExists;
+import org.apache.camel.component.properties.PropertiesComponent;
 import org.apache.camel.component.stub.StubComponent;
 import org.apache.camel.dsl.yaml.YamlRoutesBuilderLoader;
 import org.apache.camel.dsl.yaml.validator.stub.StubBeanRepository;
@@ -41,7 +43,7 @@ import org.apache.camel.support.ResourceHelper;
  * Camel YAML parser that parses YAML DSL routes and also checks the routes 
can be loaded by Camel. This parser does not
  * start any routes, and will stub every component, dataformat, language which 
would require to have all dependencies on
  * classpath and 3rd party JARs may trigger some initialization that can 
distort this parser.
- *
+ * <p>
  * This is a faster and lighter parser than the {@link YamlValidator} which 
uses a similar concept as in camel-jbang.
  */
 public class CamelYamlParser {
@@ -62,6 +64,25 @@ public class CamelYamlParser {
                     (name, context) -> new StubLanguage());
             
camelContext.getCamelContextExtension().addContextPlugin(TransformerResolver.class,
                     (name, context) -> new StubTransformer());
+
+            // when exporting we should ignore some errors and keep attempting 
to export as far as we can
+            PropertiesComponent pc = (PropertiesComponent) 
camelContext.getPropertiesComponent();
+            
pc.addInitialProperty("camel.component.properties.ignore-missing-property", 
"true");
+            
pc.addInitialProperty("camel.component.properties.ignore-missing-location", 
"true");
+            pc.setPropertiesParser(new DummyPropertiesParser(camelContext));
+
+            // override default type converters with our export converter that 
is more flexible during exporting
+            DummyTypeConverter ec = new DummyTypeConverter();
+            
camelContext.getTypeConverterRegistry().setTypeConverterExists(TypeConverterExists.Override);
+            
camelContext.getTypeConverterRegistry().addTypeConverter(Integer.class, 
String.class, ec);
+            
camelContext.getTypeConverterRegistry().addTypeConverter(Long.class, 
String.class, ec);
+            
camelContext.getTypeConverterRegistry().addTypeConverter(Double.class, 
String.class, ec);
+            
camelContext.getTypeConverterRegistry().addTypeConverter(Float.class, 
String.class, ec);
+            
camelContext.getTypeConverterRegistry().addTypeConverter(Byte.class, 
String.class, ec);
+            
camelContext.getTypeConverterRegistry().addTypeConverter(Boolean.class, 
String.class, ec);
+            
camelContext.getTypeConverterRegistry().addFallbackTypeConverter(ec, false);
+
+            // start camel
             camelContext.start();
 
             YamlRoutesBuilderLoader loader = new YamlRoutesBuilderLoader();
diff --git 
a/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/DummyPropertiesParser.java
 
b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/DummyPropertiesParser.java
new file mode 100644
index 000000000000..9cc4d26d1842
--- /dev/null
+++ 
b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/DummyPropertiesParser.java
@@ -0,0 +1,52 @@
+/*
+ * 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.dsl.yaml.validator;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.component.properties.DefaultPropertiesParser;
+import org.apache.camel.component.properties.PropertiesLookup;
+import org.apache.camel.support.component.PropertyConfigurerSupport;
+
+/**
+ * During parsing then we can be more flexible and allow missing property 
placeholders to resolve to a hardcoded value,
+ * so we can keep attempting to parse.
+ */
+public class DummyPropertiesParser extends DefaultPropertiesParser {
+
+    private final CamelContext camelContext;
+
+    public DummyPropertiesParser(CamelContext camelContext) {
+        this.camelContext = camelContext;
+    }
+
+    @Override
+    public String parseProperty(String key, String value, PropertiesLookup 
properties) {
+        if (value == null) {
+            // the key may refer to a properties function so make sure we 
include this during export
+            if (key != null) {
+                try {
+                    
camelContext.getPropertiesComponent().getPropertiesFunction(key);
+                } catch (Exception e) {
+                    // ignore
+                }
+            }
+            return PropertyConfigurerSupport.MAGIC_VALUE;
+        }
+        return value;
+    }
+
+}
diff --git 
a/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/DummyTypeConverter.java
 
b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/DummyTypeConverter.java
new file mode 100644
index 000000000000..d84deef9613d
--- /dev/null
+++ 
b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/DummyTypeConverter.java
@@ -0,0 +1,77 @@
+/*
+ * 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.dsl.yaml.validator;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.TypeConversionException;
+import org.apache.camel.converter.ObjectConverter;
+import org.apache.camel.support.TypeConverterSupport;
+import org.apache.camel.support.component.PropertyConfigurerSupport;
+import org.apache.camel.util.ObjectHelper;
+
+/**
+ * During parsing then we can be more flexible and allow missing property 
placeholders to resolve to a hardcoded value,
+ * so we can keep attempting to parse.
+ */
+public class DummyTypeConverter extends TypeConverterSupport {
+
+    @Override
+    public <T> T convertTo(Class<T> type, Exchange exchange, Object value) 
throws TypeConversionException {
+        if (PropertyConfigurerSupport.MAGIC_VALUE.equals(value)) {
+            // attempt to convert to the given type using different common 
inputs (boolean, numeric, string)
+            if (boolean.class == type || Boolean.class == type) {
+                return (T) Boolean.TRUE;
+            } else if (type == int.class || type == Integer.class) {
+                return (T) Integer.valueOf("1");
+            } else if (type == long.class || type == Long.class) {
+                return (T) Long.valueOf("1");
+            } else if (type == double.class || type == Double.class) {
+                return (T) Double.valueOf("1");
+            } else if (type == float.class || type == Float.class) {
+                return (T) Float.valueOf("1");
+            } else if (type == short.class || type == Short.class) {
+                return (T) Short.valueOf("1");
+            } else if (type == byte.class || type == Byte.class) {
+                return (T) Byte.valueOf("0");
+            } else if (type == String.class) {
+                return (T) PropertyConfigurerSupport.MAGIC_VALUE;
+            }
+        } else {
+            String s = value.toString();
+            // regular values so convert normally
+            if (boolean.class == type || Boolean.class == type) {
+                return (T) ObjectHelper.toBoolean(s);
+            } else if (type == int.class || type == Integer.class) {
+                return (T) ObjectConverter.toInteger(s);
+            } else if (type == long.class || type == Long.class) {
+                return (T) ObjectConverter.toLong(s);
+            } else if (type == double.class || type == Double.class) {
+                return (T) ObjectConverter.toDouble(s);
+            } else if (type == float.class || type == Float.class) {
+                return (T) ObjectConverter.toFloat(s);
+            } else if (type == short.class || type == Short.class) {
+                return (T) ObjectConverter.toShort(s);
+            } else if (type == byte.class || type == Byte.class) {
+                return (T) ObjectConverter.toByte(s);
+            } else if (type == String.class) {
+                return (T) s;
+            }
+        }
+        return null;
+    }
+
+}
diff --git 
a/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/java/org/apache/camel/dsl/yaml/validator/CamelYamlParserTest.java
 
b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/java/org/apache/camel/dsl/yaml/validator/CamelYamlParserTest.java
index 21c58c494e7c..084069fc45df 100644
--- 
a/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/java/org/apache/camel/dsl/yaml/validator/CamelYamlParserTest.java
+++ 
b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/java/org/apache/camel/dsl/yaml/validator/CamelYamlParserTest.java
@@ -36,6 +36,11 @@ public class CamelYamlParserTest {
         Assertions.assertTrue(parser.parse(new 
File("src/test/resources/foo.yaml")).isEmpty());
     }
 
+    @Test
+    public void testParseOkPlaceholder() throws Exception {
+        Assertions.assertTrue(parser.parse(new 
File("src/test/resources/foo2.yaml")).isEmpty());
+    }
+
     @Test
     public void testParseBad() throws Exception {
         var report = parser.parse(new File("src/test/resources/bad.yaml"));
@@ -44,4 +49,13 @@ public class CamelYamlParserTest {
         Assertions.assertTrue(report.get(0).getMessage().contains("Unknown 
node id: setCheese"));
         Assertions.assertTrue(report.get(0).getMessage().contains("- 
setCheese:"));
     }
+
+    @Test
+    public void testParseBadPlaceholder() throws Exception {
+        var report = parser.parse(new File("src/test/resources/bad2.yaml"));
+        Assertions.assertFalse(report.isEmpty());
+        Assertions.assertEquals(1, report.size());
+        Assertions.assertTrue(report.get(0).getMessage().contains("Unknown 
node id: setCheese"));
+        Assertions.assertTrue(report.get(0).getMessage().contains("- 
setCheese:"));
+    }
 }
diff --git 
a/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/java/org/apache/camel/dsl/yaml/validator/YamlParserTest.java
 
b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/java/org/apache/camel/dsl/yaml/validator/YamlParserTest.java
index a689f97d0048..2f8c1892fd42 100644
--- 
a/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/java/org/apache/camel/dsl/yaml/validator/YamlParserTest.java
+++ 
b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/java/org/apache/camel/dsl/yaml/validator/YamlParserTest.java
@@ -34,7 +34,9 @@ public class YamlParserTest {
     @Test
     public void testParseOk() throws Exception {
         Assertions.assertTrue(parser.parse(new 
File("src/test/resources/foo.yaml")).isEmpty());
+        Assertions.assertTrue(parser.parse(new 
File("src/test/resources/foo2.yaml")).isEmpty());
         Assertions.assertTrue(parser.parse(new 
File("src/test/resources/bad.yaml")).isEmpty());
+        Assertions.assertTrue(parser.parse(new 
File("src/test/resources/bad2.yaml")).isEmpty());
     }
 
     @Test
diff --git 
a/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/java/org/apache/camel/dsl/yaml/validator/YamlValidatorTest.java
 
b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/java/org/apache/camel/dsl/yaml/validator/YamlValidatorTest.java
index 5c6ca2e6c963..5605c07f1814 100644
--- 
a/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/java/org/apache/camel/dsl/yaml/validator/YamlValidatorTest.java
+++ 
b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/java/org/apache/camel/dsl/yaml/validator/YamlValidatorTest.java
@@ -37,6 +37,11 @@ public class YamlValidatorTest {
         Assertions.assertTrue(validator.validate(new 
File("src/test/resources/foo.yaml")).isEmpty());
     }
 
+    @Test
+    public void testValidateOkPlaceholder() throws Exception {
+        Assertions.assertTrue(validator.validate(new 
File("src/test/resources/foo2.yaml")).isEmpty());
+    }
+
     @Test
     public void testValidateBad() throws Exception {
         var report = validator.validate(new 
File("src/test/resources/bad.yaml"));
@@ -44,4 +49,12 @@ public class YamlValidatorTest {
         Assertions.assertEquals(1, report.size());
         
Assertions.assertTrue(report.get(0).getMessage().contains("setCheese"));
     }
+
+    @Test
+    public void testValidateBadPlaceholder() throws Exception {
+        var report = validator.validate(new 
File("src/test/resources/bad2.yaml"));
+        Assertions.assertFalse(report.isEmpty());
+        Assertions.assertEquals(1, report.size());
+        
Assertions.assertTrue(report.get(0).getMessage().contains("setCheese"));
+    }
 }
diff --git 
a/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/resources/bad2.yaml 
b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/resources/bad2.yaml
new file mode 100644
index 000000000000..971860843afb
--- /dev/null
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/resources/bad2.yaml
@@ -0,0 +1,26 @@
+#
+# 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.
+#
+
+- route:
+    from:
+      uri: timer:yaml
+      parameters:
+        period: "{{myPeriod}}"
+      steps:
+        - setCheese:
+            simple: "Hello {{myUser}}"
+        - log: ${body}
\ No newline at end of file
diff --git 
a/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/resources/foo2.yaml 
b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/resources/foo2.yaml
new file mode 100644
index 000000000000..e469f21a7d23
--- /dev/null
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/resources/foo2.yaml
@@ -0,0 +1,26 @@
+#
+# 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.
+#
+
+- route:
+    from:
+      uri: timer:yaml
+      parameters:
+        period: "{{myPeriod}}"
+      steps:
+        - setBody:
+            simple: "Hello {{myUser}}"
+        - log: ${body}
\ No newline at end of file

Reply via email to