You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2021/08/03 12:33:49 UTC
[camel] 19/22: CAMEL-16757: route configuration added to classic
spring xml (also for cdi xml)
This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch CAMEL-16757b
in repository https://gitbox.apache.org/repos/asf/camel.git
commit 33beec2734a530d044f6ce4f15592824ab10e90a
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Tue Aug 3 11:03:12 2021 +0200
CAMEL-16757: route configuration added to classic spring xml (also for cdi xml)
---
.../camel/cdi/xml/CamelContextFactoryBean.java | 14 ++++
.../camel/cdi/test/XmlRouteConfigurationTest.java | 77 ++++++++++++++++++++++
.../resources/camel-context-routeConfiguration.xml | 49 ++++++++++++++
.../org/apache/camel/spring/xml/camelContext.json | 1 +
.../camel/spring/xml/CamelContextFactoryBean.java | 18 +++++
.../spring/xml/handler/CamelNamespaceHandler.java | 1 +
...gRoutesConfigurationBuilderIdOrPatternTest.java | 48 ++++++++++++++
...ngRoutesConfigurationBuilderIdOrPatternTest.xml | 52 +++++++++++++++
.../java/org/apache/camel/impl/DefaultModel.java | 9 +++
...ainer.java => RouteConfigurationContainer.java} | 16 ++---
.../camel/model/RouteConfigurationsDefinition.java | 2 +-
.../org/apache/camel/model/RouteContainer.java | 2 +-
.../apache/camel/model/RouteTemplateContainer.java | 2 +-
.../core/xml/AbstractCamelContextFactoryBean.java | 45 +++++++++++--
.../RoutesConfigurationBuilderIdOrPatternTest.java | 21 ++++++
15 files changed, 342 insertions(+), 15 deletions(-)
diff --git a/components/camel-cdi/src/main/java/org/apache/camel/cdi/xml/CamelContextFactoryBean.java b/components/camel-cdi/src/main/java/org/apache/camel/cdi/xml/CamelContextFactoryBean.java
index 001012d..96b7170 100644
--- a/components/camel-cdi/src/main/java/org/apache/camel/cdi/xml/CamelContextFactoryBean.java
+++ b/components/camel-cdi/src/main/java/org/apache/camel/cdi/xml/CamelContextFactoryBean.java
@@ -59,6 +59,7 @@ import org.apache.camel.model.PackageScanDefinition;
import org.apache.camel.model.Resilience4jConfigurationDefinition;
import org.apache.camel.model.RestContextRefDefinition;
import org.apache.camel.model.RouteBuilderDefinition;
+import org.apache.camel.model.RouteConfigurationDefinition;
import org.apache.camel.model.RouteContextRefDefinition;
import org.apache.camel.model.RouteDefinition;
import org.apache.camel.model.RouteTemplateContextRefDefinition;
@@ -296,6 +297,9 @@ public class CamelContextFactoryBean extends AbstractCamelContextFactoryBean<Def
@XmlElement(name = "rest")
private List<RestDefinition> rests = new ArrayList<>();
+ @XmlElement(name = "routeConfiguration")
+ private List<RouteConfigurationDefinition> routeConfigurations = new ArrayList<>();
+
@XmlElement(name = "routeTemplate")
private List<RouteTemplateDefinition> routeTemplates = new ArrayList<>();
@@ -492,6 +496,16 @@ public class CamelContextFactoryBean extends AbstractCamelContextFactoryBean<Def
}
@Override
+ public List<RouteConfigurationDefinition> getRouteConfigurations() {
+ return routeConfigurations;
+ }
+
+ @Override
+ public void setRouteConfigurations(List<RouteConfigurationDefinition> routeConfigurations) {
+ this.routeConfigurations = routeConfigurations;
+ }
+
+ @Override
public List<RouteTemplateDefinition> getRouteTemplates() {
return routeTemplates;
}
diff --git a/components/camel-cdi/src/test/java/org/apache/camel/cdi/test/XmlRouteConfigurationTest.java b/components/camel-cdi/src/test/java/org/apache/camel/cdi/test/XmlRouteConfigurationTest.java
new file mode 100644
index 0000000..7bbcb0d
--- /dev/null
+++ b/components/camel-cdi/src/test/java/org/apache/camel/cdi/test/XmlRouteConfigurationTest.java
@@ -0,0 +1,77 @@
+/*
+ * 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.cdi.test;
+
+import java.nio.file.Paths;
+
+import javax.inject.Inject;
+
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.cdi.CdiCamelExtension;
+import org.apache.camel.cdi.ImportResource;
+import org.apache.camel.cdi.Uri;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.shrinkwrap.api.Archive;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.asset.EmptyAsset;
+import org.jboss.shrinkwrap.api.spec.JavaArchive;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.fail;
+
+@RunWith(Arquillian.class)
+@ImportResource("imported-context.xml")
+public class XmlRouteConfigurationTest {
+
+ @Inject
+ private ProducerTemplate template;
+
+ @Inject
+ @Uri("mock:error")
+ private MockEndpoint mock;
+
+ @Deployment
+ public static Archive<?> deployment() {
+ return ShrinkWrap.create(JavaArchive.class)
+ // Camel CDI
+ .addPackage(CdiCamelExtension.class.getPackage())
+ // Test Camel XML
+ .addAsResource(
+ Paths.get("src/test/resources/camel-context-routeConfiguration.xml").toFile(),
+ "imported-context.xml")
+ // Bean archive deployment descriptor
+ .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");
+ }
+
+ @Test
+ public void testRoutesConfigurationOnException() throws Exception {
+ mock.expectedBodiesReceived("Bye World");
+
+ try {
+ template.sendBody("direct:start", "Hello World");
+ fail("Should throw exception");
+ } catch (Exception e) {
+ // expected
+ }
+ template.sendBody("direct:start2", "Bye World");
+
+ mock.assertIsSatisfied();
+ }
+}
diff --git a/components/camel-cdi/src/test/resources/camel-context-routeConfiguration.xml b/components/camel-cdi/src/test/resources/camel-context-routeConfiguration.xml
new file mode 100644
index 0000000..a77cae3
--- /dev/null
+++ b/components/camel-cdi/src/test/resources/camel-context-routeConfiguration.xml
@@ -0,0 +1,49 @@
+<?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://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
+
+ <camelContext xmlns="http://camel.apache.org/schema/spring">
+
+ <routeConfiguration id="handleError">
+ <onException>
+ <exception>java.lang.Exception</exception>
+ <handled>
+ <constant>true</constant>
+ </handled>
+ <to uri="mock:error"/>
+ </onException>
+ </routeConfiguration>
+
+ <route>
+ <from uri="direct:start"/>
+ <throwException exceptionType="java.lang.IllegalArgumentException" message="Foo"/>
+ </route>
+
+ <route routeConfigurationId="handleError">
+ <from uri="direct:start2"/>
+ <throwException exceptionType="java.lang.IllegalArgumentException" message="Foo2"/>
+ </route>
+
+ </camelContext>
+
+</beans>
diff --git a/components/camel-spring-xml/src/generated/resources/org/apache/camel/spring/xml/camelContext.json b/components/camel-spring-xml/src/generated/resources/org/apache/camel/spring/xml/camelContext.json
index fb39212..9a6507f 100644
--- a/components/camel-spring-xml/src/generated/resources/org/apache/camel/spring/xml/camelContext.json
+++ b/components/camel-spring-xml/src/generated/resources/org/apache/camel/spring/xml/camelContext.json
@@ -80,6 +80,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": "Configuration of interceptors that triggers sending messages to endpoints." },
"restConfiguration": { "kind": "element", "displayName": "Rest Configuration", "required": false, "type": "object", "javaType": "org.apache.camel.model.rest.RestConfigurationDefinition", "deprecated": false, "autowired": false, "secret": false, "description": "Configuration for rest-dsl" },
"rest": { "kind": "element", "displayName": "Rest", "required": false, "type": "array", "javaType": "java.util.List<org.apache.camel.model.rest.RestDefinition>", "deprecated": false, "autowired": false, "secret": false, "description": "Contains the rest services defined using the rest-dsl" },
+ "routeConfiguration": { "kind": "element", "displayName": "Route Configuration", "required": false, "type": "array", "javaType": "java.util.List<org.apache.camel.model.RouteConfigurationDefinition>", "deprecated": false, "autowired": false, "secret": false, "description": "Contains the Camel route configurations" },
"routeTemplate": { "kind": "element", "displayName": "Route Template", "required": false, "type": "array", "javaType": "java.util.List<org.apache.camel.model.RouteTemplateDefinition>", "deprecated": false, "autowired": false, "secret": false, "description": "Contains the Camel route templates" },
"route": { "kind": "element", "displayName": "Route", "required": false, "type": "array", "javaType": "java.util.List<org.apache.camel.model.RouteDefinition>", "deprecated": false, "autowired": false, "secret": false, "description": "Contains the Camel routes" },
"id": { "kind": "attribute", "displayName": "Id", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }
diff --git a/components/camel-spring-xml/src/main/java/org/apache/camel/spring/xml/CamelContextFactoryBean.java b/components/camel-spring-xml/src/main/java/org/apache/camel/spring/xml/CamelContextFactoryBean.java
index 87a990e..4aa862d 100644
--- a/components/camel-spring-xml/src/main/java/org/apache/camel/spring/xml/CamelContextFactoryBean.java
+++ b/components/camel-spring-xml/src/main/java/org/apache/camel/spring/xml/CamelContextFactoryBean.java
@@ -57,6 +57,7 @@ import org.apache.camel.model.PackageScanDefinition;
import org.apache.camel.model.Resilience4jConfigurationDefinition;
import org.apache.camel.model.RestContextRefDefinition;
import org.apache.camel.model.RouteBuilderDefinition;
+import org.apache.camel.model.RouteConfigurationDefinition;
import org.apache.camel.model.RouteContextRefDefinition;
import org.apache.camel.model.RouteDefinition;
import org.apache.camel.model.RouteTemplateContextRefDefinition;
@@ -263,6 +264,8 @@ public class CamelContextFactoryBean extends AbstractCamelContextFactoryBean<Spr
private RestConfigurationDefinition restConfiguration;
@XmlElement(name = "rest")
private List<RestDefinition> rests = new ArrayList<>();
+ @XmlElement(name = "routeConfiguration")
+ private List<RouteConfigurationDefinition> routeConfigurations = new ArrayList<>();
@XmlElement(name = "routeTemplate")
private List<RouteTemplateDefinition> routeTemplates = new ArrayList<>();
@XmlElement(name = "route")
@@ -557,6 +560,20 @@ public class CamelContextFactoryBean extends AbstractCamelContextFactoryBean<Spr
this.routes = routes;
}
+ @Override
+ public List<RouteConfigurationDefinition> getRouteConfigurations() {
+ return routeConfigurations;
+ }
+
+ /**
+ * Contains the Camel route configurations
+ */
+ @Override
+ public void setRouteConfigurations(List<RouteConfigurationDefinition> routeConfigurations) {
+ this.routeConfigurations = routeConfigurations;
+ }
+
+ @Override
public List<RouteTemplateDefinition> getRouteTemplates() {
return routeTemplates;
}
@@ -564,6 +581,7 @@ public class CamelContextFactoryBean extends AbstractCamelContextFactoryBean<Spr
/**
* Contains the Camel route templates
*/
+ @Override
public void setRouteTemplates(List<RouteTemplateDefinition> routeTemplates) {
this.routeTemplates = routeTemplates;
}
diff --git a/components/camel-spring-xml/src/main/java/org/apache/camel/spring/xml/handler/CamelNamespaceHandler.java b/components/camel-spring-xml/src/main/java/org/apache/camel/spring/xml/handler/CamelNamespaceHandler.java
index d7272be..fed1bba 100644
--- a/components/camel-spring-xml/src/main/java/org/apache/camel/spring/xml/handler/CamelNamespaceHandler.java
+++ b/components/camel-spring-xml/src/main/java/org/apache/camel/spring/xml/handler/CamelNamespaceHandler.java
@@ -390,6 +390,7 @@ public class CamelNamespaceHandler extends NamespaceHandlerSupport {
builder.addPropertyValue("implicitId", implicitId);
builder.addPropertyValue("restConfiguration", factoryBean.getRestConfiguration());
builder.addPropertyValue("rests", factoryBean.getRests());
+ builder.addPropertyValue("routeConfigurations", factoryBean.getRouteConfigurations());
builder.addPropertyValue("routeTemplates", factoryBean.getRouteTemplates());
builder.addPropertyValue("routes", factoryBean.getRoutes());
builder.addPropertyValue("intercepts", factoryBean.getIntercepts());
diff --git a/components/camel-spring-xml/src/test/java/org/apache/camel/spring/SpringRoutesConfigurationBuilderIdOrPatternTest.java b/components/camel-spring-xml/src/test/java/org/apache/camel/spring/SpringRoutesConfigurationBuilderIdOrPatternTest.java
new file mode 100644
index 0000000..5e9a316
--- /dev/null
+++ b/components/camel-spring-xml/src/test/java/org/apache/camel/spring/SpringRoutesConfigurationBuilderIdOrPatternTest.java
@@ -0,0 +1,48 @@
+/*
+ * 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.spring;
+
+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.fail;
+
+public class SpringRoutesConfigurationBuilderIdOrPatternTest extends SpringTestSupport {
+
+ @Override
+ protected AbstractXmlApplicationContext createApplicationContext() {
+ return new ClassPathXmlApplicationContext(
+ "org/apache/camel/spring/SpringRoutesConfigurationBuilderIdOrPatternTest.xml");
+ }
+
+ @Test
+ public void testRoutesConfigurationOnException() throws Exception {
+ getMockEndpoint("mock:error").expectedBodiesReceived("Bye World");
+
+ try {
+ template.sendBody("direct:start", "Hello World");
+ fail("Should throw exception");
+ } catch (Exception e) {
+ // expected
+ }
+ template.sendBody("direct:start2", "Bye World");
+
+ assertMockEndpointsSatisfied();
+ }
+
+}
diff --git a/components/camel-spring-xml/src/test/resources/org/apache/camel/spring/SpringRoutesConfigurationBuilderIdOrPatternTest.xml b/components/camel-spring-xml/src/test/resources/org/apache/camel/spring/SpringRoutesConfigurationBuilderIdOrPatternTest.xml
new file mode 100644
index 0000000..f8b4d43
--- /dev/null
+++ b/components/camel-spring-xml/src/test/resources/org/apache/camel/spring/SpringRoutesConfigurationBuilderIdOrPatternTest.xml
@@ -0,0 +1,52 @@
+<?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://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd
+ ">
+
+
+ <camelContext xmlns="http://camel.apache.org/schema/spring">
+
+ <routeConfiguration id="handleError">
+ <onException>
+ <exception>java.lang.Exception</exception>
+ <handled>
+ <constant>true</constant>
+ </handled>
+ <to uri="mock:error"/>
+ </onException>
+ </routeConfiguration>
+
+ <route>
+ <from uri="direct:start"/>
+ <throwException exceptionType="java.lang.IllegalArgumentException" message="Foo"/>
+ </route>
+
+ <route routeConfigurationId="handleError">
+ <from uri="direct:start2"/>
+ <throwException exceptionType="java.lang.IllegalArgumentException" message="Foo2"/>
+ </route>
+
+ </camelContext>
+
+</beans>
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 475a975..b658b6b 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
@@ -123,6 +123,15 @@ public class DefaultModel implements Model {
// only add if not already exists (route-loader may let Java DSL add route configuration twice
// because it extends RouteBuilder as base class)
if (!this.routesConfigurations.contains(routesConfiguration)) {
+ // check that there is no id clash
+ if (routesConfiguration.getId() != null) {
+ boolean clash = this.routesConfigurations.stream()
+ .anyMatch(r -> ObjectHelper.equal(r.getId(), routesConfiguration.getId()));
+ if (clash) {
+ throw new IllegalArgumentException(
+ "Route configuration already exists with id: " + routesConfiguration.getId());
+ }
+ }
this.routesConfigurations.add(routesConfiguration);
}
}
diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/RouteContainer.java b/core/camel-core-model/src/main/java/org/apache/camel/model/RouteConfigurationContainer.java
similarity index 69%
copy from core/camel-core-model/src/main/java/org/apache/camel/model/RouteContainer.java
copy to core/camel-core-model/src/main/java/org/apache/camel/model/RouteConfigurationContainer.java
index 5e4ba8e..c46aabe 100644
--- a/core/camel-core-model/src/main/java/org/apache/camel/model/RouteContainer.java
+++ b/core/camel-core-model/src/main/java/org/apache/camel/model/RouteConfigurationContainer.java
@@ -21,22 +21,22 @@ import java.util.List;
import javax.xml.bind.annotation.XmlElementRef;
/**
- * Container to hold {@link org.apache.camel.model.RouteDefinition Route}.
+ * Container to hold {@link RouteConfigurationDefinition route configurations}.
*/
-public interface RouteContainer {
+public interface RouteConfigurationContainer {
/**
- * Returns the routes
+ * Returns the route configurations
*
- * @return the routes
+ * @return the route configurations
*/
@XmlElementRef
- List<RouteDefinition> getRoutes();
+ List<RouteConfigurationDefinition> getRouteConfigurations();
/**
- * Sets the routes to use
+ * Sets the route configurations to use
*
- * @param routes the routes
+ * @param routes the route configurations
*/
- void setRoutes(List<RouteDefinition> routes);
+ void setRouteConfigurations(List<RouteConfigurationDefinition> routes);
}
diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/RouteConfigurationsDefinition.java b/core/camel-core-model/src/main/java/org/apache/camel/model/RouteConfigurationsDefinition.java
index c56874b..92ec02c 100644
--- a/core/camel-core-model/src/main/java/org/apache/camel/model/RouteConfigurationsDefinition.java
+++ b/core/camel-core-model/src/main/java/org/apache/camel/model/RouteConfigurationsDefinition.java
@@ -34,7 +34,7 @@ import org.apache.camel.spi.Metadata;
@Metadata(label = "configuration")
@XmlRootElement(name = "routeConfigurations")
@XmlAccessorType(XmlAccessType.FIELD)
-public class RouteConfigurationsDefinition {
+public class RouteConfigurationsDefinition implements RouteConfigurationContainer {
@XmlElementRef
private List<RouteConfigurationDefinition> routeConfigurations = new ArrayList<>();
diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/RouteContainer.java b/core/camel-core-model/src/main/java/org/apache/camel/model/RouteContainer.java
index 5e4ba8e..ba548f2 100644
--- a/core/camel-core-model/src/main/java/org/apache/camel/model/RouteContainer.java
+++ b/core/camel-core-model/src/main/java/org/apache/camel/model/RouteContainer.java
@@ -21,7 +21,7 @@ import java.util.List;
import javax.xml.bind.annotation.XmlElementRef;
/**
- * Container to hold {@link org.apache.camel.model.RouteDefinition Route}.
+ * Container to hold {@link org.apache.camel.model.RouteDefinition routes}.
*/
public interface RouteContainer {
diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/RouteTemplateContainer.java b/core/camel-core-model/src/main/java/org/apache/camel/model/RouteTemplateContainer.java
index ae4e8c8..b2715c8 100644
--- a/core/camel-core-model/src/main/java/org/apache/camel/model/RouteTemplateContainer.java
+++ b/core/camel-core-model/src/main/java/org/apache/camel/model/RouteTemplateContainer.java
@@ -21,7 +21,7 @@ import java.util.List;
import javax.xml.bind.annotation.XmlElementRef;
/**
- * Container to hold {@link RouteTemplateDefinition Route}.
+ * Container to hold {@link RouteTemplateDefinition route templates}.
*/
public interface RouteTemplateContainer {
diff --git a/core/camel-core-xml/src/main/java/org/apache/camel/core/xml/AbstractCamelContextFactoryBean.java b/core/camel-core-xml/src/main/java/org/apache/camel/core/xml/AbstractCamelContextFactoryBean.java
index 2e88712..9b62c51 100644
--- a/core/camel-core-xml/src/main/java/org/apache/camel/core/xml/AbstractCamelContextFactoryBean.java
+++ b/core/camel-core-xml/src/main/java/org/apache/camel/core/xml/AbstractCamelContextFactoryBean.java
@@ -72,6 +72,8 @@ import org.apache.camel.model.PackageScanDefinition;
import org.apache.camel.model.Resilience4jConfigurationDefinition;
import org.apache.camel.model.RestContextRefDefinition;
import org.apache.camel.model.RouteBuilderDefinition;
+import org.apache.camel.model.RouteConfigurationContainer;
+import org.apache.camel.model.RouteConfigurationDefinition;
import org.apache.camel.model.RouteContainer;
import org.apache.camel.model.RouteContextRefDefinition;
import org.apache.camel.model.RouteDefinition;
@@ -132,6 +134,7 @@ import org.apache.camel.spi.UuidGenerator;
import org.apache.camel.spi.Validator;
import org.apache.camel.support.CamelContextHelper;
import org.apache.camel.support.ObjectHelper;
+import org.apache.camel.support.PatternHelper;
import org.apache.camel.util.StringHelper;
import org.apache.camel.util.concurrent.ThreadPoolRejectedPolicy;
import org.slf4j.Logger;
@@ -143,7 +146,7 @@ import org.slf4j.LoggerFactory;
*/
@XmlAccessorType(XmlAccessType.FIELD)
public abstract class AbstractCamelContextFactoryBean<T extends ModelCamelContext> extends IdentifiedType
- implements RouteTemplateContainer, RouteContainer, RestContainer {
+ implements RouteTemplateContainer, RouteConfigurationContainer, RouteContainer, RestContainer {
private static final Logger LOG = LoggerFactory.getLogger(AbstractCamelContextFactoryBean.class);
@@ -444,6 +447,9 @@ public abstract class AbstractCamelContextFactoryBean<T extends ModelCamelContex
// mark that we are setting up routes
getContext().adapt(ExtendedCamelContext.class).setupRoutes(false);
+ // add route configurations
+ getContext().addRouteConfigurations(getRouteConfigurations());
+
// init route templates
initRouteTemplateRefs();
@@ -546,9 +552,37 @@ public abstract class AbstractCamelContextFactoryBean<T extends ModelCamelContex
// sanity check first as the route is created using XML
RouteDefinitionHelper.sanityCheckRoute(route);
- // leverage logic from route definition helper to prepare the route
- RouteDefinitionHelper.prepareRoute(getContext(), route, getOnExceptions(), getIntercepts(), getInterceptFroms(),
- getInterceptSendToEndpoints(), getOnCompletions());
+ // merge global and route scoped together
+ List<OnExceptionDefinition> oe = new ArrayList<>(getOnExceptions());
+ List<InterceptDefinition> icp = new ArrayList<>(getIntercepts());
+ List<InterceptFromDefinition> ifrom = new ArrayList<>(getInterceptFroms());
+ List<InterceptSendToEndpointDefinition> ito = new ArrayList<>(getInterceptSendToEndpoints());
+ List<OnCompletionDefinition> oc = new ArrayList<>(getOnCompletions());
+ if (getContext() != null) {
+ List<RouteConfigurationDefinition> globalConfigurations
+ = getContext().adapt(ModelCamelContext.class).getRouteConfigurationDefinitions();
+ if (globalConfigurations != null) {
+ globalConfigurations.stream()
+ // global configurations have no id assigned or is a wildcard
+ // if the route has a route configuration assigned then use pattern matching
+ .filter(g -> (g.getId() == null || g.getId().equals("*"))
+ || (PatternHelper.matchPattern(g.getId(), route.getRouteConfigurationId())))
+ .forEach(g -> {
+ oe.addAll(g.getOnExceptions());
+ icp.addAll(g.getIntercepts());
+ ifrom.addAll(g.getInterceptFroms());
+ ito.addAll(g.getInterceptSendTos());
+ oc.addAll(g.getOnCompletions());
+ });
+ }
+ }
+
+ // must prepare the route before we can add it to the routes list
+ RouteDefinitionHelper.prepareRoute(getContext(), route, oe, icp, ifrom, ito, oc);
+
+ if (LOG.isDebugEnabled() && route.getRouteConfigurationId() != null) {
+ LOG.debug("Route: {} is using routeConfigurationsId: {}", route.getId(), route.getRouteConfigurationId());
+ }
// mark the route as prepared now
route.markPrepared();
@@ -857,6 +891,9 @@ public abstract class AbstractCamelContextFactoryBean<T extends ModelCamelContex
public abstract List<RouteTemplateDefinition> getRouteTemplates();
@Override
+ public abstract List<RouteConfigurationDefinition> getRouteConfigurations();
+
+ @Override
public abstract List<RouteDefinition> getRoutes();
@Override
diff --git a/core/camel-core/src/test/java/org/apache/camel/model/RoutesConfigurationBuilderIdOrPatternTest.java b/core/camel-core/src/test/java/org/apache/camel/model/RoutesConfigurationBuilderIdOrPatternTest.java
index ebefa1b..d79b4d0 100644
--- a/core/camel-core/src/test/java/org/apache/camel/model/RoutesConfigurationBuilderIdOrPatternTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/model/RoutesConfigurationBuilderIdOrPatternTest.java
@@ -16,6 +16,7 @@
*/
package org.apache.camel.model;
+import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@@ -28,6 +29,7 @@ import org.apache.camel.builder.RouteConfigurationBuilder;
import org.apache.camel.support.OrderedComparator;
import org.junit.jupiter.api.Test;
+import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.fail;
public class RoutesConfigurationBuilderIdOrPatternTest extends ContextTestSupport {
@@ -219,4 +221,23 @@ public class RoutesConfigurationBuilderIdOrPatternTest extends ContextTestSuppor
assertMockEndpointsSatisfied();
}
+ @Test
+ public void testRoutesConfigurationIdClash() throws Exception {
+ RouteConfigurationBuilder rcb = new RouteConfigurationBuilder() {
+ @Override
+ public void configuration() throws Exception {
+ routeConfiguration().onException(Exception.class).handled(true).to("mock:foo");
+ routeConfiguration("foo").onException(IOException.class).handled(true).to("mock:foo");
+ routeConfiguration("bar").onException(FileNotFoundException.class).handled(true).to("mock:bar");
+ routeConfiguration("foo").onException(IllegalArgumentException.class).handled(true).to("mock:foo");
+ }
+ };
+ try {
+ context.addRoutesConfigurations(rcb);
+ fail("Should throw exception");
+ } catch (IllegalArgumentException e) {
+ assertEquals("Route configuration already exists with id: foo", e.getMessage());
+ }
+ }
+
}