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/05/02 08:12:54 UTC
(camel) 01/01: CAMEL-23381: camel-core - Simple language inlined result type for a few common types
This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch sc
in repository https://gitbox.apache.org/repos/asf/camel.git
commit ce55608d865d212f3bc689f05711a18f52369504
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Sat May 2 10:12:32 2026 +0200
CAMEL-23381: camel-core - Simple language inlined result type for a few common types
---
.../org/apache/camel/catalog/CamelCatalogTest.java | 9 ++++
.../jsonpath/JsonPathSimpleResultTypeTest.java | 57 ++++++++++++++++++++++
.../modules/languages/pages/simple-language.adoc | 25 ++++++++++
.../simple/ast/SimpleFunctionExpression.java | 29 ++++++++++-
.../apache/camel/language/simple/SimpleTest.java | 23 +++++++++
5 files changed, 142 insertions(+), 1 deletion(-)
diff --git a/catalog/camel-catalog/src/test/java/org/apache/camel/catalog/CamelCatalogTest.java b/catalog/camel-catalog/src/test/java/org/apache/camel/catalog/CamelCatalogTest.java
index 211e6873b138..2e15696f0f3d 100644
--- a/catalog/camel-catalog/src/test/java/org/apache/camel/catalog/CamelCatalogTest.java
+++ b/catalog/camel-catalog/src/test/java/org/apache/camel/catalog/CamelCatalogTest.java
@@ -1133,6 +1133,15 @@ public class CamelCatalogTest {
result = catalog.validateLanguagePredicate(null, "simple", "${body.length} =!= 12");
assertFalse(result.isSuccess());
assertEquals("Unexpected token =", result.getShortError());
+
+ result = catalog.validateLanguageExpression(null, "simple", "${int:body}");
+ assertTrue(result.isSuccess());
+ assertEquals("${int:body}", result.getText());
+
+ result = catalog.validateLanguageExpression(null, "simple", "${unknown:body}");
+ assertFalse(result.isSuccess());
+ assertEquals("${unknown:body}", result.getText());
+ assertEquals("Unknown function: unknown:body", result.getShortError());
}
@Test
diff --git a/components/camel-jsonpath/src/test/java/org/apache/camel/jsonpath/JsonPathSimpleResultTypeTest.java b/components/camel-jsonpath/src/test/java/org/apache/camel/jsonpath/JsonPathSimpleResultTypeTest.java
new file mode 100644
index 000000000000..fbd1523cf1b6
--- /dev/null
+++ b/components/camel-jsonpath/src/test/java/org/apache/camel/jsonpath/JsonPathSimpleResultTypeTest.java
@@ -0,0 +1,57 @@
+/*
+ * 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.jsonpath;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.test.junit6.CamelTestSupport;
+import org.junit.jupiter.api.Test;
+
+public class JsonPathSimpleResultTypeTest extends CamelTestSupport {
+
+ @Override
+ protected RouteBuilder createRouteBuilder() {
+ return new RouteBuilder() {
+ @Override
+ public void configure() {
+ from("direct:start")
+ .setHeader("age", simple("${int:jsonpath($.age)}"))
+ .setHeader("id", simple("${long:jsonpath($.id)}"))
+ .setHeader("name", simple("${string:jsonpath($.name)}"))
+ .setHeader("vip", simple("${boolean:jsonpath($.vip)}"))
+ .to("mock:result");
+ }
+ };
+ }
+
+ @Test
+ public void testInlinedResultType() throws Exception {
+ getMockEndpoint("mock:result").expectedMessageCount(1);
+ getMockEndpoint("mock:result").expectedHeaderReceived("age", Integer.valueOf("42"));
+ getMockEndpoint("mock:result").message(0).header("age").isInstanceOf(Integer.class);
+ getMockEndpoint("mock:result").expectedHeaderReceived("id", Long.valueOf("1234567890"));
+ getMockEndpoint("mock:result").message(0).header("id").isInstanceOf(Long.class);
+ getMockEndpoint("mock:result").expectedHeaderReceived("name", "scott");
+ getMockEndpoint("mock:result").expectedHeaderReceived("vip", Boolean.valueOf("true"));
+ getMockEndpoint("mock:result").message(0).header("vip").isInstanceOf(Boolean.class);
+
+ template.sendBody("direct:start", "{\"id\": \"1234567890\", \"age\": \"42\", \"name\": \"scott\", \"vip\": \"true\"}");
+
+ MockEndpoint.assertIsSatisfied(context);
+ }
+
+}
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 ccceb2ce08f3..dd7d05762846 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
@@ -122,6 +122,31 @@ The Simple language has many built-in functions which allows access to various p
NOTE: Some functions take 1 or more arguments enclosed in parentheses, and arguments separated by comma (ie `${replace('custID','customerId')}`.
+=== Inlined Result Type Function
+
+**Available as of Camel 4.21**
+
+The simple language, has many built-in functions, and each of them take different set of parameters, and some are more advanced than others, for example
+the functions working with JSon or XML payloads. Regards of that, you may have need for being able to easily specify that the function should return the value
+as an integer instead of _what it would otherwise do_. To make this easy we have built-in a fixed set of very common result types to make this easy.
+
+[width="100%",cols="10%,10%,80%",options="header",]
+|====
+|Prefix |Response Type |Description
+|`int:` | `Integer` | To use `Integer` as a result type.
+|`integer:` | `Integer` | To use `Integer` as a result type.
+|`long:` | `Long` | To use `Long` as a result type.
+|`boolean:` | `Boolean` | To use `Boolean` as a result type.
+|`string:` | `String` | To use `String` (text) as a result type.
+|====
+
+You do this by prefixing the function with any of the above, such as `${int:header.age}` to return the age header as an integer.
+If you use XML then the XPath function can do this as well such as `${int:xpath(//food/quantity)`.
+
+If you need to use a type that is not in the table above, then you can combine two functions together with the `${convertTo(type)}` function, as follows:
+
+`${xpath(//food[name='food1']/price/text())} ~> ${convertTo(java.math.BigDecimal)}`
+
=== Core Camel Functions
The Camel functions are as the name implies specific to Apache Camel and these functions are primary used
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 c3d1f9528ae8..825478e0fd76 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
@@ -81,6 +81,33 @@ public class SimpleFunctionExpression extends LiteralExpression {
}
private Expression createSimpleExpression(CamelContext camelContext, String function, boolean strict) {
+ Class<?> type = null;
+
+ // is it a known result type (make it easy in simple to return the value as you need)
+ if (function.startsWith("int:")) {
+ type = int.class;
+ function = function.substring(4);
+ } else if (function.startsWith("integer:")) {
+ type = int.class;
+ function = function.substring(8);
+ } else if (function.startsWith("long:")) {
+ type = long.class;
+ function = function.substring(5);
+ } else if (function.startsWith("boolean:")) {
+ type = boolean.class;
+ function = function.substring(8);
+ } else if (function.startsWith("string:")) {
+ type = String.class;
+ function = function.substring(7);
+ }
+ Expression exp = doCreateSimpleExpression(camelContext, function, strict);
+ if (type != null) {
+ exp = ExpressionBuilder.convertToExpression(exp, type);
+ }
+ return exp;
+ }
+
+ private Expression doCreateSimpleExpression(CamelContext camelContext, String function, boolean strict) {
// return the function directly if we can create function without analyzing the prefix
Expression answer = createSimpleExpressionDirectly(camelContext, function);
if (answer != null) {
@@ -713,7 +740,7 @@ public class SimpleFunctionExpression extends LiteralExpression {
String exp = StringHelper.beforeLast(remainder, ")");
if (exp == null) {
throw new SimpleParserException(
- "Valid syntax: ${simpleJsonpath(input,exp)} was: " + function, token.getIndex());
+ "Valid syntax: ${simpleJsonpath(exp)} was: " + function, token.getIndex());
}
String input = null;
exp = StringHelper.removeLeadingAndEndingQuotes(exp);
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 71522c9f59e0..1bd1a04f4faa 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
@@ -2738,6 +2738,29 @@ public class SimpleTest extends LanguageTestSupport {
assertEquals(Boolean.TRUE, s);
}
+ @Test
+ public void testInlinedResultType() {
+ exchange.getMessage().setBody("123");
+ Expression expression = context.resolveLanguage("simple").createExpression("${int:body}");
+ Object s = expression.evaluate(exchange, Object.class);
+ assertIsInstanceOf(Integer.class, s);
+ expression = context.resolveLanguage("simple").createExpression("${integer:body}");
+ s = expression.evaluate(exchange, Object.class);
+ assertIsInstanceOf(Integer.class, s);
+ expression = context.resolveLanguage("simple").createExpression("${long:body}");
+ s = expression.evaluate(exchange, Object.class);
+ assertIsInstanceOf(Long.class, s);
+
+ exchange.getMessage().setBody("true");
+ expression = context.resolveLanguage("simple").createExpression("${boolean:body}");
+ s = expression.evaluate(exchange, Object.class);
+ assertIsInstanceOf(Boolean.class, s);
+
+ exchange.getMessage().setBody("Hello World");
+ expression = context.resolveLanguage("simple").createExpression("${string:body}");
+ s = expression.evaluate(exchange, String.class);
+ }
+
@Test
public void testConvertToCamelJson() {
exchange.getMessage().setBody("{ \"name\": \"Scott\", \"age\": 44 }");