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/01/14 10:27:27 UTC

(camel) 02/02: CAMEL-22583: camel-core - Add convertTo function to simple language

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

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

commit bd9e46bdc712a157febb8f6f3a5e45a3f9c8bd62
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Wed Jan 14 11:27:04 2026 +0100

    CAMEL-22583: camel-core - Add convertTo function to simple language
---
 .../org/apache/camel/catalog/languages/simple.json |  2 +-
 .../language/csimple/joor/OriginalSimpleTest.java  | 10 +++++++++
 .../modules/languages/pages/simple-language.adoc   |  1 +
 .../language/simple/SimpleExpressionBuilder.java   |  3 +++
 .../simple/ast/SimpleFunctionExpression.java       | 24 ++++++++++++++++++----
 .../apache/camel/language/simple/SimpleTest.java   | 18 ++++++++++++++++
 6 files changed, 53 insertions(+), 5 deletions(-)

diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/simple.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/simple.json
index 924442008b66..f7dbf5cd4835 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/simple.json
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/simple.json
@@ -71,7 +71,7 @@
     "substring(head,tail)": { "index": 45, "kind": "function", "displayName": "Substring", "group": "function", "label": "function", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Returns a substring of the message body\/expression. If only one positive number, then the returned string is clipped from the beginning. If only one negative number, then the returned string is clipped fr [...]
     "random(min,max)": { "index": 46, "kind": "function", "displayName": "Generate Random Number", "group": "function", "label": "function", "required": false, "javaType": "int", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Returns a random number between min (included) and max (excluded).", "ognl": false, "suffix": "}" },
     "skip(num)": { "index": 47, "kind": "function", "displayName": "Skip First Items from the Message Body", "group": "function", "label": "function", "required": false, "javaType": "java.util.Iterator", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The skip function iterates the message body and skips the first number of items. This can be used with the Splitter EIP to split a message body and skip the first N number of  [...]
-    "convertTo(exp,type)": { "index": 48, "kind": "function", "displayName": "Convert To", "group": "function", "label": "function", "required": false, "javaType": "", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Converts the message body (or expression) to the specified type.", "ognl": false, "suffix": "}" },
+    "convertTo(exp,type)": { "index": 48, "kind": "function", "displayName": "Convert To", "group": "function", "label": "function", "required": false, "javaType": "", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Converts the message body (or expression) to the specified type.", "ognl": true, "suffix": "}" },
     "trim(exp)": { "index": 49, "kind": "function", "displayName": "Trim", "group": "function", "label": "function", "required": false, "javaType": "String", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The trim function trims the message body (or expression) by removing all leading and trailing white spaces.", "ognl": false, "suffix": "}" },
     "length(exp)": { "index": 50, "kind": "function", "displayName": "Length", "group": "function", "label": "function", "required": false, "javaType": "int", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The payload length (number of bytes) of the message body (or expression).", "ognl": false, "suffix": "}" },
     "size(exp)": { "index": 51, "kind": "function", "displayName": "Size", "group": "function", "label": "function", "required": false, "javaType": "int", "prefix": "${", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The size of the message body (or expression). If the payload is java.util.Collection or java.util.Map based then the size is the number of elements; otherwise the payload size in bytes.", "ognl": false, "suffix": "}" },
diff --git a/components/camel-csimple-joor/src/test/java/org/apache/camel/language/csimple/joor/OriginalSimpleTest.java b/components/camel-csimple-joor/src/test/java/org/apache/camel/language/csimple/joor/OriginalSimpleTest.java
index 806bf99e03fc..118a62abacb5 100644
--- a/components/camel-csimple-joor/src/test/java/org/apache/camel/language/csimple/joor/OriginalSimpleTest.java
+++ b/components/camel-csimple-joor/src/test/java/org/apache/camel/language/csimple/joor/OriginalSimpleTest.java
@@ -42,6 +42,7 @@ import org.apache.camel.Predicate;
 import org.apache.camel.component.bean.MethodNotFoundException;
 import org.apache.camel.language.bean.RuntimeBeanExpressionException;
 import org.apache.camel.language.csimple.CSimpleLanguage;
+import org.apache.camel.language.simple.SimpleTest;
 import org.apache.camel.language.simple.types.SimpleIllegalSyntaxException;
 import org.apache.camel.spi.ExchangeFormatter;
 import org.apache.camel.spi.Language;
@@ -2276,6 +2277,15 @@ public class OriginalSimpleTest extends LanguageTestSupport {
         assertEquals(Boolean.TRUE, s);
     }
 
+    @Test
+    public void testConvertToOGNL() {
+        exchange.getIn().setBody(new SimpleTest.OrderLine(123, "Camel in Action"));
+
+        assertExpression("${convertTo(${body},org.apache.camel.language.simple.SimpleTest$OrderLine).getId}", 123);
+        assertExpression("${convertTo(${body},org.apache.camel.language.simple.SimpleTest$OrderLine).getName}",
+                "Camel in Action");
+    }
+
     @Test
     public void testSize() {
         exchange.getMessage().setBody(new int[] { 4, 7, 9 });
diff --git a/core/camel-core-languages/src/main/docs/modules/languages/pages/simple-language.adoc b/core/camel-core-languages/src/main/docs/modules/languages/pages/simple-language.adoc
index 4b0fee763ebd..e6ad1b8eb142 100644
--- a/core/camel-core-languages/src/main/docs/modules/languages/pages/simple-language.adoc
+++ b/core/camel-core-languages/src/main/docs/modules/languages/pages/simple-language.adoc
@@ -295,6 +295,7 @@ log sensitive data from the message itself.
 |concat(exp,exp,separator) |String |Performs a string concat using two expressions (message body as default) with optional separator
 
 |convertTo(exp,type) |Object |Converts the message body (or expression) to the specified type.
+|convertTo(exp,type).*OGNL* |Object |Converts the message body (or expression) to the specified type and then invoke methods using a Camel OGNL expression.
 
 |length(exp) |int |The payload length (number of bytes) of the message body (or expression).
 
diff --git a/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/SimpleExpressionBuilder.java b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/SimpleExpressionBuilder.java
index 54f4c3f53347..b57a79616241 100644
--- a/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/SimpleExpressionBuilder.java
+++ b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/SimpleExpressionBuilder.java
@@ -322,6 +322,9 @@ public final class SimpleExpressionBuilder {
             @Override
             public Object evaluate(Exchange exchange) {
                 Object body = exp.evaluate(exchange, clazz);
+                if (body == null) {
+                    return null;
+                }
                 Expression ognlExp = bean.createExpression(null, new Object[] { null, body, ognl });
                 ognlExp.init(exchange.getContext());
                 return ognlExp.evaluate(exchange, Object.class);
diff --git a/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/ast/SimpleFunctionExpression.java b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/ast/SimpleFunctionExpression.java
index b331eab0617d..aeb19e589610 100644
--- a/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/ast/SimpleFunctionExpression.java
+++ b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/ast/SimpleFunctionExpression.java
@@ -2086,12 +2086,12 @@ public class SimpleFunctionExpression extends LiteralExpression {
         }
 
         // convertTo function
-        // TODO: ongl
         remainder = ifStartsWithReturnRemainder("convertTo(", function);
         if (remainder != null) {
+            String ognl = null;
             String exp = "body";
             String type;
-            String values = StringHelper.beforeLast(remainder, ")");
+            String values = StringHelper.before(remainder, ")");
             if (values == null || ObjectHelper.isEmpty(values)) {
                 throw new SimpleParserException(
                         "Valid syntax: ${convertTo(type)} or ${convertTo(exp,type)} was: " + function,
@@ -2114,11 +2114,27 @@ public class SimpleFunctionExpression extends LiteralExpression {
             }
             type = appendClass(type);
             type = type.replace('$', '.');
-
             if (ObjectHelper.isEmpty(exp)) {
                 exp = "null";
             }
-            return "Object value = " + exp + ";\n        return convertTo(exchange, " + type + ", value);";
+
+            remainder = StringHelper.after(remainder, ")");
+            if (ObjectHelper.isNotEmpty(remainder)) {
+                boolean invalid = OgnlHelper.isInvalidValidOgnlExpression(remainder);
+                if (invalid) {
+                    throw new SimpleParserException(
+                            "Valid syntax: ${convertTo(type).OGNL} or ${convertTo(exp,type).OGNL} was: " + function,
+                            token.getIndex());
+                }
+                ognl = ognlCodeMethods(remainder, type);
+            }
+
+            String code = "Object value = " + exp + ";\n        return convertTo(exchange, " + type + ", value)";
+            if (ognl != null) {
+                code += ognl;
+            }
+            code += ";";
+            return code;
         }
 
         // uppercase function
diff --git a/core/camel-core/src/test/java/org/apache/camel/language/simple/SimpleTest.java b/core/camel-core/src/test/java/org/apache/camel/language/simple/SimpleTest.java
index 30744c367c33..b0605feca4e9 100644
--- a/core/camel-core/src/test/java/org/apache/camel/language/simple/SimpleTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/language/simple/SimpleTest.java
@@ -2504,6 +2504,24 @@ public class SimpleTest extends LanguageTestSupport {
         assertEquals(Boolean.TRUE, s);
     }
 
+    @Test
+    public void testConvertToOGNL() {
+        exchange.getIn().setBody(new OrderLine(123, "Camel in Action"));
+
+        assertExpression("${convertTo(${body},org.apache.camel.language.simple.SimpleTest$OrderLine).getId}", 123);
+        assertExpression("${convertTo(${body},org.apache.camel.language.simple.SimpleTest$OrderLine).getName}",
+                "Camel in Action");
+    }
+
+    @Test
+    public void testConvertToOGNLArray() {
+        exchange.getIn().setBody(new SimpleTest.OrderLine(123, "Camel in Action"));
+
+        assertExpression("${convertTo(${body},org.apache.camel.language.simple.SimpleTest$OrderLine).getId}", 123);
+        assertExpression("${convertTo(${body},org.apache.camel.language.simple.SimpleTest$OrderLine).getName}",
+                "Camel in Action");
+    }
+
     @Test
     public void testTrim() {
         exchange.getMessage().setBody("   Hello World ");