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 2023/02/25 17:27:21 UTC

[camel] branch camel-3.x updated: CAMEL-19079: camel-language - Should init expression. Add resultType as configuration option.

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

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


The following commit(s) were added to refs/heads/camel-3.x by this push:
     new 9c5339b82bb CAMEL-19079: camel-language - Should init expression. Add resultType as configuration option.
9c5339b82bb is described below

commit 9c5339b82bb2c067f02de40c3f582e83a4dba4f7
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Sat Feb 25 18:26:04 2023 +0100

    CAMEL-19079: camel-language - Should init expression. Add resultType as configuration option.
---
 .../apache/camel/catalog/components/language.json  |  1 +
 .../language/LanguageEndpointConfigurer.java       |  6 ++++
 .../language/LanguageEndpointUriFactory.java       |  3 +-
 .../apache/camel/component/language/language.json  |  1 +
 .../camel/component/language/LanguageEndpoint.java | 32 +++++++++++++----
 .../camel/component/language/LanguageProducer.java | 14 +++++++-
 .../XQueryLanguageProducerTemplateTest.java        | 41 ++++++++++++++++++++++
 .../dsl/LanguageEndpointBuilderFactory.java        | 14 ++++++++
 8 files changed, 103 insertions(+), 9 deletions(-)

diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/language.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/language.json
index da622e8e69d..5bce1dc1155 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/language.json
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/language.json
@@ -35,6 +35,7 @@
     "binary": { "kind": "parameter", "displayName": "Binary", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the script is binary content or text content. By default the script is read as text content (eg java.lang.String)" },
     "cacheScript": { "kind": "parameter", "displayName": "Cache Script", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to cache the compiled script and reuse Notice reusing the script can cause side effects from processing one Camel org.apache.camel.Exchange to the next org.apache.camel.Exchange." },
     "contentCache": { "kind": "parameter", "displayName": "Content Cache", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Sets whether to use resource content cache or not" },
+    "resultType": { "kind": "parameter", "displayName": "Result Type", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the class of the result type (type from output)" },
     "script": { "kind": "parameter", "displayName": "Script", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the script to execute" },
     "transform": { "kind": "parameter", "displayName": "Transform", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether or not the result of the script should be used as message body. This options is default true." },
     "lazyStartProducer": { "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may other [...]
diff --git a/components/camel-language/src/generated/java/org/apache/camel/component/language/LanguageEndpointConfigurer.java b/components/camel-language/src/generated/java/org/apache/camel/component/language/LanguageEndpointConfigurer.java
index ead8210e747..7260366f861 100644
--- a/components/camel-language/src/generated/java/org/apache/camel/component/language/LanguageEndpointConfigurer.java
+++ b/components/camel-language/src/generated/java/org/apache/camel/component/language/LanguageEndpointConfigurer.java
@@ -30,6 +30,8 @@ public class LanguageEndpointConfigurer extends PropertyConfigurerSupport implem
         case "contentCache": target.setContentCache(property(camelContext, boolean.class, value)); return true;
         case "lazystartproducer":
         case "lazyStartProducer": target.setLazyStartProducer(property(camelContext, boolean.class, value)); return true;
+        case "resulttype":
+        case "resultType": target.setResultType(property(camelContext, java.lang.String.class, value)); return true;
         case "script": target.setScript(property(camelContext, java.lang.String.class, value)); return true;
         case "transform": target.setTransform(property(camelContext, boolean.class, value)); return true;
         default: return false;
@@ -48,6 +50,8 @@ public class LanguageEndpointConfigurer extends PropertyConfigurerSupport implem
         case "contentCache": return boolean.class;
         case "lazystartproducer":
         case "lazyStartProducer": return boolean.class;
+        case "resulttype":
+        case "resultType": return java.lang.String.class;
         case "script": return java.lang.String.class;
         case "transform": return boolean.class;
         default: return null;
@@ -67,6 +71,8 @@ public class LanguageEndpointConfigurer extends PropertyConfigurerSupport implem
         case "contentCache": return target.isContentCache();
         case "lazystartproducer":
         case "lazyStartProducer": return target.isLazyStartProducer();
+        case "resulttype":
+        case "resultType": return target.getResultType();
         case "script": return target.getScript();
         case "transform": return target.isTransform();
         default: return null;
diff --git a/components/camel-language/src/generated/java/org/apache/camel/component/language/LanguageEndpointUriFactory.java b/components/camel-language/src/generated/java/org/apache/camel/component/language/LanguageEndpointUriFactory.java
index 7a4c12385ee..f49a39fdec2 100644
--- a/components/camel-language/src/generated/java/org/apache/camel/component/language/LanguageEndpointUriFactory.java
+++ b/components/camel-language/src/generated/java/org/apache/camel/component/language/LanguageEndpointUriFactory.java
@@ -21,7 +21,7 @@ public class LanguageEndpointUriFactory extends org.apache.camel.support.compone
     private static final Set<String> SECRET_PROPERTY_NAMES;
     private static final Set<String> MULTI_VALUE_PREFIXES;
     static {
-        Set<String> props = new HashSet<>(9);
+        Set<String> props = new HashSet<>(10);
         props.add("allowContextMapAll");
         props.add("binary");
         props.add("cacheScript");
@@ -29,6 +29,7 @@ public class LanguageEndpointUriFactory extends org.apache.camel.support.compone
         props.add("languageName");
         props.add("lazyStartProducer");
         props.add("resourceUri");
+        props.add("resultType");
         props.add("script");
         props.add("transform");
         PROPERTY_NAMES = Collections.unmodifiableSet(props);
diff --git a/components/camel-language/src/generated/resources/org/apache/camel/component/language/language.json b/components/camel-language/src/generated/resources/org/apache/camel/component/language/language.json
index da622e8e69d..5bce1dc1155 100644
--- a/components/camel-language/src/generated/resources/org/apache/camel/component/language/language.json
+++ b/components/camel-language/src/generated/resources/org/apache/camel/component/language/language.json
@@ -35,6 +35,7 @@
     "binary": { "kind": "parameter", "displayName": "Binary", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the script is binary content or text content. By default the script is read as text content (eg java.lang.String)" },
     "cacheScript": { "kind": "parameter", "displayName": "Cache Script", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to cache the compiled script and reuse Notice reusing the script can cause side effects from processing one Camel org.apache.camel.Exchange to the next org.apache.camel.Exchange." },
     "contentCache": { "kind": "parameter", "displayName": "Content Cache", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Sets whether to use resource content cache or not" },
+    "resultType": { "kind": "parameter", "displayName": "Result Type", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the class of the result type (type from output)" },
     "script": { "kind": "parameter", "displayName": "Script", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the script to execute" },
     "transform": { "kind": "parameter", "displayName": "Transform", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether or not the result of the script should be used as message body. This options is default true." },
     "lazyStartProducer": { "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may other [...]
diff --git a/components/camel-language/src/main/java/org/apache/camel/component/language/LanguageEndpoint.java b/components/camel-language/src/main/java/org/apache/camel/component/language/LanguageEndpoint.java
index e46f308c20e..3e0d71b8e75 100644
--- a/components/camel-language/src/main/java/org/apache/camel/component/language/LanguageEndpoint.java
+++ b/components/camel-language/src/main/java/org/apache/camel/component/language/LanguageEndpoint.java
@@ -18,8 +18,8 @@ package org.apache.camel.component.language;
 
 import java.io.IOException;
 import java.io.InputStream;
-import java.io.UnsupportedEncodingException;
 import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
 
 import org.apache.camel.Category;
 import org.apache.camel.Component;
@@ -37,6 +37,7 @@ import org.apache.camel.spi.UriPath;
 import org.apache.camel.support.CamelContextHelper;
 import org.apache.camel.support.EndpointHelper;
 import org.apache.camel.support.ResourceHelper;
+import org.apache.camel.support.TypedLanguageSupport;
 import org.apache.camel.util.IOHelper;
 
 /**
@@ -58,7 +59,7 @@ public class LanguageEndpoint extends ResourceEndpoint {
     private String languageName;
     // resourceUri is optional in the language endpoint
     @UriPath(description = "Path to the resource, or a reference to lookup a bean in the Registry to use as the resource")
-    @Metadata(required = false)
+    @Metadata
     private String resourceUri;
     @UriParam
     private String script;
@@ -70,6 +71,8 @@ public class LanguageEndpoint extends ResourceEndpoint {
     private boolean cacheScript;
     @UriParam(defaultValue = "true", description = "Sets whether to use resource content cache or not")
     private boolean contentCache;
+    @UriParam
+    private String resultType;
 
     public LanguageEndpoint() {
         // enable cache by default
@@ -90,6 +93,10 @@ public class LanguageEndpoint extends ResourceEndpoint {
         if (language == null && languageName != null) {
             language = getCamelContext().resolveLanguage(languageName);
         }
+        if (language instanceof TypedLanguageSupport && resultType != null) {
+            Class<?> clazz = getCamelContext().getClassResolver().resolveMandatoryClass(resultType);
+            ((TypedLanguageSupport) language).setResultType(clazz);
+        }
         if (cacheScript && expression == null && script != null) {
             boolean external = script.startsWith("file:") || script.startsWith("http:");
             if (!external) {
@@ -98,6 +105,9 @@ public class LanguageEndpoint extends ResourceEndpoint {
                 expression = language.createExpression(script);
             }
         }
+        if (expression != null) {
+            expression.init(getCamelContext());
+        }
     }
 
     @Override
@@ -105,6 +115,7 @@ public class LanguageEndpoint extends ResourceEndpoint {
         if (cacheScript && expression == null && script != null) {
             script = resolveScript(script);
             expression = language.createExpression(script);
+            expression.init(getCamelContext());
         }
 
         return new LanguageProducer(this);
@@ -141,11 +152,7 @@ public class LanguageEndpoint extends ResourceEndpoint {
     @Override
     protected String createEndpointUri() {
         String s = script;
-        try {
-            s = URLEncoder.encode(s, "UTF-8");
-        } catch (UnsupportedEncodingException e) {
-            // ignore
-        }
+        s = URLEncoder.encode(s, StandardCharsets.UTF_8);
         return languageName + ":" + s;
     }
 
@@ -254,6 +261,17 @@ public class LanguageEndpoint extends ResourceEndpoint {
         this.cacheScript = cacheScript;
     }
 
+    public String getResultType() {
+        return resultType;
+    }
+
+    /**
+     * Sets the class of the result type (type from output)
+     */
+    public void setResultType(String resultType) {
+        this.resultType = resultType;
+    }
+
     @Override
     public void clearContentCache() {
         super.clearContentCache();
diff --git a/components/camel-language/src/main/java/org/apache/camel/component/language/LanguageProducer.java b/components/camel-language/src/main/java/org/apache/camel/component/language/LanguageProducer.java
index ae825ad4779..966d0f78a7a 100644
--- a/components/camel-language/src/main/java/org/apache/camel/component/language/LanguageProducer.java
+++ b/components/camel-language/src/main/java/org/apache/camel/component/language/LanguageProducer.java
@@ -36,6 +36,8 @@ public class LanguageProducer extends DefaultProducer {
 
     private static final Logger LOG = LoggerFactory.getLogger(LanguageProducer.class);
 
+    private Class<?> resultType = Object.class;
+
     public LanguageProducer(LanguageEndpoint endpoint) {
         super(endpoint);
     }
@@ -52,6 +54,7 @@ public class LanguageProducer extends DefaultProducer {
                 // the script may be a file: so resolve it before using
                 script = getEndpoint().resolveScript(script);
                 exp = getEndpoint().getLanguage().createExpression(script);
+                exp.init(getEndpoint().getCamelContext());
             }
         }
         // if not fallback to use expression from endpoint
@@ -95,6 +98,7 @@ public class LanguageProducer extends DefaultProducer {
         if (script != null) {
             // create the expression from the script
             exp = getEndpoint().getLanguage().createExpression(script);
+            exp.init(getEndpoint().getCamelContext());
             // expression was resolved from resource
             getEndpoint().setContentResolvedFromResource(true);
             // if we cache then set this as expression on endpoint so we don't re-create it again
@@ -107,7 +111,7 @@ public class LanguageProducer extends DefaultProducer {
         Object result;
         if (exp != null) {
             try {
-                result = exp.evaluate(exchange, Object.class);
+                result = exp.evaluate(exchange, resultType);
                 LOG.debug("Evaluated expression as: {} with: {}", result, exchange);
             } finally {
                 if (!getEndpoint().isCacheScript()) {
@@ -131,4 +135,12 @@ public class LanguageProducer extends DefaultProducer {
     public LanguageEndpoint getEndpoint() {
         return (LanguageEndpoint) super.getEndpoint();
     }
+
+    @Override
+    protected void doBuild() throws Exception {
+        if (getEndpoint().getResultType() != null) {
+            resultType = getEndpoint().getCamelContext()
+                    .getClassResolver().resolveMandatoryClass(getEndpoint().getResultType());
+        }
+    }
 }
diff --git a/components/camel-saxon/src/test/java/org/apache/camel/language/XQueryLanguageProducerTemplateTest.java b/components/camel-saxon/src/test/java/org/apache/camel/language/XQueryLanguageProducerTemplateTest.java
new file mode 100644
index 00000000000..f998dea06bb
--- /dev/null
+++ b/components/camel-saxon/src/test/java/org/apache/camel/language/XQueryLanguageProducerTemplateTest.java
@@ -0,0 +1,41 @@
+/*
+ * 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.language;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.impl.DefaultCamelContext;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class XQueryLanguageProducerTemplateTest {
+
+    @Test
+    public void testXQueryLanguage() {
+        CamelContext context = new DefaultCamelContext();
+        context.start();
+
+        ProducerTemplate producer = context.createProducerTemplate();
+        String result = producer.requestBody(
+                "language:xquery:upper-case(/message/text())?resultType=String",
+                "<message>Hello from XQuery</message>",
+                String.class);
+        Assertions.assertEquals("HELLO FROM XQUERY", result);
+
+        context.stop();
+    }
+}
diff --git a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/LanguageEndpointBuilderFactory.java b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/LanguageEndpointBuilderFactory.java
index af2b5ed1dda..1efd0c6a072 100644
--- a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/LanguageEndpointBuilderFactory.java
+++ b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/LanguageEndpointBuilderFactory.java
@@ -181,6 +181,20 @@ public interface LanguageEndpointBuilderFactory {
             doSetProperty("contentCache", contentCache);
             return this;
         }
+        /**
+         * Sets the class of the result type (type from output).
+         * 
+         * The option is a: &lt;code&gt;java.lang.String&lt;/code&gt; type.
+         * 
+         * Group: producer
+         * 
+         * @param resultType the value to set
+         * @return the dsl builder
+         */
+        default LanguageEndpointBuilder resultType(String resultType) {
+            doSetProperty("resultType", resultType);
+            return this;
+        }
         /**
          * Sets the script to execute.
          *