Author: davsclaus
Date: Fri Mar 12 15:27:40 2010
New Revision: 922296

URL: http://svn.apache.org/viewvc?rev=922296&view=rev
Log:
CAMEL-1588: Added ShutdownableService to have both stop/shutdown state. So you 
can do different work.

Added:
    
camel/trunk/camel-core/src/main/java/org/apache/camel/ShutdownableService.java
      - copied, changed from r922137, 
camel/trunk/camel-core/src/main/java/org/apache/camel/SuspendableService.java
    
camel/trunk/camel-core/src/test/java/org/apache/camel/processor/aggregator/AggregateShutdownThreadPoolTest.java
      - copied, changed from r922137, 
camel/trunk/camel-core/src/test/java/org/apache/camel/processor/aggregator/AggregateSimpleSizeTest.java
Modified:
    camel/trunk/camel-core/src/main/java/org/apache/camel/CamelContext.java
    camel/trunk/camel-core/src/main/java/org/apache/camel/ServiceStatus.java
    
camel/trunk/camel-core/src/main/java/org/apache/camel/component/seda/SedaConsumer.java
    
camel/trunk/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
    camel/trunk/camel-core/src/main/java/org/apache/camel/impl/RouteService.java
    
camel/trunk/camel-core/src/main/java/org/apache/camel/impl/ServiceSupport.java
    
camel/trunk/camel-core/src/main/java/org/apache/camel/processor/MulticastProcessor.java
    
camel/trunk/camel-core/src/main/java/org/apache/camel/processor/OnCompletionProcessor.java
    
camel/trunk/camel-core/src/main/java/org/apache/camel/processor/SendAsyncProcessor.java
    
camel/trunk/camel-core/src/main/java/org/apache/camel/processor/ThreadsProcessor.java
    
camel/trunk/camel-core/src/main/java/org/apache/camel/processor/WireTapProcessor.java
    
camel/trunk/camel-core/src/main/java/org/apache/camel/processor/aggregate/AggregateProcessor.java
    
camel/trunk/camel-core/src/main/java/org/apache/camel/util/ServiceHelper.java
    
camel/trunk/camel-core/src/test/java/org/apache/camel/impl/ServiceSupportTest.java

Modified: 
camel/trunk/camel-core/src/main/java/org/apache/camel/CamelContext.java
URL: 
http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/CamelContext.java?rev=922296&r1=922295&r2=922296&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/CamelContext.java 
(original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/CamelContext.java Fri 
Mar 12 15:27:40 2010
@@ -67,6 +67,13 @@ public interface CamelContext extends Se
      */
     String getVersion();
 
+    /**
+     * Get the status of this context
+     *
+     * @return the status
+     */
+    ServiceStatus getStatus();
+
     // Service Methods
     //-----------------------------------------------------------------------
 

Modified: 
camel/trunk/camel-core/src/main/java/org/apache/camel/ServiceStatus.java
URL: 
http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/ServiceStatus.java?rev=922296&r1=922295&r2=922296&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/ServiceStatus.java 
(original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/ServiceStatus.java 
Fri Mar 12 15:27:40 2010
@@ -19,7 +19,7 @@ package org.apache.camel;
 import java.io.Serializable;
 
 /**
- * Reresents the status of a {...@link Service} instance
+ * Represents the status of a {...@link Service} instance
  *
  * @version $Revision$
  */

Copied: 
camel/trunk/camel-core/src/main/java/org/apache/camel/ShutdownableService.java 
(from r922137, 
camel/trunk/camel-core/src/main/java/org/apache/camel/SuspendableService.java)
URL: 
http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/ShutdownableService.java?p2=camel/trunk/camel-core/src/main/java/org/apache/camel/ShutdownableService.java&p1=camel/trunk/camel-core/src/main/java/org/apache/camel/SuspendableService.java&r1=922137&r2=922296&rev=922296&view=diff
==============================================================================
--- 
camel/trunk/camel-core/src/main/java/org/apache/camel/SuspendableService.java 
(original)
+++ 
camel/trunk/camel-core/src/main/java/org/apache/camel/ShutdownableService.java 
Fri Mar 12 15:27:40 2010
@@ -17,32 +17,22 @@
 package org.apache.camel;
 
 /**
- * A {...@link Service} which is also capable of suspending and resuming.
+ * A {...@link org.apache.camel.Service} which is also capable of shutting 
down.
  * <p/>
- * This is useable for services which needs more fine grained control at 
runtime supporting suspension.
- * Other services may select to mimic suspending by just stopping the service.
+ * This is useable for services which needs more fine grained control when 
{...@link CamelContext} is shutting down.
+ * Then its possible to have different behavior when stopping or shutting down.
  * <p/>
- * For example this is use by the JmsConsumer which suspends the Spring JMS 
listener instead of stopping
- * the consumer totally.
+ * For example to shutdown thread pools on shutdown and <b>not</b> on stop.
  *
  * @version $Revision$
  */
-public interface SuspendableService extends Service {
+public interface ShutdownableService extends Service {
 
     /**
-     * Suspends the service.
-     */
-    void suspend();
-
-    /**
-     * Resumes the service.
-     */
-    void resume();
-
-    /**
-     * Tests whether the service is suspended or not.
+     * Shutdown the service, which means it cannot be started again.
      *
-     * @return <tt>true</tt> if suspended
+     * @throws Exception is thrown if shutting down failed
      */
-    boolean isSuspended();
-}
+    void shutdown() throws Exception;
+
+}
\ No newline at end of file

Modified: 
camel/trunk/camel-core/src/main/java/org/apache/camel/component/seda/SedaConsumer.java
URL: 
http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/component/seda/SedaConsumer.java?rev=922296&r1=922295&r2=922296&view=diff
==============================================================================
--- 
camel/trunk/camel-core/src/main/java/org/apache/camel/component/seda/SedaConsumer.java
 (original)
+++ 
camel/trunk/camel-core/src/main/java/org/apache/camel/component/seda/SedaConsumer.java
 Fri Mar 12 15:27:40 2010
@@ -189,6 +189,7 @@ public class SedaConsumer extends Servic
 
     protected void doStop() throws Exception {
         endpoint.onStopped(this);
+        // must shutdown executor on stop to avoid overhead of having them 
running
         executor.shutdownNow();
         executor = null;
 

Modified: 
camel/trunk/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
URL: 
http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java?rev=922296&r1=922295&r2=922296&view=diff
==============================================================================
--- 
camel/trunk/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
 (original)
+++ 
camel/trunk/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
 Fri Mar 12 15:27:40 2010
@@ -1172,34 +1172,34 @@ public class DefaultCamelContext extends
     }
 
     protected synchronized void doStop() throws Exception {
-        LOG.info("Apache Camel " + getVersion() + " (CamelContext:" + 
getName() + ") is stopping");
+        LOG.info("Apache Camel " + getVersion() + " (CamelContext:" + 
getName() + ") is shutting down");
         EventHelper.notifyCamelContextStopping(this);
 
         // stop route inputs in the same order as they was started so we stop 
the very first inputs first
         shutdownStrategy.shutdown(this, getRouteStartupOrder());
         getRouteStartupOrder().clear();
 
-        stopServices(routeServices.values());
+        shutdownServices(routeServices.values());
         // do not clear route services as we can start Camel again and get the 
route back as before
 
         // the stop order is important
 
-        stopServices(servicesToClose);
+        shutdownServices(servicesToClose);
         servicesToClose.clear();
 
-        stopServices(endpoints.values());
+        shutdownServices(endpoints.values());
         endpoints.clear();
 
-        stopServices(components.values());
+        shutdownServices(components.values());
         components.clear();
 
         // special shutdown of a shared producer service pool as it should 
only be shutdown by camel context
         if (producerServicePool instanceof SharedProducerServicePool) {
             ((SharedProducerServicePool) producerServicePool).shutdown(this);
         } else {
-            stopServices(producerServicePool);
+            shutdownServices(producerServicePool);
         }
-        stopServices(inflightRepository);
+        shutdownServices(inflightRepository);
 
         try {
             for (LifecycleStrategy strategy : lifecycleStrategies) {
@@ -1212,10 +1212,10 @@ public class DefaultCamelContext extends
         // must notify that we are stopped before stopping the management 
strategy
         EventHelper.notifyCamelContextStopped(this);
 
-        // stop management as the last one
-        stopServices(getManagementStrategy());
+        // shutdown management as the last one
+        shutdownServices(getManagementStrategy());
 
-        LOG.info("Apache Camel " + getVersion() + " (CamelContext:" + 
getName() + ") stopped");
+        LOG.info("Apache Camel " + getVersion() + " (CamelContext:" + 
getName() + ") shutdown");
     }
 
     private void stopServices(Object service) throws Exception {
@@ -1229,12 +1229,23 @@ public class DefaultCamelContext extends
         }
     }
 
-    private void stopServices(Collection<?> services) throws Exception {
+    private void shutdownServices(Object service) throws Exception {
+        // allow us to do custom work before delegating to service helper
+        try {
+            ServiceHelper.stopAndShutdownService(service);
+        } catch (Exception e) {
+            LOG.warn("Error occurred while shutting down service: " + service 
+ ". This exception will be ignored.");
+            // fire event
+            EventHelper.notifyServiceStopFailure(this, service, e);
+        }
+    }
+
+    private void shutdownServices(Collection<?> services) throws Exception {
         // reverse stopping by default
-        stopServices(services, true);
+        shutdownServices(services, true);
     }
 
-    private void stopServices(Collection<?> services, boolean reverse) throws 
Exception {
+    private void shutdownServices(Collection<?> services, boolean reverse) 
throws Exception {
         Collection<Object> list = CastUtils.cast(services);
         if (reverse) {
             ArrayList<Object> reverseList = new ArrayList<Object>(services);
@@ -1243,7 +1254,7 @@ public class DefaultCamelContext extends
         }
 
         for (Object service : list) {
-            stopServices(service);
+            shutdownServices(service);
         }
     }
 

Modified: 
camel/trunk/camel-core/src/main/java/org/apache/camel/impl/RouteService.java
URL: 
http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/impl/RouteService.java?rev=922296&r1=922295&r2=922296&view=diff
==============================================================================
--- 
camel/trunk/camel-core/src/main/java/org/apache/camel/impl/RouteService.java 
(original)
+++ 
camel/trunk/camel-core/src/main/java/org/apache/camel/impl/RouteService.java 
Fri Mar 12 15:27:40 2010
@@ -165,6 +165,9 @@ public class RouteService extends Servic
             strategy.onRoutesRemove(routes);
         }
 
+        // if we are stopping CamelContext then we are shutting down
+        boolean isShutdownCamelContext = camelContext.isStopping();
+
         for (Route route : routes) {
             if (LOG.isTraceEnabled()) {
                 LOG.trace("Stopping route: " + route);
@@ -177,10 +180,14 @@ public class RouteService extends Servic
             for (Service service : services) {
                 doGetChildServices(list, service);
             }
-            stopChildService(route, list);
+            stopChildService(route, list, isShutdownCamelContext);
 
             // stop the route itself
-            ServiceHelper.stopService(route);
+            if (isShutdownCamelContext) {
+                ServiceHelper.stopAndShutdownService(route);
+            } else {
+                ServiceHelper.stopService(route);
+            }
 
             // fire event
             EventHelper.notifyRouteStopped(camelContext, route);
@@ -204,12 +211,16 @@ public class RouteService extends Servic
         }
     }
 
-    protected void stopChildService(Route route, List<Service> services) 
throws Exception {
+    protected void stopChildService(Route route, List<Service> services, 
boolean shutdown) throws Exception {
         for (Service service : services) {
             for (LifecycleStrategy strategy : 
camelContext.getLifecycleStrategies()) {
                 strategy.onServiceRemove(camelContext, service, route);
             }
-            ServiceHelper.stopService(service);
+            if (shutdown) {
+                ServiceHelper.stopAndShutdownService(service);
+            } else {
+                ServiceHelper.stopService(service);
+            }
             removeChildService(service);
         }
     }

Modified: 
camel/trunk/camel-core/src/main/java/org/apache/camel/impl/ServiceSupport.java
URL: 
http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/impl/ServiceSupport.java?rev=922296&r1=922295&r2=922296&view=diff
==============================================================================
--- 
camel/trunk/camel-core/src/main/java/org/apache/camel/impl/ServiceSupport.java 
(original)
+++ 
camel/trunk/camel-core/src/main/java/org/apache/camel/impl/ServiceSupport.java 
Fri Mar 12 15:27:40 2010
@@ -22,6 +22,7 @@ import java.util.concurrent.atomic.Atomi
 
 import org.apache.camel.Service;
 import org.apache.camel.ServiceStatus;
+import org.apache.camel.ShutdownableService;
 import org.apache.camel.util.ObjectHelper;
 import org.apache.camel.util.ServiceHelper;
 
@@ -31,12 +32,14 @@ import org.apache.camel.util.ServiceHelp
  *
  * @version $Revision$
  */
-public abstract class ServiceSupport implements Service {
+public abstract class ServiceSupport implements Service, ShutdownableService {
 
     private final AtomicBoolean started = new AtomicBoolean(false);
     private final AtomicBoolean starting = new AtomicBoolean(false);
     private final AtomicBoolean stopping = new AtomicBoolean(false);
     private final AtomicBoolean stopped = new AtomicBoolean(false);
+    private final AtomicBoolean shuttingdown = new AtomicBoolean(false);
+    private final AtomicBoolean shutdown = new AtomicBoolean(false);
     private Collection<Object> childServices;
     private String version;
 
@@ -101,6 +104,26 @@ public abstract class ServiceSupport imp
         }
     }
 
+    public void shutdown() throws Exception {
+        // ensure we are stopped first
+        stop();
+
+        if (shuttingdown.compareAndSet(false, true)) {
+            try {
+                try {
+                    doShutdown();
+                } finally {
+                    if (childServices != null) {
+                        ServiceHelper.stopAndShutdownService(childServices);
+                    }
+                }
+            } finally {
+                shutdown.set(true);
+                shuttingdown.set(false);
+            }
+        }
+    }
+
     /**
      * Returns the current status
      */
@@ -165,6 +188,10 @@ public abstract class ServiceSupport imp
 
     protected abstract void doStop() throws Exception;
 
+    protected void doShutdown() throws Exception {
+        // noop
+    }
+
     @SuppressWarnings("unchecked")
     protected void addChildService(Object childService) {
         synchronized (this) {

Modified: 
camel/trunk/camel-core/src/main/java/org/apache/camel/processor/MulticastProcessor.java
URL: 
http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/MulticastProcessor.java?rev=922296&r1=922295&r2=922296&view=diff
==============================================================================
--- 
camel/trunk/camel-core/src/main/java/org/apache/camel/processor/MulticastProcessor.java
 (original)
+++ 
camel/trunk/camel-core/src/main/java/org/apache/camel/processor/MulticastProcessor.java
 Fri Mar 12 15:27:40 2010
@@ -355,19 +355,23 @@ public class MulticastProcessor extends 
         return new ProcessorExchangePair(processor, prepared, exchange);
     }
 
+    protected void doStart() throws Exception {
+        ServiceHelper.startServices(processors);
+    }
+
     protected void doStop() throws Exception {
+        ServiceHelper.stopServices(processors);
+    }
+
+    @Override
+    protected void doShutdown() throws Exception {
+        // only shutdown thread pool on shutdown
         if (executorService != null) {
-            executorService.shutdown();
-            executorService.awaitTermination(0, TimeUnit.SECONDS);
+            executorService.shutdownNow();
             executorService = null;
         }
-        ServiceHelper.stopServices(processors);
     }
 
-    protected void doStart() throws Exception {
-        ServiceHelper.startServices(processors);
-    }
-    
     private static void setToEndpoint(Exchange exchange, Processor processor) {
         if (processor instanceof Producer) {
             Producer producer = (Producer) processor;

Modified: 
camel/trunk/camel-core/src/main/java/org/apache/camel/processor/OnCompletionProcessor.java
URL: 
http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/OnCompletionProcessor.java?rev=922296&r1=922295&r2=922296&view=diff
==============================================================================
--- 
camel/trunk/camel-core/src/main/java/org/apache/camel/processor/OnCompletionProcessor.java
 (original)
+++ 
camel/trunk/camel-core/src/main/java/org/apache/camel/processor/OnCompletionProcessor.java
 Fri Mar 12 15:27:40 2010
@@ -63,12 +63,17 @@ public class OnCompletionProcessor exten
 
     @Override
     protected void doStop() throws Exception {
+        ServiceHelper.stopService(processor);
+    }
+
+    @Override
+    protected void doShutdown() throws Exception {
+        // only shutdown thread pool on shutdown
         if (executorService != null) {
-            executorService.shutdown();
+            executorService.shutdownNow();
             // must null it so we can restart
             executorService = null;
         }
-        ServiceHelper.stopService(processor);
     }
 
     public void process(Exchange exchange) throws Exception {

Modified: 
camel/trunk/camel-core/src/main/java/org/apache/camel/processor/SendAsyncProcessor.java
URL: 
http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/SendAsyncProcessor.java?rev=922296&r1=922295&r2=922296&view=diff
==============================================================================
--- 
camel/trunk/camel-core/src/main/java/org/apache/camel/processor/SendAsyncProcessor.java
 (original)
+++ 
camel/trunk/camel-core/src/main/java/org/apache/camel/processor/SendAsyncProcessor.java
 Fri Mar 12 15:27:40 2010
@@ -275,6 +275,7 @@ public class SendAsyncProcessor extends 
     protected void doStop() throws Exception {
         super.doStop();
 
+        // must shutdown thread pools on stop as we are consumers
         if (producerExecutorService != null) {
             producerExecutorService.shutdownNow();
             producerExecutorService = null;
@@ -284,7 +285,6 @@ public class SendAsyncProcessor extends 
             executorService = null;
         }
         completedTasks.clear();
-
     }
 
 }

Modified: 
camel/trunk/camel-core/src/main/java/org/apache/camel/processor/ThreadsProcessor.java
URL: 
http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/ThreadsProcessor.java?rev=922296&r1=922295&r2=922296&view=diff
==============================================================================
--- 
camel/trunk/camel-core/src/main/java/org/apache/camel/processor/ThreadsProcessor.java
 (original)
+++ 
camel/trunk/camel-core/src/main/java/org/apache/camel/processor/ThreadsProcessor.java
 Fri Mar 12 15:27:40 2010
@@ -23,6 +23,7 @@ import java.util.concurrent.Future;
 import org.apache.camel.CamelContext;
 import org.apache.camel.Exchange;
 import org.apache.camel.Processor;
+import org.apache.camel.ShutdownableService;
 import org.apache.camel.WaitForTaskToComplete;
 import org.apache.camel.util.ExchangeHelper;
 import org.apache.camel.util.ObjectHelper;
@@ -108,11 +109,12 @@ public class ThreadsProcessor extends De
         return executorService;
     }
 
-    protected void doStop() throws Exception {
-        super.doStop();
+    @Override
+    protected void doShutdown() throws Exception {
+        super.doShutdown();
+        // only shutdown thread pool on shutdown
         if (executorService != null) {
-            executorService.shutdown();
-            // must null it so we can restart
+            executorService.shutdownNow();
             executorService = null;
         }
     }

Modified: 
camel/trunk/camel-core/src/main/java/org/apache/camel/processor/WireTapProcessor.java
URL: 
http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/WireTapProcessor.java?rev=922296&r1=922295&r2=922296&view=diff
==============================================================================
--- 
camel/trunk/camel-core/src/main/java/org/apache/camel/processor/WireTapProcessor.java
 (original)
+++ 
camel/trunk/camel-core/src/main/java/org/apache/camel/processor/WireTapProcessor.java
 Fri Mar 12 15:27:40 2010
@@ -53,18 +53,14 @@ public class WireTapProcessor extends Se
     }
 
     @Override
-    protected void doStart() throws Exception {
-        super.doStart();
-    }
-
-    @Override
-    protected void doStop() throws Exception {
+    protected void doShutdown() throws Exception {
+        super.doShutdown();
+        // only shutdown thread pool on shutdown
         if (executorService != null) {
-            executorService.shutdown();
+            executorService.shutdownNow();
             // must null it so we can restart
             executorService = null;
         }
-        super.doStop();
     }
 
     @Override
@@ -81,7 +77,7 @@ public class WireTapProcessor extends Se
         getProducerCache(exchange).doInProducer(destination, exchange, 
pattern, new ProducerCallback<Exchange>() {
             public Exchange doInProducer(Producer producer, Exchange exchange, 
ExchangePattern pattern) throws Exception {
                 Exchange wireTapExchange = configureExchange(exchange, 
pattern);
-                procesWireTap(producer, wireTapExchange);
+                processWireTap(producer, wireTapExchange);
                 return wireTapExchange;
             }
         });
@@ -92,10 +88,10 @@ public class WireTapProcessor extends Se
      *
      * @param exchange  the exchange to wire tap
      */
-    protected void procesWireTap(final Producer producer, final Exchange 
exchange) {
+    protected void processWireTap(final Producer producer, final Exchange 
exchange) {
         // use submit instead of execute to force it to use a new thread, 
execute might
         // decide to use current thread, so we must submit a new task
-        // as we dont care for the response we dont hold the future object and 
wait for the result
+        // as we don't care for the response we dont hold the future object 
and wait for the result
         getExecutorService().submit(new Callable<Exchange>() {
             public Exchange call() throws Exception {
                 if (LOG.isDebugEnabled()) {
@@ -153,7 +149,7 @@ public class WireTapProcessor extends Se
     }
 
     public ExecutorService getExecutorService() {
-        if (executorService == null || executorService.isShutdown()) {
+        if (executorService == null) {
             executorService = createExecutorService();
         }
         return executorService;

Modified: 
camel/trunk/camel-core/src/main/java/org/apache/camel/processor/aggregate/AggregateProcessor.java
URL: 
http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/aggregate/AggregateProcessor.java?rev=922296&r1=922295&r2=922296&view=diff
==============================================================================
--- 
camel/trunk/camel-core/src/main/java/org/apache/camel/processor/aggregate/AggregateProcessor.java
 (original)
+++ 
camel/trunk/camel-core/src/main/java/org/apache/camel/processor/aggregate/AggregateProcessor.java
 Fri Mar 12 15:27:40 2010
@@ -495,11 +495,6 @@ public class AggregateProcessor extends 
     protected void doStop() throws Exception {
         ServiceHelper.stopService(timeoutMap);
 
-        if (executorService != null) {
-            executorService.shutdown();
-            executorService = null;
-        }
-
         ServiceHelper.stopService(aggregationRepository);
 
         if (closedCorrelationKeys != null) {
@@ -507,4 +502,13 @@ public class AggregateProcessor extends 
         }
     }
 
+    @Override
+    protected void doShutdown() throws Exception {
+        // only shutdown thread pool when we are shutting down
+        if (executorService != null) {
+            executorService.shutdownNow();
+            executorService = null;
+        }
+    }
+
 }

Modified: 
camel/trunk/camel-core/src/main/java/org/apache/camel/util/ServiceHelper.java
URL: 
http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/util/ServiceHelper.java?rev=922296&r1=922295&r2=922296&view=diff
==============================================================================
--- 
camel/trunk/camel-core/src/main/java/org/apache/camel/util/ServiceHelper.java 
(original)
+++ 
camel/trunk/camel-core/src/main/java/org/apache/camel/util/ServiceHelper.java 
Fri Mar 12 15:27:40 2010
@@ -21,6 +21,7 @@ import java.util.Collection;
 import java.util.List;
 
 import org.apache.camel.Service;
+import org.apache.camel.ShutdownableService;
 import org.apache.camel.SuspendableService;
 import org.apache.camel.impl.ServiceSupport;
 import org.apache.commons.logging.Log;
@@ -40,6 +41,9 @@ public final class ServiceHelper {
     private ServiceHelper() {
     }
 
+    /**
+     * Starts all of the given services
+     */
     public static void startService(Object value) throws Exception {
         if (value instanceof Service) {
             Service service = (Service)value;
@@ -84,6 +88,9 @@ public final class ServiceHelper {
         stopServices(list);
     }
 
+    /**
+     * Stops all of the given services, throwing the first exception caught
+     */
     public static void stopService(Object value) throws Exception {
         if (value instanceof Service) {
             Service service = (Service)value;
@@ -110,7 +117,72 @@ public final class ServiceHelper {
                     }
                     service.stop();
                 } catch (Exception e) {
-                    LOG.debug("Caught exception shutting down: " + e, e);
+                    if (LOG.isDebugEnabled()) {
+                        LOG.debug("Caught exception stopping service: " + 
service, e);
+                    }
+                    if (firstException == null) {
+                        firstException = e;
+                    }
+                }
+            }
+        }
+        if (firstException != null) {
+            throw firstException;
+        }
+    }
+
+    /**
+     * Stops and shutdowns all of the given services, throwing the first 
exception caught
+     */
+    public static void stopAndShutdownServices(Object... services) throws 
Exception {
+        List<Object> list = Arrays.asList(services);
+        stopAndShutdownServices(list);
+    }
+
+    /**
+     * Stops and shutdowns all of the given services, throwing the first 
exception caught
+     */
+    public static void stopAndShutdownService(Object value) throws Exception {
+        if (value instanceof Service) {
+            // must stop it first
+            stopService(value);
+        }
+
+        // then try to shutdown
+        if (value instanceof ShutdownableService) {
+            ShutdownableService service = (ShutdownableService)value;
+            if (LOG.isTraceEnabled()) {
+                LOG.trace("Shutting down service " + value);
+            }
+            service.shutdown();
+        } else if (value instanceof Collection) {
+            stopAndShutdownServices((Collection<?>)value);
+        }
+    }
+
+    /**
+     * Stops and shutdowns all of the given services, throwing the first 
exception caught
+     */
+    public static void stopAndShutdownServices(Collection<?> services) throws 
Exception {
+        Exception firstException = null;
+
+        for (Object value : services) {
+
+            // must stop it first
+            stopService(value);
+
+            // then try to shutdown
+            if (value instanceof ShutdownableService) {
+                ShutdownableService service = (ShutdownableService)value;
+                try {
+                    if (LOG.isTraceEnabled()) {
+                        LOG.trace("Shutting down service: " + service);
+                    }
+                    service.shutdown();
+                } catch (Exception e) {
+                    if (LOG.isDebugEnabled()) {
+                        LOG.debug("Caught exception shutting down service: " + 
service, e);
+                    }
                     if (firstException == null) {
                         firstException = e;
                     }

Modified: 
camel/trunk/camel-core/src/test/java/org/apache/camel/impl/ServiceSupportTest.java
URL: 
http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/impl/ServiceSupportTest.java?rev=922296&r1=922295&r2=922296&view=diff
==============================================================================
--- 
camel/trunk/camel-core/src/test/java/org/apache/camel/impl/ServiceSupportTest.java
 (original)
+++ 
camel/trunk/camel-core/src/test/java/org/apache/camel/impl/ServiceSupportTest.java
 Fri Mar 12 15:27:40 2010
@@ -48,4 +48,48 @@ public class ServiceSupportTest extends 
         assertEquals(false, service.isStarted());
         assertEquals(false, service.isStarting());
     }
+
+    private class MyShutdownService extends ServiceSupport {
+
+        private boolean shutdown;
+
+        @Override
+        protected void doStart() throws Exception {
+        }
+
+        @Override
+        protected void doStop() throws Exception {
+        }
+
+        @Override
+        protected void doShutdown() throws Exception {
+            shutdown = true;
+        }
+
+        public boolean isShutdown() {
+            return shutdown;
+        }
+    }
+
+    public void testServiceSupportShutdown() throws Exception {
+        MyShutdownService service = new MyShutdownService();
+        service.start();
+
+        assertEquals(true, service.isStarted());
+        assertEquals(false, service.isStarting());
+        assertEquals(false, service.isStopped());
+        assertEquals(false, service.isStopping());
+        assertEquals(false, service.isShutdown());
+
+        service.shutdown();
+
+        assertEquals(true, service.isStopped());
+        assertEquals(false, service.isStopping());
+        assertEquals(false, service.isStarted());
+        assertEquals(false, service.isStarting());
+
+        assertEquals(true, service.isShutdown());
+    }
+
+
 }

Copied: 
camel/trunk/camel-core/src/test/java/org/apache/camel/processor/aggregator/AggregateShutdownThreadPoolTest.java
 (from r922137, 
camel/trunk/camel-core/src/test/java/org/apache/camel/processor/aggregator/AggregateSimpleSizeTest.java)
URL: 
http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/aggregator/AggregateShutdownThreadPoolTest.java?p2=camel/trunk/camel-core/src/test/java/org/apache/camel/processor/aggregator/AggregateShutdownThreadPoolTest.java&p1=camel/trunk/camel-core/src/test/java/org/apache/camel/processor/aggregator/AggregateSimpleSizeTest.java&r1=922137&r2=922296&rev=922296&view=diff
==============================================================================
--- 
camel/trunk/camel-core/src/test/java/org/apache/camel/processor/aggregator/AggregateSimpleSizeTest.java
 (original)
+++ 
camel/trunk/camel-core/src/test/java/org/apache/camel/processor/aggregator/AggregateShutdownThreadPoolTest.java
 Fri Mar 12 15:27:40 2010
@@ -16,23 +16,78 @@
  */
 package org.apache.camel.processor.aggregator;
 
+import java.util.concurrent.ExecutorService;
+
 import org.apache.camel.ContextTestSupport;
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.processor.BodyInAggregatingStrategy;
+import org.apache.camel.util.concurrent.ExecutorServiceHelper;
 
 /**
  * @version $Revision$
  */
-public class AggregateSimpleSizeTest extends ContextTestSupport {
+public class AggregateShutdownThreadPoolTest extends ContextTestSupport {
+
+    private ExecutorService myPool = 
ExecutorServiceHelper.newCachedThreadPool("myPool", true);
 
-    public void testAggregateSimpleSize() throws Exception {
+    public void testAggregateShutdownDefaultThreadPoolTest() throws Exception {
         getMockEndpoint("mock:aggregated").expectedBodiesReceived("A+B+C");
 
-        template.sendBodyAndHeader("direct:start", "A", "id", 123);
-        template.sendBodyAndHeader("direct:start", "B", "id", 123);
-        template.sendBodyAndHeader("direct:start", "C", "id", 123);
+        template.sendBodyAndHeader("direct:foo", "A", "id", 123);
+        template.sendBodyAndHeader("direct:foo", "B", "id", 123);
+        template.sendBodyAndHeader("direct:foo", "C", "id", 123);
+
+        assertMockEndpointsSatisfied();
+
+        context.stopRoute("foo");
+
+        resetMocks();
+
+        context.startRoute("foo");
+
+        getMockEndpoint("mock:aggregated").expectedBodiesReceived("D+E+F");
+
+        template.sendBodyAndHeader("direct:foo", "D", "id", 123);
+        template.sendBodyAndHeader("direct:foo", "E", "id", 123);
+        template.sendBodyAndHeader("direct:foo", "F", "id", 123);
 
         assertMockEndpointsSatisfied();
+
+        context.stop();
+    }
+
+    public void testAggregateShutdownCustomThreadPoolTest() throws Exception {
+        assertEquals(false, myPool.isShutdown());
+
+        getMockEndpoint("mock:aggregated").expectedBodiesReceived("A+B+C");
+
+        template.sendBodyAndHeader("direct:bar", "A", "id", 123);
+        template.sendBodyAndHeader("direct:bar", "B", "id", 123);
+        template.sendBodyAndHeader("direct:bar", "C", "id", 123);
+
+        assertMockEndpointsSatisfied();
+        assertEquals(false, myPool.isShutdown());
+
+        context.stopRoute("bar");
+        assertEquals(false, myPool.isShutdown());
+
+        resetMocks();
+
+        context.startRoute("bar");
+        assertEquals(false, myPool.isShutdown());
+
+        getMockEndpoint("mock:aggregated").expectedBodiesReceived("D+E+F");
+
+        template.sendBodyAndHeader("direct:bar", "D", "id", 123);
+        template.sendBodyAndHeader("direct:bar", "E", "id", 123);
+        template.sendBodyAndHeader("direct:bar", "F", "id", 123);
+
+        assertMockEndpointsSatisfied();
+        assertEquals(false, myPool.isShutdown());
+
+        context.stop();
+        // now it should be shutdown when CamelContext is stopped/shutdown
+        assertEquals(true, myPool.isShutdown());
     }
 
     @Override
@@ -40,15 +95,13 @@ public class AggregateSimpleSizeTest ext
         return new RouteBuilder() {
             @Override
             public void configure() throws Exception {
-                // START SNIPPET: e1
-                from("direct:start")
-                    // aggregate all exchanges correlated by the id header.
-                    // Aggregate them using the BodyInAggregatingStrategy 
strategy which
-                    // and after 3 messages has been aggregated then complete 
the aggregation
-                    // and send it to mock:aggregated
+                from("direct:foo").routeId("foo")
                     .aggregate(header("id"), new 
BodyInAggregatingStrategy()).completionSize(3)
                         .to("mock:aggregated");
-                // END SNIPPET: e1
+
+                from("direct:bar").routeId("bar")
+                    .aggregate(header("id"), new 
BodyInAggregatingStrategy()).executorService(myPool).completionSize(3)
+                        .to("mock:aggregated");
             }
         };
     }


Reply via email to