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