You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by nf...@apache.org on 2022/03/07 17:52:17 UTC
[camel] branch CAMEL-17754/route-configuration-precondition created (now 1c4279b)
This is an automated email from the ASF dual-hosted git repository.
nfilotto pushed a change to branch CAMEL-17754/route-configuration-precondition
in repository https://gitbox.apache.org/repos/asf/camel.git.
at 1c4279b CAMEL-17754: Precondition to hard exclude route configurations
This branch includes the following new commits:
new 1c4279b CAMEL-17754: Precondition to hard exclude route configurations
The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
[camel] 01/01: CAMEL-17754: Precondition to hard exclude route configurations
Posted by nf...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
nfilotto pushed a commit to branch CAMEL-17754/route-configuration-precondition
in repository https://gitbox.apache.org/repos/asf/camel.git
commit 1c4279b0d9d1b670f36607a3a386d6448012cc16
Author: Nicolas Filotto <nf...@talend.com>
AuthorDate: Mon Mar 7 18:50:19 2022 +0100
CAMEL-17754: Precondition to hard exclude route configurations
---
.../camel/catalog/models/routeConfiguration.json | 1 +
.../apache/camel/catalog/schemas/camel-spring.xsd | 8 +++
...ava => RouteConfigurationPreconditionTest.java} | 25 +++-----
.../apache/camel/spring/RoutePreconditionTest.java | 2 +-
...Test.properties => PreconditionTest.properties} | 0
.../spring/RouteConfigurationPreconditionTest.xml | 75 ++++++++++++++++++++++
.../apache/camel/spring/RoutePreconditionTest.xml | 2 +-
.../org/apache/camel/impl/DefaultCamelContext.java | 20 +-----
.../java/org/apache/camel/impl/DefaultModel.java | 12 +++-
.../org/apache/camel/impl/PreconditionHelper.java | 66 +++++++++++++++++++
.../org/apache/camel/model/routeConfiguration.json | 1 +
.../apache/camel/model/PreconditionContainer.java | 37 +++++++++++
.../camel/model/RouteConfigurationDefinition.java | 37 ++++++++++-
.../org/apache/camel/model/RouteDefinition.java | 11 ++--
...ava => RouteConfigurationPreconditionTest.java} | 71 +++++++++-----------
.../camel/processor/RoutePreconditionTest.java | 2 +-
.../java/org/apache/camel/xml/in/ModelParser.java | 9 ++-
.../modules/ROOT/pages/route-configuration.adoc | 45 +++++++++++++
.../RouteConfigurationDefinitionDeserializer.java | 4 ++
.../src/generated/resources/camel-yaml-dsl.json | 3 +
.../src/generated/resources/camelYamlDsl.json | 3 +
.../camel/dsl/yaml/RouteConfigurationTest.groovy | 53 ++++++++++++++-
22 files changed, 400 insertions(+), 87 deletions(-)
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/routeConfiguration.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/routeConfiguration.json
index 29af0d6..a1b45b6 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/routeConfiguration.json
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/routeConfiguration.json
@@ -17,6 +17,7 @@
"interceptSendToEndpoint": { "kind": "element", "displayName": "Intercept Send To Endpoint", "required": false, "type": "array", "javaType": "java.util.List<org.apache.camel.model.InterceptSendToEndpointDefinition>", "deprecated": false, "autowired": false, "secret": false, "description": "Applies a route for an interceptor if an exchange is send to the given endpoint" },
"onException": { "kind": "element", "displayName": "On Exception", "required": false, "type": "array", "javaType": "java.util.List<org.apache.camel.model.OnExceptionDefinition>", "deprecated": false, "autowired": false, "secret": false, "description": "Exception clause for catching certain exceptions and handling them." },
"onCompletion": { "kind": "element", "displayName": "On Completion", "required": false, "type": "array", "javaType": "java.util.List<org.apache.camel.model.OnCompletionDefinition>", "deprecated": false, "autowired": false, "secret": false, "description": "On completion callback for doing custom routing when the org.apache.camel.Exchange is complete." },
+ "precondition": { "kind": "attribute", "displayName": "Precondition", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The predicate of the precondition in simple language to evaluate in order to determine if this route configuration should be included or not." },
"id": { "kind": "attribute", "displayName": "Id", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the id of this node" },
"description": { "kind": "element", "displayName": "Description", "required": false, "type": "object", "javaType": "org.apache.camel.model.DescriptionDefinition", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the description of this node" }
}
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd
index 6dd00d4..d06f7df 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd
@@ -10612,6 +10612,14 @@ Reference to the route templates in the xml dsl.
<xs:element maxOccurs="unbounded" minOccurs="0" ref="tns:onException"/>
<xs:element maxOccurs="unbounded" minOccurs="0" ref="tns:onCompletion"/>
</xs:sequence>
+ <xs:attribute name="precondition" type="xs:string">
+ <xs:annotation>
+ <xs:documentation xml:lang="en"><![CDATA[
+The predicate of the precondition in simple language to evaluate in order to
+determine if this route configuration should be included or not.
+ ]]></xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
</xs:extension>
</xs:complexContent>
</xs:complexType>
diff --git a/components/camel-spring-xml/src/test/java/org/apache/camel/spring/RoutePreconditionTest.java b/components/camel-spring-xml/src/test/java/org/apache/camel/spring/RouteConfigurationPreconditionTest.java
similarity index 60%
copy from components/camel-spring-xml/src/test/java/org/apache/camel/spring/RoutePreconditionTest.java
copy to components/camel-spring-xml/src/test/java/org/apache/camel/spring/RouteConfigurationPreconditionTest.java
index 9d910bb..9e3e45b 100644
--- a/components/camel-spring-xml/src/test/java/org/apache/camel/spring/RoutePreconditionTest.java
+++ b/components/camel-spring-xml/src/test/java/org/apache/camel/spring/RouteConfigurationPreconditionTest.java
@@ -20,33 +20,28 @@ import org.junit.jupiter.api.Test;
import org.springframework.context.support.AbstractXmlApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static org.junit.jupiter.api.Assertions.assertNull;
-
/**
- * The test ensuring that the precondition set on a rule determines if the route is included or not.
+ * The test ensuring that the precondition set on a route configuration determines if the route configuration is
+ * included or not
*/
-class RoutePreconditionTest extends SpringTestSupport {
+class RouteConfigurationPreconditionTest extends SpringTestSupport {
@Override
protected AbstractXmlApplicationContext createApplicationContext() {
- return new ClassPathXmlApplicationContext("org/apache/camel/spring/RoutePreconditionTest.xml");
+ return new ClassPathXmlApplicationContext("org/apache/camel/spring/RouteConfigurationPreconditionTest.xml");
}
@Test
- void testRoutesAreIncludedOrExcludedAsExpected() throws Exception {
+ void testRouteConfigurationAreIncludedOrExcludedAsExpected() throws Exception {
+ assertCollectionSize(context.getRouteConfigurationDefinitions(), 2);
assertCollectionSize(context.getRouteDefinitions(), 2);
assertCollectionSize(context.getRoutes(), 2);
- assertNotNull(context.getRoute("templatedRouteIncluded"));
- assertNotNull(context.getRoute("routeIncluded"));
- assertNull(context.getRoute("templatedRouteExcluded"));
- assertNull(context.getRoute("routeExcluded"));
- getMockEndpoint("mock:out").expectedMessageCount(1);
- getMockEndpoint("mock:outT").expectedMessageCount(1);
+ getMockEndpoint("mock:error").expectedMessageCount(2);
+ getMockEndpoint("mock:error").expectedBodiesReceived("Activated", "Default");
- template.sendBody("direct:in", "Hello Included Route");
- template.sendBody("direct:inT", "Hello Included Templated Route");
+ template.sendBody("direct:start", "Hello Activated Route Config");
+ template.sendBody("direct:start2", "Hello Not Activated Route Config");
assertMockEndpointsSatisfied();
}
diff --git a/components/camel-spring-xml/src/test/java/org/apache/camel/spring/RoutePreconditionTest.java b/components/camel-spring-xml/src/test/java/org/apache/camel/spring/RoutePreconditionTest.java
index 9d910bb..f02994e 100644
--- a/components/camel-spring-xml/src/test/java/org/apache/camel/spring/RoutePreconditionTest.java
+++ b/components/camel-spring-xml/src/test/java/org/apache/camel/spring/RoutePreconditionTest.java
@@ -24,7 +24,7 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
/**
- * The test ensuring that the precondition set on a rule determines if the route is included or not.
+ * The test ensuring that the precondition set on a route determines if the route is included or not.
*/
class RoutePreconditionTest extends SpringTestSupport {
diff --git a/components/camel-spring-xml/src/test/resources/org/apache/camel/spring/RoutePreconditionTest.properties b/components/camel-spring-xml/src/test/resources/org/apache/camel/spring/PreconditionTest.properties
similarity index 100%
rename from components/camel-spring-xml/src/test/resources/org/apache/camel/spring/RoutePreconditionTest.properties
rename to components/camel-spring-xml/src/test/resources/org/apache/camel/spring/PreconditionTest.properties
diff --git a/components/camel-spring-xml/src/test/resources/org/apache/camel/spring/RouteConfigurationPreconditionTest.xml b/components/camel-spring-xml/src/test/resources/org/apache/camel/spring/RouteConfigurationPreconditionTest.xml
new file mode 100644
index 0000000..4b46716
--- /dev/null
+++ b/components/camel-spring-xml/src/test/resources/org/apache/camel/spring/RouteConfigurationPreconditionTest.xml
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ 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.
+
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="
+ http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
+
+ <camelContext xmlns="http://camel.apache.org/schema/spring">
+ <propertyPlaceholder id="properties" location="classpath:org/apache/camel/spring/PreconditionTest.properties"/>
+ <routeConfiguration>
+ <onException>
+ <exception>java.lang.Exception</exception>
+ <handled>
+ <constant>true</constant>
+ </handled>
+ <transform>
+ <constant>Default</constant>
+ </transform>
+ <to uri="mock:error"/>
+ </onException>
+ </routeConfiguration>
+ <routeConfiguration precondition="{{activate}}">
+ <onException>
+ <exception>java.lang.IllegalArgumentException</exception>
+ <handled>
+ <constant>true</constant>
+ </handled>
+ <transform>
+ <constant>Activated</constant>
+ </transform>
+ <to uri="mock:error"/>
+ </onException>
+ </routeConfiguration>
+ <routeConfiguration precondition="{{!activate}}">
+ <onException>
+ <exception>java.lang.IllegalArgumentException</exception>
+ <handled>
+ <constant>true</constant>
+ </handled>
+ <transform>
+ <constant>Not Activated</constant>
+ </transform>
+ <to uri="mock:error"/>
+ </onException>
+ </routeConfiguration>
+
+ <route>
+ <from uri="direct:start"/>
+ <throwException exceptionType="java.lang.IllegalArgumentException" message="Foo"/>
+ </route>
+ <route>
+ <from uri="direct:start2"/>
+ <throwException exceptionType="java.lang.RuntimeException" message="Foo"/>
+ </route>
+ </camelContext>
+
+</beans>
diff --git a/components/camel-spring-xml/src/test/resources/org/apache/camel/spring/RoutePreconditionTest.xml b/components/camel-spring-xml/src/test/resources/org/apache/camel/spring/RoutePreconditionTest.xml
index 03e6a66..45694d7 100644
--- a/components/camel-spring-xml/src/test/resources/org/apache/camel/spring/RoutePreconditionTest.xml
+++ b/components/camel-spring-xml/src/test/resources/org/apache/camel/spring/RoutePreconditionTest.xml
@@ -24,7 +24,7 @@
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<camelContext xmlns="http://camel.apache.org/schema/spring">
- <propertyPlaceholder id="properties" location="classpath:org/apache/camel/spring/RoutePreconditionTest.properties"/>
+ <propertyPlaceholder id="properties" location="classpath:org/apache/camel/spring/PreconditionTest.properties"/>
<routeTemplate id="myTemplate">
<templateParameter name="activateT"/>
<route precondition="{{activateT}}">
diff --git a/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultCamelContext.java b/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
index 8a25e37..d2b4dcb 100644
--- a/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
+++ b/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
@@ -65,7 +65,6 @@ import org.apache.camel.model.RoutesDefinition;
import org.apache.camel.model.TemplatedRouteDefinition;
import org.apache.camel.model.cloud.ServiceCallConfigurationDefinition;
import org.apache.camel.model.language.ExpressionDefinition;
-import org.apache.camel.model.language.SimpleExpression;
import org.apache.camel.model.rest.RestDefinition;
import org.apache.camel.model.rest.RestsDefinition;
import org.apache.camel.model.transformer.TransformerDefinition;
@@ -85,7 +84,6 @@ import org.apache.camel.spi.Transformer;
import org.apache.camel.spi.UuidGenerator;
import org.apache.camel.spi.Validator;
import org.apache.camel.support.CamelContextHelper;
-import org.apache.camel.support.DefaultExchange;
import org.apache.camel.support.DefaultRegistry;
import org.apache.camel.support.LocalBeanRegistry;
import org.apache.camel.support.SimpleUuidGenerator;
@@ -998,23 +996,7 @@ public class DefaultCamelContext extends SimpleCamelContext implements ModelCame
* @return {@code true} if the route should be included, {@code false} otherwise.
*/
private boolean includedRoute(RouteDefinition definition) {
- final String precondition = definition.getPrecondition();
- if (precondition == null) {
- LOG.trace("No precondition found, the route is included by default");
- return true;
- }
- final ExpressionDefinition expression = new SimpleExpression(precondition);
- expression.initPredicate(this);
-
- Predicate predicate = expression.getPredicate();
- predicate.initPredicate(this);
-
- boolean matches = predicate.matches(new DefaultExchange(this));
- if (LOG.isTraceEnabled()) {
- LOG.trace("The precondition has been evaluated to {}, consequently the route is {}", matches,
- matches ? "included" : "excluded");
- }
- return matches;
+ return PreconditionHelper.included(definition, this);
}
private static ValueHolder<String> createTransformerKey(TransformerDefinition def) {
diff --git a/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultModel.java b/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultModel.java
index fcb834f..179cc44 100644
--- a/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultModel.java
+++ b/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultModel.java
@@ -122,7 +122,8 @@ public class DefaultModel implements Model {
@Override
public void addRouteConfiguration(RouteConfigurationDefinition routesConfiguration) {
- if (routesConfiguration == null) {
+ // Ensure that the route configuration should be included
+ if (routesConfiguration == null || !includedRouteConfiguration(routesConfiguration)) {
return;
}
// only add if not already exists (route-loader may let Java DSL add route configuration twice
@@ -925,4 +926,13 @@ public class DefaultModel implements Model {
}
}
+ /**
+ * Indicates whether the route configuration should be included according to the precondition.
+ *
+ * @param definition the definition of the route configuration to check.
+ * @return {@code true} if the route configuration should be included, {@code false} otherwise.
+ */
+ private boolean includedRouteConfiguration(RouteConfigurationDefinition definition) {
+ return PreconditionHelper.included(definition, camelContext);
+ }
}
diff --git a/core/camel-core-engine/src/main/java/org/apache/camel/impl/PreconditionHelper.java b/core/camel-core-engine/src/main/java/org/apache/camel/impl/PreconditionHelper.java
new file mode 100644
index 0000000..a3d3ebb
--- /dev/null
+++ b/core/camel-core-engine/src/main/java/org/apache/camel/impl/PreconditionHelper.java
@@ -0,0 +1,66 @@
+/*
+ * 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.impl;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Predicate;
+import org.apache.camel.model.PreconditionContainer;
+import org.apache.camel.model.language.ExpressionDefinition;
+import org.apache.camel.model.language.SimpleExpression;
+import org.apache.camel.support.DefaultExchange;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Helper class for preconditions.
+ */
+final class PreconditionHelper {
+
+ /**
+ * The logger.
+ */
+ private static final Logger LOG = LoggerFactory.getLogger(PreconditionHelper.class);
+
+ private PreconditionHelper() {
+ }
+
+ /**
+ * Indicates whether the given {@link PreconditionContainer} should be included according to the precondition.
+ *
+ * @param container the container to check.
+ * @return {@code true} if the {@link PreconditionContainer} should be included, {@code false} otherwise.
+ */
+ static boolean included(PreconditionContainer container, CamelContext context) {
+ final String precondition = container.getPrecondition();
+ if (precondition == null) {
+ LOG.trace("No precondition found, the {} is included by default", container.getLabel());
+ return true;
+ }
+ final ExpressionDefinition expression = new SimpleExpression(precondition);
+ expression.initPredicate(context);
+
+ Predicate predicate = expression.getPredicate();
+ predicate.initPredicate(context);
+
+ boolean matches = predicate.matches(new DefaultExchange(context));
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("The precondition has been evaluated to {}, consequently the {} is {}", matches, container.getLabel(),
+ matches ? "included" : "excluded");
+ }
+ return matches;
+ }
+}
diff --git a/core/camel-core-model/src/generated/resources/org/apache/camel/model/routeConfiguration.json b/core/camel-core-model/src/generated/resources/org/apache/camel/model/routeConfiguration.json
index 29af0d6..a1b45b6 100644
--- a/core/camel-core-model/src/generated/resources/org/apache/camel/model/routeConfiguration.json
+++ b/core/camel-core-model/src/generated/resources/org/apache/camel/model/routeConfiguration.json
@@ -17,6 +17,7 @@
"interceptSendToEndpoint": { "kind": "element", "displayName": "Intercept Send To Endpoint", "required": false, "type": "array", "javaType": "java.util.List<org.apache.camel.model.InterceptSendToEndpointDefinition>", "deprecated": false, "autowired": false, "secret": false, "description": "Applies a route for an interceptor if an exchange is send to the given endpoint" },
"onException": { "kind": "element", "displayName": "On Exception", "required": false, "type": "array", "javaType": "java.util.List<org.apache.camel.model.OnExceptionDefinition>", "deprecated": false, "autowired": false, "secret": false, "description": "Exception clause for catching certain exceptions and handling them." },
"onCompletion": { "kind": "element", "displayName": "On Completion", "required": false, "type": "array", "javaType": "java.util.List<org.apache.camel.model.OnCompletionDefinition>", "deprecated": false, "autowired": false, "secret": false, "description": "On completion callback for doing custom routing when the org.apache.camel.Exchange is complete." },
+ "precondition": { "kind": "attribute", "displayName": "Precondition", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The predicate of the precondition in simple language to evaluate in order to determine if this route configuration should be included or not." },
"id": { "kind": "attribute", "displayName": "Id", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the id of this node" },
"description": { "kind": "element", "displayName": "Description", "required": false, "type": "object", "javaType": "org.apache.camel.model.DescriptionDefinition", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the description of this node" }
}
diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/PreconditionContainer.java b/core/camel-core-model/src/main/java/org/apache/camel/model/PreconditionContainer.java
new file mode 100644
index 0000000..078d1a6
--- /dev/null
+++ b/core/camel-core-model/src/main/java/org/apache/camel/model/PreconditionContainer.java
@@ -0,0 +1,37 @@
+/*
+ * 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.model;
+
+import org.apache.camel.NamedNode;
+
+/**
+ * Container to hold a precondition to determine if it should be included or not.
+ */
+public interface PreconditionContainer extends NamedNode {
+
+ /**
+ * The predicate of the precondition in simple language to evaluate in order to determine if it should be included
+ * or not.
+ */
+ String getPrecondition();
+
+ /**
+ * The predicate of the precondition in simple language to evaluate in order to determine if it should be included
+ * or not.
+ */
+ void setPrecondition(String precondition);
+}
diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/RouteConfigurationDefinition.java b/core/camel-core-model/src/main/java/org/apache/camel/model/RouteConfigurationDefinition.java
index 56df20c..1a7b65f 100644
--- a/core/camel-core-model/src/main/java/org/apache/camel/model/RouteConfigurationDefinition.java
+++ b/core/camel-core-model/src/main/java/org/apache/camel/model/RouteConfigurationDefinition.java
@@ -22,6 +22,7 @@ import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
@@ -33,7 +34,8 @@ import org.apache.camel.spi.Metadata;
@Metadata(label = "configuration")
@XmlRootElement(name = "routeConfiguration")
@XmlAccessorType(XmlAccessType.FIELD)
-public class RouteConfigurationDefinition extends OptionalIdentifiedDefinition<RouteConfigurationDefinition> {
+public class RouteConfigurationDefinition extends OptionalIdentifiedDefinition<RouteConfigurationDefinition>
+ implements PreconditionContainer {
// TODO: Model for ErrorHandler (requires to move error handler model from spring-xml, blueprint to core)
@@ -47,6 +49,9 @@ public class RouteConfigurationDefinition extends OptionalIdentifiedDefinition<R
private List<OnExceptionDefinition> onExceptions = new ArrayList<>();
@XmlElement(name = "onCompletion")
private List<OnCompletionDefinition> onCompletions = new ArrayList<>();
+ @XmlAttribute
+ @Metadata(label = "advanced")
+ private String precondition;
public RouteConfigurationDefinition() {
}
@@ -106,10 +111,40 @@ public class RouteConfigurationDefinition extends OptionalIdentifiedDefinition<R
this.interceptSendTos = interceptSendTos;
}
+ /**
+ * The predicate of the precondition in simple language to evaluate in order to determine if this route
+ * configuration should be included or not.
+ */
+ @Override
+ public String getPrecondition() {
+ return precondition;
+ }
+
+ /**
+ * The predicate of the precondition in simple language to evaluate in order to determine if this route
+ * configuration should be included or not.
+ */
+ @Override
+ public void setPrecondition(String precondition) {
+ this.precondition = precondition;
+ }
+
// Fluent API
// -------------------------------------------------------------------------
/**
+ * Sets the predicate of the precondition in simple language to evaluate in order to determine if this route
+ * configuration should be included or not.
+ *
+ * @param precondition the predicate corresponding to the test to evaluate.
+ * @return the builder
+ */
+ public RouteConfigurationDefinition precondition(String precondition) {
+ setPrecondition(precondition);
+ return this;
+ }
+
+ /**
* <a href="http://camel.apache.org/exception-clause.html">Exception clause</a> for catching certain exceptions and
* handling them.
*
diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/RouteDefinition.java b/core/camel-core-model/src/main/java/org/apache/camel/model/RouteDefinition.java
index c639ce2..c7e2d3e 100644
--- a/core/camel-core-model/src/main/java/org/apache/camel/model/RouteDefinition.java
+++ b/core/camel-core-model/src/main/java/org/apache/camel/model/RouteDefinition.java
@@ -34,6 +34,7 @@ import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
import javax.xml.bind.annotation.XmlType;
+import org.apache.camel.CamelContext;
import org.apache.camel.Endpoint;
import org.apache.camel.ErrorHandlerFactory;
import org.apache.camel.NamedRoute;
@@ -57,7 +58,7 @@ import org.apache.camel.spi.RoutePolicy;
@XmlType(propOrder = { "input", "inputType", "outputType", "outputs", "routeProperties" })
@XmlAccessorType(XmlAccessType.PROPERTY)
// must use XmlAccessType.PROPERTY as there is some custom logic needed to be executed in the setter methods
-public class RouteDefinition extends OutputDefinition<RouteDefinition> implements NamedRoute {
+public class RouteDefinition extends OutputDefinition<RouteDefinition> implements NamedRoute, PreconditionContainer {
private final AtomicBoolean prepared = new AtomicBoolean();
private FromDefinition input;
private String routeConfigurationId;
@@ -117,7 +118,7 @@ public class RouteDefinition extends OutputDefinition<RouteDefinition> implement
* Check if the route has been prepared
*
* @return whether the route has been prepared or not
- * @see RouteDefinitionHelper#prepareRoute(ModelCamelContext, RouteDefinition)
+ * @see RouteDefinitionHelper#prepareRoute(CamelContext, RouteDefinition)
*/
public boolean isPrepared() {
return prepared.get();
@@ -926,9 +927,10 @@ public class RouteDefinition extends OutputDefinition<RouteDefinition> implement
}
/**
- * The predicate of the precondition in simple language to evaluate in order to determine if this given route should
- * be included or not.
+ * The predicate of the precondition in simple language to evaluate in order to determine if this route should be
+ * included or not.
*/
+ @Override
public String getPrecondition() {
return precondition;
}
@@ -939,6 +941,7 @@ public class RouteDefinition extends OutputDefinition<RouteDefinition> implement
*/
@XmlAttribute
@Metadata(label = "advanced")
+ @Override
public void setPrecondition(String precondition) {
this.precondition = precondition;
}
diff --git a/core/camel-core/src/test/java/org/apache/camel/processor/RoutePreconditionTest.java b/core/camel-core/src/test/java/org/apache/camel/processor/RouteConfigurationPreconditionTest.java
similarity index 51%
copy from core/camel-core/src/test/java/org/apache/camel/processor/RoutePreconditionTest.java
copy to core/camel-core/src/test/java/org/apache/camel/processor/RouteConfigurationPreconditionTest.java
index 508fa3c..bb11a29 100644
--- a/core/camel-core/src/test/java/org/apache/camel/processor/RoutePreconditionTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/processor/RouteConfigurationPreconditionTest.java
@@ -20,15 +20,14 @@ import java.util.Properties;
import org.apache.camel.ContextTestSupport;
import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.builder.RouteConfigurationBuilder;
import org.junit.jupiter.api.Test;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static org.junit.jupiter.api.Assertions.assertNull;
-
/**
- * The test ensuring that the precondition set on a rule determines if the route is included or not
+ * The test ensuring that the precondition set on a route configuration determines if the route configuration is
+ * included or not
*/
-class RoutePreconditionTest extends ContextTestSupport {
+class RouteConfigurationPreconditionTest extends ContextTestSupport {
@Override
public boolean isUseRouteBuilder() {
@@ -36,71 +35,61 @@ class RoutePreconditionTest extends ContextTestSupport {
}
@Test
- void testRouteIncluded() throws Exception {
+ void testRouteConfigurationIncluded() throws Exception {
Properties init = new Properties();
- init.setProperty("protocol", "json");
+ init.setProperty("activate", "true");
context.getPropertiesComponent().setInitialProperties(init);
context.addRoutes(createRouteBuilder());
context.start();
- assertCollectionSize(context.getRouteDefinitions(), 2);
- assertCollectionSize(context.getRoutes(), 2);
- assertNotNull(context.getRoute("myRoute"));
- assertNotNull(context.getRoute("myRouteNP"));
+ assertCollectionSize(context.getRouteConfigurationDefinitions(), 2);
+ assertCollectionSize(context.getRouteDefinitions(), 1);
+ assertCollectionSize(context.getRoutes(), 1);
- getMockEndpoint("mock:out").expectedMessageCount(1);
+ getMockEndpoint("mock:error").expectedMessageCount(1);
+ getMockEndpoint("mock:error").expectedBodiesReceived("Activated");
- template.sendBody("direct:in", "Hello Included Route");
+ template.sendBody("direct:start", "Hello Activated Route Config");
assertMockEndpointsSatisfied();
}
@Test
- void testRouteExcluded() throws Exception {
+ void testRouteConfigurationExcluded() throws Exception {
Properties init = new Properties();
- init.setProperty("protocol", "avro");
+ init.setProperty("activate", "false");
context.getPropertiesComponent().setInitialProperties(init);
context.addRoutes(createRouteBuilder());
context.start();
+ assertCollectionSize(context.getRouteConfigurationDefinitions(), 1);
assertCollectionSize(context.getRouteDefinitions(), 1);
assertCollectionSize(context.getRoutes(), 1);
- assertNull(context.getRoute("myRoute"));
- assertNotNull(context.getRoute("myRouteNP"));
- }
- @Test
- void testRouteIncludedByDefault() throws Exception {
- Properties init = new Properties();
- init.setProperty("protocol", "foo");
- context.getPropertiesComponent().setInitialProperties(init);
+ getMockEndpoint("mock:error").expectedMessageCount(1);
+ getMockEndpoint("mock:error").expectedBodiesReceived("Default");
- context.addRoutes(createRouteBuilder());
- context.start();
-
- assertCollectionSize(context.getRouteDefinitions(), 1);
- assertCollectionSize(context.getRoutes(), 1);
- assertNotNull(context.getRoute("myRouteNP"));
-
- getMockEndpoint("mock:outNP").expectedMessageCount(1);
-
- template.sendBody("direct:inNP", "Hello Included Route");
+ template.sendBody("direct:start", "Hello Not Activated Route Config");
assertMockEndpointsSatisfied();
}
@Override
- protected RouteBuilder createRouteBuilder() {
- return new RouteBuilder() {
- public void configure() {
- from("direct:in").routeId("myRoute").precondition("'{{protocol}}' == 'json'")
- .to("mock:out");
- from("direct:inNP").routeId("myRouteNP")
- .to("mock:outNP");
+ protected RouteBuilder createRouteBuilder() throws Exception {
+ return new RouteConfigurationBuilder() {
+ @Override
+ public void configuration() {
+ from("direct:start")
+ .throwException(new IllegalArgumentException("Foo"));
+ routeConfiguration().precondition("{{activate}}").onException(IllegalArgumentException.class).handled(true)
+ .transform(constant("Activated"))
+ .to("mock:error");
+ routeConfiguration().onException(Exception.class).handled(true)
+ .transform(constant("Default"))
+ .to("mock:error");
}
};
}
-
}
diff --git a/core/camel-core/src/test/java/org/apache/camel/processor/RoutePreconditionTest.java b/core/camel-core/src/test/java/org/apache/camel/processor/RoutePreconditionTest.java
index 508fa3c..f295238 100644
--- a/core/camel-core/src/test/java/org/apache/camel/processor/RoutePreconditionTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/processor/RoutePreconditionTest.java
@@ -26,7 +26,7 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
/**
- * The test ensuring that the precondition set on a rule determines if the route is included or not
+ * The test ensuring that the precondition set on a route determines if the route is included or not
*/
class RoutePreconditionTest extends ContextTestSupport {
diff --git a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java
index bd2d248..4aaca5f 100644
--- a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java
+++ b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java
@@ -984,8 +984,13 @@ public class ModelParser extends BaseParser {
}, noElementHandler(), noValueHandler());
}
protected RouteConfigurationDefinition doParseRouteConfigurationDefinition() throws IOException, XmlPullParserException {
- return doParse(new RouteConfigurationDefinition(),
- optionalIdentifiedDefinitionAttributeHandler(), (def, key) -> {
+ return doParse(new RouteConfigurationDefinition(), (def, key, val) -> {
+ if ("precondition".equals(key)) {
+ def.setPrecondition(val);
+ return true;
+ }
+ return optionalIdentifiedDefinitionAttributeHandler().accept(def, key, val);
+ }, (def, key) -> {
switch (key) {
case "interceptFrom": doAdd(doParseInterceptFromDefinition(), def.getInterceptFroms(), def::setInterceptFroms); break;
case "interceptSendToEndpoint": doAdd(doParseInterceptSendToEndpointDefinition(), def.getInterceptSendTos(), def::setInterceptSendTos); break;
diff --git a/docs/user-manual/modules/ROOT/pages/route-configuration.adoc b/docs/user-manual/modules/ROOT/pages/route-configuration.adoc
index de16d2d..2215ffb 100644
--- a/docs/user-manual/modules/ROOT/pages/route-configuration.adoc
+++ b/docs/user-manual/modules/ROOT/pages/route-configuration.adoc
@@ -323,6 +323,51 @@ And in Camel Main / Quarkus:
camel.main.startup-summary-level = verbose
----
+== Route Precondition
+
+The route configurations can be included or not according to the result of a test expressed in simple language that is evaluated only once during the initialization phase.
+
+In the next example, the route configuration is only included if the parameter `activate` has been set to `true`.
+
+[source,java]
+----
+routeConfiguration().precondition("{{activate}}")
+ .onException(IllegalArgumentException.class)
+ .handled(true)
+ .log("WARN: ${exception.message}");
+----
+
+And the same example using XML DSL:
+
+[source,xml]
+----
+<routeConfiguration precondition="{{activate}}">
+ <onException>
+ <exception>java.lang.IllegalArgumentException</exception>
+ <handled>
+ <constant>true</constant>
+ </handled>
+ <log message="XML WARN: ${exception.message}"/>
+ </onException>
+</routeConfiguration>
+----
+
+And in YAML DSL:
+
+[source,yaml]
+----
+- route-configuration:
+ - precondition: "{{activate}}"
+ - on-exception:
+ exception:
+ - "java.lang.IllegalArgumentException"
+ handled:
+ constant: "true"
+ steps:
+ - log:
+ message: "YAML WARN ${exception.message}"
+----
+
== More Information
See these examples:
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/main/java/org/apache/camel/dsl/yaml/deserializers/RouteConfigurationDefinitionDeserializer.java b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/main/java/org/apache/camel/dsl/yaml/deserializers/RouteConfigurationDefinitionDeserializer.java
index 1fcb898..5b99d26 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/main/java/org/apache/camel/dsl/yaml/deserializers/RouteConfigurationDefinitionDeserializer.java
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/main/java/org/apache/camel/dsl/yaml/deserializers/RouteConfigurationDefinitionDeserializer.java
@@ -40,6 +40,7 @@ import org.snakeyaml.engine.v2.nodes.SequenceNode;
nodes = { "route-configuration", "routeConfiguration" },
properties = {
@YamlProperty(name = "id", type = "string"),
+ @YamlProperty(name = "precondition", type = "string"),
@YamlProperty(name = "intercept", type = "array:org.apache.camel.model.InterceptDefinition"),
@YamlProperty(name = "intercept-from", type = "array:org.apache.camel.model.InterceptFromDefinition"),
@YamlProperty(name = "intercept-send-to-endpoint",
@@ -75,6 +76,9 @@ public class RouteConfigurationDefinitionDeserializer extends YamlDeserializerBa
target.setId(asText(val));
break;
}
+ case "precondition":
+ target.setPrecondition(asText(val));
+ break;
case "on-exception":
setDeserializationContext(val, dc);
OnExceptionDefinition oed = asType(val, OnExceptionDefinition.class);
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/camel-yaml-dsl.json b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/camel-yaml-dsl.json
index b96eb2e..e7ac7f4 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/camel-yaml-dsl.json
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/camel-yaml-dsl.json
@@ -2482,6 +2482,9 @@
"items" : {
"$ref" : "#/items/definitions/org.apache.camel.model.OnExceptionDefinition"
}
+ },
+ "precondition" : {
+ "type" : "string"
}
}
} ]
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/camelYamlDsl.json b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/camelYamlDsl.json
index a7c11d0..7179ecf 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/camelYamlDsl.json
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/camelYamlDsl.json
@@ -2383,6 +2383,9 @@
"items" : {
"$ref" : "#/items/definitions/org.apache.camel.model.OnExceptionDefinition"
}
+ },
+ "precondition" : {
+ "type" : "string"
}
}
} ]
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/RouteConfigurationTest.groovy b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/RouteConfigurationTest.groovy
index ba7e9a8..dbaabb0 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/RouteConfigurationTest.groovy
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/RouteConfigurationTest.groovy
@@ -22,7 +22,8 @@ import org.apache.camel.dsl.yaml.support.YamlTestSupport
import org.apache.camel.dsl.yaml.support.model.MyException
import org.apache.camel.dsl.yaml.support.model.MyFailingProcessor
import org.junit.jupiter.api.Assertions
-import org.junit.jupiter.api.Disabled
+
+import static org.apache.camel.util.PropertiesHelper.asProperties
class RouteConfigurationTest extends YamlTestSupport {
def "route-configuration"() {
@@ -62,6 +63,56 @@ class RouteConfigurationTest extends YamlTestSupport {
MockEndpoint.assertIsSatisfied(context)
}
+ def "route-configuration-precondition"() {
+ setup:
+ context.getPropertiesComponent().setInitialProperties(asProperties("activate", "true"))
+ loadRoutes """
+ - beans:
+ - name: myFailingProcessor
+ type: ${MyFailingProcessor.name}
+ - route-configuration:
+ - precondition: "{{!activate}}"
+ - on-exception:
+ handled:
+ constant: "true"
+ exception:
+ - ${MyException.name}
+ steps:
+ - transform:
+ constant: "Not Activated"
+ - to: "mock:on-exception"
+ - route-configuration:
+ - precondition: "{{activate}}"
+ - on-exception:
+ handled:
+ constant: "true"
+ exception:
+ - ${MyException.name}
+ steps:
+ - transform:
+ constant: "Activated"
+ - to: "mock:on-exception"
+ - from:
+ uri: "direct:start"
+ steps:
+ - process:
+ ref: "myFailingProcessor"
+ """
+
+ withMock('mock:on-exception') {
+ expectedBodiesReceived 'Activated'
+ }
+
+ when:
+ context.start()
+
+ withTemplate {
+ to('direct:start').withBody('hello').send()
+ }
+ then:
+ MockEndpoint.assertIsSatisfied(context)
+ }
+
def "route-configuration-separate"() {
setup:
// global configurations