Return-Path: X-Original-To: apmail-camel-commits-archive@www.apache.org Delivered-To: apmail-camel-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 265C5BB7A for ; Sat, 31 Dec 2011 13:32:09 +0000 (UTC) Received: (qmail 58807 invoked by uid 500); 31 Dec 2011 13:32:09 -0000 Delivered-To: apmail-camel-commits-archive@camel.apache.org Received: (qmail 58777 invoked by uid 500); 31 Dec 2011 13:32:09 -0000 Mailing-List: contact commits-help@camel.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@camel.apache.org Delivered-To: mailing list commits@camel.apache.org Received: (qmail 58770 invoked by uid 99); 31 Dec 2011 13:32:09 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Sat, 31 Dec 2011 13:32:09 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Sat, 31 Dec 2011 13:32:07 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id A60E82388900 for ; Sat, 31 Dec 2011 13:31:46 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: 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... Date: Sat, 31 Dec 2011 13:31:45 -0000 To: commits@camel.apache.org From: davsclaus@apache.org X-Mailer: svnmailer-1.0.8-patched Message-Id: <20111231133146.A60E82388900@eris.apache.org> 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. + *

+ * The service is assumed to have been previously added using {@link #addService(Object)} method. + * This method will not change the service lifecycle. + * + * @param object the service + * @throws Exception can be thrown if error removing the service + * @return true if the service was removed, false 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 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 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 services = route.getServices(); + + // gather list of services to stop as we need to start child services as well + Set list = new LinkedHashSet(); + 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 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 = "world!"; - - public void testStartRouteThenStopMutateAndStartRouteAgain() throws Exception { - List 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 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); + } }