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 2016/03/17 11:54:49 UTC

[2/3] camel git commit: CAMEL-9720: camel-spring-boot - Make it easy to keep the JVM running

CAMEL-9720: camel-spring-boot - Make it easy to keep the JVM running


Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/28c83d58
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/28c83d58
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/28c83d58

Branch: refs/heads/master
Commit: 28c83d58db7c50be9aecbcd81b45af5004bcb304
Parents: 89218fd
Author: Claus Ibsen <da...@apache.org>
Authored: Thu Mar 17 11:15:22 2016 +0100
Committer: Claus Ibsen <da...@apache.org>
Committed: Thu Mar 17 11:54:32 2016 +0100

----------------------------------------------------------------------
 .../sample/camel/SampleCamelApplication.java    |  8 +---
 .../java/sample/camel/SampleCamelRouter.java    |  2 +-
 .../src/main/resources/application.properties   | 15 ++++++-
 .../boot/CamelConfigurationProperties.java      | 13 ++++++
 .../spring/boot/CamelMainRunController.java     | 47 ++++++++++++++++++++
 .../CamelSpringBootApplicationController.java   | 45 ++++++++++++++++---
 .../apache/camel/spring/boot/FatJarRouter.java  |  2 +-
 .../camel/spring/boot/RoutesCollector.java      | 24 +++++++---
 8 files changed, 133 insertions(+), 23 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/28c83d58/components/camel-spring-boot-starter/camel-spring-boot-sample/src/main/java/sample/camel/SampleCamelApplication.java
----------------------------------------------------------------------
diff --git a/components/camel-spring-boot-starter/camel-spring-boot-sample/src/main/java/sample/camel/SampleCamelApplication.java b/components/camel-spring-boot-starter/camel-spring-boot-sample/src/main/java/sample/camel/SampleCamelApplication.java
index fe4e4dd..8a68b69 100644
--- a/components/camel-spring-boot-starter/camel-spring-boot-sample/src/main/java/sample/camel/SampleCamelApplication.java
+++ b/components/camel-spring-boot-starter/camel-spring-boot-sample/src/main/java/sample/camel/SampleCamelApplication.java
@@ -16,19 +16,13 @@
  */
 package sample.camel;
 
