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 051b2de CAMEL-16630: camel-core - Allow to use joor script for
aggregation strategy pojo. CAMEL-16630: camel-core - Allow to use BiFunction
for aggregation strategy pojo.
051b2de is described below
commit 051b2de1b243503c691eb2e831bf936bf6a355d8
Author: Claus Ibsen <[email protected]>
AuthorDate: Wed Jun 30 09:56:20 2021 +0200
CAMEL-16630: camel-core - Allow to use joor script for aggregation strategy
pojo.
CAMEL-16630: camel-core - Allow to use BiFunction for aggregation strategy
pojo.
---
.../camel-joor/src/main/docs/joor-language.adoc | 75 +++++---
.../apache/camel/language/joor/JoorCompiler.java | 12 ++
.../camel/language/joor/JoorScriptingCompiler.java | 12 ++
.../kamelet/KameletEipAggregateJoorTest.java | 74 ++++++++
.../AggregationStrategyBiFunctionAdapter.java | 86 +++++++++
.../org/apache/camel/reifier/AggregateReifier.java | 10 +
.../apache/camel/reifier/ClaimCheckReifier.java | 5 +
.../org/apache/camel/reifier/EnrichReifier.java | 11 ++
.../org/apache/camel/reifier/MulticastReifier.java | 10 +
.../apache/camel/reifier/PollEnrichReifier.java | 11 ++
.../apache/camel/reifier/RecipientListReifier.java | 10 +
.../org/apache/camel/reifier/SplitReifier.java | 10 +
.../aggregator/AggregateBiFunctionTest.java | 54 ++++++
.../processor/aggregator/AggregateDslTest.java | 5 +-
.../processor/enricher/EnricherBiFunctionTest.java | 73 ++++++++
.../apache/camel/util/function/TriConsumer.java | 10 +-
dsl/camel-yaml-dsl/camel-yaml-dsl/pom.xml | 5 +
.../apache/camel/dsl/yaml/RouteTemplateTest.groovy | 205 +++++++++++++--------
18 files changed, 568 insertions(+), 110 deletions(-)
diff --git a/components/camel-joor/src/main/docs/joor-language.adoc
b/components/camel-joor/src/main/docs/joor-language.adoc
index 4b1e30e..413ca62 100644
--- a/components/camel-joor/src/main/docs/joor-language.adoc
+++ b/components/camel-joor/src/main/docs/joor-language.adoc
@@ -12,7 +12,8 @@
include::{cq-version}@camel-quarkus:ROOT:partial$reference/languages/joor.adoc[o
The jOOR language allows to use Java code in your Camel expression, with some
limitations.
The jOOR library integrates with the Java compiler and performs runtime
compilation of Java code.
-NOTE: Java 8 is not supported. Java 11 or 14 is required.
+NOTE: Java 8 is not supported.
+Java 11 or 14 is required.
== jOOR Options
@@ -22,14 +23,14 @@ NOTE: Java 8 is not supported. Java 11 or 14 is required.
// language options: START
The jOOR language supports 4 options, which are listed below.
-
-
[width="100%",cols="2,1m,1m,6",options="header"]
|===
| Name | Default | Java Type | Description
-| preCompile | true | Boolean | Whether the expression should be pre compiled
once during initialization phase. If this is turned off, then the expression is
reloaded and compiled on each evaluation.
+| preCompile | true | Boolean | Whether the expression should be pre compiled
once during initialization phase.
+If this is turned off, then the expression is reloaded and compiled on each
evaluation.
| resultType | | String | Sets the class name of the result type (type from
output)
-| singleQuotes | true | Boolean | Whether single quotes can be used as
replacement for double quotes. This is convenient when you need to work with
strings inside strings.
+| singleQuotes | true | Boolean | Whether single quotes can be used as
replacement for double quotes.
+This is convenient when you need to work with strings inside strings.
| trim | true | Boolean | Whether to trim the value to remove leading and
trailing whitespaces and line breaks
|===
// language options: END
@@ -57,9 +58,11 @@ The jOOR language allows the following functions to be used
in the script:
| Function | Description
| bodyAs(type) | To convert the body to the given type.
| headerAs(name, type) | To convert the header with the name to the given type.
-| headerAs(name, defaultValue, type) | To convert the header with the name to
the given type. If no header exists then use the given default value.
+| headerAs(name, defaultValue, type) | To convert the header with the name to
the given type.
+If no header exists then use the given default value.
| exchangePropertyAs(name, type) | To convert the exchange property with the
name to the given type.
-| exchangePropertyAs(name, defaultValue, type) | To convert the exchange
property with the name to the given type. If no exchange property exists then
use the given default value.
+| exchangePropertyAs(name, defaultValue, type) | To convert the exchange
property with the name to the given type.
+If no exchange property exists then use the given default value.
| optionalBodyAs(type) | To convert the body to the given type returned
wrapped in `java.util.Optional`.
| optionalHeaderAs(name, type) | To convert the header with the name to the
given type returned wrapped in `java.util.Optional`.
| optionalExchangePropertyAs(name, type) | To convert the exchange property
with the name to the given type returned wrapped in `java.util.Optional`.
@@ -68,19 +71,21 @@ The jOOR language allows the following functions to be used
in the script:
These functions are convenient for getting the message body, header or
exchange properties as a specific Java type.
Here we want to get the message body as a `com.foo.MyUser` type we can do as
follows:
+
[source,java]
----
var user = bodyAs(com.foo.MyUser.class);
----
You can omit _.class_ to make the function a little bit smaller:
+
[source,java]
----
var user = bodyAs(com.foo.MyUser);
----
-The type must be a fully qualified class type, but that can be inconvenient to
type all the time. In such a situation, you can configure an import
-in the `camel-joor.properties` file as shown below:
+The type must be a fully qualified class type, but that can be inconvenient to
type all the time.
+In such a situation, you can configure an import in the
`camel-joor.properties` file as shown below:
[source,properties]
----
@@ -88,6 +93,7 @@ import com.foo.MyUser;
----
And then the function can be shortened:
+
[source,java]
----
var user = bodyAs(MyUser);
@@ -128,8 +134,7 @@ from("direct:start")
.to("mock:result");
----
-Now this code may seem a bit magically, but what happens is that the `myEcho`
bean is injected via a constructor,
-and then called directly in the script so its as fast as possible.
+Now this code may seem a bit magically, but what happens is that the `myEcho`
bean is injected via a constructor, and then called directly in the script so
its as fast as possible.
Under the hod Camel jOOR generates the following source code that is compiled
once:
@@ -159,8 +164,8 @@ from("direct:start")
.to("mock:result");
----
-Notice how we declare the bean as if its a local variable via `var bean =
#bean:myEcho`. When doing this we must use
-a different name as `myEcho` is the variable used by the dependency injection
and therefore we use _bean_ as name in the script.
+Notice how we declare the bean as if its a local variable via `var bean =
#bean:myEcho`.
+When doing this we must use a different name as `myEcho` is the variable used
by the dependency injection and therefore we use _bean_ as name in the script.
== Auto imports
@@ -240,6 +245,7 @@ from("seda:orders")
----
And in XML DSL:
+
[source,xml]
----
<route>
@@ -253,7 +259,8 @@ And in XML DSL:
== Multi statements
-It is possible to include multiple statements. The code below shows an example
where the `user` header is retrieved in a first statement.
+It is possible to include multiple statements.
+The code below shows an example where the `user` header is retrieved in a
first statement.
And then, in a second statement we return a value whether the user is `null`
or not.
[source,java]
@@ -287,8 +294,7 @@ from("jms:incoming")
.to("jms:orders");
----
-Here the jOOR script is externalized into the file
`src/main/resources/orders.joor` which allows you to edit this source
-file while running the Camel application and try the changes with
hot-reloading.
+Here the jOOR script is externalized into the file
`src/main/resources/orders.joor` which allows you to edit this source file
while running the Camel application and try the changes with hot-reloading.
In XML DSL it's easier because you can turn off pre-compilation in the
`<joor>` XML element:
@@ -303,6 +309,33 @@ In XML DSL it's easier because you can turn off
pre-compilation in the `<joor>`
</route>
----
+== Lambda based AggregationStrategy
+
+The jOOR language have special support for defining an
`org.apache.camel.AggregationStrategy` as a lambda expression.
+This is useful when using EIP patterns that uses aggregation such as the
Aggregator, Splitter, Recipient List, Enrich, and others.
+
+To use this then the jOOR language script must be in the following syntax:
+
+----
+(e1, e2) -> { }
+----
+
+Where `e1` and `e2` are the _old_ Exchange and _new_ Exchange from the
`aggregate` method in the `AggregationStrategy`.
+The returned value is used as the aggregated message body, or use `null` to
skip this.
+
+The lambda syntax is representing a Java util `BiFunction<Exchange, Exchange,
Object>` type.
+
+For example to aggregate message bodies together we can do this as shown:
+
+[source,java]
+----
+(e1, e2) -> {
+ String b1 = e1.getMessage().getBody(String.class);
+ String b2 = e2.getMessage().getBody(String.class);
+ return b1 + ',' + b2;
+}
+----
+
== Limitations
The jOOR Camel language is only supported as a block of Java code that gets
compiled into a Java class with a single method.
@@ -311,17 +344,13 @@ The code that you can write is therefore limited to a
number of Java statements.
The supported runtime is intended for Java standalone, Spring Boot, Camel
Quarkus and other microservices runtimes.
It is not supported in OSGi, Camel Karaf or any kind of Java Application
Server runtime.
-jOOR does not support runtime compilation with Spring Boot using _fat jar_
packaging (https://github.com/jOOQ/jOOR/issues/69),
-it works with exploded classpath.
+jOOR does not support runtime compilation with Spring Boot using _fat jar_
packaging (https://github.com/jOOQ/jOOR/issues/69), it works with exploded
classpath.
== Dependencies
-To use scripting languages in your camel routes you need to add a
-dependency on *camel-joor*.
+To use scripting languages in your camel routes you need to add a dependency
on *camel-joor*.
-If you use Maven you could just add the following to your `pom.xml`,
-substituting the version number for the latest and greatest release (see
-the download page for the latest versions).
+If you use Maven you could just add the following to your `pom.xml`,
substituting the version number for the latest and greatest release (see the
download page for the latest versions).
[source,xml]
---------------------------------------
diff --git
a/components/camel-joor/src/main/java/org/apache/camel/language/joor/JoorCompiler.java
b/components/camel-joor/src/main/java/org/apache/camel/language/joor/JoorCompiler.java
index 9d8418c..9361bfe 100644
---
a/components/camel-joor/src/main/java/org/apache/camel/language/joor/JoorCompiler.java
+++
b/components/camel-joor/src/main/java/org/apache/camel/language/joor/JoorCompiler.java
@@ -124,6 +124,8 @@ public class JoorCompiler extends ServiceSupport implements
StaticService {
// trim text
script = script.trim();
+ // special for evaluating aggregation strategy via a BiFunction
+ boolean biFunction = script.startsWith("(e1, e2) ->");
script = staticHelper(script);
script = alias(script);
@@ -137,6 +139,7 @@ public class JoorCompiler extends ServiceSupport implements
StaticService {
sb.append("\n");
sb.append("import java.util.*;\n");
sb.append("import java.util.concurrent.*;\n");
+ sb.append("import java.util.function.*;\n");
sb.append("import java.util.stream.*;\n");
sb.append("\n");
sb.append("import org.apache.camel.*;\n");
@@ -182,6 +185,12 @@ public class JoorCompiler extends ServiceSupport
implements StaticService {
if (!script.contains("return ")) {
sb.append("return ");
}
+ if (biFunction) {
+ if (!sb.toString().endsWith("return ")) {
+ sb.append("return ");
+ }
+ sb.append("(BiFunction<Exchange, Exchange, Object>) ");
+ }
if (singleQuotes) {
// single quotes instead of double quotes, as its very annoying
for string in strings
@@ -193,6 +202,9 @@ public class JoorCompiler extends ServiceSupport implements
StaticService {
if (!script.endsWith("}") && !script.endsWith(";")) {
sb.append(";");
}
+ if (biFunction && !script.endsWith(";")) {
+ sb.append(";");
+ }
sb.append("\n");
sb.append(" }\n");
sb.append("}\n");
diff --git
a/components/camel-joor/src/main/java/org/apache/camel/language/joor/JoorScriptingCompiler.java
b/components/camel-joor/src/main/java/org/apache/camel/language/joor/JoorScriptingCompiler.java
index e5c3106..4890bdf 100644
---
a/components/camel-joor/src/main/java/org/apache/camel/language/joor/JoorScriptingCompiler.java
+++
b/components/camel-joor/src/main/java/org/apache/camel/language/joor/JoorScriptingCompiler.java
@@ -106,6 +106,8 @@ public class JoorScriptingCompiler extends ServiceSupport
implements StaticServi
// trim text
script = script.trim();
+ // special for evaluating aggregation strategy via a BiFunction
+ boolean biFunction = script.startsWith("(e1, e2) ->");
Set<String> scriptImports = new LinkedHashSet<>();
Map<String, Class> scriptBeans = new HashMap<>();
@@ -117,6 +119,7 @@ public class JoorScriptingCompiler extends ServiceSupport
implements StaticServi
sb.append("\n");
sb.append("import java.util.*;\n");
sb.append("import java.util.concurrent.*;\n");
+ sb.append("import java.util.function.*;\n");
sb.append("import java.util.stream.*;\n");
sb.append("\n");
sb.append("import org.apache.camel.*;\n");
@@ -172,6 +175,12 @@ public class JoorScriptingCompiler extends ServiceSupport
implements StaticServi
if (!script.contains("return ")) {
sb.append("return ");
}
+ if (biFunction) {
+ if (!sb.toString().endsWith("return ")) {
+ sb.append("return ");
+ }
+ sb.append("(BiFunction<Exchange, Exchange, Object>) ");
+ }
if (singleQuotes) {
// single quotes instead of double quotes, as its very annoying
for string in strings
@@ -183,6 +192,9 @@ public class JoorScriptingCompiler extends ServiceSupport
implements StaticServi
if (!script.endsWith("}") && !script.endsWith(";")) {
sb.append(";");
}
+ if (biFunction && !script.endsWith(";")) {
+ sb.append(";");
+ }
sb.append("\n");
sb.append(" }\n");
sb.append("}\n");
diff --git
a/components/camel-kamelet/src/test/java/org/apache/camel/component/kamelet/KameletEipAggregateJoorTest.java
b/components/camel-kamelet/src/test/java/org/apache/camel/component/kamelet/KameletEipAggregateJoorTest.java
new file mode 100644
index 0000000..893d921
--- /dev/null
+++
b/components/camel-kamelet/src/test/java/org/apache/camel/component/kamelet/KameletEipAggregateJoorTest.java
@@ -0,0 +1,74 @@
+/*
+ * 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.component.kamelet;
+
+import org.apache.camel.RoutesBuilder;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.test.junit5.CamelTestSupport;
+import org.junit.jupiter.api.Test;
+
+public class KameletEipAggregateJoorTest extends CamelTestSupport {
+
+ @Test
+ public void testAggregate() throws Exception {
+ getMockEndpoint("mock:result").expectedBodiesReceived("A,B,C,D,E");
+
+ template.sendBody("direct:start", "A");
+ template.sendBody("direct:start", "B");
+ template.sendBody("direct:start", "C");
+ template.sendBody("direct:start", "D");
+ template.sendBody("direct:start", "E");
+
+ assertMockEndpointsSatisfied();
+ }
+
+ // **********************************************
+ //
+ // test set-up
+ //
+ // **********************************************
+
+ protected RoutesBuilder createRouteBuilder() throws Exception {
+ return new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+ routeTemplate("my-aggregate")
+ .templateBean("myAgg", "joor",
+ // for aggregation we can use a BiFunction
that takes Exchange as input and return the aggregated response
+ // camel-joor has special support for this if
we use (e1, e2) -> { ... } as a lambda expression
+ "(e1, e2) -> {" +
+ " String b1 =
e1.getMessage().getBody(String.class);" +
+ " String b2 =
e2.getMessage().getBody(String.class);" +
+ " return b1 + ',' + b2;
}")
+ .templateParameter("count")
+ .from("kamelet:source")
+ .aggregate(constant(true))
+ .completionSize("{{count}}")
+ // use the groovy script bean for aggregation
+ .aggregationStrategyRef("{{myAgg}}")
+ .to("log:aggregate")
+ .to("kamelet:sink")
+ .end();
+
+ from("direct:start")
+ .kamelet("my-aggregate?count=5")
+ .to("log:info")
+ .to("mock:result");
+ }
+ };
+ }
+}
diff --git
a/core/camel-core-processor/src/main/java/org/apache/camel/processor/aggregate/AggregationStrategyBiFunctionAdapter.java
b/core/camel-core-processor/src/main/java/org/apache/camel/processor/aggregate/AggregationStrategyBiFunctionAdapter.java
new file mode 100644
index 0000000..ecdef3f
--- /dev/null
+++
b/core/camel-core-processor/src/main/java/org/apache/camel/processor/aggregate/AggregationStrategyBiFunctionAdapter.java
@@ -0,0 +1,86 @@
+/*
+ * 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.aggregate;
+
+import java.util.function.BiFunction;
+
+import org.apache.camel.AggregationStrategy;
+import org.apache.camel.Exchange;
+
+/**
+ * An {@link AggregationStrategy} that adapts to a {@link BiFunction}.
+ * <p/>
+ * This allows end users to use {@link BiFunction} for the aggregation logic,
instead of having to implement the Camel
+ * API {@link AggregationStrategy}.
+ * <p/>
+ * This is supported for example by camel-joor that makes it possible to write
a {@link BiFunction} as a lambda script
+ * that can be compiled and used by Camel.
+ */
+public class AggregationStrategyBiFunctionAdapter implements
AggregationStrategy {
+
+ private final BiFunction<Exchange, Exchange, Object> function;
+ private boolean allowNullOldExchange;
+ private boolean allowNullNewExchange;
+
+ public AggregationStrategyBiFunctionAdapter(BiFunction<Exchange, Exchange,
Object> function) {
+ this.function = function;
+ }
+
+ public boolean isAllowNullOldExchange() {
+ return allowNullOldExchange;
+ }
+
+ public void setAllowNullOldExchange(boolean allowNullOldExchange) {
+ this.allowNullOldExchange = allowNullOldExchange;
+ }
+
+ public boolean isAllowNullNewExchange() {
+ return allowNullNewExchange;
+ }
+
+ public void setAllowNullNewExchange(boolean allowNullNewExchange) {
+ this.allowNullNewExchange = allowNullNewExchange;
+ }
+
+ @Override
+ public Exchange aggregate(Exchange oldExchange, Exchange newExchange) {
+ if (!allowNullOldExchange && oldExchange == null) {
+ return newExchange;
+ }
+ if (!allowNullNewExchange && newExchange == null) {
+ return oldExchange;
+ }
+
+ try {
+ Object out = function.apply(oldExchange, newExchange);
+ if (out != null && !(out instanceof Exchange)) {
+ if (oldExchange != null) {
+ oldExchange.getIn().setBody(out);
+ } else {
+ newExchange.getIn().setBody(out);
+ }
+ }
+ } catch (Exception e) {
+ if (oldExchange != null) {
+ oldExchange.setException(e);
+ } else {
+ newExchange.setException(e);
+ }
+ }
+ return oldExchange != null ? oldExchange : newExchange;
+ }
+}
diff --git
a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/AggregateReifier.java
b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/AggregateReifier.java
index 05a622f..d20ac70 100644
---
a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/AggregateReifier.java
+++
b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/AggregateReifier.java
@@ -18,6 +18,7 @@ package org.apache.camel.reifier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ScheduledExecutorService;
+import java.util.function.BiFunction;
import org.apache.camel.AggregationStrategy;
import org.apache.camel.AsyncProcessor;
@@ -33,6 +34,7 @@ import org.apache.camel.model.ProcessorDefinition;
import org.apache.camel.processor.aggregate.AggregateController;
import org.apache.camel.processor.aggregate.AggregateProcessor;
import org.apache.camel.processor.aggregate.AggregationStrategyBeanAdapter;
+import
org.apache.camel.processor.aggregate.AggregationStrategyBiFunctionAdapter;
import org.apache.camel.processor.aggregate.OptimisticLockRetryPolicy;
import org.apache.camel.spi.AggregationRepository;
import org.apache.camel.spi.ExecutorServiceManager;
@@ -234,6 +236,14 @@ public class AggregateReifier extends
ProcessorReifier<AggregateDefinition> {
Object aggStrategy = lookup(definition.getStrategyRef(),
Object.class);
if (aggStrategy instanceof AggregationStrategy) {
strategy = (AggregationStrategy) aggStrategy;
+ } else if (aggStrategy instanceof BiFunction) {
+ AggregationStrategyBiFunctionAdapter adapter
+ = new
AggregationStrategyBiFunctionAdapter((BiFunction) aggStrategy);
+ if (definition.getStrategyMethodAllowNull() != null) {
+
adapter.setAllowNullNewExchange(parseBoolean(definition.getStrategyMethodAllowNull(),
false));
+
adapter.setAllowNullOldExchange(parseBoolean(definition.getStrategyMethodAllowNull(),
false));
+ }
+ strategy = adapter;
} else if (aggStrategy != null) {
AggregationStrategyBeanAdapter adapter
= new AggregationStrategyBeanAdapter(aggStrategy,
definition.getAggregationStrategyMethodName());
diff --git
a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/ClaimCheckReifier.java
b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/ClaimCheckReifier.java
index 8fb2982..6b46b38 100644
---
a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/ClaimCheckReifier.java
+++
b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/ClaimCheckReifier.java
@@ -16,6 +16,8 @@
*/
package org.apache.camel.reifier;
+import java.util.function.BiFunction;
+
import org.apache.camel.AggregationStrategy;
import org.apache.camel.CamelContextAware;
import org.apache.camel.Processor;
@@ -25,6 +27,7 @@ import org.apache.camel.model.ClaimCheckOperation;
import org.apache.camel.model.ProcessorDefinition;
import org.apache.camel.processor.ClaimCheckProcessor;
import org.apache.camel.processor.aggregate.AggregationStrategyBeanAdapter;
+import
org.apache.camel.processor.aggregate.AggregationStrategyBiFunctionAdapter;
import org.apache.camel.support.ObjectHelper;
import static org.apache.camel.util.ObjectHelper.notNull;
@@ -114,6 +117,8 @@ public class ClaimCheckReifier extends
ProcessorReifier<ClaimCheckDefinition> {
Object aggStrategy = lookup(ref, Object.class);
if (aggStrategy instanceof AggregationStrategy) {
strategy = (AggregationStrategy) aggStrategy;
+ } else if (aggStrategy instanceof BiFunction) {
+ strategy = new
AggregationStrategyBiFunctionAdapter((BiFunction) aggStrategy);
} else if (aggStrategy != null) {
strategy = new AggregationStrategyBeanAdapter(aggStrategy,
definition.getAggregationStrategyMethodName());
} else {
diff --git
a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/EnrichReifier.java
b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/EnrichReifier.java
index 5e9e90e..1a3b310 100644
---
a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/EnrichReifier.java
+++
b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/EnrichReifier.java
@@ -16,6 +16,8 @@
*/
package org.apache.camel.reifier;
+import java.util.function.BiFunction;
+
import org.apache.camel.AggregationStrategy;
import org.apache.camel.CamelContextAware;
import org.apache.camel.Expression;
@@ -25,6 +27,7 @@ import org.apache.camel.model.EnrichDefinition;
import org.apache.camel.model.ProcessorDefinition;
import org.apache.camel.processor.Enricher;
import org.apache.camel.processor.aggregate.AggregationStrategyBeanAdapter;
+import
org.apache.camel.processor.aggregate.AggregationStrategyBiFunctionAdapter;
public class EnrichReifier extends ExpressionReifier<EnrichDefinition> {
@@ -65,6 +68,14 @@ public class EnrichReifier extends
ExpressionReifier<EnrichDefinition> {
Object aggStrategy =
lookup(definition.getAggregationStrategyRef(), Object.class);
if (aggStrategy instanceof AggregationStrategy) {
strategy = (AggregationStrategy) aggStrategy;
+ } else if (aggStrategy instanceof BiFunction) {
+ AggregationStrategyBiFunctionAdapter adapter
+ = new
AggregationStrategyBiFunctionAdapter((BiFunction) aggStrategy);
+ if (definition.getAggregationStrategyMethodAllowNull() !=
null) {
+
adapter.setAllowNullNewExchange(parseBoolean(definition.getAggregationStrategyMethodAllowNull(),
false));
+
adapter.setAllowNullOldExchange(parseBoolean(definition.getAggregationStrategyMethodAllowNull(),
false));
+ }
+ strategy = adapter;
} else if (aggStrategy != null) {
AggregationStrategyBeanAdapter adapter
= new AggregationStrategyBeanAdapter(aggStrategy,
definition.getAggregationStrategyMethodName());
diff --git
a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/MulticastReifier.java
b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/MulticastReifier.java
index 4f99734..aa0962b 100644
---
a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/MulticastReifier.java
+++
b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/MulticastReifier.java
@@ -19,6 +19,7 @@ package org.apache.camel.reifier;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
+import java.util.function.BiFunction;
import org.apache.camel.AggregationStrategy;
import org.apache.camel.CamelContextAware;
@@ -28,6 +29,7 @@ import org.apache.camel.model.MulticastDefinition;
import org.apache.camel.model.ProcessorDefinition;
import org.apache.camel.processor.MulticastProcessor;
import org.apache.camel.processor.aggregate.AggregationStrategyBeanAdapter;
+import
org.apache.camel.processor.aggregate.AggregationStrategyBiFunctionAdapter;
import org.apache.camel.processor.aggregate.ShareUnitOfWorkAggregationStrategy;
import org.apache.camel.processor.aggregate.UseLatestAggregationStrategy;
@@ -88,6 +90,14 @@ public class MulticastReifier extends
ProcessorReifier<MulticastDefinition> {
Object aggStrategy = lookup(ref, Object.class);
if (aggStrategy instanceof AggregationStrategy) {
strategy = (AggregationStrategy) aggStrategy;
+ } else if (aggStrategy instanceof BiFunction) {
+ AggregationStrategyBiFunctionAdapter adapter
+ = new
AggregationStrategyBiFunctionAdapter((BiFunction) aggStrategy);
+ if (definition.getStrategyMethodAllowNull() != null) {
+
adapter.setAllowNullNewExchange(parseBoolean(definition.getStrategyMethodAllowNull(),
false));
+
adapter.setAllowNullOldExchange(parseBoolean(definition.getStrategyMethodAllowNull(),
false));
+ }
+ strategy = adapter;
} else if (aggStrategy != null) {
AggregationStrategyBeanAdapter adapter
= new AggregationStrategyBeanAdapter(aggStrategy,
parseString(definition.getStrategyMethodName()));
diff --git
a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/PollEnrichReifier.java
b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/PollEnrichReifier.java
index 75c5e51..8ad9057 100644
---
a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/PollEnrichReifier.java
+++
b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/PollEnrichReifier.java
@@ -16,6 +16,8 @@
*/
package org.apache.camel.reifier;
+import java.util.function.BiFunction;
+
import org.apache.camel.AggregationStrategy;
import org.apache.camel.CamelContextAware;
import org.apache.camel.Exchange;
@@ -27,6 +29,7 @@ import org.apache.camel.model.ProcessorDefinition;
import org.apache.camel.model.language.ConstantExpression;
import org.apache.camel.processor.PollEnricher;
import org.apache.camel.processor.aggregate.AggregationStrategyBeanAdapter;
+import
org.apache.camel.processor.aggregate.AggregationStrategyBiFunctionAdapter;
import org.apache.camel.support.DefaultExchange;
public class PollEnrichReifier extends ProcessorReifier<PollEnrichDefinition> {
@@ -78,6 +81,14 @@ public class PollEnrichReifier extends
ProcessorReifier<PollEnrichDefinition> {
Object aggStrategy = lookup(ref, Object.class);
if (aggStrategy instanceof AggregationStrategy) {
strategy = (AggregationStrategy) aggStrategy;
+ } else if (aggStrategy instanceof BiFunction) {
+ AggregationStrategyBiFunctionAdapter adapter
+ = new
AggregationStrategyBiFunctionAdapter((BiFunction) aggStrategy);
+ if (definition.getAggregationStrategyMethodName() != null) {
+
adapter.setAllowNullNewExchange(parseBoolean(definition.getAggregationStrategyMethodAllowNull(),
false));
+
adapter.setAllowNullOldExchange(parseBoolean(definition.getAggregationStrategyMethodAllowNull(),
false));
+ }
+ strategy = adapter;
} else if (aggStrategy != null) {
AggregationStrategyBeanAdapter adapter = new
AggregationStrategyBeanAdapter(
aggStrategy,
parseString(definition.getAggregationStrategyMethodName()));
diff --git
a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/RecipientListReifier.java
b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/RecipientListReifier.java
index 6a6238a..2c1793f 100644
---
a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/RecipientListReifier.java
+++
b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/RecipientListReifier.java
@@ -19,6 +19,7 @@ package org.apache.camel.reifier;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
+import java.util.function.BiFunction;
import org.apache.camel.AggregationStrategy;
import org.apache.camel.CamelContextAware;
@@ -30,6 +31,7 @@ import org.apache.camel.model.RecipientListDefinition;
import org.apache.camel.processor.EvaluateExpressionProcessor;
import org.apache.camel.processor.RecipientList;
import org.apache.camel.processor.aggregate.AggregationStrategyBeanAdapter;
+import
org.apache.camel.processor.aggregate.AggregationStrategyBiFunctionAdapter;
import org.apache.camel.processor.aggregate.ShareUnitOfWorkAggregationStrategy;
import org.apache.camel.processor.aggregate.UseLatestAggregationStrategy;
@@ -118,6 +120,14 @@ public class RecipientListReifier extends
ProcessorReifier<RecipientListDefiniti
Object aggStrategy = lookup(ref, Object.class);
if (aggStrategy instanceof AggregationStrategy) {
strategy = (AggregationStrategy) aggStrategy;
+ } else if (aggStrategy instanceof BiFunction) {
+ AggregationStrategyBiFunctionAdapter adapter
+ = new
AggregationStrategyBiFunctionAdapter((BiFunction) aggStrategy);
+ if (definition.getStrategyMethodAllowNull() != null) {
+
adapter.setAllowNullNewExchange(parseBoolean(definition.getStrategyMethodAllowNull(),
false));
+
adapter.setAllowNullOldExchange(parseBoolean(definition.getStrategyMethodAllowNull(),
false));
+ }
+ strategy = adapter;
} else if (aggStrategy != null) {
AggregationStrategyBeanAdapter adapter
= new AggregationStrategyBeanAdapter(aggStrategy,
parseString(definition.getStrategyMethodName()));
diff --git
a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/SplitReifier.java
b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/SplitReifier.java
index 71866b9..90ede30 100644
---
a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/SplitReifier.java
+++
b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/SplitReifier.java
@@ -17,6 +17,7 @@
package org.apache.camel.reifier;
import java.util.concurrent.ExecutorService;
+import java.util.function.BiFunction;
import org.apache.camel.AggregationStrategy;
import org.apache.camel.CamelContextAware;
@@ -27,6 +28,7 @@ import org.apache.camel.model.ProcessorDefinition;
import org.apache.camel.model.SplitDefinition;
import org.apache.camel.processor.Splitter;
import org.apache.camel.processor.aggregate.AggregationStrategyBeanAdapter;
+import
org.apache.camel.processor.aggregate.AggregationStrategyBiFunctionAdapter;
import org.apache.camel.processor.aggregate.ShareUnitOfWorkAggregationStrategy;
public class SplitReifier extends ExpressionReifier<SplitDefinition> {
@@ -83,6 +85,14 @@ public class SplitReifier extends
ExpressionReifier<SplitDefinition> {
Object aggStrategy = lookup(definition.getStrategyRef(),
Object.class);
if (aggStrategy instanceof AggregationStrategy) {
strategy = (AggregationStrategy) aggStrategy;
+ } else if (aggStrategy instanceof BiFunction) {
+ AggregationStrategyBiFunctionAdapter adapter
+ = new
AggregationStrategyBiFunctionAdapter((BiFunction) aggStrategy);
+ if (definition.getStrategyMethodAllowNull() != null) {
+
adapter.setAllowNullNewExchange(parseBoolean(definition.getStrategyMethodAllowNull(),
false));
+
adapter.setAllowNullOldExchange(parseBoolean(definition.getStrategyMethodAllowNull(),
false));
+ }
+ strategy = adapter;
} else if (aggStrategy != null) {
AggregationStrategyBeanAdapter adapter
= new AggregationStrategyBeanAdapter(aggStrategy,
definition.getStrategyMethodName());
diff --git
a/core/camel-core/src/test/java/org/apache/camel/processor/aggregator/AggregateBiFunctionTest.java
b/core/camel-core/src/test/java/org/apache/camel/processor/aggregator/AggregateBiFunctionTest.java
new file mode 100644
index 0000000..4cc3dbf
--- /dev/null
+++
b/core/camel-core/src/test/java/org/apache/camel/processor/aggregator/AggregateBiFunctionTest.java
@@ -0,0 +1,54 @@
+/*
+ * 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.aggregator;
+
+import java.util.function.BiFunction;
+
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.Exchange;
+import org.apache.camel.builder.RouteBuilder;
+import org.junit.jupiter.api.Test;
+
+public class AggregateBiFunctionTest extends ContextTestSupport {
+
+ private BiFunction<Exchange, Exchange, Object> myAgg
+ = (Exchange e1, Exchange e2) ->
e1.getMessage().getBody(String.class) + "+" +
e2.getMessage().getBody(String.class);
+
+ @Test
+ public void testBiFunction() throws Exception {
+ getMockEndpoint("mock:aggregated").expectedBodiesReceived("A+B+C");
+
+ template.sendBodyAndHeader("direct:start", "A", "id", 123);
+ template.sendBodyAndHeader("direct:start", "B", "id", 123);
+ template.sendBodyAndHeader("direct:start", "C", "id", 123);
+
+ assertMockEndpointsSatisfied();
+ }
+
+ @Override
+ protected RouteBuilder createRouteBuilder() throws Exception {
+ return new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+ context.getRegistry().bind("myAgg", myAgg);
+
+ from("direct:start")
+
.aggregate(header("id")).aggregationStrategyRef("myAgg").completionSize(3).to("mock:aggregated");
+ }
+ };
+ }
+}
diff --git
a/core/camel-core/src/test/java/org/apache/camel/processor/aggregator/AggregateDslTest.java
b/core/camel-core/src/test/java/org/apache/camel/processor/aggregator/AggregateDslTest.java
index 8d067f7..20b9bfa 100644
---
a/core/camel-core/src/test/java/org/apache/camel/processor/aggregator/AggregateDslTest.java
+++
b/core/camel-core/src/test/java/org/apache/camel/processor/aggregator/AggregateDslTest.java
@@ -45,11 +45,12 @@ public class AggregateDslTest extends ContextTestSupport {
return new RouteBuilder() {
@Override
public void configure() throws Exception {
- from("direct:start").aggregate().message(m ->
m.getHeader("type")).strategy()
+ from("direct:start").aggregate().message(m ->
m.getHeader("type")).aggregationStrategy()
.body(String.class,
AggregateDslTest::joinString).completion()
.body(String.class, s -> s.split(",").length ==
2).to("mock:aggregated");
-
from("direct:start-supplier").aggregate().header("type").strategy(AggregateDslTest::joinStringStrategy)
+ from("direct:start-supplier").aggregate().header("type")
+
.aggregationStrategy(AggregateDslTest::joinStringStrategy)
.completion()
.body(String.class, s -> s.split(",").length ==
3).to("mock:aggregated-supplier");
}
diff --git
a/core/camel-core/src/test/java/org/apache/camel/processor/enricher/EnricherBiFunctionTest.java
b/core/camel-core/src/test/java/org/apache/camel/processor/enricher/EnricherBiFunctionTest.java
new file mode 100644
index 0000000..2cd5646
--- /dev/null
+++
b/core/camel-core/src/test/java/org/apache/camel/processor/enricher/EnricherBiFunctionTest.java
@@ -0,0 +1,73 @@
+/*
+ * 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.enricher;
+
+import java.util.function.BiFunction;
+
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockComponent;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spi.Registry;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class EnricherBiFunctionTest extends ContextTestSupport {
+
+ private MockEndpoint cool = new MockEndpoint("mock:cool", new
MockComponent(context));
+
+ private BiFunction<Exchange, Exchange, Object> myAgg
+ = (Exchange e1, Exchange e2) ->
e1.getMessage().getBody(String.class) + "+" +
e2.getMessage().getBody(String.class);
+
+ @Override
+ protected Registry createRegistry() throws Exception {
+ Registry jndi = super.createRegistry();
+ jndi.bind("cool", cool);
+ jndi.bind("agg", myAgg);
+ return jndi;
+ }
+
+ @Test
+ public void testEnrichRef() throws Exception {
+ cool.whenAnyExchangeReceived(new Processor() {
+ public void process(Exchange exchange) throws Exception {
+ exchange.getMessage().setBody("Bye World");
+ }
+ });
+ cool.expectedBodiesReceived("Hello World");
+
+ String out = template.requestBody("direct:start", "Hello World",
String.class);
+ assertEquals("Hello World+Bye World", out);
+
+ cool.assertIsSatisfied();
+ }
+
+ @Override
+ protected RouteBuilder createRouteBuilder() throws Exception {
+ return new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+ cool.setCamelContext(context);
+
+
from("direct:start").enrich().simple("ref:cool").aggregationStrategyRef("agg");
+ }
+ };
+ }
+}
diff --git
a/core/camel-util/src/main/java/org/apache/camel/util/function/TriConsumer.java
b/core/camel-util/src/main/java/org/apache/camel/util/function/TriConsumer.java
index deb9032..5ca376a 100644
---
a/core/camel-util/src/main/java/org/apache/camel/util/function/TriConsumer.java
+++
b/core/camel-util/src/main/java/org/apache/camel/util/function/TriConsumer.java
@@ -25,13 +25,13 @@ package org.apache.camel.util.function;
*/
@FunctionalInterface
public interface TriConsumer<I1, I2, I3> {
+
/**
- * Applies this function to the given arguments..
+ * Applies this function to the given arguments.
*
- * @param i1 the first argument
- * @param i2 the second argument
- * @param i3 the third argument
- * @return the function result
+ * @param i1 the first argument
+ * @param i2 the second argument
+ * @param i3 the third argument
*/
void accept(I1 i1, I2 i2, I3 i3);
}
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl/pom.xml
b/dsl/camel-yaml-dsl/camel-yaml-dsl/pom.xml
index 8ba23b0..58add82 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl/pom.xml
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl/pom.xml
@@ -141,6 +141,11 @@
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
+ <artifactId>camel-joor</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
<artifactId>camel-mustache</artifactId>
<scope>test</scope>
</dependency>
diff --git
a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/RouteTemplateTest.groovy
b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/RouteTemplateTest.groovy
index a09f3d1..abc2982 100644
---
a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/RouteTemplateTest.groovy
+++
b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/RouteTemplateTest.groovy
@@ -29,7 +29,7 @@ import org.junit.jupiter.api.Assertions
class RouteTemplateTest extends YamlTestSupport {
def "create template"() {
when:
- loadRoutes '''
+ loadRoutes '''
- template:
id: "myTemplate"
from:
@@ -38,45 +38,45 @@ class RouteTemplateTest extends YamlTestSupport {
- log: "message"
'''
then:
- context.routeTemplateDefinitions.size() == 1
+ context.routeTemplateDefinitions.size() == 1
- with(context.routeTemplateDefinitions[0], RouteTemplateDefinition)
{
- id == 'myTemplate'
+ with(context.routeTemplateDefinitions[0], RouteTemplateDefinition) {
+ id == 'myTemplate'
- route.input.endpointUri == 'direct:info'
- with (route.outputs[0], LogDefinition) {
- message == 'message'
- }
+ route.input.endpointUri == 'direct:info'
+ with(route.outputs[0], LogDefinition) {
+ message == 'message'
}
+ }
}
def "create template with beans (#resource.location)"(Resource resource) {
setup:
- context.routesLoader.loadRoutes(resource)
+ context.routesLoader.loadRoutes(resource)
- withMock('mock:result') {
- expectedMessageCount 1
- expectedBodiesReceived 'HELLO'
- }
+ withMock('mock:result') {
+ expectedMessageCount 1
+ expectedBodiesReceived 'HELLO'
+ }
when:
- context.addRouteFromTemplate('myId', 'myTemplate', ['directName':
'myId'])
- context.start()
+ context.addRouteFromTemplate('myId', 'myTemplate', ['directName':
'myId'])
+ context.start()
- withTemplate {
- to('direct:start').withBody('hello').send()
- }
+ withTemplate {
+ to('direct:start').withBody('hello').send()
+ }
then:
- context.routeTemplateDefinitions.size() == 1
+ context.routeTemplateDefinitions.size() == 1
- with(context.routeTemplateDefinitions[0], RouteTemplateDefinition)
{
- id == 'myTemplate'
- templateBeans.size() == 1
- }
+ with(context.routeTemplateDefinitions[0], RouteTemplateDefinition) {
+ id == 'myTemplate'
+ templateBeans.size() == 1
+ }
- MockEndpoint.assertIsSatisfied(context)
+ MockEndpoint.assertIsSatisfied(context)
where:
- resource << [
- asResource('beans', """
+ resource << [
+ asResource('beans', """
- template:
id: "myTemplate"
beans:
@@ -93,7 +93,7 @@ class RouteTemplateTest extends YamlTestSupport {
- to: "direct:myId"
- to: "mock:result"
"""),
- asResource('script', """
+ asResource('script', """
- template:
id: "myTemplate"
beans:
@@ -111,7 +111,7 @@ class RouteTemplateTest extends YamlTestSupport {
- to: "direct:myId"
- to: "mock:result"
"""),
- asResource('script-bean-type', """
+ asResource('script-bean-type', """
- template:
id: "myTemplate"
beans:
@@ -130,7 +130,7 @@ class RouteTemplateTest extends YamlTestSupport {
- to: "direct:myId"
- to: "mock:result"
"""),
- asResource('script-block', """
+ asResource('script-block', """
- template:
id: "myTemplate"
beans:
@@ -149,12 +149,12 @@ class RouteTemplateTest extends YamlTestSupport {
- to: "direct:myId"
- to: "mock:result"
""")
- ]
+ ]
}
def "create template with bean and properties"() {
setup:
- loadRoutes """
+ loadRoutes """
- template:
id: "myTemplate"
beans:
@@ -174,31 +174,31 @@ class RouteTemplateTest extends YamlTestSupport {
- to: "mock:result"
"""
- withMock('mock:result') {
- expectedMessageCount 1
- expectedBodiesReceived 'test-payload'
- }
+ withMock('mock:result') {
+ expectedMessageCount 1
+ expectedBodiesReceived 'test-payload'
+ }
when:
- context.addRouteFromTemplate('myId', 'myTemplate', ['directName':
'myId'])
- context.start()
+ context.addRouteFromTemplate('myId', 'myTemplate', ['directName':
'myId'])
+ context.start()
- withTemplate {
- to('direct:start').withBody('hello').send()
- }
+ withTemplate {
+ to('direct:start').withBody('hello').send()
+ }
then:
- context.routeTemplateDefinitions.size() == 1
+ context.routeTemplateDefinitions.size() == 1
- with(context.routeTemplateDefinitions[0], RouteTemplateDefinition)
{
- id == 'myTemplate'
- templateBeans.size() == 1
- }
+ with(context.routeTemplateDefinitions[0], RouteTemplateDefinition) {
+ id == 'myTemplate'
+ templateBeans.size() == 1
+ }
- MockEndpoint.assertIsSatisfied(context)
+ MockEndpoint.assertIsSatisfied(context)
}
def "create template with bean and property"() {
setup:
- loadRoutes """
+ loadRoutes """
- template:
id: "myTemplate"
beans:
@@ -219,31 +219,31 @@ class RouteTemplateTest extends YamlTestSupport {
- to: "mock:result"
"""
- withMock('mock:result') {
- expectedMessageCount 1
- expectedBodiesReceived 'test-payload'
- }
+ withMock('mock:result') {
+ expectedMessageCount 1
+ expectedBodiesReceived 'test-payload'
+ }
when:
- context.addRouteFromTemplate('myId', 'myTemplate', ['directName':
'myId'])
- context.start()
+ context.addRouteFromTemplate('myId', 'myTemplate', ['directName':
'myId'])
+ context.start()
- withTemplate {
- to('direct:start').withBody('hello').send()
- }
+ withTemplate {
+ to('direct:start').withBody('hello').send()
+ }
then:
- context.routeTemplateDefinitions.size() == 1
+ context.routeTemplateDefinitions.size() == 1
- with(context.routeTemplateDefinitions[0], RouteTemplateDefinition)
{
- id == 'myTemplate'
- templateBeans.size() == 1
- }
+ with(context.routeTemplateDefinitions[0], RouteTemplateDefinition) {
+ id == 'myTemplate'
+ templateBeans.size() == 1
+ }
- MockEndpoint.assertIsSatisfied(context)
+ MockEndpoint.assertIsSatisfied(context)
}
def "create template with properties"() {
when:
- loadRoutes """
+ loadRoutes """
- template:
id: "myTemplate"
parameters:
@@ -258,24 +258,24 @@ class RouteTemplateTest extends YamlTestSupport {
- log: "message"
"""
then:
- context.routeTemplateDefinitions.size() == 1
+ context.routeTemplateDefinitions.size() == 1
- with(context.routeTemplateDefinitions[0], RouteTemplateDefinition)
{
- id == 'myTemplate'
- configurer == null
-
- templateParameters.any {
- it.name == 'foo' && it.defaultValue == 'myDefaultFoo' &&
it.description == 'myFooDescription'
- }
- templateParameters.any {
- it.name == 'bar' && it.defaultValue == null &&
it.description == 'myBarDescription'
- }
-
- route.input.endpointUri == 'direct:info'
- with (route.outputs[0], LogDefinition) {
- message == 'message'
- }
+ with(context.routeTemplateDefinitions[0], RouteTemplateDefinition) {
+ id == 'myTemplate'
+ configurer == null
+
+ templateParameters.any {
+ it.name == 'foo' && it.defaultValue == 'myDefaultFoo' &&
it.description == 'myFooDescription'
}
+ templateParameters.any {
+ it.name == 'bar' && it.defaultValue == null && it.description
== 'myBarDescription'
+ }
+
+ route.input.endpointUri == 'direct:info'
+ with(route.outputs[0], LogDefinition) {
+ message == 'message'
+ }
+ }
}
def "create template with optional properties"() {
@@ -307,7 +307,7 @@ class RouteTemplateTest extends YamlTestSupport {
}
route.input.endpointUri == 'direct:{{foo}}'
- with (route.outputs[0], ToDefinition) {
+ with(route.outputs[0], ToDefinition) {
uri == 'mock:result?retainFirst={{?bar}}'
}
}
@@ -330,4 +330,49 @@ class RouteTemplateTest extends YamlTestSupport {
mock2.assertIsSatisfied()
}
+ def "create template with joor"() {
+ setup:
+ loadRoutes """
+ - template:
+ id: "myTemplate"
+ beans:
+ - name: "myAgg"
+ type: "joor"
+ script: "(e1, e2) -> { return
e2.getMessage().getBody(); }"
+ from:
+ uri: "direct:route"
+ steps:
+ - aggregate:
+ strategy-ref: "{{myAgg}}"
+ completion-size: 2
+ correlation-expression:
+ header: "StockSymbol"
+ steps:
+ - to: "mock:result"
+ """
+ withMock('mock:result') {
+ expectedMessageCount 2
+ expectedBodiesReceived '101', '199'
+ }
+ when:
+ context.addRouteFromTemplate('myId', 'myTemplate', [:])
+ context.start()
+
+ withTemplate {
+ to('direct:route').withBody('99').withHeader('StockSymbol',
1).send()
+ to('direct:route').withBody('101').withHeader('StockSymbol',
1).send()
+ to('direct:route').withBody('200').withHeader('StockSymbol',
2).send()
+ to('direct:route').withBody('199').withHeader('StockSymbol',
2).send()
+ }
+ then:
+ context.routeTemplateDefinitions.size() == 1
+
+ with(context.routeTemplateDefinitions[0], RouteTemplateDefinition)
{
+ id == 'myTemplate'
+ templateBeans.size() == 1
+ }
+
+ MockEndpoint.assertIsSatisfied(context)
+ }
+
}