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 2019/05/30 08:21:10 UTC

[camel] branch master updated: CAMEL-13599: Claim check - Allow to use dynamic key via simple language

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

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


The following commit(s) were added to refs/heads/master by this push:
     new 8d714fa  CAMEL-13599: Claim check - Allow to use dynamic key via simple language
8d714fa is described below

commit 8d714faaf1d12b60ae701da1544db708881f8d1c
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Thu May 30 09:58:46 2019 +0200

    CAMEL-13599: Claim check - Allow to use dynamic key via simple language
---
 .../camel/processor/ClaimCheckProcessor.java       | 29 +++++++----
 .../src/main/docs/eips/claimCheck-eip.adoc         | 41 ++++++++++-----
 .../apache/camel/model/ClaimCheckDefinition.java   |  2 +-
 .../ClaimCheckEipDynamicKeyGetSetTest.java         | 59 ++++++++++++++++++++++
 4 files changed, 108 insertions(+), 23 deletions(-)

diff --git a/core/camel-base/src/main/java/org/apache/camel/processor/ClaimCheckProcessor.java b/core/camel-base/src/main/java/org/apache/camel/processor/ClaimCheckProcessor.java
index 8667f62..587fed6 100644
--- a/core/camel-base/src/main/java/org/apache/camel/processor/ClaimCheckProcessor.java
+++ b/core/camel-base/src/main/java/org/apache/camel/processor/ClaimCheckProcessor.java
@@ -21,11 +21,13 @@ import org.apache.camel.AsyncCallback;
 import org.apache.camel.CamelContext;
 import org.apache.camel.CamelContextAware;
 import org.apache.camel.Exchange;
+import org.apache.camel.Expression;
 import org.apache.camel.impl.engine.DefaultClaimCheckRepository;
 import org.apache.camel.spi.ClaimCheckRepository;
 import org.apache.camel.spi.IdAware;
 import org.apache.camel.support.AsyncProcessorSupport;
 import org.apache.camel.support.ExchangeHelper;
+import org.apache.camel.support.LanguageSupport;
 import org.apache.camel.support.service.ServiceHelper;
 import org.apache.camel.util.ObjectHelper;
 
@@ -44,6 +46,7 @@ public class ClaimCheckProcessor extends AsyncProcessorSupport implements IdAwar
     private String operation;
     private AggregationStrategy aggregationStrategy;
     private String key;
+    private Expression keyExpression;
     private String filter;
 
     @Override