-import org.apache.camel.spring.boot.CamelSpringBootApplicationController;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 import org.springframework.boot.builder.SpringApplicationBuilder;
-import org.springframework.context.ConfigurableApplicationContext;
 
 @SpringBootApplication
 public class SampleCamelApplication {
 
     public static void main(String[] args) {
-        ConfigurableApplicationContext ctx = new SpringApplicationBuilder().sources(SampleCamelApplication.class).run(args);
-
-        // keep the JVM running as Camel uses only daemon threads in the sample
-        CamelSpringBootApplicationController controller = ctx.getBean(CamelSpringBootApplicationController.class);
-        controller.blockMainThread();
+        new SpringApplicationBuilder().sources(SampleCamelApplication.class).run(args).registerShutdownHook();
     }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/28c83d58/components/camel-spring-boot-starter/camel-spring-boot-sample/src/main/java/sample/camel/SampleCamelRouter.java
----------------------------------------------------------------------
diff --git a/components/camel-spring-boot-starter/camel-spring-boot-sample/src/main/java/sample/camel/SampleCamelRouter.java b/components/camel-spring-boot-starter/camel-spring-boot-sample/src/main/java/sample/camel/SampleCamelRouter.java
index d3c2dd4..5ce9cb7 100644
--- a/components/camel-spring-boot-starter/camel-spring-boot-sample/src/main/java/sample/camel/SampleCamelRouter.java
+++ b/components/camel-spring-boot-starter/camel-spring-boot-sample/src/main/java/sample/camel/SampleCamelRouter.java
@@ -22,7 +22,7 @@ public class SampleCamelRouter extends RouteBuilder {
 
     @Override
     public void configure() throws Exception {
-        from("timer:{{timer.name}}?period={{timer.period}}")
+        from("timer:hello?period={{timer.period}}")
                 .transform(method("myBean", "saySomething"))
                 .to("stream:out");
     }

http://git-wip-us.apache.org/repos/asf/camel/blob/28c83d58/components/camel-spring-boot-starter/camel-spring-boot-sample/src/main/resources/application.properties
----------------------------------------------------------------------
diff --git a/components/camel-spring-boot-starter/camel-spring-boot-sample/src/main/resources/application.properties b/components/camel-spring-boot-starter/camel-spring-boot-sample/src/main/resources/application.properties
index eb5bdee..9270963 100644
--- a/components/camel-spring-boot-starter/camel-spring-boot-sample/src/main/resources/application.properties
+++ b/components/camel-spring-boot-starter/camel-spring-boot-sample/src/main/resources/application.properties
@@ -17,7 +17,20 @@
 
 spring.main.sources: sample.camel.SampleCamelRouter
 
+
+# the name of Camel
+camel.springboot.name = SampleCamel
+
+# we want the main thread to keep running
+camel.springboot.main-run-controller = true
+
+
+
+# properties used in the Camel route and beans
+# --------------------------------------------
+
+# what to say
 greeting = Hello World
 
-timer.name = myTimer
+# how often to trigger the timer
 timer.period = 2000

http://git-wip-us.apache.org/repos/asf/camel/blob/28c83d58/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelConfigurationProperties.java
----------------------------------------------------------------------
diff --git a/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelConfigurationProperties.java b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelConfigurationProperties.java
index c8f1793..41b90df 100644
--- a/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelConfigurationProperties.java
+++ b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelConfigurationProperties.java
@@ -60,6 +60,12 @@ public class CamelConfigurationProperties {
      */
     private String xmlRests = "classpath:camel-rest/*.xml";
 
+    /**
+     * Whether to use the main run controller to ensure the Spring-Boot application
+     * keeps running until being stopped or the JVM terminated.
+     */
+    private boolean mainRunController;
+
     // Getters & setters
 
     public boolean isJmxEnabled() {
@@ -118,4 +124,11 @@ public class CamelConfigurationProperties {
         this.xmlRests = xmlRests;
     }
 
+    public boolean isMainRunController() {
+        return mainRunController;
+    }
+
+    public void setMainRunController(boolean mainRunController) {
+        this.mainRunController = mainRunController;
+    }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/28c83d58/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelMainRunController.java
----------------------------------------------------------------------
diff --git a/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelMainRunController.java b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelMainRunController.java
new file mode 100644
index 0000000..a09ade4
--- /dev/null
+++ b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelMainRunController.java
@@ -0,0 +1,47 @@
+/**
+ * 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.CamelContext;
+import org.springframework.context.ApplicationContext;
+
+/**
+ * Controller to keep the main running and perform graceful shutdown when the JVM is stopped.
+ */
+public class CamelMainRunController {
+
+    private final CamelSpringBootApplicationController controller;
+    private final Thread daemon;
+
+    public CamelMainRunController(ApplicationContext applicationContext, CamelContext camelContext) {
+        controller = new CamelSpringBootApplicationController(applicationContext, camelContext);
+        daemon = new Thread(new DaemonTask(), "CamelMainRunController");
+    }
+
+    public void start() {
+        daemon.run();
+    }
+
+    private final class DaemonTask implements Runnable {
+
+        @Override
+        public void run() {
+            controller.run();
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/28c83d58/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelSpringBootApplicationController.java
----------------------------------------------------------------------
diff --git a/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelSpringBootApplicationController.java b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelSpringBootApplicationController.java
index abafd8a..bbca474 100644
--- a/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelSpringBootApplicationController.java
+++ b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelSpringBootApplicationController.java
@@ -18,20 +18,25 @@ package org.apache.camel.spring.boot;
 
 import java.util.Collections;
 import java.util.Map;
-
+import java.util.concurrent.CountDownLatch;
 import javax.annotation.PreDestroy;
 
 import org.apache.camel.CamelContext;
 import org.apache.camel.ProducerTemplate;
-import org.apache.camel.main.MainSupport;
+import org.apache.camel.main.Main;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.context.ApplicationContext;
 
 public class CamelSpringBootApplicationController {
 
-    private final MainSupport mainSupport;
+    private static final Logger LOG = LoggerFactory.getLogger(CamelSpringBootApplicationController.class);
+
+    private final Main main;
+    private final CountDownLatch latch = new CountDownLatch(1);
 
     public CamelSpringBootApplicationController(final ApplicationContext applicationContext, final CamelContext camelContext) {
-        this.mainSupport = new MainSupport() {
+        this.main = new Main() {
             @Override
             protected ProducerTemplate findOrCreateCamelTemplate() {
                 return applicationContext.getBean(ProducerTemplate.class);
@@ -41,20 +46,46 @@ public class CamelSpringBootApplicationController {
             protected Map<String, CamelContext> getCamelContextMap() {
                 return Collections.singletonMap("camelContext", camelContext);
             }
+
+            @Override
+            protected void doStop() throws Exception {
+                LOG.debug("Controller is shutting down CamelContext");
+                try {
+                    super.doStop();
+                } finally {
+                    latch.countDown();
+                }
+            }
         };
     }
 
-    public void blockMainThread() {
+    /**
+     * Runs the application and blocks the main thread and shutdown Camel graceful when the JVM is stopping.
+     */
+    public void run() {
+        LOG.debug("Controller is starting and waiting for Spring-Boot to stop or JVM to terminate");
         try {
-            mainSupport.run();
+            main.run();
+            // keep the daemon thread running
+            LOG.debug("Waiting for CamelContext to complete shutdown");
+            latch.await();
         } catch (Exception e) {
             throw new RuntimeException(e);
         }
+        LOG.debug("CamelContext shutdown complete.");
+    }
+
+    /**
+     * @deprecated use {@link #run()}
+     */
+    @Deprecated
+    public void blockMainThread() {
+        run();
     }
 
     @PreDestroy
     private void destroy() {
-        mainSupport.completed();
+        main.completed();
     }
 
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/28c83d58/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/FatJarRouter.java
----------------------------------------------------------------------
diff --git a/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/FatJarRouter.java b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/FatJarRouter.java
index 94458ef..f5a376c 100644
--- a/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/FatJarRouter.java
+++ b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/FatJarRouter.java
@@ -26,7 +26,7 @@ public class FatJarRouter extends RouteBuilder {
         ApplicationContext applicationContext = new SpringApplication(FatJarRouter.class).run(args);
         CamelSpringBootApplicationController applicationController =
                 applicationContext.getBean(CamelSpringBootApplicationController.class);
-        applicationController.blockMainThread();
+        applicationController.run();
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/camel/blob/28c83d58/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/RoutesCollector.java
----------------------------------------------------------------------
diff --git a/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/RoutesCollector.java b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/RoutesCollector.java
index 61b5378..6d589e5 100644
--- a/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/RoutesCollector.java
+++ b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/RoutesCollector.java
@@ -64,11 +64,13 @@ public class RoutesCollector implements ApplicationListener<ContextRefreshedEven
     // Overridden
 
     @Override
-    public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
-        ApplicationContext applicationContext = contextRefreshedEvent.getApplicationContext();
+    public void onApplicationEvent(ContextRefreshedEvent event) {
+        ApplicationContext applicationContext = event.getApplicationContext();
+
         // only listen to context refresh of "my" applicationContext
         if (this.applicationContext.equals(applicationContext)) {
-            CamelContext camelContext = contextRefreshedEvent.getApplicationContext().getBean(CamelContext.class);
+
+            CamelContext camelContext = event.getApplicationContext().getBean(CamelContext.class);
 
             // only add and start Camel if its stopped (initial state)
             if (camelContext.getStatus().isStopped()) {
@@ -100,16 +102,26 @@ public class RoutesCollector implements ApplicationListener<ContextRefreshedEven
                     }
 
                     for (CamelContextConfiguration camelContextConfiguration : camelContextConfigurations) {
-                        LOG.debug("CamelContextConfiguration found. Invoking: {}", camelContextConfiguration);
+                        LOG.debug("CamelContextConfiguration found. Invoking beforeApplicationStart: {}", camelContextConfiguration);
                         camelContextConfiguration.beforeApplicationStart(camelContext);
                     }
 
-                    camelContext.start();
+                    if (configurationProperties.isMainRunController()) {
+                        LOG.info("Starting CamelMainRunController to ensure the main thread keeps running");
+                        CamelMainRunController controller = new CamelMainRunController(applicationContext, camelContext);
+                        // controller will start Camel
+                        controller.start();
+                    } else {
+                        // start camel manually
+                        camelContext.start();
+                    }
 
                     for (CamelContextConfiguration camelContextConfiguration : camelContextConfigurations) {
+                        LOG.debug("CamelContextConfiguration found. Invoking afterApplicationStart: {}", camelContextConfiguration);
                         camelContextConfiguration.afterApplicationStart(camelContext);
                     }
 
+
                 } catch (Exception e) {
                     throw new CamelSpringBootInitializationException(e);
                 }
@@ -117,7 +129,7 @@ public class RoutesCollector implements ApplicationListener<ContextRefreshedEven
                 LOG.debug("Camel already started, not adding routes.");
             }
         } else {
-            LOG.debug("Ignore ContextRefreshedEvent: {}", contextRefreshedEvent);
+            LOG.debug("Ignore ContextRefreshedEvent: {}", event);
         }
     }