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
commit 5c8713bb6cebeb53bbac8c6d1a80edcf712eab53 Author: Claus Ibsen <[email protected]> AuthorDate: Sat Dec 4 11:29:02 2021 +0100 CAMEL-17272: camel-spring-xml - Classic Spring XML add support for external route configuration XML files --- .../org/apache/camel/spring/xml/camelContext.json | 1 + .../camel/spring/xml/CamelContextFactoryBean.java | 15 ++++++ .../spring/xml/handler/CamelNamespaceHandler.java | 1 + .../SpringRoutesConfigurationExternalTest.java | 48 +++++++++++++++++ .../SpringRoutesConfigurationExternalTest.xml | 57 ++++++++++++++++++++ .../services/org/apache/camel/model.properties | 1 + .../resources/org/apache/camel/model/jaxb.index | 1 + .../camel/model/routeConfigurationContextRef.json | 16 ++++++ .../RouteConfigurationContextRefDefinition.java | 62 ++++++++++++++++++++++ ...uteConfigurationContextRefDefinitionHelper.java | 53 ++++++++++++++++++ .../core/xml/AbstractCamelContextFactoryBean.java | 19 +++++++ .../java/org/apache/camel/xml/in/ModelParser.java | 9 ++++ 12 files changed, 283 insertions(+) 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 42cb0b3..72f27e7 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 @@ -63,6 +63,7 @@ "resilience4jConfiguration": { "kind": "element", "displayName": "Resilience4j Configuration", "required": false, "type": "array", "javaType": "java.util.List<org.apache.camel.model.Resilience4jConfigurationDefinition>", "deprecated": false, "autowired": false, "secret": false, "description": "Resilience4j Circuit Breaker EIP configurations" }, "defaultFaultToleranceConfiguration": { "kind": "element", "displayName": "Default Fault Tolerance Configuration", "required": false, "type": "object", "javaType": "org.apache.camel.model.FaultToleranceConfigurationDefinition", "deprecated": false, "autowired": false, "secret": false, "description": "MicroProfile Fault Tolerance EIP default configuration" }, "faultToleranceConfiguration": { "kind": "element", "displayName": "Fault Tolerance Configuration", "required": false, "type": "array", "javaType": "java.util.List<org.apache.camel.model.FaultToleranceConfigurationDefinition>", "deprecated": false, "autowired": false, "secret": false, "description": "MicroProfile Circuit Breaker EIP configurations" }, + "routeConfigurationContextRef": { "kind": "element", "displayName": "Route Configuration Context Ref", "required": false, "type": "array", "javaType": "java.util.List<org.apache.camel.model.RouteConfigurationContextRefDefinition>", "deprecated": false, "autowired": false, "secret": false, "description": "Refers to XML route configurations to include as route configurations in this CamelContext." }, "routeTemplateContextRef": { "kind": "element", "displayName": "Route Template Context Ref", "required": false, "type": "array", "javaType": "java.util.List<org.apache.camel.model.RouteTemplateContextRefDefinition>", "deprecated": false, "autowired": false, "secret": false, "description": "Refers to XML route templates to include as route templates in this CamelContext." }, "routeBuilder": { "kind": "element", "displayName": "Route Builder", "required": false, "type": "array", "javaType": "java.util.List<org.apache.camel.model.RouteBuilderDefinition>", "deprecated": false, "autowired": false, "secret": false, "description": "Refers to Java RouteBuilder instances to include as routes in this CamelContext." }, "routeContextRef": { "kind": "element", "displayName": "Route Context Ref", "required": false, "type": "array", "javaType": "java.util.List<org.apache.camel.model.RouteContextRefDefinition>", "deprecated": false, "autowired": false, "secret": false, "description": "Refers to XML routes to include as routes in this CamelContext." }, 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 6c2bca3..cd47887 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.RouteConfigurationContextRefDefinition; import org.apache.camel.model.RouteConfigurationDefinition; import org.apache.camel.model.RouteContextRefDefinition; import org.apache.camel.model.RouteDefinition; @@ -231,6 +232,8 @@ public class CamelContextFactoryBean extends AbstractCamelContextFactoryBean<Spr private FaultToleranceConfigurationDefinition defaultFaultToleranceConfiguration; @XmlElement(name = "faultToleranceConfiguration", type = Resilience4jConfigurationDefinition.class) private List<FaultToleranceConfigurationDefinition> faultToleranceConfigurations; + @XmlElement(name = "routeConfigurationContextRef") + private List<RouteConfigurationContextRefDefinition> routeConfigurationRefs = new ArrayList<>(); @XmlElement(name = "routeTemplateContextRef") private List<RouteTemplateContextRefDefinition> routeTemplateRefs = new ArrayList<>(); @XmlElement(name = "routeBuilder") @@ -1225,6 +1228,18 @@ public class CamelContextFactoryBean extends AbstractCamelContextFactoryBean<Spr } @Override + public List<RouteConfigurationContextRefDefinition> getRouteConfigurationRefs() { + return routeConfigurationRefs; + } + + /** + * Refers to XML route configurations to include as route configurations in this CamelContext. + */ + public void setRouteConfigurationRefs(List<RouteConfigurationContextRefDefinition> routeConfigurationRefs) { + this.routeConfigurationRefs = routeConfigurationRefs; + } + + @Override public List<RouteTemplateContextRefDefinition> getRouteTemplateRefs() { return routeTemplateRefs; } 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 d525e8d..13268bd 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 @@ -434,6 +434,7 @@ public class CamelNamespaceHandler extends NamespaceHandlerSupport { builder.addPropertyValue("validators", factoryBean.getValidators()); builder.addPropertyValue("onCompletions", factoryBean.getOnCompletions()); builder.addPropertyValue("onExceptions", factoryBean.getOnExceptions()); + builder.addPropertyValue("routeConfigurationRefs", factoryBean.getRouteConfigurationRefs()); builder.addPropertyValue("routeTemplateRefs", factoryBean.getRouteTemplateRefs()); builder.addPropertyValue("builderRefs", factoryBean.getBuilderRefs()); builder.addPropertyValue("routeRefs", factoryBean.getRouteRefs()); diff --git a/components/camel-spring-xml/src/test/java/org/apache/camel/spring/SpringRoutesConfigurationExternalTest.java b/components/camel-spring-xml/src/test/java/org/apache/camel/spring/SpringRoutesConfigurationExternalTest.java new file mode 100644 index 0000000..a372b30 --- /dev/null +++ b/components/camel-spring-xml/src/test/java/org/apache/camel/spring/SpringRoutesConfigurationExternalTest.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 SpringRoutesConfigurationExternalTest extends SpringTestSupport { + + @Override + protected AbstractXmlApplicationContext createApplicationContext() { + return new ClassPathXmlApplicationContext( + "org/apache/camel/spring/SpringRoutesConfigurationExternalTest.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/SpringRoutesConfigurationExternalTest.xml b/components/camel-spring-xml/src/test/resources/org/apache/camel/spring/SpringRoutesConfigurationExternalTest.xml new file mode 100644 index 0000000..c83f58e --- /dev/null +++ b/components/camel-spring-xml/src/test/resources/org/apache/camel/spring/SpringRoutesConfigurationExternalTest.xml @@ -0,0 +1,57 @@ +<?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 + "> + + <!-- this can be in another XML file that spring imports, but for testing we keep it in the same file --> + <routeConfigurationContext id="myConf" 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> + </routeConfigurationContext> + + <camelContext xmlns="http://camel.apache.org/schema/spring"> + + <!-- refer to external snippet --> + <routeConfigurationContextRef ref="myConf"/> + + <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-model/src/generated/resources/META-INF/services/org/apache/camel/model.properties b/core/camel-core-model/src/generated/resources/META-INF/services/org/apache/camel/model.properties index 9a05154..f08ac58 100644 --- a/core/camel-core-model/src/generated/resources/META-INF/services/org/apache/camel/model.properties +++ b/core/camel-core-model/src/generated/resources/META-INF/services/org/apache/camel/model.properties @@ -138,6 +138,7 @@ roundRobin route routeBuilder routeConfiguration +routeConfigurationContextRef routeConfigurations routeContextRef routeTemplate diff --git a/core/camel-core-model/src/generated/resources/org/apache/camel/model/jaxb.index b/core/camel-core-model/src/generated/resources/org/apache/camel/model/jaxb.index index c9a58d7..d1cf5b7 100644 --- a/core/camel-core-model/src/generated/resources/org/apache/camel/model/jaxb.index +++ b/core/camel-core-model/src/generated/resources/org/apache/camel/model/jaxb.index @@ -63,6 +63,7 @@ Resilience4jConfigurationDefinition RestContextRefDefinition RollbackDefinition RouteBuilderDefinition +RouteConfigurationContextRefDefinition RouteConfigurationDefinition RouteConfigurationsDefinition RouteContextRefDefinition diff --git a/core/camel-core-model/src/generated/resources/org/apache/camel/model/routeConfigurationContextRef.json b/core/camel-core-model/src/generated/resources/org/apache/camel/model/routeConfigurationContextRef.json new file mode 100644 index 0000000..0e7b143 --- /dev/null +++ b/core/camel-core-model/src/generated/resources/org/apache/camel/model/routeConfigurationContextRef.json @@ -0,0 +1,16 @@ +{ + "model": { + "kind": "model", + "name": "routeConfigurationContextRef", + "title": "Route Configuration Context Ref", + "description": "To refer to an XML file with route configuration defined using the xml-dsl", + "deprecated": false, + "label": "configuration", + "javaType": "org.apache.camel.model.RouteConfigurationContextRefDefinition", + "input": false, + "output": false + }, + "properties": { + "ref": { "kind": "attribute", "displayName": "Ref", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Reference to the route templates in the xml dsl" } + } +} diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/RouteConfigurationContextRefDefinition.java b/core/camel-core-model/src/main/java/org/apache/camel/model/RouteConfigurationContextRefDefinition.java new file mode 100644 index 0000000..6ebabdd --- /dev/null +++ b/core/camel-core-model/src/main/java/org/apache/camel/model/RouteConfigurationContextRefDefinition.java @@ -0,0 +1,62 @@ +/* + * 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 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.XmlRootElement; + +import org.apache.camel.CamelContext; +import org.apache.camel.spi.Metadata; + +/** + * To refer to an XML file with route configuration defined using the xml-dsl + */ +@Metadata(label = "configuration") +@XmlRootElement(name = "routeConfigurationContextRef") +@XmlAccessorType(XmlAccessType.FIELD) +public class RouteConfigurationContextRefDefinition { + @XmlAttribute(required = true) + private String ref; + + public RouteConfigurationContextRefDefinition() { + } + + @Override + public String toString() { + return "RouteConfigurationContextRef[" + getRef() + "]"; + } + + public String getRef() { + return ref; + } + + /** + * Reference to the route templates in the xml dsl + */ + public void setRef(String ref) { + this.ref = ref; + } + + public List<RouteConfigurationDefinition> lookupRouteConfigurations(CamelContext camelContext) { + return RouteConfigurationContextRefDefinitionHelper.lookupRouteConfigurations(camelContext, ref); + } + +} diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/RouteConfigurationContextRefDefinitionHelper.java b/core/camel-core-model/src/main/java/org/apache/camel/model/RouteConfigurationContextRefDefinitionHelper.java new file mode 100644 index 0000000..b0d878e --- /dev/null +++ b/core/camel-core-model/src/main/java/org/apache/camel/model/RouteConfigurationContextRefDefinitionHelper.java @@ -0,0 +1,53 @@ +/* + * 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 java.util.List; + +import org.apache.camel.CamelContext; +import org.apache.camel.support.CamelContextHelper; +import org.apache.camel.util.ObjectHelper; + +/** + * Helper for {@link RouteConfigurationContextRefDefinition}. + */ +public final class RouteConfigurationContextRefDefinitionHelper { + + private RouteConfigurationContextRefDefinitionHelper() { + } + + /** + * Lookup the route configurations from the {@link RouteConfigurationContextRefDefinition}. + * + * @param camelContext the CamelContext + * @param ref the id of the {@link RouteConfigurationContextRefDefinition} to lookup and get the route + * configurations. + * @return the route configurations. + */ + @SuppressWarnings("unchecked") + public static List<RouteConfigurationDefinition> lookupRouteConfigurations(CamelContext camelContext, String ref) { + ObjectHelper.notNull(camelContext, "camelContext"); + ObjectHelper.notNull(ref, "ref"); + + List<RouteConfigurationDefinition> answer = CamelContextHelper.lookup(camelContext, ref, List.class); + if (answer == null) { + throw new IllegalArgumentException("Cannot find RouteConfigurationContext with id " + ref); + } + return answer; + } + +} 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 5cbb090..79d77b4 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 @@ -73,6 +73,7 @@ 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.RouteConfigurationContextRefDefinition; import org.apache.camel.model.RouteConfigurationDefinition; import org.apache.camel.model.RouteContainer; import org.apache.camel.model.RouteContextRefDefinition; @@ -456,6 +457,9 @@ public abstract class AbstractCamelContextFactoryBean<T extends ModelCamelContex // add route configurations getContext().addRouteConfigurations(getRouteConfigurations()); + // init route configurations + initRouteConfigurationRefs(); + // init route templates initRouteTemplateRefs(); @@ -868,6 +872,19 @@ public abstract class AbstractCamelContextFactoryBean<T extends ModelCamelContex } } + protected void initRouteConfigurationRefs() throws Exception { + // add route configuration refs to existing route configurations + if (getRouteConfigurationRefs() != null) { + for (RouteConfigurationContextRefDefinition ref : getRouteConfigurationRefs()) { + List<RouteConfigurationDefinition> defs = ref.lookupRouteConfigurations(getContext()); + for (RouteConfigurationDefinition def : defs) { + LOG.debug("Adding route configuration from {} -> {}", ref, def); + getRouteConfigurations().add(def); + } + } + } + } + protected void initRouteTemplateRefs() throws Exception { // add route template refs to existing route templates if (getRouteTemplateRefs() != null) { @@ -1013,6 +1030,8 @@ public abstract class AbstractCamelContextFactoryBean<T extends ModelCamelContex public abstract CamelRouteControllerDefinition getCamelRouteController(); + public abstract List<RouteConfigurationContextRefDefinition> getRouteConfigurationRefs(); + public abstract List<RouteBuilderDefinition> getBuilderRefs(); public abstract List<RouteContextRefDefinition> getRouteRefs(); 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 8be755e..60eb730 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 @@ -936,6 +936,15 @@ public class ModelParser extends BaseParser { return identifiedTypeAttributeHandler().accept(def, key, val); }, noElementHandler(), noValueHandler()); } + protected RouteConfigurationContextRefDefinition doParseRouteConfigurationContextRefDefinition() throws IOException, XmlPullParserException { + return doParse(new RouteConfigurationContextRefDefinition(), (def, key, val) -> { + if ("ref".equals(key)) { + def.setRef(val); + return true; + } + return false; + }, noElementHandler(), noValueHandler()); + } protected RouteConfigurationDefinition doParseRouteConfigurationDefinition() throws IOException, XmlPullParserException { return doParse(new RouteConfigurationDefinition(), optionalIdentifiedDefinitionAttributeHandler(), (def, key) -> {