@@ -108,18 +111,20 @@ public class ClaimCheckProcessor extends AsyncProcessorSupport implements IdAwar
         }
 
         try {
+            String claimKey = keyExpression.evaluate(exchange, String.class);
+
             if ("Set".equals(operation)) {
                 // copy exchange, and do not share the unit of work
                 Exchange copy = ExchangeHelper.createCorrelatedCopy(exchange, false);
-                boolean addedNew = repo.add(key, copy);
+                boolean addedNew = repo.add(claimKey, copy);
                 if (addedNew) {
-                    log.debug("Add: {} -> {}", key, copy);
+                    log.debug("Add: {} -> {}", claimKey, copy);
                 } else {
-                    log.debug("Override: {} -> {}", key, copy);
+                    log.debug("Override: {} -> {}", claimKey, copy);
                 }
             } else if ("Get".equals(operation)) {
-                Exchange copy = repo.get(key);
-                log.debug("Get: {} -> {}", key, exchange);
+                Exchange copy = repo.get(claimKey);
+                log.debug("Get: {} -> {}", claimKey, exchange);
                 if (copy != null) {
                     Exchange result = aggregationStrategy.aggregate(exchange, copy);
                     if (result != null) {
@@ -127,8 +132,8 @@ public class ClaimCheckProcessor extends AsyncProcessorSupport implements IdAwar
                     }
                 }
             } else if ("GetAndRemove".equals(operation)) {
-                Exchange copy = repo.getAndRemove(key);
-                log.debug("GetAndRemove: {} -> {}", key, exchange);
+                Exchange copy = repo.getAndRemove(claimKey);
+                log.debug("GetAndRemove: {} -> {}", claimKey, exchange);
                 if (copy != null) {
                     // prepare the exchanges for aggregation
                     ExchangeHelper.prepareAggregation(exchange, copy);
@@ -140,11 +145,11 @@ public class ClaimCheckProcessor extends AsyncProcessorSupport implements IdAwar
             } else if ("Push".equals(operation)) {
                 // copy exchange, and do not share the unit of work
                 Exchange copy = ExchangeHelper.createCorrelatedCopy(exchange, false);
-                log.debug("Push: {} -> {}", key, copy);
+                log.debug("Push: {} -> {}", claimKey, copy);
                 repo.push(copy);
             } else if ("Pop".equals(operation)) {
                 Exchange copy = repo.pop();
-                log.debug("Pop: {} -> {}", key, exchange);
+                log.debug("Pop: {} -> {}", claimKey, exchange);
                 if (copy != null) {
                     // prepare the exchanges for aggregation
                     ExchangeHelper.prepareAggregation(exchange, copy);
@@ -173,6 +178,12 @@ public class ClaimCheckProcessor extends AsyncProcessorSupport implements IdAwar
             ((CamelContextAware) aggregationStrategy).setCamelContext(camelContext);
         }
 
+        if (LanguageSupport.hasSimpleFunction(key)) {
+            keyExpression = camelContext.resolveLanguage("simple").createExpression(key);
+        } else {
+            keyExpression = camelContext.resolveLanguage("constant").createExpression(key);
+        }
+
         ServiceHelper.startService(aggregationStrategy);
     }
 
diff --git a/core/camel-core/src/main/docs/eips/claimCheck-eip.adoc b/core/camel-core/src/main/docs/eips/claimCheck-eip.adoc
index a3fa60a..2643bfb 100644
--- a/core/camel-core/src/main/docs/eips/claimCheck-eip.adoc
+++ b/core/camel-core/src/main/docs/eips/claimCheck-eip.adoc
@@ -20,7 +20,7 @@ The Claim Check EIP supports 5 options which are listed below:
 |===
 | Name | Description | Default | Type
 | *operation* | *Required* The claim check operation to use. The following operations is supported: Get - Gets (does not remove) the claim check by the given key. GetAndRemove - Gets and remove the claim check by the given key. Set - Sets a new (will override if key already exists) claim check with the given key. Push - Sets a new claim check on the stack (does not use key). Pop - Gets the latest claim check from the stack (does not use key). |  | ClaimCheckOperation
-| *key* | To use a specific key for claim check id. |  | String
+| *key* | To use a specific key for claim check id (for dynamic keys use simple language syntax as the key). |  | String
 | *filter* | Specified a filter to control what data gets merging data back from the claim check repository. The following syntax is supported: body - to aggregate the message body attachments - to aggregate all the message attachments headers - to aggregate all the message headers header:pattern - to aggregate all the message headers that matches the pattern. The pattern uses the following rules are applied in this order: exact match, returns true wildcard match (pattern ends with a and [...]
 | *strategyRef* | To use a custom AggregationStrategy instead of the default implementation. Notice you cannot use both custom aggregation strategy and configure data at the same time. |  | String
 | *strategyMethodName* | This option can be used to explicit declare the method name to use, when using POJOs as the AggregationStrategy. |  | String
@@ -67,35 +67,30 @@ You can specify multiple rules separated by comma.
 
 For example to include the message body and all headers starting with _foo_:
 
-[text]
 ----
 body,header:foo*
 ----
 
 To only merge back the message body:
 
-[text]
 ----
 body
 ----
 
 To only merge back the message attachments:
 
-[text]
 ----
 attachments
 ----
 
 To only merge back headers:
 
-[text]
 ----
 headers
 ----
 
 To only merge back a header name foo:
 
-[text]
 ----
 header:foo
 ----
@@ -104,7 +99,7 @@ If the filter rule is specified as empty or as wildcard then everything is merge
 
 Notice that when merging back data, then any existing data is overwritten, and any other existing data is preserved.
 
-==== Fine grained filtering with include and explude pattern
+==== Fine grained filtering with include and exclude pattern
 
 The syntax also supports the following prefixes which can be used to specify include,exclude, or remove
 
@@ -129,12 +124,32 @@ You can also instruct to remove headers when merging data back, for example to r
 
 Note you cannot have both include (`+`) and exclude (`-`) `header:pattern` at the same time.
 
+=== Dynamic keys
+
+The claim check key are static, but you can use the `simple` language syntax to define dynamic keys,
+for example to use a header from the message named `myKey`:
+
+[source,java]
+----
+from("direct:start")
+    .to("mock:a")
+    .claimCheck(ClaimCheckOperation.Set, "${header.myKey}")
+    .transform().constant("Bye World")
+    .to("mock:b")
+    .claimCheck(ClaimCheckOperation.Get, "${header.myKey}")
+    .to("mock:c")
+    .transform().constant("Hi World")
+    .to("mock:d")
+    .claimCheck(ClaimCheckOperation.Get, "${header.myKey}")
+    .to("mock:e");
+----
+
 
 === Java Examples
 
 The following example shows the `Push` and `Pop` operations in action;
 
-[java]
+[source,java]
 ----
 from("direct:start")
     .to("mock:a")
@@ -151,7 +166,7 @@ then the original message body is retrieved and merged back so `mock:c` will ret
 
 Here is an example using `Get` and `Set` operations, which uses the key `foo`:
 
-[java]
+[source,java]
 ----
 from("direct:start")
     .to("mock:a")
@@ -171,7 +186,7 @@ to get the data once, you can use `GetAndRemove`.
 
 The last example shows how to use the `filter` option where we only want to get back header named `foo` or `bar`:
 
-[java]
+[source,java]
 ----
 from("direct:start")
     .to("mock:a")
@@ -189,7 +204,7 @@ from("direct:start")
 
 The following example shows the `Push` and `Pop` operations in action;
 
-[xml]
+[source,xml]
 ----
 <route>
   <from uri="direct:start"/>
@@ -210,7 +225,7 @@ then the original message body is retrieved and merged back so `mock:c` will ret
 
 Here is an example using `Get` and `Set` operations, which uses the key `foo`:
 
-[xml]
+[source,xml]
 ----
 <route>
   <from uri="direct:start"/>
@@ -236,7 +251,7 @@ to get the data once, you can use `GetAndRemove`.
 
 The last example shows how to use the `filter` option where we only want to get back header named `foo` or `bar`:
 
-[xml]
+[source,xml]
 ----
 <route>
   <from uri="direct:start"/>
diff --git a/core/camel-core/src/main/java/org/apache/camel/model/ClaimCheckDefinition.java b/core/camel-core/src/main/java/org/apache/camel/model/ClaimCheckDefinition.java
index 27d983a..54240df 100644
--- a/core/camel-core/src/main/java/org/apache/camel/model/ClaimCheckDefinition.java
+++ b/core/camel-core/src/main/java/org/apache/camel/model/ClaimCheckDefinition.java
@@ -89,7 +89,7 @@ public class ClaimCheckDefinition extends NoOutputDefinition<ClaimCheckDefinitio
     }
 
     /**
-     * To use a specific key for claim check id.
+     * To use a specific key for claim check id (for dynamic keys use simple language syntax as the key).
      */
     public ClaimCheckDefinition key(String key) {
         setKey(key);
diff --git a/core/camel-core/src/test/java/org/apache/camel/processor/ClaimCheckEipDynamicKeyGetSetTest.java b/core/camel-core/src/test/java/org/apache/camel/processor/ClaimCheckEipDynamicKeyGetSetTest.java
new file mode 100644
index 0000000..456c6cf
--- /dev/null
+++ b/core/camel-core/src/test/java/org/apache/camel/processor/ClaimCheckEipDynamicKeyGetSetTest.java
@@ -0,0 +1,59 @@
+/*
+ * 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.processor;
+
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.model.ClaimCheckOperation;
+import org.junit.Test;
+
+public class ClaimCheckEipDynamicKeyGetSetTest extends ContextTestSupport {
+
+    @Test
+    public void testGetSet() throws Exception {
+        getMockEndpoint("mock:a").expectedBodiesReceived("Hello World", "Bonjour World");
+        getMockEndpoint("mock:b").expectedBodiesReceived("Bye World", "Bye World");
+        getMockEndpoint("mock:c").expectedBodiesReceived("Hello World", "Bonjour World");
+        getMockEndpoint("mock:d").expectedBodiesReceived("Hi World", "Hi World");
+        getMockEndpoint("mock:e").expectedBodiesReceived("Hello World", "Bonjour World");
+
+        template.sendBodyAndHeader("direct:start", "Hello World", "myHeader", "foo");
+        template.sendBodyAndHeader("direct:start", "Bonjour World", "myHeader", "bar");
+
+        assertMockEndpointsSatisfied();
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("direct:start")
+                    .to("mock:a")
+                    .claimCheck(ClaimCheckOperation.Set, "${header.myKey}")
+                    .transform().constant("Bye World")
+                    .to("mock:b")
+                    .claimCheck(ClaimCheckOperation.Get, "${header.myKey}")
+                    .to("mock:c")
+                    .transform().constant("Hi World")
+                    .to("mock:d")
+                    .claimCheck(ClaimCheckOperation.Get, "${header.myKey}")
+                    .to("mock:e");
+            }
+        };
+    }
+}