This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch feature/CAMEL-24961-catalog-body-types-languages in repository https://gitbox.apache.org/repos/asf/camel.git
commit 91b9b57123cce3990ae3081748547be78cc4ffb7 Author: Claus Ibsen <[email protected]> AuthorDate: Sat Oct 24 10:55:17 2026 +0200 CAMEL-24961: Catalog body types for the last 13 languages The body types of datasonnet, hl7terser, jactl, java, js, quickjs, python, python3, ognl, spel, openfeature, semantic and typesafe-ai, checked at runtime with camel run. With them every language has body types. The doc prose about the body is fixed: js and python have no this variable, ognl has no message variable and its root object is not the Exchange, spel has a body variable, datasonnet reads JSON text only with a body media type, openfeature gives the string value as an expression, and quickjs and typesafe-ai say which bodies they read and give. The bugs found are in CAMEL-26115. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]> Signed-off-by: Claus Ibsen <[email protected]> --- .../org/apache/camel/catalog/docs/datasonnet-language.adoc | 6 +++++- .../resources/org/apache/camel/catalog/docs/js-language.adoc | 1 - .../org/apache/camel/catalog/docs/ognl-language.adoc | 5 ++--- .../org/apache/camel/catalog/docs/openfeature-language.adoc | 4 ++-- .../org/apache/camel/catalog/docs/python-language.adoc | 4 +++- .../org/apache/camel/catalog/docs/quickjs-language.adoc | 10 +++++++--- .../org/apache/camel/catalog/docs/spel-language.adoc | 3 ++- .../org/apache/camel/catalog/docs/typesafe-ai-language.adoc | 2 +- .../org/apache/camel/catalog/languages/datasonnet.json | 4 ++++ .../org/apache/camel/catalog/languages/hl7terser.json | 4 ++++ .../resources/org/apache/camel/catalog/languages/jactl.json | 4 ++++ .../resources/org/apache/camel/catalog/languages/java.json | 4 ++++ .../resources/org/apache/camel/catalog/languages/js.json | 4 ++++ .../resources/org/apache/camel/catalog/languages/ognl.json | 4 ++++ .../org/apache/camel/catalog/languages/openfeature.json | 4 ++++ .../resources/org/apache/camel/catalog/languages/python.json | 4 ++++ .../org/apache/camel/catalog/languages/python3.json | 4 ++++ .../org/apache/camel/catalog/languages/quickjs.json | 4 ++++ .../org/apache/camel/catalog/languages/semantic.json | 4 ++++ .../resources/org/apache/camel/catalog/languages/spel.json | 4 ++++ .../org/apache/camel/catalog/languages/typesafe-ai.json | 4 ++++ .../org/apache/camel/language/semantic/semantic.json | 4 ++++ .../org/apache/camel/language/semantic/SemanticLanguage.java | 10 ++++++++++ .../org/apache/camel/language/typesafeai/typesafe-ai.json | 4 ++++ .../src/main/docs/typesafe-ai-language.adoc | 2 +- .../apache/camel/language/typesafeai/TypeSafeAiLanguage.java | 8 ++++++++ .../org/apache/camel/language/datasonnet/datasonnet.json | 4 ++++ .../camel-datasonnet/src/main/docs/datasonnet-language.adoc | 6 +++++- .../apache/camel/language/datasonnet/DatasonnetLanguage.java | 11 +++++++++++ .../META-INF/org/apache/camel/component/hl7/hl7terser.json | 4 ++++ .../org/apache/camel/component/hl7/Hl7TerserLanguage.java | 9 +++++++++ .../META-INF/org/apache/camel/language/jactl/jactl.json | 4 ++++ .../java/org/apache/camel/language/jactl/JactlLanguage.java | 8 ++++++++ .../resources/META-INF/org/apache/camel/language/js/js.json | 4 ++++ components/camel-javascript/src/main/docs/js-language.adoc | 1 - .../org/apache/camel/language/js/JavaScriptLanguage.java | 9 +++++++++ .../META-INF/org/apache/camel/language/joor/java.json | 4 ++++ .../java/org/apache/camel/language/joor/JavaLanguage.java | 7 +++++++ .../META-INF/org/apache/camel/language/ognl/ognl.json | 4 ++++ components/camel-ognl/src/main/docs/ognl-language.adoc | 5 ++--- .../java/org/apache/camel/language/ognl/OgnlLanguage.java | 6 ++++++ .../org/apache/camel/language/openfeature/openfeature.json | 4 ++++ .../src/main/docs/openfeature-language.adoc | 4 ++-- .../camel/language/openfeature/OpenFeatureLanguage.java | 9 +++++++++ .../META-INF/org/apache/camel/language/python/python.json | 4 ++++ components/camel-python/src/main/docs/python-language.adoc | 4 +++- .../org/apache/camel/language/python/PythonLanguage.java | 9 +++++++++ .../META-INF/org/apache/camel/language/python3/python3.json | 4 ++++ .../org/apache/camel/language/python3/Python3Language.java | 10 ++++++++++ .../META-INF/org/apache/camel/language/quickjs/quickjs.json | 4 ++++ components/camel-quickjs/src/main/docs/quickjs-language.adoc | 10 +++++++--- .../org/apache/camel/language/quickjs/QuickjsLanguage.java | 12 ++++++++++++ .../META-INF/org/apache/camel/language/spel/spel.json | 4 ++++ .../camel-spring/src/main/docs/spel-language.adoc | 3 ++- .../java/org/apache/camel/language/spel/SpelLanguage.java | 7 +++++++ 55 files changed, 263 insertions(+), 26 deletions(-) diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/datasonnet-language.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/datasonnet-language.adoc index 9a4894c4de70..827c8dff23fe 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/datasonnet-language.adoc +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/datasonnet-language.adoc @@ -87,7 +87,7 @@ YAML:: In XML and YAML DSL, `resultType` is the fully qualified class name. If the expression results in an array, or an object, you can instruct the expression to return you `List.class` -or `Map.class`, respectively. However, you must also set the output media type to `application/x-java-object`. +or `Map.class`, respectively, as long as the output media type is `application/x-java-object`, which is the default. NOTE: The default `Document` object is useful in situations where there are intermediate transformation steps, and so retaining the content metadata through a route execution is valuable. @@ -116,6 +116,10 @@ And for output media type: 4. The DataSonnet Header output media type directive 5. `application/x-java-object` +NOTE: With the body media type `application/x-java-object`, the body is the Java object it is: JSON text is a string, +not an object, so `body.foo` fails on it. Set `bodyMediaType`, or a `Content-Type` header, to read text, bytes, a +stream or a file in that format, such as `application/json`, `application/xml` or `application/csv`. + === Functions Camel adds the following DataSonnet functions that can be used to access the diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/js-language.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/js-language.adoc index 7adba6032a66..4a31948fccd2 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/js-language.adoc +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/js-language.adoc @@ -29,7 +29,6 @@ include::partial$language-options.adoc[] [width="100%",cols="10%,10%,80%",options="header",] |======================================================================= |Variable |Type |Description -|*this* |Exchange |the Exchange is the root object |exchange |Exchange |the Exchange |camelContext |CamelContext |the CamelContext |exchangeId |String |the exchange id diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/ognl-language.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/ognl-language.adoc index 5894057a024d..19f734145d2c 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/ognl-language.adoc +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/ognl-language.adoc @@ -15,7 +15,7 @@ supported by https://commons.apache.org/dormant/commons-ognl/[(Apache Commons OG used as an xref:manual::expression.adoc[Expression] or xref:manual::predicate.adoc[Predicate] in Camel routes. -For example, you can use MVEL in a xref:manual::predicate.adoc[Predicate] +For example, you can use OGNL in a xref:manual::predicate.adoc[Predicate] with the xref:eips:choice-eip.adoc[Content-Based Router] EIP. You can use OGNL dot notation to invoke operations. If you for instance @@ -48,13 +48,12 @@ include::partial$language-options.adoc[] [width="100%",cols="10%,10%,80%",options="header",] |======================================================================= |Variable |Type |Description -|*this* |Exchange |the Exchange is the root object +|*this* |RootObject |the root object, whose properties are the variables below |context |CamelContext |the CamelContext |exchange |Exchange |the Exchange |exchangeId |String |the exchange id |exception |Throwable |the Exchange exception (if any) |request |Message |the message -|message |Message |the message |headers |Map |the message headers |getHeader(name) |Object |the message header by the given name |getHeader(name, type) |Type |the message header by the given name as the given type diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/openfeature-language.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/openfeature-language.adoc index fa02ab66ca18..2daed955d900 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/openfeature-language.adoc +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/openfeature-language.adoc @@ -29,8 +29,8 @@ This language is provided by the `camel-openfeature` component: == Usage -The language evaluates the given flag key as a boolean and returns the -result. It uses the `openfeature:flags` endpoint by default, inheriting +As a predicate, the language evaluates the given flag key as a boolean. +As an expression, it gives the string value of the flag, see below. It uses the `openfeature:flags` endpoint by default, inheriting component-level configuration such as `flagsResource` or `host`. The language does not modify the exchange — it reads targeting context diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/python-language.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/python-language.adoc index 76a14e411d11..a0e494416a4b 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/python-language.adoc +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/python-language.adoc @@ -29,7 +29,6 @@ include::partial$language-options.adoc[] [width="100%",cols="10%,10%,80%",options="header",] |======================================================================= |Variable |Type |Description -|*this* |Exchange |the Exchange is the root object |exchange |Exchange |the Exchange |camelContext |CamelContext |the CamelContext |exchangeId |String |the exchange id @@ -55,6 +54,9 @@ The `variable` and `variables` bindings are the exchange-scoped variables (for e xref:eips:setVariable-eip.adoc[Set Variable] EIP). Global and route variables, such as `global:foo`, are not in this map; use `exchange.getVariable('global:foo')` for those. +The result of a script is its Python text, as `str()` gives it: a dict gives its Python text, and `None` gives the +text `None`. Set `resultType` to convert the text to another type. + == Examples A Python predicate in a xref:eips:choice-eip.adoc[Content-Based Router]: diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/quickjs-language.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/quickjs-language.adoc index c849fb61469c..ff56cae58b61 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/quickjs-language.adoc +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/quickjs-language.adoc @@ -142,7 +142,8 @@ Values cross the Java/JavaScript boundary as JSON: `headers.MyHeader` and `headers['MyHeader']` both work. * `List` and arrays become JavaScript arrays. * `byte[]` becomes a Base64 JSON string. `char[]` becomes a JSON string. -* Other Java types are serialized with Jackson into a JSON object or array snapshot. +* Other Java types are serialized with Jackson into a JSON snapshot: an object or an array, or a value + such as the milliseconds of a `Date`. Java methods such as `getAge()` are not callable from JavaScript; use JSON fields such as `body.age`. * `Exchange`, `Message`, `CamelContext`, `Class`, and `ClassLoader` values are rejected @@ -159,8 +160,11 @@ the unsupported type. == Expression and predicate -As an expression, the JavaScript value of the script becomes the Camel result (then converted -with Camel type converters when a result type is requested). +As an expression, the JSON value of the script becomes the Camel result (then converted +with Camel type converters when a result type is requested): an object becomes a `Map` and an +array a `List`, a `Date` becomes its ISO text, and `undefined`, `NaN` or a function becomes `null`. +A `Set` or a typed array does not keep its values. In `setBody` and `transform` this result +replaces a body the script set with `camel.setBody(...)`. As a predicate (`.when().quickjs(...)` or `.filter().quickjs(...)`), the result is converted to boolean with Camel's standard `ObjectHelper.evaluateValuePredicate` rules: a `Boolean` is used diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/spel-language.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/spel-language.adoc index 76c0c583257f..4b6a8e16d796 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/spel-language.adoc +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/spel-language.adoc @@ -32,13 +32,14 @@ The following Camel related variables are made available: [width="100%",cols="10%,10%,80%",options="header",] |======================================================================= |Variable |Type |Description -|*this* |Exchange |the Exchange is the root object +|*this* |RootObject |the root object, whose properties are the variables below |context |CamelContext |the CamelContext |exchange |Exchange |the Exchange |exchangeId |String |the exchange id |exception |Throwable |the Exchange exception (if any) |request |Message |the message |message |Message |the message +|body |Object |the message body |headers |Map |the message headers |getHeader(name) |Object |the message header by the given name |getHeader(name, type) |Type |the message header by the given name as the given type diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/typesafe-ai-language.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/typesafe-ai-language.adoc index 7cd3ee9a3455..9cba3d17e68c 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/typesafe-ai-language.adoc +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/typesafe-ai-language.adoc @@ -37,7 +37,7 @@ settings belong to the component or selected endpoint. | `threshold` | Endpoint `threshold` (`0.5`) | Probability at or above this value matches outside the uncertainty band. | `uncertainty` | Endpoint `uncertainty` (`0`) | Half-width of the inclusive band around the threshold; zero disables it. | `uncertainty-policy` | Endpoint `uncertaintyPolicy` (`NonMatch`) | `NonMatch` returns false within the band; `Fail` raises `TypeSafeAiUncertainResultException`. -| `state` | Endpoint `state` (`$\{body}`) | Simple expression selecting the state to send. For streams, use `${bodyAs(String)}`. +| `state` | Endpoint `state` (`$\{body}`) | Simple expression selecting the state to send: text, a Map or a List. For a stream, bytes or another object, use `${bodyAs(String)}`. |=== Prefix these properties with `camel.language.typesafe-ai.`. Unset language properties fall back to diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/datasonnet.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/datasonnet.json index 75df2e619fd5..94621b1abcc6 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/datasonnet.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/datasonnet.json @@ -15,6 +15,10 @@ "modelName": "datasonnet", "modelJavaType": "org.apache.camel.model.language.DatasonnetExpression" }, + "bodyTypes": { + "expressionIn": { "carriers": [ "any" ], "dependsOn": [ "bodyMediaType", "source" ], "description": "The body as it is, in the variable body. JSON, XML or CSV text is read in that format only with bodyMediaType or a Content-Type header, and a stream needs one of them" }, + "expressionOut": { "carriers": [ "pojo" ], "javaType": "com.datasonnet.document.Document", "dependsOn": [ "resultType", "outputMediaType" ], "description": "A Document with the result: a Java object, or text in outputMediaType when it is set. With resultType, the result converted to that type" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node." }, "expression": { "index": 1, "kind": "value", "displayName": "Expression", "group": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The expression value in your chosen language syntax." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/hl7terser.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/hl7terser.json index d781c669d73a..bd1b1add84ee 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/hl7terser.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/hl7terser.json @@ -15,6 +15,10 @@ "modelName": "hl7terser", "modelJavaType": "org.apache.camel.model.language.Hl7TerserExpression" }, + "bodyTypes": { + "expressionIn": { "carriers": [ "text", "bytes", "pojo" ], "format": "hl7", "dependsOn": [ "source" ], "description": "An HL7 message as text or bytes, in ER7 or XML, a HAPI Message, or a DOM of HL7 XML. A stream or a file fails: convert it to text first" }, + "expressionOut": { "carriers": [ "text", "null" ], "javaType": "java.lang.String", "dependsOn": [ "resultType" ], "description": "The value of the field as text, null when the field is empty" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node." }, "expression": { "index": 1, "kind": "value", "displayName": "Expression", "group": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The expression value in your chosen language syntax." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/jactl.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/jactl.json index c9e43d62a2f6..056fbdec476e 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/jactl.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/jactl.json @@ -15,6 +15,10 @@ "modelName": "jactl", "modelJavaType": "org.apache.camel.model.language.JactlExpression" }, + "bodyTypes": { + "expressionIn": { "carriers": [ "any" ], "description": "The body as it is, in the variable body. Without host access a script uses text, a number, bytes, a Map or a List, not the methods of other objects: JSON text is not parsed" }, + "expressionOut": { "carriers": [ "unknown" ], "description": "What the script returns" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node." }, "expression": { "index": 1, "kind": "value", "displayName": "Expression", "group": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The expression value in your chosen language syntax." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/java.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/java.json index bc7236c0bc51..d6bd93b95112 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/java.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/java.json @@ -15,6 +15,10 @@ "modelName": "java", "modelJavaType": "org.apache.camel.model.language.JavaExpression" }, + "bodyTypes": { + "expressionIn": { "carriers": [ "any" ], "description": "The body as it is, in the variable body of type Object: bodyAs(type) converts it" }, + "expressionOut": { "carriers": [ "unknown" ], "description": "What the script returns" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node." }, "expression": { "index": 1, "kind": "value", "displayName": "Expression", "group": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The expression value in your chosen language syntax." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/js.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/js.json index f3c44d3430ce..697d1e15777d 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/js.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/js.json @@ -15,6 +15,10 @@ "modelName": "js", "modelJavaType": "org.apache.camel.model.language.JavaScriptExpression" }, + "bodyTypes": { + "expressionIn": { "carriers": [ "any" ], "description": "The body as it is, in the variable body: a String is a JavaScript string, and other Java objects keep their methods" }, + "expressionOut": { "carriers": [ "unknown" ], "description": "What the script returns: an object as a Map, an array as a List, a Set as a Set and a Date as an Instant" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node." }, "expression": { "index": 1, "kind": "value", "displayName": "Expression", "group": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The expression value in your chosen language syntax." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/ognl.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/ognl.json index dc5ede9c92b0..4be079c57039 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/ognl.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/ognl.json @@ -15,6 +15,10 @@ "modelName": "ognl", "modelJavaType": "org.apache.camel.model.language.OgnlExpression" }, + "bodyTypes": { + "expressionIn": { "carriers": [ "any" ], "description": "The body as it is, in request.body: there is no variable body" }, + "expressionOut": { "carriers": [ "unknown" ], "description": "What the expression returns" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node." }, "expression": { "index": 1, "kind": "value", "displayName": "Expression", "group": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The expression value in your chosen language syntax." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/openfeature.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/openfeature.json index 674c1231be8e..06e473388476 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/openfeature.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/openfeature.json @@ -15,6 +15,10 @@ "modelName": "language", "modelJavaType": "org.apache.camel.model.language.LanguageExpression" }, + "bodyTypes": { + "expressionIn": { "carriers": [ "any" ], "description": "Not read: the expression is the flag key, and the targeting key and the context come from headers" }, + "expressionOut": { "carriers": [ "text" ], "javaType": "java.lang.String", "description": "The string value of the flag, or the defaultValue of the endpoint when the flag is not a string flag or is missing" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node." }, "language": { "index": 1, "kind": "attribute", "displayName": "Language", "group": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The name of the language to use." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/python.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/python.json index 7efbe57892d8..bfa3cd98fa59 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/python.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/python.json @@ -15,6 +15,10 @@ "modelName": "python", "modelJavaType": "org.apache.camel.model.language.PythonExpression" }, + "bodyTypes": { + "expressionIn": { "carriers": [ "any" ], "description": "The body as it is, in the variable body: a String is a Python unicode string, and other Java objects keep their methods" }, + "expressionOut": { "carriers": [ "text" ], "javaType": "java.lang.String", "dependsOn": [ "resultType" ], "description": "The Python text, str(), of what the script returns: a dict as its Python text, and None as the text None" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node." }, "expression": { "index": 1, "kind": "value", "displayName": "Expression", "group": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The expression value in your chosen language syntax." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/python3.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/python3.json index a2eb531c38cf..f3f647ace109 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/python3.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/python3.json @@ -15,6 +15,10 @@ "modelName": "python3", "modelJavaType": "org.apache.camel.model.language.Python3Expression" }, + "bodyTypes": { + "expressionIn": { "carriers": [ "any" ], "description": "The body as it is, in the variable body: a Map, a List or an array can be indexed, and other Java objects have no methods unless the language is created with createWithHostAccess()" }, + "expressionOut": { "carriers": [ "unknown" ], "description": "What the script returns: a dict as a Map, a list or a tuple as a List, a set as a Set, bytes as a List of numbers, and None as null" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node." }, "expression": { "index": 1, "kind": "value", "displayName": "Expression", "group": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The expression value in your chosen language syntax." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/quickjs.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/quickjs.json index 5f813683212e..f4e206c0b39f 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/quickjs.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/quickjs.json @@ -15,6 +15,10 @@ "modelName": "quickjs", "modelJavaType": "org.apache.camel.model.language.QuickjsExpression" }, + "bodyTypes": { + "expressionIn": { "carriers": [ "text", "bytes", "value", "map", "list", "pojo" ], "description": "A JSON copy of the body, in the variable body: bytes as Base64 text, and a POJO through Jackson. A stream fails: convert it to text first" }, + "expressionOut": { "carriers": [ "text", "value", "map", "list", "null" ], "dependsOn": [ "resultType" ], "description": "The JSON value the script returns: an object as a Map, an array as a List, and undefined, NaN or a function as null" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node." }, "expression": { "index": 1, "kind": "value", "displayName": "Expression", "group": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The expression value in your chosen language syntax." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/semantic.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/semantic.json index 14080a7680ee..c7a087edc1ee 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/semantic.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/semantic.json @@ -15,6 +15,10 @@ "modelName": "language", "modelJavaType": "org.apache.camel.model.language.LanguageExpression" }, + "bodyTypes": { + "expressionIn": { "carriers": [ "text", "map", "list", "bytes", "stream" ], "description": "The state, the body unless the declaration selects another: text, a Map or a List, and bytes, a stream or Base64 text only with an image Content-Type. Another body fails: select ${bodyAs(String)}" }, + "expressionOut": { "carriers": [ "value", "text", "list", "map" ], "description": "What the operation of the expert gives: a Boolean, a category as text, a score or a Set of labels, and with refs: a Map of the results by name" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node." }, "language": { "index": 1, "kind": "attribute", "displayName": "Language", "group": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The name of the language to use." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/spel.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/spel.json index 7a7abac5e448..ef218b49f9b7 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/spel.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/spel.json @@ -15,6 +15,10 @@ "modelName": "spel", "modelJavaType": "org.apache.camel.model.language.SpELExpression" }, + "bodyTypes": { + "expressionIn": { "carriers": [ "any" ], "description": "The body as it is, in body, request.body or message.body" }, + "expressionOut": { "carriers": [ "unknown" ], "description": "What the expression returns, and text when text surrounds the #{ } parts" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node." }, "expression": { "index": 1, "kind": "value", "displayName": "Expression", "group": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The expression value in your chosen language syntax." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/typesafe-ai.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/typesafe-ai.json index 2f9096baaa93..949a02df25f8 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/typesafe-ai.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/typesafe-ai.json @@ -15,6 +15,10 @@ "modelName": "language", "modelJavaType": "org.apache.camel.model.language.LanguageExpression" }, + "bodyTypes": { + "expressionIn": { "carriers": [ "text", "map", "list" ], "description": "The state, the body unless the state option selects another: text, or a Map or a List of JSON values. Another body fails: select ${bodyAs(String)}" }, + "expressionOut": { "carriers": [ "value" ], "javaType": "java.lang.Boolean", "description": "Whether the Noul probability reaches the threshold" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node." }, "language": { "index": 1, "kind": "attribute", "displayName": "Language", "group": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The name of the language to use." }, diff --git a/components/camel-ai/camel-semantic/src/generated/resources/META-INF/org/apache/camel/language/semantic/semantic.json b/components/camel-ai/camel-semantic/src/generated/resources/META-INF/org/apache/camel/language/semantic/semantic.json index 14080a7680ee..c7a087edc1ee 100644 --- a/components/camel-ai/camel-semantic/src/generated/resources/META-INF/org/apache/camel/language/semantic/semantic.json +++ b/components/camel-ai/camel-semantic/src/generated/resources/META-INF/org/apache/camel/language/semantic/semantic.json @@ -15,6 +15,10 @@ "modelName": "language", "modelJavaType": "org.apache.camel.model.language.LanguageExpression" }, + "bodyTypes": { + "expressionIn": { "carriers": [ "text", "map", "list", "bytes", "stream" ], "description": "The state, the body unless the declaration selects another: text, a Map or a List, and bytes, a stream or Base64 text only with an image Content-Type. Another body fails: select ${bodyAs(String)}" }, + "expressionOut": { "carriers": [ "value", "text", "list", "map" ], "description": "What the operation of the expert gives: a Boolean, a category as text, a score or a Set of labels, and with refs: a Map of the results by name" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node." }, "language": { "index": 1, "kind": "attribute", "displayName": "Language", "group": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The name of the language to use." }, diff --git a/components/camel-ai/camel-semantic/src/main/java/org/apache/camel/language/semantic/SemanticLanguage.java b/components/camel-ai/camel-semantic/src/main/java/org/apache/camel/language/semantic/SemanticLanguage.java index 4bc97b8b3f9e..a2a154c310ac 100644 --- a/components/camel-ai/camel-semantic/src/main/java/org/apache/camel/language/semantic/SemanticLanguage.java +++ b/components/camel-ai/camel-semantic/src/main/java/org/apache/camel/language/semantic/SemanticLanguage.java @@ -41,6 +41,9 @@ import org.apache.camel.semantic.SemanticExpert.ResultType; import org.apache.camel.semantic.SemanticInput; import org.apache.camel.semantic.SemanticResult; import org.apache.camel.semantic.internal.SemanticAuditService; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.annotations.Language; import org.apache.camel.support.ExpressionAdapter; @@ -51,6 +54,13 @@ import org.apache.camel.support.LanguageSupport; @Metadata(title = "Semantic Evaluation", description = "Invoke named evaluations of message content to produce boolean decisions, categories, scores and label sets through provider adapters", label = "language,ai", firstVersion = "4.23.0") +@BodyTypes(expressionIn = @BodyType(value = { Carrier.TEXT, Carrier.MAP, Carrier.LIST, Carrier.BYTES, Carrier.STREAM }, + description = "The state, the body unless the declaration selects another: text, a Map or a" + + " List, and bytes, a stream or Base64 text only with an image Content-Type." + + " Another body fails: select ${bodyAs(String)}"), + expressionOut = @BodyType(value = { Carrier.VALUE, Carrier.TEXT, Carrier.LIST, Carrier.MAP }, + description = "What the operation of the expert gives: a Boolean, a category as text, a" + + " score or a Set of labels, and with refs: a Map of the results by name")) public class SemanticLanguage extends LanguageSupport { public static final String RESULT = "CamelSemanticResult"; public static final String RESULTS = "CamelSemanticResults"; diff --git a/components/camel-ai/camel-typesafe-ai/src/generated/resources/META-INF/org/apache/camel/language/typesafeai/typesafe-ai.json b/components/camel-ai/camel-typesafe-ai/src/generated/resources/META-INF/org/apache/camel/language/typesafeai/typesafe-ai.json index 2f9096baaa93..949a02df25f8 100644 --- a/components/camel-ai/camel-typesafe-ai/src/generated/resources/META-INF/org/apache/camel/language/typesafeai/typesafe-ai.json +++ b/components/camel-ai/camel-typesafe-ai/src/generated/resources/META-INF/org/apache/camel/language/typesafeai/typesafe-ai.json @@ -15,6 +15,10 @@ "modelName": "language", "modelJavaType": "org.apache.camel.model.language.LanguageExpression" }, + "bodyTypes": { + "expressionIn": { "carriers": [ "text", "map", "list" ], "description": "The state, the body unless the state option selects another: text, or a Map or a List of JSON values. Another body fails: select ${bodyAs(String)}" }, + "expressionOut": { "carriers": [ "value" ], "javaType": "java.lang.Boolean", "description": "Whether the Noul probability reaches the threshold" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node." }, "language": { "index": 1, "kind": "attribute", "displayName": "Language", "group": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The name of the language to use." }, diff --git a/components/camel-ai/camel-typesafe-ai/src/main/docs/typesafe-ai-language.adoc b/components/camel-ai/camel-typesafe-ai/src/main/docs/typesafe-ai-language.adoc index 7cd3ee9a3455..9cba3d17e68c 100644 --- a/components/camel-ai/camel-typesafe-ai/src/main/docs/typesafe-ai-language.adoc +++ b/components/camel-ai/camel-typesafe-ai/src/main/docs/typesafe-ai-language.adoc @@ -37,7 +37,7 @@ settings belong to the component or selected endpoint. | `threshold` | Endpoint `threshold` (`0.5`) | Probability at or above this value matches outside the uncertainty band. | `uncertainty` | Endpoint `uncertainty` (`0`) | Half-width of the inclusive band around the threshold; zero disables it. | `uncertainty-policy` | Endpoint `uncertaintyPolicy` (`NonMatch`) | `NonMatch` returns false within the band; `Fail` raises `TypeSafeAiUncertainResultException`. -| `state` | Endpoint `state` (`$\{body}`) | Simple expression selecting the state to send. For streams, use `${bodyAs(String)}`. +| `state` | Endpoint `state` (`$\{body}`) | Simple expression selecting the state to send: text, a Map or a List. For a stream, bytes or another object, use `${bodyAs(String)}`. |=== Prefix these properties with `camel.language.typesafe-ai.`. Unset language properties fall back to diff --git a/components/camel-ai/camel-typesafe-ai/src/main/java/org/apache/camel/language/typesafeai/TypeSafeAiLanguage.java b/components/camel-ai/camel-typesafe-ai/src/main/java/org/apache/camel/language/typesafeai/TypeSafeAiLanguage.java index b02ad6a40ea2..ac7014105a1f 100644 --- a/components/camel-ai/camel-typesafe-ai/src/main/java/org/apache/camel/language/typesafeai/TypeSafeAiLanguage.java +++ b/components/camel-ai/camel-typesafe-ai/src/main/java/org/apache/camel/language/typesafeai/TypeSafeAiLanguage.java @@ -26,6 +26,9 @@ import org.apache.camel.RuntimeCamelException; import org.apache.camel.component.typesafeai.TypeSafeAiConfiguration; import org.apache.camel.component.typesafeai.TypeSafeAiEndpoint; import org.apache.camel.component.typesafeai.TypeSafeAiUncertainResultException; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.annotations.Language; import org.apache.camel.support.ExpressionAdapter; @@ -36,6 +39,11 @@ import org.apache.camel.util.json.JsonObject; @Language(value = "typesafe-ai", modelName = "language") @Metadata(title = "TypeSafe AI", description = "Evaluate a Noul question with the TypeSafe AI decision API", label = "language,ai", firstVersion = "4.23.0") +@BodyTypes(expressionIn = @BodyType(value = { Carrier.TEXT, Carrier.MAP, Carrier.LIST }, + description = "The state, the body unless the state option selects another: text, or a Map" + + " or a List of JSON values. Another body fails: select ${bodyAs(String)}"), + expressionOut = @BodyType(value = Carrier.VALUE, javaType = "java.lang.Boolean", + description = "Whether the Noul probability reaches the threshold")) public class TypeSafeAiLanguage extends LanguageSupport { public static final String RESULT = "CamelTypeSafeAiResult"; diff --git a/components/camel-datasonnet/src/generated/resources/META-INF/org/apache/camel/language/datasonnet/datasonnet.json b/components/camel-datasonnet/src/generated/resources/META-INF/org/apache/camel/language/datasonnet/datasonnet.json index 75df2e619fd5..94621b1abcc6 100644 --- a/components/camel-datasonnet/src/generated/resources/META-INF/org/apache/camel/language/datasonnet/datasonnet.json +++ b/components/camel-datasonnet/src/generated/resources/META-INF/org/apache/camel/language/datasonnet/datasonnet.json @@ -15,6 +15,10 @@ "modelName": "datasonnet", "modelJavaType": "org.apache.camel.model.language.DatasonnetExpression" }, + "bodyTypes": { + "expressionIn": { "carriers": [ "any" ], "dependsOn": [ "bodyMediaType", "source" ], "description": "The body as it is, in the variable body. JSON, XML or CSV text is read in that format only with bodyMediaType or a Content-Type header, and a stream needs one of them" }, + "expressionOut": { "carriers": [ "pojo" ], "javaType": "com.datasonnet.document.Document", "dependsOn": [ "resultType", "outputMediaType" ], "description": "A Document with the result: a Java object, or text in outputMediaType when it is set. With resultType, the result converted to that type" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node." }, "expression": { "index": 1, "kind": "value", "displayName": "Expression", "group": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The expression value in your chosen language syntax." }, diff --git a/components/camel-datasonnet/src/main/docs/datasonnet-language.adoc b/components/camel-datasonnet/src/main/docs/datasonnet-language.adoc index 9a4894c4de70..827c8dff23fe 100644 --- a/components/camel-datasonnet/src/main/docs/datasonnet-language.adoc +++ b/components/camel-datasonnet/src/main/docs/datasonnet-language.adoc @@ -87,7 +87,7 @@ YAML:: In XML and YAML DSL, `resultType` is the fully qualified class name. If the expression results in an array, or an object, you can instruct the expression to return you `List.class` -or `Map.class`, respectively. However, you must also set the output media type to `application/x-java-object`. +or `Map.class`, respectively, as long as the output media type is `application/x-java-object`, which is the default. NOTE: The default `Document` object is useful in situations where there are intermediate transformation steps, and so retaining the content metadata through a route execution is valuable. @@ -116,6 +116,10 @@ And for output media type: 4. The DataSonnet Header output media type directive 5. `application/x-java-object` +NOTE: With the body media type `application/x-java-object`, the body is the Java object it is: JSON text is a string, +not an object, so `body.foo` fails on it. Set `bodyMediaType`, or a `Content-Type` header, to read text, bytes, a +stream or a file in that format, such as `application/json`, `application/xml` or `application/csv`. + === Functions Camel adds the following DataSonnet functions that can be used to access the diff --git a/components/camel-datasonnet/src/main/java/org/apache/camel/language/datasonnet/DatasonnetLanguage.java b/components/camel-datasonnet/src/main/java/org/apache/camel/language/datasonnet/DatasonnetLanguage.java index 4948bcd52b6d..64de43a4b8a7 100644 --- a/components/camel-datasonnet/src/main/java/org/apache/camel/language/datasonnet/DatasonnetLanguage.java +++ b/components/camel-datasonnet/src/main/java/org/apache/camel/language/datasonnet/DatasonnetLanguage.java @@ -31,6 +31,9 @@ import org.apache.camel.Expression; import org.apache.camel.Predicate; import org.apache.camel.component.dataweave.DataWeaveConversionException; import org.apache.camel.component.dataweave.DataWeaveConverter; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.annotations.Language; import org.apache.camel.support.LRUCacheFactory; import org.apache.camel.support.SingleInputTypedLanguageSupport; @@ -38,6 +41,14 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; @Language("datasonnet") +@BodyTypes(expressionIn = @BodyType(value = Carrier.ANY, dependsOn = { "bodyMediaType", "source" }, + description = "The body as it is, in the variable body. JSON, XML or CSV text is read in" + + " that format only with bodyMediaType or a Content-Type header, and a" + + " stream needs one of them"), + expressionOut = @BodyType(value = Carrier.POJO, javaType = "com.datasonnet.document.Document", + dependsOn = { "resultType", "outputMediaType" }, + description = "A Document with the result: a Java object, or text in outputMediaType" + + " when it is set. With resultType, the result converted to that type")) public class DatasonnetLanguage extends SingleInputTypedLanguageSupport { private static final Logger LOG = LoggerFactory.getLogger(DatasonnetLanguage.class); private final Map<String, String> classpathImports; diff --git a/components/camel-hl7/src/generated/resources/META-INF/org/apache/camel/component/hl7/hl7terser.json b/components/camel-hl7/src/generated/resources/META-INF/org/apache/camel/component/hl7/hl7terser.json index d781c669d73a..bd1b1add84ee 100644 --- a/components/camel-hl7/src/generated/resources/META-INF/org/apache/camel/component/hl7/hl7terser.json +++ b/components/camel-hl7/src/generated/resources/META-INF/org/apache/camel/component/hl7/hl7terser.json @@ -15,6 +15,10 @@ "modelName": "hl7terser", "modelJavaType": "org.apache.camel.model.language.Hl7TerserExpression" }, + "bodyTypes": { + "expressionIn": { "carriers": [ "text", "bytes", "pojo" ], "format": "hl7", "dependsOn": [ "source" ], "description": "An HL7 message as text or bytes, in ER7 or XML, a HAPI Message, or a DOM of HL7 XML. A stream or a file fails: convert it to text first" }, + "expressionOut": { "carriers": [ "text", "null" ], "javaType": "java.lang.String", "dependsOn": [ "resultType" ], "description": "The value of the field as text, null when the field is empty" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node." }, "expression": { "index": 1, "kind": "value", "displayName": "Expression", "group": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The expression value in your chosen language syntax." }, diff --git a/components/camel-hl7/src/main/java/org/apache/camel/component/hl7/Hl7TerserLanguage.java b/components/camel-hl7/src/main/java/org/apache/camel/component/hl7/Hl7TerserLanguage.java index 2a2d20803ad0..d9544cf11657 100644 --- a/components/camel-hl7/src/main/java/org/apache/camel/component/hl7/Hl7TerserLanguage.java +++ b/components/camel-hl7/src/main/java/org/apache/camel/component/hl7/Hl7TerserLanguage.java @@ -23,6 +23,9 @@ import org.apache.camel.CamelContext; import org.apache.camel.Exchange; import org.apache.camel.Expression; import org.apache.camel.RuntimeCamelException; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.annotations.Language; import org.apache.camel.support.ExpressionAdapter; import org.apache.camel.support.SingleInputTypedLanguageSupport; @@ -30,6 +33,12 @@ import org.apache.camel.support.builder.ExpressionBuilder; import org.apache.camel.util.ObjectHelper; @Language("hl7terser") +@BodyTypes(expressionIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.POJO }, format = "hl7", dependsOn = "source", + description = "An HL7 message as text or bytes, in ER7 or XML, a HAPI Message, or a DOM of" + + " HL7 XML. A stream or a file fails: convert it to text first"), + expressionOut = @BodyType(value = { Carrier.TEXT, Carrier.NULL }, javaType = "java.lang.String", + dependsOn = "resultType", + description = "The value of the field as text, null when the field is empty")) public class Hl7TerserLanguage extends SingleInputTypedLanguageSupport { public static Expression terser(final String expression) { diff --git a/components/camel-jactl/src/generated/resources/META-INF/org/apache/camel/language/jactl/jactl.json b/components/camel-jactl/src/generated/resources/META-INF/org/apache/camel/language/jactl/jactl.json index c9e43d62a2f6..056fbdec476e 100644 --- a/components/camel-jactl/src/generated/resources/META-INF/org/apache/camel/language/jactl/jactl.json +++ b/components/camel-jactl/src/generated/resources/META-INF/org/apache/camel/language/jactl/jactl.json @@ -15,6 +15,10 @@ "modelName": "jactl", "modelJavaType": "org.apache.camel.model.language.JactlExpression" }, + "bodyTypes": { + "expressionIn": { "carriers": [ "any" ], "description": "The body as it is, in the variable body. Without host access a script uses text, a number, bytes, a Map or a List, not the methods of other objects: JSON text is not parsed" }, + "expressionOut": { "carriers": [ "unknown" ], "description": "What the script returns" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node." }, "expression": { "index": 1, "kind": "value", "displayName": "Expression", "group": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The expression value in your chosen language syntax." }, diff --git a/components/camel-jactl/src/main/java/org/apache/camel/language/jactl/JactlLanguage.java b/components/camel-jactl/src/main/java/org/apache/camel/language/jactl/JactlLanguage.java index c4cbf705ae79..6aea3956ffd6 100644 --- a/components/camel-jactl/src/main/java/org/apache/camel/language/jactl/JactlLanguage.java +++ b/components/camel-jactl/src/main/java/org/apache/camel/language/jactl/JactlLanguage.java @@ -27,6 +27,9 @@ import org.apache.camel.Exchange; import org.apache.camel.Expression; import org.apache.camel.Message; import org.apache.camel.Predicate; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.ScriptingLanguage; import org.apache.camel.spi.annotations.Language; import org.apache.camel.support.LRUCacheFactory; @@ -80,6 +83,11 @@ import org.apache.camel.support.TypedLanguageSupport; * </p> */ @Language("jactl") +@BodyTypes(expressionIn = @BodyType(value = Carrier.ANY, + description = "The body as it is, in the variable body. Without host access a script uses" + + " text, a number, bytes, a Map or a List, not the methods of other objects:" + + " JSON text is not parsed"), + expressionOut = @BodyType(value = Carrier.UNKNOWN, description = "What the script returns")) public class JactlLanguage extends TypedLanguageSupport implements ScriptingLanguage { // Create a globals variable for use during compilation. diff --git a/components/camel-javascript/src/generated/resources/META-INF/org/apache/camel/language/js/js.json b/components/camel-javascript/src/generated/resources/META-INF/org/apache/camel/language/js/js.json index f3c44d3430ce..697d1e15777d 100644 --- a/components/camel-javascript/src/generated/resources/META-INF/org/apache/camel/language/js/js.json +++ b/components/camel-javascript/src/generated/resources/META-INF/org/apache/camel/language/js/js.json @@ -15,6 +15,10 @@ "modelName": "js", "modelJavaType": "org.apache.camel.model.language.JavaScriptExpression" }, + "bodyTypes": { + "expressionIn": { "carriers": [ "any" ], "description": "The body as it is, in the variable body: a String is a JavaScript string, and other Java objects keep their methods" }, + "expressionOut": { "carriers": [ "unknown" ], "description": "What the script returns: an object as a Map, an array as a List, a Set as a Set and a Date as an Instant" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node." }, "expression": { "index": 1, "kind": "value", "displayName": "Expression", "group": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The expression value in your chosen language syntax." }, diff --git a/components/camel-javascript/src/main/docs/js-language.adoc b/components/camel-javascript/src/main/docs/js-language.adoc index 7adba6032a66..4a31948fccd2 100644 --- a/components/camel-javascript/src/main/docs/js-language.adoc +++ b/components/camel-javascript/src/main/docs/js-language.adoc @@ -29,7 +29,6 @@ include::partial$language-options.adoc[] [width="100%",cols="10%,10%,80%",options="header",] |======================================================================= |Variable |Type |Description -|*this* |Exchange |the Exchange is the root object |exchange |Exchange |the Exchange |camelContext |CamelContext |the CamelContext |exchangeId |String |the exchange id diff --git a/components/camel-javascript/src/main/java/org/apache/camel/language/js/JavaScriptLanguage.java b/components/camel-javascript/src/main/java/org/apache/camel/language/js/JavaScriptLanguage.java index 228353ef3444..af10ff69f518 100644 --- a/components/camel-javascript/src/main/java/org/apache/camel/language/js/JavaScriptLanguage.java +++ b/components/camel-javascript/src/main/java/org/apache/camel/language/js/JavaScriptLanguage.java @@ -31,6 +31,9 @@ import org.apache.camel.NoTypeConversionAvailableException; import org.apache.camel.Predicate; import org.apache.camel.RuntimeCamelException; import org.apache.camel.Service; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.ScriptingLanguage; import org.apache.camel.spi.annotations.Language; import org.apache.camel.support.LRUCacheFactory; @@ -50,6 +53,12 @@ import org.graalvm.polyglot.Value; * {@code engine()} accessor also builds it on demand for an expression used before start. */ @Language("js") +@BodyTypes(expressionIn = @BodyType(value = Carrier.ANY, + description = "The body as it is, in the variable body: a String is a JavaScript string," + + " and other Java objects keep their methods"), + expressionOut = @BodyType(value = Carrier.UNKNOWN, + description = "What the script returns: an object as a Map, an array as a List, a Set as a" + + " Set and a Date as an Instant")) public class JavaScriptLanguage extends TypedLanguageSupport implements ScriptingLanguage, Service { // Source is not a Service, so nothing is stopped on eviction diff --git a/components/camel-joor/src/generated/resources/META-INF/org/apache/camel/language/joor/java.json b/components/camel-joor/src/generated/resources/META-INF/org/apache/camel/language/joor/java.json index bc7236c0bc51..d6bd93b95112 100644 --- a/components/camel-joor/src/generated/resources/META-INF/org/apache/camel/language/joor/java.json +++ b/components/camel-joor/src/generated/resources/META-INF/org/apache/camel/language/joor/java.json @@ -15,6 +15,10 @@ "modelName": "java", "modelJavaType": "org.apache.camel.model.language.JavaExpression" }, + "bodyTypes": { + "expressionIn": { "carriers": [ "any" ], "description": "The body as it is, in the variable body of type Object: bodyAs(type) converts it" }, + "expressionOut": { "carriers": [ "unknown" ], "description": "What the script returns" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node." }, "expression": { "index": 1, "kind": "value", "displayName": "Expression", "group": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The expression value in your chosen language syntax." }, diff --git a/components/camel-joor/src/main/java/org/apache/camel/language/joor/JavaLanguage.java b/components/camel-joor/src/main/java/org/apache/camel/language/joor/JavaLanguage.java index 1b246cac11a7..e568bebc2fff 100644 --- a/components/camel-joor/src/main/java/org/apache/camel/language/joor/JavaLanguage.java +++ b/components/camel-joor/src/main/java/org/apache/camel/language/joor/JavaLanguage.java @@ -26,6 +26,9 @@ import org.apache.camel.Expression; import org.apache.camel.Predicate; import org.apache.camel.RuntimeCamelException; import org.apache.camel.StaticService; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.ScriptingLanguage; import org.apache.camel.spi.annotations.Language; import org.apache.camel.support.ExpressionToPredicateAdapter; @@ -37,6 +40,10 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; @Language("java") +@BodyTypes(expressionIn = @BodyType(value = Carrier.ANY, + description = "The body as it is, in the variable body of type Object: bodyAs(type)" + + " converts it"), + expressionOut = @BodyType(value = Carrier.UNKNOWN, description = "What the script returns")) public class JavaLanguage extends TypedLanguageSupport implements ScriptingLanguage, StaticService { private static final Logger LOG = LoggerFactory.getLogger(JavaLanguage.class); diff --git a/components/camel-ognl/src/generated/resources/META-INF/org/apache/camel/language/ognl/ognl.json b/components/camel-ognl/src/generated/resources/META-INF/org/apache/camel/language/ognl/ognl.json index dc5ede9c92b0..4be079c57039 100644 --- a/components/camel-ognl/src/generated/resources/META-INF/org/apache/camel/language/ognl/ognl.json +++ b/components/camel-ognl/src/generated/resources/META-INF/org/apache/camel/language/ognl/ognl.json @@ -15,6 +15,10 @@ "modelName": "ognl", "modelJavaType": "org.apache.camel.model.language.OgnlExpression" }, + "bodyTypes": { + "expressionIn": { "carriers": [ "any" ], "description": "The body as it is, in request.body: there is no variable body" }, + "expressionOut": { "carriers": [ "unknown" ], "description": "What the expression returns" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node." }, "expression": { "index": 1, "kind": "value", "displayName": "Expression", "group": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The expression value in your chosen language syntax." }, diff --git a/components/camel-ognl/src/main/docs/ognl-language.adoc b/components/camel-ognl/src/main/docs/ognl-language.adoc index 5894057a024d..19f734145d2c 100644 --- a/components/camel-ognl/src/main/docs/ognl-language.adoc +++ b/components/camel-ognl/src/main/docs/ognl-language.adoc @@ -15,7 +15,7 @@ supported by https://commons.apache.org/dormant/commons-ognl/[(Apache Commons OG used as an xref:manual::expression.adoc[Expression] or xref:manual::predicate.adoc[Predicate] in Camel routes. -For example, you can use MVEL in a xref:manual::predicate.adoc[Predicate] +For example, you can use OGNL in a xref:manual::predicate.adoc[Predicate] with the xref:eips:choice-eip.adoc[Content-Based Router] EIP. You can use OGNL dot notation to invoke operations. If you for instance @@ -48,13 +48,12 @@ include::partial$language-options.adoc[] [width="100%",cols="10%,10%,80%",options="header",] |======================================================================= |Variable |Type |Description -|*this* |Exchange |the Exchange is the root object +|*this* |RootObject |the root object, whose properties are the variables below |context |CamelContext |the CamelContext |exchange |Exchange |the Exchange |exchangeId |String |the exchange id |exception |Throwable |the Exchange exception (if any) |request |Message |the message -|message |Message |the message |headers |Map |the message headers |getHeader(name) |Object |the message header by the given name |getHeader(name, type) |Type |the message header by the given name as the given type diff --git a/components/camel-ognl/src/main/java/org/apache/camel/language/ognl/OgnlLanguage.java b/components/camel-ognl/src/main/java/org/apache/camel/language/ognl/OgnlLanguage.java index 0ceb31c9ca05..580abfea74d0 100644 --- a/components/camel-ognl/src/main/java/org/apache/camel/language/ognl/OgnlLanguage.java +++ b/components/camel-ognl/src/main/java/org/apache/camel/language/ognl/OgnlLanguage.java @@ -24,11 +24,17 @@ import ognl.OgnlContext; import org.apache.camel.Expression; import org.apache.camel.ExpressionIllegalSyntaxException; import org.apache.camel.Predicate; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.ScriptingLanguage; import org.apache.camel.spi.annotations.Language; import org.apache.camel.support.TypedLanguageSupport; @Language("ognl") +@BodyTypes(expressionIn = @BodyType(value = Carrier.ANY, + description = "The body as it is, in request.body: there is no variable body"), + expressionOut = @BodyType(value = Carrier.UNKNOWN, description = "What the expression returns")) public class OgnlLanguage extends TypedLanguageSupport implements ScriptingLanguage { @Override diff --git a/components/camel-openfeature/src/generated/resources/META-INF/org/apache/camel/language/openfeature/openfeature.json b/components/camel-openfeature/src/generated/resources/META-INF/org/apache/camel/language/openfeature/openfeature.json index 674c1231be8e..06e473388476 100644 --- a/components/camel-openfeature/src/generated/resources/META-INF/org/apache/camel/language/openfeature/openfeature.json +++ b/components/camel-openfeature/src/generated/resources/META-INF/org/apache/camel/language/openfeature/openfeature.json @@ -15,6 +15,10 @@ "modelName": "language", "modelJavaType": "org.apache.camel.model.language.LanguageExpression" }, + "bodyTypes": { + "expressionIn": { "carriers": [ "any" ], "description": "Not read: the expression is the flag key, and the targeting key and the context come from headers" }, + "expressionOut": { "carriers": [ "text" ], "javaType": "java.lang.String", "description": "The string value of the flag, or the defaultValue of the endpoint when the flag is not a string flag or is missing" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node." }, "language": { "index": 1, "kind": "attribute", "displayName": "Language", "group": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The name of the language to use." }, diff --git a/components/camel-openfeature/src/main/docs/openfeature-language.adoc b/components/camel-openfeature/src/main/docs/openfeature-language.adoc index fa02ab66ca18..2daed955d900 100644 --- a/components/camel-openfeature/src/main/docs/openfeature-language.adoc +++ b/components/camel-openfeature/src/main/docs/openfeature-language.adoc @@ -29,8 +29,8 @@ This language is provided by the `camel-openfeature` component: == Usage -The language evaluates the given flag key as a boolean and returns the -result. It uses the `openfeature:flags` endpoint by default, inheriting +As a predicate, the language evaluates the given flag key as a boolean. +As an expression, it gives the string value of the flag, see below. It uses the `openfeature:flags` endpoint by default, inheriting component-level configuration such as `flagsResource` or `host`. The language does not modify the exchange — it reads targeting context diff --git a/components/camel-openfeature/src/main/java/org/apache/camel/language/openfeature/OpenFeatureLanguage.java b/components/camel-openfeature/src/main/java/org/apache/camel/language/openfeature/OpenFeatureLanguage.java index 7a6f5bb68992..8ce1fe1639d1 100644 --- a/components/camel-openfeature/src/main/java/org/apache/camel/language/openfeature/OpenFeatureLanguage.java +++ b/components/camel-openfeature/src/main/java/org/apache/camel/language/openfeature/OpenFeatureLanguage.java @@ -25,6 +25,9 @@ import org.apache.camel.Predicate; import org.apache.camel.RuntimeCamelException; import org.apache.camel.component.openfeature.OpenFeatureConstants; import org.apache.camel.component.openfeature.OpenFeatureEndpoint; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.annotations.Language; import org.apache.camel.support.ExpressionAdapter; @@ -35,6 +38,12 @@ import org.apache.camel.support.LanguageSupport; @Language(value = "openfeature", modelName = "language") @Metadata(title = "OpenFeature", description = "Evaluate a feature flag as a boolean predicate", label = "language,cloud", firstVersion = "4.23.0") +@BodyTypes(expressionIn = @BodyType(value = Carrier.ANY, + description = "Not read: the expression is the flag key, and the targeting key and the" + + " context come from headers"), + expressionOut = @BodyType(value = Carrier.TEXT, javaType = "java.lang.String", + description = "The string value of the flag, or the defaultValue of the endpoint when the" + + " flag is not a string flag or is missing")) public class OpenFeatureLanguage extends LanguageSupport { private String endpoint = "openfeature:flags"; diff --git a/components/camel-python/src/generated/resources/META-INF/org/apache/camel/language/python/python.json b/components/camel-python/src/generated/resources/META-INF/org/apache/camel/language/python/python.json index 7efbe57892d8..bfa3cd98fa59 100644 --- a/components/camel-python/src/generated/resources/META-INF/org/apache/camel/language/python/python.json +++ b/components/camel-python/src/generated/resources/META-INF/org/apache/camel/language/python/python.json @@ -15,6 +15,10 @@ "modelName": "python", "modelJavaType": "org.apache.camel.model.language.PythonExpression" }, + "bodyTypes": { + "expressionIn": { "carriers": [ "any" ], "description": "The body as it is, in the variable body: a String is a Python unicode string, and other Java objects keep their methods" }, + "expressionOut": { "carriers": [ "text" ], "javaType": "java.lang.String", "dependsOn": [ "resultType" ], "description": "The Python text, str(), of what the script returns: a dict as its Python text, and None as the text None" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node." }, "expression": { "index": 1, "kind": "value", "displayName": "Expression", "group": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The expression value in your chosen language syntax." }, diff --git a/components/camel-python/src/main/docs/python-language.adoc b/components/camel-python/src/main/docs/python-language.adoc index 76a14e411d11..a0e494416a4b 100644 --- a/components/camel-python/src/main/docs/python-language.adoc +++ b/components/camel-python/src/main/docs/python-language.adoc @@ -29,7 +29,6 @@ include::partial$language-options.adoc[] [width="100%",cols="10%,10%,80%",options="header",] |======================================================================= |Variable |Type |Description -|*this* |Exchange |the Exchange is the root object |exchange |Exchange |the Exchange |camelContext |CamelContext |the CamelContext |exchangeId |String |the exchange id @@ -55,6 +54,9 @@ The `variable` and `variables` bindings are the exchange-scoped variables (for e xref:eips:setVariable-eip.adoc[Set Variable] EIP). Global and route variables, such as `global:foo`, are not in this map; use `exchange.getVariable('global:foo')` for those. +The result of a script is its Python text, as `str()` gives it: a dict gives its Python text, and `None` gives the +text `None`. Set `resultType` to convert the text to another type. + == Examples A Python predicate in a xref:eips:choice-eip.adoc[Content-Based Router]: diff --git a/components/camel-python/src/main/java/org/apache/camel/language/python/PythonLanguage.java b/components/camel-python/src/main/java/org/apache/camel/language/python/PythonLanguage.java index e0aa4a8c6d7c..0b0b2298567e 100644 --- a/components/camel-python/src/main/java/org/apache/camel/language/python/PythonLanguage.java +++ b/components/camel-python/src/main/java/org/apache/camel/language/python/PythonLanguage.java @@ -23,6 +23,9 @@ import java.util.Map; import org.apache.camel.Expression; import org.apache.camel.ExpressionIllegalSyntaxException; import org.apache.camel.Predicate; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.ScriptingLanguage; import org.apache.camel.spi.annotations.Language; import org.apache.camel.support.LRUCacheFactory; @@ -32,6 +35,12 @@ import org.python.core.PyObject; import org.python.util.PythonInterpreter; @Language("python") +@BodyTypes(expressionIn = @BodyType(value = Carrier.ANY, + description = "The body as it is, in the variable body: a String is a Python unicode" + + " string, and other Java objects keep their methods"), + expressionOut = @BodyType(value = Carrier.TEXT, javaType = "java.lang.String", dependsOn = "resultType", + description = "The Python text, str(), of what the script returns: a dict as its Python" + + " text, and None as the text None")) public class PythonLanguage extends TypedLanguageSupport implements ScriptingLanguage { private final Map<String, PyCode> compiledScriptsCache; diff --git a/components/camel-python3/src/generated/resources/META-INF/org/apache/camel/language/python3/python3.json b/components/camel-python3/src/generated/resources/META-INF/org/apache/camel/language/python3/python3.json index a2eb531c38cf..f3f647ace109 100644 --- a/components/camel-python3/src/generated/resources/META-INF/org/apache/camel/language/python3/python3.json +++ b/components/camel-python3/src/generated/resources/META-INF/org/apache/camel/language/python3/python3.json @@ -15,6 +15,10 @@ "modelName": "python3", "modelJavaType": "org.apache.camel.model.language.Python3Expression" }, + "bodyTypes": { + "expressionIn": { "carriers": [ "any" ], "description": "The body as it is, in the variable body: a Map, a List or an array can be indexed, and other Java objects have no methods unless the language is created with createWithHostAccess()" }, + "expressionOut": { "carriers": [ "unknown" ], "description": "What the script returns: a dict as a Map, a list or a tuple as a List, a set as a Set, bytes as a List of numbers, and None as null" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node." }, "expression": { "index": 1, "kind": "value", "displayName": "Expression", "group": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The expression value in your chosen language syntax." }, diff --git a/components/camel-python3/src/main/java/org/apache/camel/language/python3/Python3Language.java b/components/camel-python3/src/main/java/org/apache/camel/language/python3/Python3Language.java index f8f15d99c31b..dd921ce8c2b5 100644 --- a/components/camel-python3/src/main/java/org/apache/camel/language/python3/Python3Language.java +++ b/components/camel-python3/src/main/java/org/apache/camel/language/python3/Python3Language.java @@ -36,6 +36,9 @@ import org.apache.camel.Message; import org.apache.camel.Predicate; import org.apache.camel.RuntimeCamelException; import org.apache.camel.Service; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.ScriptingLanguage; import org.apache.camel.spi.annotations.Language; import org.apache.camel.support.LRUCacheFactory; @@ -71,6 +74,13 @@ import org.graalvm.polyglot.Value; * </pre> */ @Language("python3") +@BodyTypes(expressionIn = @BodyType(value = Carrier.ANY, + description = "The body as it is, in the variable body: a Map, a List or an array can be" + + " indexed, and other Java objects have no methods unless the language is" + + " created with createWithHostAccess()"), + expressionOut = @BodyType(value = Carrier.UNKNOWN, + description = "What the script returns: a dict as a Map, a list or a tuple as a List, a set" + + " as a Set, bytes as a List of numbers, and None as null")) public class Python3Language extends TypedLanguageSupport implements ScriptingLanguage, Service { private final HostAccess hostAccess; diff --git a/components/camel-quickjs/src/generated/resources/META-INF/org/apache/camel/language/quickjs/quickjs.json b/components/camel-quickjs/src/generated/resources/META-INF/org/apache/camel/language/quickjs/quickjs.json index 5f813683212e..f4e206c0b39f 100644 --- a/components/camel-quickjs/src/generated/resources/META-INF/org/apache/camel/language/quickjs/quickjs.json +++ b/components/camel-quickjs/src/generated/resources/META-INF/org/apache/camel/language/quickjs/quickjs.json @@ -15,6 +15,10 @@ "modelName": "quickjs", "modelJavaType": "org.apache.camel.model.language.QuickjsExpression" }, + "bodyTypes": { + "expressionIn": { "carriers": [ "text", "bytes", "value", "map", "list", "pojo" ], "description": "A JSON copy of the body, in the variable body: bytes as Base64 text, and a POJO through Jackson. A stream fails: convert it to text first" }, + "expressionOut": { "carriers": [ "text", "value", "map", "list", "null" ], "dependsOn": [ "resultType" ], "description": "The JSON value the script returns: an object as a Map, an array as a List, and undefined, NaN or a function as null" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node." }, "expression": { "index": 1, "kind": "value", "displayName": "Expression", "group": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The expression value in your chosen language syntax." }, diff --git a/components/camel-quickjs/src/main/docs/quickjs-language.adoc b/components/camel-quickjs/src/main/docs/quickjs-language.adoc index c849fb61469c..ff56cae58b61 100644 --- a/components/camel-quickjs/src/main/docs/quickjs-language.adoc +++ b/components/camel-quickjs/src/main/docs/quickjs-language.adoc @@ -142,7 +142,8 @@ Values cross the Java/JavaScript boundary as JSON: `headers.MyHeader` and `headers['MyHeader']` both work. * `List` and arrays become JavaScript arrays. * `byte[]` becomes a Base64 JSON string. `char[]` becomes a JSON string. -* Other Java types are serialized with Jackson into a JSON object or array snapshot. +* Other Java types are serialized with Jackson into a JSON snapshot: an object or an array, or a value + such as the milliseconds of a `Date`. Java methods such as `getAge()` are not callable from JavaScript; use JSON fields such as `body.age`. * `Exchange`, `Message`, `CamelContext`, `Class`, and `ClassLoader` values are rejected @@ -159,8 +160,11 @@ the unsupported type. == Expression and predicate -As an expression, the JavaScript value of the script becomes the Camel result (then converted -with Camel type converters when a result type is requested). +As an expression, the JSON value of the script becomes the Camel result (then converted +with Camel type converters when a result type is requested): an object becomes a `Map` and an +array a `List`, a `Date` becomes its ISO text, and `undefined`, `NaN` or a function becomes `null`. +A `Set` or a typed array does not keep its values. In `setBody` and `transform` this result +replaces a body the script set with `camel.setBody(...)`. As a predicate (`.when().quickjs(...)` or `.filter().quickjs(...)`), the result is converted to boolean with Camel's standard `ObjectHelper.evaluateValuePredicate` rules: a `Boolean` is used diff --git a/components/camel-quickjs/src/main/java/org/apache/camel/language/quickjs/QuickjsLanguage.java b/components/camel-quickjs/src/main/java/org/apache/camel/language/quickjs/QuickjsLanguage.java index 805302f2814b..e45dcb558728 100644 --- a/components/camel-quickjs/src/main/java/org/apache/camel/language/quickjs/QuickjsLanguage.java +++ b/components/camel-quickjs/src/main/java/org/apache/camel/language/quickjs/QuickjsLanguage.java @@ -34,6 +34,9 @@ import org.apache.camel.ExpressionEvaluationException; import org.apache.camel.ExpressionIllegalSyntaxException; import org.apache.camel.Predicate; import org.apache.camel.Service; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.ScriptingLanguage; import org.apache.camel.spi.annotations.Language; import org.apache.camel.support.TypedLanguageSupport; @@ -55,6 +58,15 @@ import run.endive.runtime.Memory; * </p> */ @Language("quickjs") +@BodyTypes(expressionIn = @BodyType(value = { + Carrier.TEXT, Carrier.BYTES, Carrier.VALUE, Carrier.MAP, Carrier.LIST, + Carrier.POJO }, + description = "A JSON copy of the body, in the variable body: bytes as Base64 text, and a" + + " POJO through Jackson. A stream fails: convert it to text first"), + expressionOut = @BodyType(value = { Carrier.TEXT, Carrier.VALUE, Carrier.MAP, Carrier.LIST, Carrier.NULL }, + dependsOn = "resultType", + description = "The JSON value the script returns: an object as a Map, an array as a List," + + " and undefined, NaN or a function as null")) public class QuickjsLanguage extends TypedLanguageSupport implements ScriptingLanguage, Service { /** diff --git a/components/camel-spring-parent/camel-spring/src/generated/resources/META-INF/org/apache/camel/language/spel/spel.json b/components/camel-spring-parent/camel-spring/src/generated/resources/META-INF/org/apache/camel/language/spel/spel.json index 7a7abac5e448..ef218b49f9b7 100644 --- a/components/camel-spring-parent/camel-spring/src/generated/resources/META-INF/org/apache/camel/language/spel/spel.json +++ b/components/camel-spring-parent/camel-spring/src/generated/resources/META-INF/org/apache/camel/language/spel/spel.json @@ -15,6 +15,10 @@ "modelName": "spel", "modelJavaType": "org.apache.camel.model.language.SpELExpression" }, + "bodyTypes": { + "expressionIn": { "carriers": [ "any" ], "description": "The body as it is, in body, request.body or message.body" }, + "expressionOut": { "carriers": [ "unknown" ], "description": "What the expression returns, and text when text surrounds the #{ } parts" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node." }, "expression": { "index": 1, "kind": "value", "displayName": "Expression", "group": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The expression value in your chosen language syntax." }, diff --git a/components/camel-spring-parent/camel-spring/src/main/docs/spel-language.adoc b/components/camel-spring-parent/camel-spring/src/main/docs/spel-language.adoc index 76c0c583257f..4b6a8e16d796 100644 --- a/components/camel-spring-parent/camel-spring/src/main/docs/spel-language.adoc +++ b/components/camel-spring-parent/camel-spring/src/main/docs/spel-language.adoc @@ -32,13 +32,14 @@ The following Camel related variables are made available: [width="100%",cols="10%,10%,80%",options="header",] |======================================================================= |Variable |Type |Description -|*this* |Exchange |the Exchange is the root object +|*this* |RootObject |the root object, whose properties are the variables below |context |CamelContext |the CamelContext |exchange |Exchange |the Exchange |exchangeId |String |the exchange id |exception |Throwable |the Exchange exception (if any) |request |Message |the message |message |Message |the message +|body |Object |the message body |headers |Map |the message headers |getHeader(name) |Object |the message header by the given name |getHeader(name, type) |Type |the message header by the given name as the given type diff --git a/components/camel-spring-parent/camel-spring/src/main/java/org/apache/camel/language/spel/SpelLanguage.java b/components/camel-spring-parent/camel-spring/src/main/java/org/apache/camel/language/spel/SpelLanguage.java index 72aa2790eefe..da0dcf5bba99 100644 --- a/components/camel-spring-parent/camel-spring/src/main/java/org/apache/camel/language/spel/SpelLanguage.java +++ b/components/camel-spring-parent/camel-spring/src/main/java/org/apache/camel/language/spel/SpelLanguage.java @@ -19,6 +19,9 @@ package org.apache.camel.language.spel; import org.apache.camel.Expression; import org.apache.camel.Predicate; import org.apache.camel.StaticService; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.annotations.Language; import org.apache.camel.spring.SpringCamelContext; import org.apache.camel.spring.util.RegistryBeanResolver; @@ -32,6 +35,10 @@ import org.springframework.expression.BeanResolver; * A Spring Expression {@link org.apache.camel.spi.Language} plugin */ @Language("spel") +@BodyTypes(expressionIn = @BodyType(value = Carrier.ANY, + description = "The body as it is, in body, request.body or message.body"), + expressionOut = @BodyType(value = Carrier.UNKNOWN, + description = "What the expression returns, and text when text surrounds the #{ } parts")) public class SpelLanguage extends TypedLanguageSupport implements StaticService { private BeanResolver beanResolver;
