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 2022/10/13 07:52:24 UTC

[camel] branch main updated: CAMEL-18576: Using property placeholder allows to turn off nested, with myKey?nested=false. (#8533)

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

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


The following commit(s) were added to refs/heads/main by this push:
     new 944724c03d3 CAMEL-18576: Using property placeholder allows to turn off nested, with myKey?nested=false. (#8533)
944724c03d3 is described below

commit 944724c03d325dc533516d01c631fb5c22441454
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Thu Oct 13 09:52:16 2022 +0200

    CAMEL-18576: Using property placeholder allows to turn off nested, with myKey?nested=false. (#8533)
---
 .../properties/DefaultPropertiesParser.java        | 15 +++++--
 ...t.java => ExpressionPlaceholderNestedTest.java} | 47 ++++++++++++++++++----
 .../ROOT/pages/using-propertyplaceholder.adoc      | 34 +++++++++++++++-
 3 files changed, 84 insertions(+), 12 deletions(-)

diff --git a/core/camel-base/src/main/java/org/apache/camel/component/properties/DefaultPropertiesParser.java b/core/camel-base/src/main/java/org/apache/camel/component/properties/DefaultPropertiesParser.java
index 7cb0d895576..83a1e16a3cf 100644
--- a/core/camel-base/src/main/java/org/apache/camel/component/properties/DefaultPropertiesParser.java
+++ b/core/camel-base/src/main/java/org/apache/camel/component/properties/DefaultPropertiesParser.java
@@ -105,7 +105,16 @@ public class DefaultPropertiesParser implements PropertiesParser {
          * @return       Evaluated string
          */
         public String parse(String input) {
-            if (nestedPlaceholder) {
+            // does the key turn on or off nested?
+            boolean nested = nestedPlaceholder;
+            if (input.contains("?nested=true")) {
+                nested = true;
+                input = input.replace("?nested=true", "");
+            } else if (input.contains("?nested=false")) {
+                nested = false;
+                input = input.replace("?nested=false", "");
+            }
+            if (nested) {
                 return doParseNested(input, new HashSet<String>());
             } else {
                 return doParse(input);
@@ -474,14 +483,14 @@ public class DefaultPropertiesParser implements PropertiesParser {
         }
 
         /**
-         * Gets the begin index of the property (including the prefix token).
+         * Gets the beginning index of the property (including the prefix token).
          */
         public int getBeginIndex() {
             return beginIndex;
         }
 
         /**
-         * Gets the end index of the property (including the suffix token).
+         * Gets the ending index of the property (including the suffix token).
          */
         public int getEndIndex() {
             return endIndex;
diff --git a/core/camel-core/src/test/java/org/apache/camel/processor/ExpressionPlaceholderTest.java b/core/camel-core/src/test/java/org/apache/camel/processor/ExpressionPlaceholderNestedTest.java
similarity index 55%
rename from core/camel-core/src/test/java/org/apache/camel/processor/ExpressionPlaceholderTest.java
rename to core/camel-core/src/test/java/org/apache/camel/processor/ExpressionPlaceholderNestedTest.java
index b331096352a..8035fe588c6 100644
--- a/core/camel-core/src/test/java/org/apache/camel/processor/ExpressionPlaceholderTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/processor/ExpressionPlaceholderNestedTest.java
@@ -20,13 +20,14 @@ import java.util.Properties;
 
 import org.apache.camel.CamelContext;
 import org.apache.camel.ContextTestSupport;
+import org.apache.camel.FailedToCreateRouteException;
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.component.mock.MockEndpoint;
-import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Test;
 
-@Disabled("CAMEL-18576")
-public class ExpressionPlaceholderTest extends ContextTestSupport {
+import static org.junit.jupiter.api.Assertions.fail;
+
+public class ExpressionPlaceholderNestedTest extends ContextTestSupport {
 
     @Override
     protected CamelContext createCamelContext() throws Exception {
@@ -34,6 +35,7 @@ public class ExpressionPlaceholderTest extends ContextTestSupport {
 
         Properties myProp = new Properties();
         myProp.put("query", "{\"query\":{\"match_all\":{}}}");
+        myProp.put("queryEscaped", "{\"query\":{\"match_all\":{}\\}}");
 
         context.getPropertiesComponent().setInitialProperties(myProp);
 
@@ -41,11 +43,38 @@ public class ExpressionPlaceholderTest extends ContextTestSupport {
     }
 
     @Test
-    public void testPlaceholder() throws Exception {
+    public void testPlaceholderFalse() throws Exception {
+        MockEndpoint mock = getMockEndpoint("mock:result");
+        mock.expectedBodiesReceived("{\"query\":{\"match_all\":{}}}");
+
+        template.sendBody("direct:off", "Hello World");
+
+        assertMockEndpointsSatisfied();
+    }
+
+    @Test
+    public void testPlaceholderOn() throws Exception {
+        try {
+            context.addRoutes(new RouteBuilder() {
+                @Override
+                public void configure() throws Exception {
+                    from("direct:on")
+                            .setBody().constant("{{query?nested=true}}")
+                            .to("mock:result");
+                }
+            });
+            fail();
+        } catch (FailedToCreateRouteException e) {
+            assertIsInstanceOf(IllegalArgumentException.class, e.getCause());
+        }
+    }
+
+    @Test
+    public void testPlaceholderEscaped() throws Exception {
         MockEndpoint mock = getMockEndpoint("mock:result");
         mock.expectedBodiesReceived("{\"query\":{\"match_all\":{}}}");
 
-        template.sendBody("direct:start", "Hello World");
+        template.sendBody("direct:escaped", "Hello World");
 
         assertMockEndpointsSatisfied();
     }
@@ -55,8 +84,12 @@ public class ExpressionPlaceholderTest extends ContextTestSupport {
         return new RouteBuilder() {
             @Override
             public void configure() throws Exception {
-                from("direct:start")
-                        .setBody().constant("{{query}}")
+                from("direct:off")
+                        .setBody().constant("{{query?nested=false}}")
+                        .to("mock:result");
+
+                from("direct:escaped")
+                        .setBody().constant("{{queryEscaped}}")
                         .to("mock:result");
             }
         };
diff --git a/docs/user-manual/modules/ROOT/pages/using-propertyplaceholder.adoc b/docs/user-manual/modules/ROOT/pages/using-propertyplaceholder.adoc
index ddb0ad3a693..1130591acda 100644
--- a/docs/user-manual/modules/ROOT/pages/using-propertyplaceholder.adoc
+++ b/docs/user-manual/modules/ROOT/pages/using-propertyplaceholder.adoc
@@ -164,7 +164,7 @@ from("direct:start")
 In the example above the mock endpoint, is already hardcoded to start with `mock:`,
 and the `where` placeholder has the value `cheese` so the resolved uri becomes `mock:cheese`.
 
-=== Property placeholders referring to other properties
+=== Property placeholders referring to other properties (nested placeholders)
 
 You can also have properties with refer to each other such as:
 
@@ -186,6 +186,36 @@ And the route in XML:
 </route>
 ----
 
+==== Turning off nested placeholders
+
+If the placeholder value contains data that interfere with the property placeholder syntax `{{` and `}}` (such as JSon data),
+you can be then explicit turn off nested placeholder by `?nested=false` in the key name, such as shown:
+
+[source,xml]
+----
+<route>
+  <from uri="direct:start"/>
+  <to uri="elasticsearch:foo?query={{myQuery?nested=false}}"/>
+</route>
+----
+
+In the example above the placeholder _myQuery_ placeholder value is as follows
+
+[source,json]
+----
+{"query":{"match_all":{}}}
+----
+
+Notice how the json query ends with `}}` which interfere with the Camel property placeholder syntax.
+
+Nested placeholders can also be turned off globally on the xref:components::properties-component.adoc[Properties] component, such as:
+
+[source,java]
+----
+CamelContext context = ...
+context.getPropertiesComponent().setNestedPlaceholder(false);
+----
+
 === Escape a property placeholder
 
 The property placeholder can be problematic if the double curly brackets are used by a third party library like for example a query in ElasticSearch of type `{"query":{"match_all":{}}}`.
@@ -196,7 +226,7 @@ If for some reason, the backslash character before the double curly brackets mus
 
 === Using property placeholders multiple times
 
-You can of couse also use placeholders several times:
+You can of course also use placeholders several times:
 
 [source,properties]
 ----