This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/camel.git
commit f08a4e6d5b08f7edce3ccf28335787acfd63907c Author: Claus Ibsen <[email protected]> AuthorDate: Thu Jun 6 11:52:01 2019 +0200 CAMEL-12868: Detect if camel on spring-boot shutdown very quickly because there is no main controller or starter-web dependency to keep the JVM alive. --- .../camel/spring/boot/CamelAutoConfiguration.java | 32 ++++++------ .../camel/spring/boot/SpringBootCamelContext.java | 57 ++++++++++++++++++++++ .../org/apache/camel/ExtendedCamelContext.java | 21 ++++++++ .../camel/impl/engine/AbstractCamelContext.java | 8 +-- 4 files changed, 93 insertions(+), 25 deletions(-) diff --git a/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelAutoConfiguration.java b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelAutoConfiguration.java index 9ee72ae..070bc68 100644 --- a/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelAutoConfiguration.java +++ b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelAutoConfiguration.java @@ -39,7 +39,6 @@ import org.apache.camel.component.properties.PropertiesParser; import org.apache.camel.health.HealthCheckRegistry; import org.apache.camel.health.HealthCheckRepository; import org.apache.camel.health.HealthCheckService; -import org.apache.camel.impl.DefaultCamelContext; import org.apache.camel.impl.FileWatcherReloadStrategy; import org.apache.camel.model.Model; import org.apache.camel.processor.interceptor.BacklogTracer; @@ -66,7 +65,6 @@ import org.apache.camel.spi.ThreadPoolProfile; import org.apache.camel.spi.UnitOfWorkFactory; import org.apache.camel.spi.UuidGenerator; import org.apache.camel.spring.CamelBeanPostProcessor; -import org.apache.camel.spring.SpringCamelContext; import org.apache.camel.spring.spi.ApplicationContextBeanRepository; import org.apache.camel.spring.spi.XmlCamelContextConfigurer; import org.apache.camel.support.DefaultRegistry; @@ -115,7 +113,7 @@ public class CamelAutoConfiguration { @ConditionalOnMissingBean(CamelContext.class) CamelContext camelContext(ApplicationContext applicationContext, CamelConfigurationProperties config) throws Exception { - CamelContext camelContext = new SpringCamelContext(applicationContext); + CamelContext camelContext = new SpringBootCamelContext(applicationContext); return doConfigureCamelContext(applicationContext, camelContext, config); } @@ -125,20 +123,18 @@ public class CamelAutoConfiguration { camelContext.init(); - if (camelContext instanceof DefaultCamelContext) { - final DefaultCamelContext defaultContext = (DefaultCamelContext) camelContext; - final Map<String, BeanRepository> repositories = applicationContext.getBeansOfType(BeanRepository.class); - - if (!repositories.isEmpty()) { - List<BeanRepository> reps = new ArrayList<>(); - // include default bean repository as well - reps.add(new ApplicationContextBeanRepository(applicationContext)); - // and then any custom - reps.addAll(repositories.values()); - // sort by ordered - OrderComparator.sort(reps); - defaultContext.setRegistry(new DefaultRegistry(reps)); - } + final Map<String, BeanRepository> repositories = applicationContext.getBeansOfType(BeanRepository.class); + + if (!repositories.isEmpty()) { + List<BeanRepository> reps = new ArrayList<>(); + // include default bean repository as well + reps.add(new ApplicationContextBeanRepository(applicationContext)); + // and then any custom + reps.addAll(repositories.values()); + // sort by ordered + OrderComparator.sort(reps); + // and plugin as new registry + camelContext.adapt(ExtendedCamelContext.class).setRegistry(new DefaultRegistry(reps)); } if (ObjectHelper.isNotEmpty(config.getFileConfigurations())) { @@ -158,7 +154,7 @@ public class CamelAutoConfiguration { } if (config.getName() != null) { - ((SpringCamelContext) camelContext).setName(config.getName()); + camelContext.adapt(ExtendedCamelContext.class).setName(config.getName()); } if (config.getShutdownTimeout() > 0) { diff --git a/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/SpringBootCamelContext.java b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/SpringBootCamelContext.java new file mode 100644 index 0000000..bbcd395 --- /dev/null +++ b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/SpringBootCamelContext.java @@ -0,0 +1,57 @@ +/* + * 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.boot; + +import org.apache.camel.spring.SpringCamelContext; +import org.apache.camel.util.StopWatch; +import org.springframework.context.ApplicationContext; + +/** + * The {@link org.apache.camel.CamelContext} created by Spring Boot. + */ +public class SpringBootCamelContext extends SpringCamelContext { + + private final StopWatch stopWatch = new StopWatch(); + + public SpringBootCamelContext(ApplicationContext applicationContext) { + super(applicationContext); + } + + @Override + protected void doStart() throws Exception { + stopWatch.restart(); + super.doStart(); + } + + @Override + protected synchronized void doStop() throws Exception { + // if we are stopping very quickly then its likely because the user may not have either spring-boot-web + // or enabled Camel's main controller, so lets log a WARN about this. + long taken = stopWatch.taken(); + if (taken < 1200) { // give it a bit of slack + String cp = System.getProperty("java.class.path"); + boolean starterWeb = cp != null && cp.contains("spring-boot-starter-web"); + boolean junit = cp != null && cp.contains("junit-"); + if (!junit && !starterWeb) { + log.warn("CamelContext has only been running for less than a second. If you intend to run Camel for a longer time " + + "then you can set the property camel.springboot.main-run-controller=true in application.properties" + + " or add spring-boot-starter-web JAR to the classpath."); + } + } + super.doStop(); + } +} diff --git a/core/camel-api/src/main/java/org/apache/camel/ExtendedCamelContext.java b/core/camel-api/src/main/java/org/apache/camel/ExtendedCamelContext.java index 1304268..450b98a 100644 --- a/core/camel-api/src/main/java/org/apache/camel/ExtendedCamelContext.java +++ b/core/camel-api/src/main/java/org/apache/camel/ExtendedCamelContext.java @@ -41,6 +41,7 @@ import org.apache.camel.spi.ModelJAXBContextFactory; import org.apache.camel.spi.NodeIdFactory; import org.apache.camel.spi.PackageScanClassResolver; import org.apache.camel.spi.ProcessorFactory; +import org.apache.camel.spi.Registry; import org.apache.camel.spi.RouteStartupOrder; import org.apache.camel.spi.UnitOfWorkFactory; @@ -51,6 +52,26 @@ import org.apache.camel.spi.UnitOfWorkFactory; public interface ExtendedCamelContext extends CamelContext { /** + * Sets the name (id) of the this context. + * <p/> + * This operation is mostly only used by different Camel runtimes such as camel-spring, camel-cdi, camel-spring-boot etc. + * Important: Setting the name should only be set before CamelContext is started. + * + * @param name the name + */ + void setName(String name); + + /** + * Sets the registry Camel should use for looking up beans by name or type. + * <p/> + * This operation is mostly only used by different Camel runtimes such as camel-spring, camel-cdi, camel-spring-boot etc. + * Important: Setting the registry should only be set before CamelContext is started. + * + * @param registry the registry such as DefaultRegistry or + */ + void setRegistry(Registry registry); + + /** * Method to signal to {@link CamelContext} that the process to initialize setup routes is in progress. * * @param done <tt>false</tt> to start the process, call again with <tt>true</tt> to signal its done. diff --git a/core/camel-base/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java b/core/camel-base/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java index dd71ffd..adc276d 100644 --- a/core/camel-base/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java +++ b/core/camel-base/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java @@ -376,14 +376,8 @@ public abstract class AbstractCamelContext extends ServiceSupport implements Ext return getNameStrategy().getName(); } - /** - * Sets the name of the this context. - * - * @param name the name - */ public void setName(String name) { - // use an explicit name strategy since an explicit name was provided to - // be used + // use an explicit name strategy since an explicit name was provided to be used setNameStrategy(new ExplicitCamelContextNameStrategy(name)); }
