camel-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From davscl...@apache.org
Subject [1/8] camel git commit: CAMEL-10599: Add ReloadStrategy to allow watching for file changes and reload routes on the fly.
Date Mon, 19 Dec 2016 15:35:13 GMT
Repository: camel
Updated Branches:
  refs/heads/master ec735be05 -> 82dbe00cf


CAMEL-10599: Add ReloadStrategy to allow watching for file changes and reload routes on the
fly.


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

Branch: refs/heads/master
Commit: 82dbe00cf9a939faf9c94714863e3ba275b9d1ad
Parents: 76218fb
Author: Claus Ibsen <davsclaus@apache.org>
Authored: Mon Dec 19 16:12:31 2016 +0100
Committer: Claus Ibsen <davsclaus@apache.org>
Committed: Mon Dec 19 16:34:46 2016 +0100

----------------------------------------------------------------------
 .../mbean/ManagedReloadStrategyMBean.java       | 39 -----------
 .../camel/impl/FileWatcherReloadStrategy.java   | 43 ++++++++++--
 .../DefaultManagementLifecycleStrategy.java     |  4 --
 .../management/mbean/ManagedReloadStrategy.java | 72 --------------------
 .../org/apache/camel/spi/ReloadStrategy.java    |  6 +-
 .../camel/support/ReloadStrategySupport.java    | 15 ++--
 .../ManagedFileWatcherReloadStrategyTest.java   | 11 ++-
 examples/README.md                              |  1 +
 .../src/main/docs/camel-maven-plugin.adoc       | 24 +++++--
 9 files changed, 77 insertions(+), 138 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/82dbe00c/camel-core/src/main/java/org/apache/camel/api/management/mbean/ManagedReloadStrategyMBean.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/api/management/mbean/ManagedReloadStrategyMBean.java
b/camel-core/src/main/java/org/apache/camel/api/management/mbean/ManagedReloadStrategyMBean.java
deleted file mode 100644
index dc13f27..0000000
--- a/camel-core/src/main/java/org/apache/camel/api/management/mbean/ManagedReloadStrategyMBean.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/**
- * 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.api.management.mbean;
-
-import org.apache.camel.api.management.ManagedAttribute;
-import org.apache.camel.api.management.ManagedOperation;
-
-public interface ManagedReloadStrategyMBean extends ManagedServiceMBean {
-
-    @ManagedOperation(description = "Force reload of CamelContext")
-    void forceReloadCamelContext();
-
-    @ManagedAttribute(description = "Strategy")
-    String getStrategy();
-
-    @ManagedAttribute(description = "Number of reloads succeeded")
-    int getReloadCounter();
-
-    @ManagedAttribute(description = "Number of reloads failed")
-    int getFailedCounter();
-
-    @ManagedOperation(description = "Reset counters")
-    void resetCounters();
-
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/82dbe00c/camel-core/src/main/java/org/apache/camel/impl/FileWatcherReloadStrategy.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/impl/FileWatcherReloadStrategy.java
b/camel-core/src/main/java/org/apache/camel/impl/FileWatcherReloadStrategy.java
index 20573b7..6c2a321 100644
--- a/camel-core/src/main/java/org/apache/camel/impl/FileWatcherReloadStrategy.java
+++ b/camel-core/src/main/java/org/apache/camel/impl/FileWatcherReloadStrategy.java
@@ -27,13 +27,15 @@ import java.util.Locale;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.TimeUnit;
 
+import static java.nio.file.StandardWatchEventKinds.ENTRY_CREATE;
+import static java.nio.file.StandardWatchEventKinds.ENTRY_MODIFY;
+
+import org.apache.camel.api.management.ManagedAttribute;
+import org.apache.camel.api.management.ManagedResource;
 import org.apache.camel.support.ReloadStrategySupport;
 import org.apache.camel.util.IOHelper;
 import org.apache.camel.util.ObjectHelper;
 
-import static java.nio.file.StandardWatchEventKinds.ENTRY_CREATE;
-import static java.nio.file.StandardWatchEventKinds.ENTRY_MODIFY;
-
 /**
  * A file based {@link org.apache.camel.spi.ReloadStrategy} which watches a file folder
  * for modified files and reload on file changes.
@@ -43,10 +45,12 @@ import static java.nio.file.StandardWatchEventKinds.ENTRY_MODIFY;
  * native file system changes and therefore the watch service is much slower than on
  * linux or windows systems.
  */
