Repository: camel Updated Branches: refs/heads/master d5d659eb4 -> 1a4e34960
CAMEL-9830: camel-spring-javaconfig - Add routes like spring-boot does Project: http://git-wip-us.apache.org/repos/asf/camel/repo Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/1a4e3496 Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/1a4e3496 Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/1a4e3496 Branch: refs/heads/master Commit: 1a4e34960fb6953bb804717a728c294f27108a4f Parents: d5d659e Author: Claus Ibsen <davscl...@apache.org> Authored: Thu Apr 7 10:16:43 2016 +0200 Committer: Claus Ibsen <davscl...@apache.org> Committed: Thu Apr 7 10:16:43 2016 +0200 ---------------------------------------------------------------------- .../spring/javaconfig/CamelConfiguration.java | 18 +-- ...SpringJavaconfigInitializationException.java | 24 ++++ .../spring/javaconfig/RoutesCollector.java | 126 +++++++++++++++++++ 3 files changed, 160 insertions(+), 8 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/camel/blob/1a4e3496/components/camel-spring-javaconfig/src/main/java/org/apache/camel/spring/javaconfig/CamelConfiguration.java ---------------------------------------------------------------------- diff --git a/components/camel-spring-javaconfig/src/main/java/org/apache/camel/spring/javaconfig/CamelConfiguration.java b/components/camel-spring-javaconfig/src/main/java/org/apache/camel/spring/javaconfig/CamelConfiguration.java index 2df05da..d0cbc2b 100644 --- a/components/camel-spring-javaconfig/src/main/java/org/apache/camel/spring/javaconfig/CamelConfiguration.java +++ b/components/camel-spring-javaconfig/src/main/java/org/apache/camel/spring/javaconfig/CamelConfiguration.java @@ -25,7 +25,6 @@ import static java.util.Collections.emptyList; import org.apache.camel.CamelContext; import org.apache.camel.ConsumerTemplate; import org.apache.camel.ProducerTemplate; -import org.apache.camel.RoutesBuilder; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.spring.CamelBeanPostProcessor; import org.apache.camel.spring.SpringCamelContext; @@ -44,8 +43,7 @@ import org.springframework.context.annotation.Configuration; * A useful base class for writing * <a * href="http://docs.spring.io/spring/docs/current/spring-framework-reference/html/beans.html#beans-annotation-config"> - * Spring annotation-based</a> configurations for working with Camel. Unless {@link #routes()} method is overridden, this configuration - * automatically load all the {@link org.apache.camel.builder.RouteBuilder} instances available in the Spring context. + * Spring annotation-based</a> configurations for working with Camel. */ @Configuration public abstract class CamelConfiguration implements BeanFactoryAware, ApplicationContextAware { @@ -84,7 +82,6 @@ public abstract class CamelConfiguration implements BeanFactoryAware, Applicatio public <T> T getBean(String beanName, Class<T> type) { return beanFactory.getBean(beanName, type); } - /** * Invoke callbacks on the object, as though it were configured in the factory. If appropriate, @@ -144,6 +141,9 @@ public abstract class CamelConfiguration implements BeanFactoryAware, Applicatio return camelContext.createConsumerTemplate(); } + /** + * Camel post processor - required to support Camel annotations. + */ @Bean public CamelBeanPostProcessor camelBeanPostProcessor() throws Exception { CamelBeanPostProcessor answer = new CamelBeanPostProcessor(); @@ -158,14 +158,16 @@ public abstract class CamelConfiguration implements BeanFactoryAware, Applicatio @Bean public CamelContext camelContext() throws Exception { CamelContext camelContext = createCamelContext(); + SpringCamelContext.setNoStart(true); setupCamelContext(camelContext); - List<RouteBuilder> routes = routes(); - for (RoutesBuilder route : routes) { - camelContext.addRoutes(route); - } return camelContext; } + @Bean + RoutesCollector routesCollector(ApplicationContext applicationContext) { + return new RoutesCollector(applicationContext, this); + } + /** * Callback to setup {@link CamelContext} before its started */ http://git-wip-us.apache.org/repos/asf/camel/blob/1a4e3496/components/camel-spring-javaconfig/src/main/java/org/apache/camel/spring/javaconfig/CamelSpringJavaconfigInitializationException.java ---------------------------------------------------------------------- diff --git a/components/camel-spring-javaconfig/src/main/java/org/apache/camel/spring/javaconfig/CamelSpringJavaconfigInitializationException.java b/components/camel-spring-javaconfig/src/main/java/org/apache/camel/spring/javaconfig/CamelSpringJavaconfigInitializationException.java new file mode 100644 index 0000000..c396cc9 --- /dev/null +++ b/components/camel-spring-javaconfig/src/main/java/org/apache/camel/spring/javaconfig/CamelSpringJavaconfigInitializationException.java @@ -0,0 +1,24 @@ +/** + * 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.javaconfig; + +public class CamelSpringJavaconfigInitializationException extends RuntimeException { + + public CamelSpringJavaconfigInitializationException(Throwable cause) { + super(cause); + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/1a4e3496/components/camel-spring-javaconfig/src/main/java/org/apache/camel/spring/javaconfig/RoutesCollector.java ---------------------------------------------------------------------- diff --git a/components/camel-spring-javaconfig/src/main/java/org/apache/camel/spring/javaconfig/RoutesCollector.java b/components/camel-spring-javaconfig/src/main/java/org/apache/camel/spring/javaconfig/RoutesCollector.java new file mode 100644 index 0000000..dccf38d --- /dev/null +++ b/components/camel-spring-javaconfig/src/main/java/org/apache/camel/spring/javaconfig/RoutesCollector.java @@ -0,0 +1,126 @@ +/** + * 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.javaconfig; + +import java.io.FileNotFoundException; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.List; + +import org.apache.camel.CamelContext; +import org.apache.camel.RoutesBuilder; +import org.apache.camel.model.RouteDefinition; +import org.apache.camel.model.RoutesDefinition; +import org.apache.camel.model.rest.RestDefinition; +import org.apache.camel.model.rest.RestsDefinition; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationListener; +import org.springframework.context.event.ContextRefreshedEvent; +import org.springframework.core.io.Resource; + +/** + * Collects routes and rests from the various sources (like Spring application context beans registry or opinionated + * classpath locations) and injects these into the Camel context. + */ +public class RoutesCollector implements ApplicationListener<ContextRefreshedEvent> { + + // Static collaborators + + private static final Logger LOG = LoggerFactory.getLogger(RoutesCollector.class); + + // Collaborators + + private final ApplicationContext applicationContext; + private final CamelConfiguration configuration; + + // Constructors + + public RoutesCollector(ApplicationContext applicationContext, CamelConfiguration configuration) { + this.applicationContext = applicationContext; + this.configuration = configuration; + } + + // Overridden + + @Override + public void onApplicationEvent(ContextRefreshedEvent event) { + ApplicationContext applicationContext = event.getApplicationContext(); + + // only listen to context refresh of "my" applicationContext + if (this.applicationContext.equals(applicationContext)) { + + CamelContext camelContext = event.getApplicationContext().getBean(CamelContext.class); + + // only add and start Camel if its stopped (initial state) + if (camelContext.getStatus().isStopped()) { + LOG.debug("Post-processing CamelContext bean: {}", camelContext.getName()); + for (RoutesBuilder routesBuilder : configuration.routes()) { + // filter out abstract classes + boolean abs = Modifier.isAbstract(routesBuilder.getClass().getModifiers()); + if (!abs) { + try { + LOG.debug("Injecting following route into the CamelContext: {}", routesBuilder); + camelContext.addRoutes(routesBuilder); + } catch (Exception e) { + throw new CamelSpringJavaconfigInitializationException(e); + } + } + } + } + } else { + LOG.debug("Ignore ContextRefreshedEvent: {}", event); + } + } + + // Helpers + + private void loadXmlRoutes(ApplicationContext applicationContext, CamelContext camelContext, String directory) throws Exception { + LOG.info("Loading additional Camel XML routes from: {}", directory); + try { + Resource[] xmlRoutes = applicationContext.getResources(directory); + for (Resource xmlRoute : xmlRoutes) { + LOG.debug("Found XML route: {}", xmlRoute); + RoutesDefinition xmlDefinition = camelContext.loadRoutesDefinition(xmlRoute.getInputStream()); + camelContext.addRouteDefinitions(xmlDefinition.getRoutes()); + } + } catch (FileNotFoundException e) { + LOG.debug("No XML routes found in {}. Skipping XML routes detection.", directory); + } + } + + private void loadXmlRests(ApplicationContext applicationContext, CamelContext camelContext, String directory) { + LOG.info("Loading additional Camel XML rests from: {}", directory); + try { + final Resource[] xmlRests = applicationContext.getResources(directory); + for (final Resource xmlRest : xmlRests) { + final RestsDefinition xmlDefinitions = camelContext.loadRestsDefinition(xmlRest.getInputStream()); + camelContext.addRestDefinitions(xmlDefinitions.getRests()); + for (final RestDefinition xmlDefinition : xmlDefinitions.getRests()) { + final List<RouteDefinition> routeDefinitions = xmlDefinition.asRouteDefinition(camelContext); + camelContext.addRouteDefinitions(routeDefinitions); + } + } + } catch (FileNotFoundException e) { + LOG.debug("No XML rests found in {}. Skipping XML rests detection.", directory); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + +}