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 2011/12/31 14:31:45 UTC

svn commit: r1226081 - in /camel/trunk/camel-core/src: main/java/org/apache/camel/ main/java/org/apache/camel/impl/ main/java/org/apache/camel/processor/ test/java/org/apache/camel/impl/ test/java/org/apache/camel/management/ test/java/org/apache/camel...

Author: davsclaus
Date: Sat Dec 31 13:31:45 2011
New Revision: 1226081

URL: http://svn.apache.org/viewvc?rev=1226081&view=rev
Log:
CAMEL-4842: Removing route should remove producer cache from JMX, as well from services to close list on CamelContext, to not eat up memory.

Added:
    camel/trunk/camel-core/src/test/java/org/apache/camel/impl/StartStopAndShutdownRouteTest.java
      - copied, changed from r1226049, camel/trunk/camel-core/src/test/java/org/apache/camel/impl/StartAndStopRoutesTest.java
    camel/trunk/camel-core/src/test/java/org/apache/camel/management/ManagedRouteAddRemoveTest.java
      - copied, changed from r1226049, camel/trunk/camel-core/src/test/java/org/apache/camel/management/ManagedRouteAddSecondRouteTest.java
    camel/trunk/camel-core/src/test/java/org/apache/camel/util/MyDummyObject.java
Modified:
    camel/trunk/camel-core/src/main/java/org/apache/camel/CamelContext.java
    camel/trunk/camel-core/src/main/java/org/apache/camel/Route.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/DefaultRoute.java
    camel/trunk/camel-core/src/main/java/org/apache/camel/impl/RouteService.java
    camel/trunk/camel-core/src/main/java/org/apache/camel/processor/RecipientList.java
    camel/trunk/camel-core/src/main/java/org/apache/camel/processor/RecipientListProcessor.java
    camel/trunk/camel-core/src/main/java/org/apache/camel/processor/RoutingSlip.java
    camel/trunk/camel-core/src/main/java/org/apache/camel/processor/SendProcessor.java
    camel/trunk/camel-core/src/test/java/org/apache/camel/util/ObjectHelperTest.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=1226081&r1=1226080&r2=1226081&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 Sat Dec 31 13:31:45 2011
@@ -154,6 +154,18 @@ public interface CamelContext extends Su
     void addService(Object object) throws Exception;
 
     /**
+     * Removes a service from this context.
+     * <p/>
+     * The service is assumed to have been previously added using {@link #addService(Object)} method.
+     * This method will <b>not</b> change the service lifecycle.
+     *
+     * @param object the service
+     * @throws Exception can be thrown if error removing the service
+     * @return <tt>true</tt> if the service was removed, <tt>false</tt> if no service existed
+     */
+    boolean removeService(Object object) throws Exception;
+
+    /**
      * Has the given service already been added to this context?
      *
      * @param object the service

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/Route.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/Route.java?rev=1226081&r1=1226080&r2=1226081&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/Route.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/Route.java Sat Dec 31 13:31:45 2011
@@ -107,4 +107,9 @@ public interface Route {
      */
     Navigate<Processor> navigate();
 
+    /**
+     * Callback preparing the route to be started, by warming up the route.
+     */
+    void warmUp();
+
 }

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=1226081&r1=1226080&r2=1226081&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 Sat Dec 31 13:31:45 2011
@@ -913,6 +913,23 @@ public class DefaultCamelContext extends
         }
     }
 
+    public boolean removeService(Object object) throws Exception {
+        if (object instanceof Service) {
+            Service service = (Service) object;
+
+            for (LifecycleStrategy strategy : lifecycleStrategies) {
+                if (service instanceof Endpoint) {
+                    // use specialized endpoint remove
+                    strategy.onEndpointRemove((Endpoint) service);
+                } else {
+                    strategy.onServiceRemove(this, service, null);
+                }
+            }
+            return servicesToClose.remove(service);
+        }
+        return false;
+    }
+
     public boolean hasService(Object object) {
         if (object instanceof Service) {
             Service service = (Service) object;

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/impl/DefaultRoute.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/impl/DefaultRoute.java?rev=1226081&r1=1226080&r2=1226081&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/impl/DefaultRoute.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/impl/DefaultRoute.java Sat Dec 31 13:31:45 2011
@@ -85,7 +85,13 @@ public abstract class DefaultRoute exten
     }
 
     public void addService(Service service) {
-        getServices().add(service);
+        if (!services.contains(service)) {
+            services.add(service);
+        }
+    }
+
+    public void warmUp() {
+        getServices().clear();
     }
 
     /**
@@ -115,7 +121,12 @@ public abstract class DefaultRoute exten
     }
 
     protected void doStop() throws Exception {
-        // clear services when stopping
+        // noop
+    }
+
+    @Override
+    protected void doShutdown() throws Exception {
+        // clear services when shutting down
         services.clear();
     }
 }

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=1226081&r1=1226080&r2=1226081&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 Sat Dec 31 13:31:45 2011
@@ -118,8 +118,10 @@ public class RouteService extends ChildS
         if (warmUpDone.compareAndSet(false, true)) {
 
             for (Route route : routes) {
-                LOG.debug("Starting services on route: {}", route.getId());
+                // warm up the route first
+                route.warmUp();
 
+                LOG.debug("Starting services on route: {}", route.getId());
                 List<Service> services = route.getServices();
 
                 // callback that we are staring these services
@@ -224,6 +226,20 @@ public class RouteService extends ChildS
     @Override
     protected void doShutdown() throws Exception {
         for (Route route : routes) {
+            LOG.debug("Shutting down services on route: {}", route.getId());
+            List<Service> services = route.getServices();
+
+            // gather list of services to stop as we need to start child services as well
+            Set<Service> list = new LinkedHashSet<Service>();
+            for (Service service : services) {
+                doGetChildServices(list, service);
+            }
+            // shutdown services
+            stopChildService(route, list, true);
+
+            // shutdown the route itself
+            ServiceHelper.stopAndShutdownServices(route);
+
             // endpoints should only be stopped when Camel is shutting down
             // see more details in the warmUp method
             ServiceHelper.stopAndShutdownServices(route.getEndpoint());
@@ -239,7 +255,8 @@ public class RouteService extends ChildS
         for (LifecycleStrategy strategy : camelContext.getLifecycleStrategies()) {
             strategy.onRoutesRemove(routes);
         }
-        
+
+        // remove the routes from the collections
         camelContext.removeRouteCollection(routes);
         
         // clear inputs on shutdown
@@ -288,7 +305,7 @@ public class RouteService extends ChildS
 
     protected void stopChildService(Route route, Set<Service> services, boolean shutdown) throws Exception {
         for (Service service : services) {
-            LOG.debug("Stopping child service on route: {} -> {}", route.getId(), service);
+            LOG.debug("{} child service on route: {} -> {}", new Object[]{shutdown ? "Shutting down" : "Stopping", route.getId(), service});
             for (LifecycleStrategy strategy : camelContext.getLifecycleStrategies()) {
                 strategy.onServiceRemove(camelContext, service, route);
             }

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/processor/RecipientList.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/RecipientList.java?rev=1226081&r1=1226080&r2=1226081&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/processor/RecipientList.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/processor/RecipientList.java Sat Dec 31 13:31:45 2011
@@ -171,6 +171,12 @@ public class RecipientList extends Servi
         ServiceHelper.stopService(producerCache);
     }
 
+    protected void doShutdown() throws Exception {
+        // remove producer cache from service
+        camelContext.removeService(producerCache);
+        ServiceHelper.stopAndShutdownService(producerCache);
+    }
+
     public boolean isStreaming() {
         return streaming;
     }

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/processor/RecipientListProcessor.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/RecipientListProcessor.java?rev=1226081&r1=1226080&r2=1226081&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/processor/RecipientListProcessor.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/processor/RecipientListProcessor.java Sat Dec 31 13:31:45 2011
@@ -233,6 +233,13 @@ public class RecipientListProcessor exte
         super.doStop();
     }
 
+    protected void doShutdown() throws Exception {
+        // remove producer cache from service
+        getCamelContext().removeService(producerCache);
+        ServiceHelper.stopAndShutdownService(producerCache);
+        super.doShutdown();
+    }
+
     @Override
     public String toString() {
         return "RecipientList";

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/processor/RoutingSlip.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/RoutingSlip.java?rev=1226081&r1=1226080&r2=1226081&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/processor/RoutingSlip.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/processor/RoutingSlip.java Sat Dec 31 13:31:45 2011
@@ -368,6 +368,12 @@ public class RoutingSlip extends Service
         ServiceHelper.stopService(producerCache);
     }
 
+    protected void doShutdown() throws Exception {
+        // remove producer cache from service
+        camelContext.removeService(producerCache);
+        ServiceHelper.stopAndShutdownService(producerCache);
+    }
+
     /**
      * Returns the outbound message if available. Otherwise return the inbound message.
      */

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/processor/SendProcessor.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/SendProcessor.java?rev=1226081&r1=1226080&r2=1226081&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/processor/SendProcessor.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/processor/SendProcessor.java Sat Dec 31 13:31:45 2011
@@ -168,4 +168,9 @@ public class SendProcessor extends Servi
         ServiceHelper.stopService(producerCache);
     }
 
+    protected void doShutdown() throws Exception {
+        // remove producer cache from service
+        camelContext.removeService(producerCache);
+        ServiceHelper.stopAndShutdownService(producerCache);
+    }
 }

Copied: camel/trunk/camel-core/src/test/java/org/apache/camel/impl/StartStopAndShutdownRouteTest.java (from r1226049, camel/trunk/camel-core/src/test/java/org/apache/camel/impl/StartAndStopRoutesTest.java)
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/impl/StartStopAndShutdownRouteTest.java?p2=camel/trunk/camel-core/src/test/java/org/apache/camel/impl/StartStopAndShutdownRouteTest.java&p1=camel/trunk/camel-core/src/test/java/org/apache/camel/impl/StartAndStopRoutesTest.java&r1=1226049&r2=1226081&rev=1226081&view=diff
==============================================================================
--- camel/trunk/camel-core/src/test/java/org/apache/camel/impl/StartAndStopRoutesTest.java (original)
+++ camel/trunk/camel-core/src/test/java/org/apache/camel/impl/StartStopAndShutdownRouteTest.java Sat Dec 31 13:31:45 2011
@@ -16,60 +16,36 @@
  */
 package org.apache.camel.impl;
 
-import java.util.List;
-
 import org.apache.camel.ContextTestSupport;
+import org.apache.camel.Route;
 import org.apache.camel.builder.RouteBuilder;
-import org.apache.camel.component.mock.MockEndpoint;
-import org.apache.camel.component.seda.SedaEndpoint;
-import org.apache.camel.model.FromDefinition;
-import org.apache.camel.model.RouteDefinition;
 
 /**
  * This test stops a route, mutates it then restarts it
  *
  * @version 
  */
-public class StartAndStopRoutesTest extends ContextTestSupport {
-    protected SedaEndpoint endpointA;
-    protected SedaEndpoint endpointB;
-    protected SedaEndpoint endpointC;
-    protected Object expectedBody = "<hello>world!</hello>";
-
-    public void testStartRouteThenStopMutateAndStartRouteAgain() throws Exception {
-        List<RouteDefinition> routes = context.getRouteDefinitions();
-        assertCollectionSize("Route", routes, 1);
-        RouteDefinition route = routes.get(0);
-
-        endpointA = getMandatoryEndpoint("seda:test.a", SedaEndpoint.class);
-        endpointB = getMandatoryEndpoint("seda:test.b", SedaEndpoint.class);
-        endpointC = getMandatoryEndpoint("seda:test.C", SedaEndpoint.class);
-
-        // send from A over B to results
-        MockEndpoint results = getMockEndpoint("mock:results");
-        results.expectedBodiesReceived(expectedBody);
+public class StartStopAndShutdownRouteTest extends ContextTestSupport {
 
-        template.sendBody(endpointA, expectedBody);
+    public void testStartStopAndShutdownRoute() throws Exception {
 
-        assertMockEndpointsSatisfied();
+        // there should still be 2 services on the route
+        Route myRoute = context.getRoute("foo");
+        int services = myRoute.getServices().size();
+        assertTrue(services > 0);
 
         // stop the route
-        context.stopRoute(route);
+        context.stopRoute("foo");
 
-        // lets mutate the route...
-        FromDefinition fromType = assertOneElement(route.getInputs());
-        fromType.setUri("seda:test.C");
-        context.startRoute(route);
-
-        // now lets check it works
-        // send from C over B to results
-        results.reset();
-        results = getMockEndpoint("mock:results");
-        results.expectedBodiesReceived(expectedBody);
+        // there should still be the same number of services on the route
+        assertEquals(services, myRoute.getServices().size());
 
-        template.sendBody(endpointC, expectedBody);
+        // shutting down the route, by stop and remove
+        context.stopRoute("foo");
+        context.removeRoute("foo");
 
-        assertMockEndpointsSatisfied();
+        // and now no more services as the route is shutdown
+        assertEquals(0, myRoute.getServices().size());
     }
 
     @Override
@@ -77,9 +53,7 @@ public class StartAndStopRoutesTest exte
         return new RouteBuilder() {
             @Override
             public void configure() throws Exception {
-                from("seda:test.a").
-                        to("seda:test.b").
-                        to("mock:results");
+                from("direct:start").routeId("foo").to("mock:foo");
             }
         };
 

Copied: camel/trunk/camel-core/src/test/java/org/apache/camel/management/ManagedRouteAddRemoveTest.java (from r1226049, camel/trunk/camel-core/src/test/java/org/apache/camel/management/ManagedRouteAddSecondRouteTest.java)
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/management/ManagedRouteAddRemoveTest.java?p2=camel/trunk/camel-core/src/test/java/org/apache/camel/management/ManagedRouteAddRemoveTest.java&p1=camel/trunk/camel-core/src/test/java/org/apache/camel/management/ManagedRouteAddSecondRouteTest.java&r1=1226049&r2=1226081&rev=1226081&view=diff
==============================================================================
--- camel/trunk/camel-core/src/test/java/org/apache/camel/management/ManagedRouteAddSecondRouteTest.java (original)
+++ camel/trunk/camel-core/src/test/java/org/apache/camel/management/ManagedRouteAddRemoveTest.java Sat Dec 31 13:31:45 2011
@@ -16,18 +16,19 @@
  */
 package org.apache.camel.management;
 
+import java.util.Set;
 import javax.management.MBeanServer;
 import javax.management.ObjectName;
 
-import org.apache.camel.ServiceStatus;
 import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
 
 /**
  * Tests mbeans is registered when adding a 2nd route after CamelContext has been started.
  *
  * @version 
  */
-public class ManagedRouteAddSecondRouteTest extends ManagementTestSupport {
+public class ManagedRouteAddRemoveTest extends ManagementTestSupport {
 
     @Override
     protected RouteBuilder createRouteBuilder() throws Exception {
@@ -39,15 +40,21 @@ public class ManagedRouteAddSecondRouteT
         };
     }
 
-    public void testRouteAddSecondRoute() throws Exception {
+    public void testRouteAddRemoteRoute() throws Exception {
+        MockEndpoint result = getMockEndpoint("mock:result");
+        result.expectedMessageCount(1);
+        template.sendBody("direct:start", "Hello World");
+        result.assertIsSatisfied();
+
         MBeanServer mbeanServer = getMBeanServer();
-        ObjectName route1 = ObjectName.getInstance("org.apache.camel:context=localhost/camel-1,type=routes,name=\"foo\"");
+        ObjectName on = ObjectName.getInstance("org.apache.camel:context=localhost/camel-1,type=services,name=ProducerCache*");
 
-        // should be started
-        String state = (String) mbeanServer.getAttribute(route1, "State");
-        assertEquals("Should be started", ServiceStatus.Started.name(), state);
+        // number of producer caches
+        Set<ObjectName> names = mbeanServer.queryNames(on, null);
+        assertEquals(1, names.size());
+        
+        log.info("Adding 2nd route");
 
-        log.info(">>>>>>>>>>>>>>>>> adding 2nd route <<<<<<<<<<<<<<");
         // add a 2nd route
         context.addRoutes(new RouteBuilder() {
             @Override
@@ -55,14 +62,30 @@ public class ManagedRouteAddSecondRouteT
                 from("direct:bar").routeId("bar").to("mock:bar");
             }
         });
-        log.info(">>>>>>>>>>>>>>>>> adding 2nd route DONE <<<<<<<<<<<<<<");
 
-        // find the 2nd route
-        ObjectName route2 = ObjectName.getInstance("org.apache.camel:context=localhost/camel-1,type=routes,name=\"bar\"");
+        // and send a message to it
+        MockEndpoint bar = getMockEndpoint("mock:bar");
+        bar.expectedMessageCount(1);
+        template.sendBody("direct:bar", "Hello World");
+        bar.assertIsSatisfied();
+
+        // there should be one more producer cache
+        names = mbeanServer.queryNames(on, null);
+        assertEquals(2, names.size());
+
+        log.info("Removing 2nd route");
+
+        // now remove the 2nd route
+        context.stopRoute("bar");
+        boolean removed = context.removeRoute("bar");
+        assertTrue(removed);
+
+        // the producer cache should have been removed
+        on = ObjectName.getInstance("org.apache.camel:context=localhost/camel-1,type=services,name=ProducerCache*");
+        names = mbeanServer.queryNames(on, null);
+        assertEquals(1, names.size());
 
-        // should be started
-        state = (String) mbeanServer.getAttribute(route2, "State");
-        assertEquals("Should be started", ServiceStatus.Started.name(), state);
+        log.info("Shutting down...");
     }
 
 }
\ No newline at end of file

Added: camel/trunk/camel-core/src/test/java/org/apache/camel/util/MyDummyObject.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/util/MyDummyObject.java?rev=1226081&view=auto
==============================================================================
--- camel/trunk/camel-core/src/test/java/org/apache/camel/util/MyDummyObject.java (added)
+++ camel/trunk/camel-core/src/test/java/org/apache/camel/util/MyDummyObject.java Sat Dec 31 13:31:45 2011
@@ -0,0 +1,34 @@
+/**
+ * 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.util;
+
+/**
+ *
+ */
+public class MyDummyObject {
+    
+    private String name;
+
+    public MyDummyObject(String name) {
+        this.name = name;
+    }
+
+    @Override
+    public String toString() {
+        return name;
+    }
+}

Modified: camel/trunk/camel-core/src/test/java/org/apache/camel/util/ObjectHelperTest.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/util/ObjectHelperTest.java?rev=1226081&r1=1226080&r2=1226081&view=diff
==============================================================================
--- camel/trunk/camel-core/src/test/java/org/apache/camel/util/ObjectHelperTest.java (original)
+++ camel/trunk/camel-core/src/test/java/org/apache/camel/util/ObjectHelperTest.java Sat Dec 31 13:31:45 2011
@@ -317,5 +317,18 @@ public class ObjectHelperTest extends Te
         assertTrue(ObjectHelper.hasDefaultPublicNoArgConstructor(ObjectHelperTest.class));
         assertFalse(ObjectHelper.hasDefaultPublicNoArgConstructor(MyStaticClass.class));
     }
+    
+    public void testIdentityHashCode() {
+        MyDummyObject dummy = new MyDummyObject("Camel");
+        
+        String code = ObjectHelper.getIdentityHashCode(dummy);
+        String code2 = ObjectHelper.getIdentityHashCode(dummy);
+
+        assertEquals(code, code2);
+
+        MyDummyObject dummyB = new MyDummyObject("Camel");
+        String code3 = ObjectHelper.getIdentityHashCode(dummyB);
+        assertNotSame(code, code3);
+    }
 
 }