+@ManagedResource(description = "Managed FileWatcherReloadStrategy")
 public class FileWatcherReloadStrategy extends ReloadStrategySupport {
 
     private String folder;
     private ExecutorService executorService;
+    private WatchFileChangesTask task;
 
     public FileWatcherReloadStrategy() {
     }
@@ -55,11 +59,20 @@ public class FileWatcherReloadStrategy extends ReloadStrategySupport {
         setFolder(directory);
     }
 
-
     public void setFolder(String folder) {
         this.folder = folder;
     }
 
+    @ManagedAttribute(description = "Folder being watched")
+    public String getFolder() {
+        return folder;
+    }
+
+    @ManagedAttribute(description = "Whether the watcher is running")
+    public boolean isRunning() {
+        return task != null && task.isRunning();
+    }
+
     @Override
     protected void doStart() throws Exception {
         if (folder == null) {
@@ -70,14 +83,23 @@ public class FileWatcherReloadStrategy extends ReloadStrategySupport {
         File dir = new File(folder);
         if (dir.exists() && dir.isDirectory()) {
             log.info("Starting ReloadStrategy to watch directory: {}", dir);
+
+            // if its mac OSX then warn its slower
+            String os = ObjectHelper.getSystemProperty("os.name", "");
+            if (os.toLowerCase(Locale.US).startsWith("mac")) {
+                log.warn("On Mac OS X the JDK WatchService is slow and it may take up till
5 seconds to notice file changes");
+            }
+
             try {
                 Path path = dir.toPath();
                 WatchService watcher = path.getFileSystem().newWatchService();
                 // we cannot support deleting files as we don't know which routes that would
be
                 path.register(watcher, ENTRY_CREATE, ENTRY_MODIFY);
 
+                task = new WatchFileChangesTask(watcher, path);
+
                 executorService = getCamelContext().getExecutorServiceManager().newSingleThreadExecutor(this,
"FileWatcherReloadStrategy");
-                executorService.submit(new WatchFileChangesTask(watcher, path));
+                executorService.submit(task);
             } catch (IOException e) {
                 throw ObjectHelper.wrapRuntimeCamelException(e);
             }
@@ -100,17 +122,24 @@ public class FileWatcherReloadStrategy extends ReloadStrategySupport
{
 
         private final WatchService watcher;
         private final Path folder;
+        private volatile boolean running;
 
         public WatchFileChangesTask(WatchService watcher, Path folder) {
             this.watcher = watcher;
             this.folder = folder;
         }
 
+        public boolean isRunning() {
+            return running;
+        }
+
         public void run() {
             log.debug("ReloadStrategy is starting watching folder: {}", folder);
 
             // allow to run while starting Camel
             while (isStarting() || isRunAllowed()) {
+                running = true;
+
                 WatchKey key;
                 try {
                     log.trace("ReloadStrategy is polling for file changes in directory: {}",
folder);
@@ -132,7 +161,7 @@ public class FileWatcherReloadStrategy extends ReloadStrategySupport {
                             log.debug("Modified/Created XML file: {}", name);
                             try {
                                 FileInputStream fis = new FileInputStream(name);
-                                onReloadRoutes(getCamelContext(), name, fis);
+                                onReloadXml(getCamelContext(), name, fis);
                                 IOHelper.close(fis);
                             } catch (Exception e) {
                                 log.warn("Error reloading routes from file: " + name + "
due " + e.getMessage() + ". This exception is ignored.", e);
@@ -148,6 +177,8 @@ public class FileWatcherReloadStrategy extends ReloadStrategySupport {
                 }
             }
 
+            running = false;
+
             log.info("ReloadStrategy is stopping watching folder: {}", folder);
         }
     }

http://git-wip-us.apache.org/repos/asf/camel/blob/82dbe00c/camel-core/src/main/java/org/apache/camel/management/DefaultManagementLifecycleStrategy.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/management/DefaultManagementLifecycleStrategy.java
b/camel-core/src/main/java/org/apache/camel/management/DefaultManagementLifecycleStrategy.java
index 1df3a7e..34c8d5e 100644
--- a/camel-core/src/main/java/org/apache/camel/management/DefaultManagementLifecycleStrategy.java
+++ b/camel-core/src/main/java/org/apache/camel/management/DefaultManagementLifecycleStrategy.java
@@ -61,7 +61,6 @@ import org.apache.camel.management.mbean.ManagedEndpoint;
 import org.apache.camel.management.mbean.ManagedEndpointRegistry;
 import org.apache.camel.management.mbean.ManagedInflightRepository;
 import org.apache.camel.management.mbean.ManagedProducerCache;
-import org.apache.camel.management.mbean.ManagedReloadStrategy;
 import org.apache.camel.management.mbean.ManagedRestRegistry;
 import org.apache.camel.management.mbean.ManagedRoute;
 import org.apache.camel.management.mbean.ManagedRuntimeEndpointRegistry;
@@ -92,7 +91,6 @@ import org.apache.camel.spi.ManagementAware;
 import org.apache.camel.spi.ManagementNameStrategy;
 import org.apache.camel.spi.ManagementObjectStrategy;
 import org.apache.camel.spi.ManagementStrategy;
-import org.apache.camel.spi.ReloadStrategy;
 import org.apache.camel.spi.RestRegistry;
 import org.apache.camel.spi.RouteContext;
 import org.apache.camel.spi.RuntimeEndpointRegistry;
@@ -489,8 +487,6 @@ public class DefaultManagementLifecycleStrategy extends ServiceSupport
implement
             answer = new ManagedStreamCachingStrategy(context, (StreamCachingStrategy) service);
         } else if (service instanceof EventNotifier) {
             answer = getManagementObjectStrategy().getManagedObjectForEventNotifier(context,
(EventNotifier) service);
-        } else if (service instanceof ReloadStrategy) {
-            answer = new ManagedReloadStrategy(context, (ReloadStrategy) service);
         } else if (service != null) {
             // fallback as generic service
             answer = getManagementObjectStrategy().getManagedObjectForService(context, service);

http://git-wip-us.apache.org/repos/asf/camel/blob/82dbe00c/camel-core/src/main/java/org/apache/camel/management/mbean/ManagedReloadStrategy.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/management/mbean/ManagedReloadStrategy.java
b/camel-core/src/main/java/org/apache/camel/management/mbean/ManagedReloadStrategy.java
deleted file mode 100644
index 616ff5d..0000000
--- a/camel-core/src/main/java/org/apache/camel/management/mbean/ManagedReloadStrategy.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/**
- * 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.management.mbean;
-
-import org.apache.camel.CamelContext;
-import org.apache.camel.api.management.ManagedResource;
-import org.apache.camel.api.management.mbean.ManagedReloadStrategyMBean;
-import org.apache.camel.spi.ManagementStrategy;
-import org.apache.camel.spi.ReloadStrategy;
-
-/**
- * @version 
- */
-@ManagedResource(description = "Managed ReloadStrategy")
-public class ManagedReloadStrategy extends ManagedService implements ManagedReloadStrategyMBean
{
-
-    private final CamelContext camelContext;
-    private final ReloadStrategy reloadStrategy;
-
-    public ManagedReloadStrategy(CamelContext camelContext, ReloadStrategy reloadStrategy)
{
-        super(camelContext, reloadStrategy);
-        this.camelContext = camelContext;
-        this.reloadStrategy = reloadStrategy;
-    }
-
-    public CamelContext getCamelContext() {
-        return camelContext;
-    }
-
-    public ReloadStrategy getReloadStrategy() {
-        return reloadStrategy;
-    }
-
-    @Override
-    public void forceReloadCamelContext() {
-        reloadStrategy.onReloadCamelContext(getContext());
-    }
-
-    @Override
-    public String getStrategy() {
-        return reloadStrategy.getClass().getSimpleName();
-    }
-
-    @Override
-    public int getReloadCounter() {
-        return reloadStrategy.getReloadCounter();
-    }
-
-    @Override
-    public int getFailedCounter() {
-        return reloadStrategy.getFailedCounter();
-    }
-
-    @Override
-    public void resetCounters() {
-        reloadStrategy.resetCounters();
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/82dbe00c/camel-core/src/main/java/org/apache/camel/spi/ReloadStrategy.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/spi/ReloadStrategy.java b/camel-core/src/main/java/org/apache/camel/spi/ReloadStrategy.java
index 0385301..9469adb 100644
--- a/camel-core/src/main/java/org/apache/camel/spi/ReloadStrategy.java
+++ b/camel-core/src/main/java/org/apache/camel/spi/ReloadStrategy.java
@@ -28,8 +28,6 @@ import org.apache.camel.StaticService;
  */
 public interface ReloadStrategy extends Service, StaticService, CamelContextAware {
 
-    // TODO: naming of this SPI?
-
     /**
      * A reload is triggered and the {@link CamelContext} is expected to do a re-start
      *
@@ -38,13 +36,13 @@ public interface ReloadStrategy extends Service, StaticService, CamelContextAwar
     void onReloadCamelContext(CamelContext camelContext);
 
     /**
-     * A reload is triggered with a resource of some sort has been changed, such as a xml
file with Camel routes.
+     * A reload is triggered when a XML resource is changed which contains Camel routes or
rest services
      *
      * @param camelContext  the running CamelContext
      * @param name          name of resource such as a file name (can be null)
      * @param resource      the changed resource
      */
-    void onReloadRoutes(CamelContext camelContext, String name, InputStream resource);
+    void onReloadXml(CamelContext camelContext, String name, InputStream resource);
 
     /**
      * Number of reloads succeeded.

http://git-wip-us.apache.org/repos/asf/camel/blob/82dbe00c/camel-core/src/main/java/org/apache/camel/support/ReloadStrategySupport.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/support/ReloadStrategySupport.java
b/camel-core/src/main/java/org/apache/camel/support/ReloadStrategySupport.java
index a2b1ec0..6ae317e 100644
--- a/camel-core/src/main/java/org/apache/camel/support/ReloadStrategySupport.java
+++ b/camel-core/src/main/java/org/apache/camel/support/ReloadStrategySupport.java
@@ -23,6 +23,8 @@ import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
 
 import org.apache.camel.CamelContext;
+import org.apache.camel.api.management.ManagedAttribute;
+import org.apache.camel.api.management.ManagedOperation;
 import org.apache.camel.model.ModelHelper;
 import org.apache.camel.model.RoutesDefinition;
 import org.apache.camel.spi.ReloadStrategy;
@@ -67,8 +69,8 @@ public abstract class ReloadStrategySupport extends ServiceSupport implements
Re
     }
 
     @Override
-    public void onReloadRoutes(CamelContext camelContext, String name, InputStream resource)
{
-        log.debug("Reloading CamelContext: {} routes from resource: {}", camelContext.getName(),
name);
+    public void onReloadXml(CamelContext camelContext, String name, InputStream resource)
{
+        log.debug("Reloading CamelContext: {} from XML resource: {}", camelContext.getName(),
name);
 
         Document dom = camelContext.getTypeConverter().tryConvertTo(Document.class, resource);
         if (dom == null) {
@@ -94,25 +96,24 @@ public abstract class ReloadStrategySupport extends ServiceSupport implements
Re
                     failed++;
                     throw ObjectHelper.wrapRuntimeCamelException(e);
                 }
-
             }
         }
 
-        log.info("Reloaded CamelContext: {} routes from resource: {}", camelContext.getName(),
name);
+        log.info("Reloaded CamelContext: {} from XML resource: {}", camelContext.getName(),
name);
         succeeded++;
     }
 
-    @Override
+    @ManagedAttribute(description = "Number of reloads succeeded")
     public int getReloadCounter() {
         return succeeded;
     }
 
-    @Override
+    @ManagedAttribute(description = "Number of reloads failed")
     public int getFailedCounter() {
         return failed;
     }
 
-    @Override
+    @ManagedOperation(description = "Reset counters")
     public void resetCounters() {
         succeeded = 0;
         failed = 0;

http://git-wip-us.apache.org/repos/asf/camel/blob/82dbe00c/camel-core/src/test/java/org/apache/camel/management/ManagedFileWatcherReloadStrategyTest.java
----------------------------------------------------------------------
diff --git a/camel-core/src/test/java/org/apache/camel/management/ManagedFileWatcherReloadStrategyTest.java
b/camel-core/src/test/java/org/apache/camel/management/ManagedFileWatcherReloadStrategyTest.java
index 76e7aa5..136ccd04 100644
--- a/camel-core/src/test/java/org/apache/camel/management/ManagedFileWatcherReloadStrategyTest.java
+++ b/camel-core/src/test/java/org/apache/camel/management/ManagedFileWatcherReloadStrategyTest.java
@@ -38,8 +38,11 @@ public class ManagedFileWatcherReloadStrategyTest extends ManagementTestSupport
         ObjectName on = ObjectName.getInstance("org.apache.camel:context=camel-1,type=services,name=FileWatcherReloadStrategy");
         assertTrue(mbeanServer.isRegistered(on));
 
-        String strategy = (String) mbeanServer.getAttribute(on, "Strategy");
-        assertEquals("FileWatcherReloadStrategy", strategy);
+        String folder = (String) mbeanServer.getAttribute(on, "Folder");
+        assertEquals("target/dummy", folder);
+
+        Boolean running = (Boolean) mbeanServer.getAttribute(on, "Running");
+        assertTrue(running);
 
         Integer reload = (Integer) mbeanServer.getAttribute(on, "ReloadCounter");
         assertEquals(0, reload.intValue());
@@ -53,6 +56,10 @@ public class ManagedFileWatcherReloadStrategyTest extends ManagementTestSupport
         return new RouteBuilder() {
             @Override
             public void configure() throws Exception {
+                // directory must exists for the watcher to be able to run
+                deleteDirectory("target/dummy");
+                createDirectory("target/dummy");
+
                 // add reload strategy
                 context.setReloadStrategy(new FileWatcherReloadStrategy("target/dummy"));
 

http://git-wip-us.apache.org/repos/asf/camel/blob/82dbe00c/examples/README.md
----------------------------------------------------------------------
diff --git a/examples/README.md b/examples/README.md
index 1e3d97d..53815db 100644
--- a/examples/README.md
+++ b/examples/README.md
@@ -19,6 +19,7 @@ All examples have been sort by type/category
 * [camel-example-console](camel-example-console/README.md)
 * [camel-example-jmx](camel-example-jmx/README.md)
 * [camel-example-ftp](camel-example-ftp/README.md)
+* [camel-example-reload](camel-example-reload/Readme.md)
 * [camel-example-ssh](camel-example-ssh/README.md)
 * [camel-example-ssh-security](camel-example-ssh-security/README.md)
 

http://git-wip-us.apache.org/repos/asf/camel/blob/82dbe00c/tooling/maven/camel-maven-plugin/src/main/docs/camel-maven-plugin.adoc
----------------------------------------------------------------------
diff --git a/tooling/maven/camel-maven-plugin/src/main/docs/camel-maven-plugin.adoc b/tooling/maven/camel-maven-plugin/src/main/docs/camel-maven-plugin.adoc
index a9ceb21..01787e4 100644
--- a/tooling/maven/camel-maven-plugin/src/main/docs/camel-maven-plugin.adoc
+++ b/tooling/maven/camel-maven-plugin/src/main/docs/camel-maven-plugin.adoc
@@ -21,7 +21,7 @@ then boot up a Spring ApplicationContext using the XML configuration files
on th
 
 If you want to boot up your Camel routes a little faster, you could try the `camel:embedded`
instead.
 
-== Running OSGi Blueprint
+=== Running OSGi Blueprint
 
 The `camel:run` plugin also supports running a Blueprint application, and by default it scans
for OSGi blueprint files in
 `OSGI-INF/blueprint/*.xml`
@@ -67,8 +67,7 @@ loading the persistence properties file.
 
 The `configAdminFileName` is the file name which will be used to load the configuration admin
service properties file.
 
-
-== Running CDI
+=== Running CDI
 
 The `camel:run` plugin also supports running a CDI application
 
@@ -80,7 +79,7 @@ From the source of Camel you can run a CDI example via
     cd examples/camel-example-cdi
     mvn compile camel:run
 
-== Logging the classpath
+=== Logging the classpath
 
 You can configure whether the classpath should be logged when `camel:run` executes.
 You can enable this in the configuration using:
@@ -93,6 +92,23 @@ You can enable this in the configuration using:
       </configuration>
     </plugin>
 
+=== Using live reload of XML files
+
+You can configure the plugin to scan for XML file changes and trigger a reload of the Camel
routes which are contained in those XML files.
+
+    <plugin>
+      <groupId>org.apache.camel</groupId>
+      <artifactId>camel-maven-plugin</artifactId>
+      <configuration>
+        <fileWatcherDirectory>src/main/resources/META-INF/spring</fileWatcherDirectory>
+      </configuration>
+    </plugin>
+
+Then the plugin watches this directory. This allows you to edit the source code from your
editor and save the file, and have
+    the running Camel application pickup those changes.
+
+Notice its only changes of Camel routes, eg `<routes>`, or `<route>` which is
supported.
+You cannot change Spring or OSGi Blueprint `<bean>` elements.
 
 == camel:validate
 


Mime
View raw message