Author: davsclaus Date: Fri Mar 2 13:26:05 2012 New Revision: 1296196 URL: http://svn.apache.org/viewvc?rev=1296196&view=rev Log: CAMEL-5041: Fixed so route scoped error handlers is removed from JMX when removing a route, to not leak memory.
Added: camel/trunk/camel-core/src/test/java/org/apache/camel/management/ManagedRouteRemoveContextScopedErrorHandlerTest.java - copied, changed from r1295578, camel/trunk/camel-core/src/test/java/org/apache/camel/management/ManagedRouteRemoveTest.java camel/trunk/camel-core/src/test/java/org/apache/camel/management/ManagedRouteRemoveRouteAndContextScopedErrorHandlerTest.java camel/trunk/camel-core/src/test/java/org/apache/camel/management/ManagedRouteRemoveRouteScopedErrorHandlerTest.java camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/management/SpringManagedRouteRemoveContextScopedErrorHandlerTest.java - copied, changed from r1296042, camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/management/SpringManagedNamePatternFixedTest.java camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/management/SpringManagedRouteRemoveRouteAndContextScopedErrorHandlerTest.java camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/management/SpringManagedRouteRemoveRouteScopedErrorHandlerTest.java camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/management/SpringManagedRouteRemoveContextScopedErrorHandlerTest.xml - copied, changed from r1296042, camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/management/SpringManagedNamePatternFixedTest.xml camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/management/SpringManagedRouteRemoveRouteAndContextScopedErrorHandlerTest.xml camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/management/SpringManagedRouteRemoveRouteScopedErrorHandlerTest.xml Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/impl/RouteService.java camel/trunk/camel-core/src/main/java/org/apache/camel/management/DefaultManagementLifecycleStrategy.java camel/trunk/camel-core/src/main/java/org/apache/camel/model/RouteDefinition.java camel/trunk/camel-core/src/main/java/org/apache/camel/processor/OnCompletionProcessor.java camel/trunk/camel-core/src/main/java/org/apache/camel/spi/LifecycleStrategy.java camel/trunk/camel-core/src/test/java/org/apache/camel/impl/DefaultCamelContextWithLifecycleStrategyRestartTest.java camel/trunk/camel-core/src/test/java/org/apache/camel/impl/DummyLifecycleStrategy.java camel/trunk/camel-core/src/test/java/org/apache/camel/impl/VetoCamelContextStartTest.java camel/trunk/components/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiServiceRegistry.java camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/DummyLifecycleStrategy.java 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=1296196&r1=1296195&r2=1296196&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 2 13:26:05 2012 @@ -26,6 +26,7 @@ import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; import org.apache.camel.CamelContext; +import org.apache.camel.Channel; import org.apache.camel.Consumer; import org.apache.camel.Processor; import org.apache.camel.Route; @@ -34,6 +35,7 @@ import org.apache.camel.model.OnCompleti import org.apache.camel.model.OnExceptionDefinition; import org.apache.camel.model.ProcessorDefinition; import org.apache.camel.model.RouteDefinition; +import org.apache.camel.processor.ErrorHandler; import org.apache.camel.spi.LifecycleStrategy; import org.apache.camel.spi.RouteContext; import org.apache.camel.spi.RoutePolicy; @@ -193,16 +195,20 @@ public class RouteService extends ChildS for (Route route : routes) { LOG.debug("Stopping services on route: {}", route.getId()); - // getServices will not add services again - List<Service> services = route.getServices(); - // also get route scoped services - doGetRouteScopedServices(services, route); // gather list of services to stop as we need to start child services as well + List<Service> services = new ArrayList<Service>(); + services.addAll(route.getServices()); + // also get route scoped services + doGetRouteScopedServices(services, route); Set<Service> list = new LinkedHashSet<Service>(); for (Service service : services) { list.addAll(ServiceHelper.getChildServices(service)); } + // also get route scoped error handler (which must be done last) + doGetRouteScopedErrorHandler(list, route); + + // stop services stopChildService(route, list, isShutdownCamelContext); // stop the route itself @@ -232,15 +238,18 @@ public class RouteService extends ChildS protected void doShutdown() throws Exception { for (Route route : routes) { LOG.debug("Shutting down services on route: {}", route.getId()); - List<Service> services = route.getServices(); - // also get route scoped services - doGetRouteScopedServices(services, route); // gather list of services to stop as we need to start child services as well + List<Service> services = new ArrayList<Service>(); + services.addAll(route.getServices()); + // also get route scoped services + doGetRouteScopedServices(services, route); Set<Service> list = new LinkedHashSet<Service>(); for (Service service : services) { list.addAll(ServiceHelper.getChildServices(service)); } + // also get route scoped error handler (which must be done last) + doGetRouteScopedErrorHandler(list, route); // shutdown services stopChildService(route, list, true); @@ -313,8 +322,15 @@ public class RouteService extends ChildS protected void stopChildService(Route route, Set<Service> services, boolean shutdown) throws Exception { for (Service service : services) { 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); + if (service instanceof ErrorHandler) { + // special for error handlers + for (LifecycleStrategy strategy : camelContext.getLifecycleStrategies()) { + strategy.onErrorHandlerRemove(route.getRouteContext(), (Processor) service, route.getRouteContext().getRoute().getErrorHandlerBuilder()); + } + } else { + for (LifecycleStrategy strategy : camelContext.getLifecycleStrategies()) { + strategy.onServiceRemove(camelContext, service, route); + } } if (shutdown) { ServiceHelper.stopAndShutdownService(service); @@ -326,7 +342,29 @@ public class RouteService extends ChildS } /** - * Gather all route scoped services from the given route, such as route scoped error handler. + * Gather the route scoped error handler from the given route + */ + private void doGetRouteScopedErrorHandler(Set<Service> services, Route route) { + // only include error handlers if they are route scoped + boolean includeErrorHandler = !routeDefinition.isContextScopedErrorHandler(route.getRouteContext().getCamelContext()); + List<Service> extra = new ArrayList<Service>(); + if (includeErrorHandler) { + for (Service service : services) { + if (service instanceof Channel) { + Processor eh = ((Channel) service).getErrorHandler(); + if (eh != null && eh instanceof Service) { + extra.add((Service) eh); + } + } + } + } + if (!extra.isEmpty()) { + services.addAll(extra); + } + } + + /** + * Gather all other kind of route scoped services from the given route, except error handler */ private void doGetRouteScopedServices(List<Service> services, Route route) { for (ProcessorDefinition<?> output : route.getRouteContext().getRoute().getOutputs()) { Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/management/DefaultManagementLifecycleStrategy.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/management/DefaultManagementLifecycleStrategy.java?rev=1296196&r1=1296195&r2=1296196&view=diff ============================================================================== --- camel/trunk/camel-core/src/main/java/org/apache/camel/management/DefaultManagementLifecycleStrategy.java (original) +++ camel/trunk/camel-core/src/main/java/org/apache/camel/management/DefaultManagementLifecycleStrategy.java Fri Mar 2 13:26:05 2012 @@ -556,6 +556,21 @@ public class DefaultManagementLifecycleS } } + public void onErrorHandlerRemove(RouteContext routeContext, Processor errorHandler, ErrorHandlerFactory errorHandlerBuilder) { + if (!initialized) { + return; + } + + Object me = getManagementObjectStrategy().getManagedObjectForErrorHandler(camelContext, routeContext, errorHandler, errorHandlerBuilder); + if (me != null) { + try { + unmanageObject(me); + } catch (Exception e) { + LOG.warn("Could not unregister error handler: " + me + " as ErrorHandler MBean.", e); + } + } + } + public void onThreadPoolAdd(CamelContext camelContext, ThreadPoolExecutor threadPool, String id, String sourceId, String routeId, String threadPoolProfileId) { Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/model/RouteDefinition.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/model/RouteDefinition.java?rev=1296196&r1=1296195&r2=1296196&view=diff ============================================================================== --- camel/trunk/camel-core/src/main/java/org/apache/camel/model/RouteDefinition.java (original) +++ camel/trunk/camel-core/src/main/java/org/apache/camel/model/RouteDefinition.java Fri Mar 2 13:26:05 2012 @@ -77,6 +77,9 @@ public class RouteDefinition extends Pro private ShutdownRunningTask shutdownRunningTask; private String errorHandlerRef; private ErrorHandlerFactory errorHandlerBuilder; + // keep state whether the error handler is context scoped or not + // (will by default be context scoped of no explicit error handler configured) + private boolean contextScopedErrorHandler = true; public RouteDefinition() { } @@ -437,6 +440,8 @@ public class RouteDefinition extends Pro */ public RouteDefinition errorHandler(ErrorHandlerFactory errorHandlerBuilder) { setErrorHandlerBuilder(errorHandlerBuilder); + // we are now using a route scoped error handler + contextScopedErrorHandler = false; return this; } @@ -714,7 +719,6 @@ public class RouteDefinition extends Pro return new ErrorHandlerBuilderRef(ErrorHandlerBuilderRef.DEFAULT_ERROR_HANDLER_BUILDER); } - @XmlTransient public ErrorHandlerFactory getErrorHandlerBuilder() { if (errorHandlerBuilder == null) { @@ -730,6 +734,21 @@ public class RouteDefinition extends Pro this.errorHandlerBuilder = errorHandlerBuilder; } + @SuppressWarnings("deprecation") + public boolean isContextScopedErrorHandler(CamelContext context) { + if (!contextScopedErrorHandler) { + return false; + } + // if error handler ref is configured it may refer to a context scoped, so we need to check this first + // the XML DSL will configure error handlers using refs, so we need this additional test + if (errorHandlerRef != null) { + ErrorHandlerFactory routeScoped = getErrorHandlerBuilder(); + ErrorHandlerFactory contextScoped = context.getErrorHandlerBuilder(); + return routeScoped != null && contextScoped != null && routeScoped == contextScoped; + } + + return contextScopedErrorHandler; + } // Implementation methods // ------------------------------------------------------------------------- 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=1296196&r1=1296195&r2=1296196&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 2 13:26:05 2012 @@ -64,6 +64,7 @@ public class OnCompletionProcessor exten this.useOriginalBody = useOriginalBody; } + @Override protected void doStart() throws Exception { ServiceHelper.startService(processor); } @@ -72,7 +73,12 @@ public class OnCompletionProcessor exten protected void doStop() throws Exception { ServiceHelper.stopService(processor); } - + + @Override + protected void doShutdown() throws Exception { + ServiceHelper.stopAndShutdownService(processor); + } + public CamelContext getCamelContext() { return camelContext; } Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/spi/LifecycleStrategy.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/spi/LifecycleStrategy.java?rev=1296196&r1=1296195&r2=1296196&view=diff ============================================================================== --- camel/trunk/camel-core/src/main/java/org/apache/camel/spi/LifecycleStrategy.java (original) +++ camel/trunk/camel-core/src/main/java/org/apache/camel/spi/LifecycleStrategy.java Fri Mar 2 13:26:05 2012 @@ -128,6 +128,15 @@ public interface LifecycleStrategy { void onErrorHandlerAdd(RouteContext routeContext, Processor errorHandler, ErrorHandlerFactory errorHandlerBuilder); /** + * Notification on removing error handler. + * + * @param routeContext the removed route context + * @param errorHandler the error handler + * @param errorHandlerBuilder the error handler builder + */ + void onErrorHandlerRemove(RouteContext routeContext, Processor errorHandler, ErrorHandlerFactory errorHandlerBuilder); + + /** * Notification on adding a thread pool. * * @param camelContext the camel context Modified: camel/trunk/camel-core/src/test/java/org/apache/camel/impl/DefaultCamelContextWithLifecycleStrategyRestartTest.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/impl/DefaultCamelContextWithLifecycleStrategyRestartTest.java?rev=1296196&r1=1296195&r2=1296196&view=diff ============================================================================== --- camel/trunk/camel-core/src/test/java/org/apache/camel/impl/DefaultCamelContextWithLifecycleStrategyRestartTest.java (original) +++ camel/trunk/camel-core/src/test/java/org/apache/camel/impl/DefaultCamelContextWithLifecycleStrategyRestartTest.java Fri Mar 2 13:26:05 2012 @@ -157,6 +157,10 @@ public class DefaultCamelContextWithLife } @Override + public void onErrorHandlerRemove(RouteContext routeContext, Processor errorHandler, ErrorHandlerFactory errorHandlerBuilder) { + } + + @Override public void onThreadPoolAdd(CamelContext camelContext, ThreadPoolExecutor threadPool, String id, String sourceId, String routeId, String threadPoolProfileId) { } Modified: camel/trunk/camel-core/src/test/java/org/apache/camel/impl/DummyLifecycleStrategy.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/impl/DummyLifecycleStrategy.java?rev=1296196&r1=1296195&r2=1296196&view=diff ============================================================================== --- camel/trunk/camel-core/src/test/java/org/apache/camel/impl/DummyLifecycleStrategy.java (original) +++ camel/trunk/camel-core/src/test/java/org/apache/camel/impl/DummyLifecycleStrategy.java Fri Mar 2 13:26:05 2012 @@ -86,6 +86,10 @@ public class DummyLifecycleStrategy impl events.add("onErrorHandlerAdd"); } + public void onErrorHandlerRemove(RouteContext routeContext, Processor errorHandler, ErrorHandlerFactory errorHandlerBuilder) { + events.add("onErrorHandlerRemove"); + } + public void onThreadPoolAdd(CamelContext camelContext, ThreadPoolExecutor threadPool, String id, String sourceId, String routeId, String threadPoolProfileId) { events.add("onThreadPoolAdd"); Modified: camel/trunk/camel-core/src/test/java/org/apache/camel/impl/VetoCamelContextStartTest.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/impl/VetoCamelContextStartTest.java?rev=1296196&r1=1296195&r2=1296196&view=diff ============================================================================== --- camel/trunk/camel-core/src/test/java/org/apache/camel/impl/VetoCamelContextStartTest.java (original) +++ camel/trunk/camel-core/src/test/java/org/apache/camel/impl/VetoCamelContextStartTest.java Fri Mar 2 13:26:05 2012 @@ -116,6 +116,10 @@ public class VetoCamelContextStartTest e } @Override + public void onErrorHandlerRemove(RouteContext routeContext, Processor errorHandler, ErrorHandlerFactory errorHandlerBuilder) { + } + + @Override public void onThreadPoolAdd(CamelContext camelContext, ThreadPoolExecutor threadPool, String id, String sourceId, String routeId, String threadPoolProfileId) { } Copied: camel/trunk/camel-core/src/test/java/org/apache/camel/management/ManagedRouteRemoveContextScopedErrorHandlerTest.java (from r1295578, camel/trunk/camel-core/src/test/java/org/apache/camel/management/ManagedRouteRemoveTest.java) URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/management/ManagedRouteRemoveContextScopedErrorHandlerTest.java?p2=camel/trunk/camel-core/src/test/java/org/apache/camel/management/ManagedRouteRemoveContextScopedErrorHandlerTest.java&p1=camel/trunk/camel-core/src/test/java/org/apache/camel/management/ManagedRouteRemoveTest.java&r1=1295578&r2=1296196&rev=1296196&view=diff ============================================================================== --- camel/trunk/camel-core/src/test/java/org/apache/camel/management/ManagedRouteRemoveTest.java (original) +++ camel/trunk/camel-core/src/test/java/org/apache/camel/management/ManagedRouteRemoveContextScopedErrorHandlerTest.java Fri Mar 2 13:26:05 2012 @@ -20,7 +20,6 @@ import java.util.Set; import javax.management.MBeanServer; import javax.management.ObjectName; -import org.apache.camel.Exchange; import org.apache.camel.ServiceStatus; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.component.mock.MockEndpoint; @@ -28,13 +27,7 @@ import org.apache.camel.component.mock.M /** * @version */ -public class ManagedRouteRemoveTest extends ManagementTestSupport { - - @Override - protected void setUp() throws Exception { - deleteDirectory("target/managed"); - super.setUp(); - } +public class ManagedRouteRemoveContextScopedErrorHandlerTest extends ManagementTestSupport { public void testRemove() throws Exception { MBeanServer mbeanServer = getMBeanServer(); @@ -43,7 +36,7 @@ public class ManagedRouteRemoveTest exte MockEndpoint mock = getMockEndpoint("mock:result"); mock.expectedBodiesReceived("Hello World"); - template.sendBodyAndHeader("file://target/managed", "Hello World", Exchange.FILE_NAME, "hello.txt"); + template.sendBody("seda:foo", "Hello World"); assertMockEndpointsSatisfied(); @@ -51,6 +44,10 @@ public class ManagedRouteRemoveTest exte String state = (String) mbeanServer.getAttribute(on, "State"); assertEquals("Should be started", ServiceStatus.Started.name(), state); + // and one context scoped error handler + Set<ObjectName> set = mbeanServer.queryNames(new ObjectName("*:type=errorhandlers,*"), null); + assertEquals(1, set.size()); + // stop mbeanServer.invoke(on, "stop", null, null); @@ -65,8 +62,12 @@ public class ManagedRouteRemoveTest exte assertFalse("Route mbean should have been unregistered", registered); // and no more routes - Set<ObjectName> set = mbeanServer.queryNames(new ObjectName("*:type=routes,*"), null); + set = mbeanServer.queryNames(new ObjectName("*:type=routes,*"), null); assertEquals(0, set.size()); + + // but still 1 context scoped error handler + set = mbeanServer.queryNames(new ObjectName("*:type=errorhandlers,*"), null); + assertEquals(1, set.size()); } static ObjectName getRouteObjectName(MBeanServer mbeanServer) throws Exception { @@ -81,7 +82,11 @@ public class ManagedRouteRemoveTest exte return new RouteBuilder() { @Override public void configure() throws Exception { - from("file://target/managed").to("mock:result"); + // context scoped error handler + errorHandler(deadLetterChannel("mock:dead")); + + // which this route will use + from("seda:foo").to("mock:result"); } }; } Added: camel/trunk/camel-core/src/test/java/org/apache/camel/management/ManagedRouteRemoveRouteAndContextScopedErrorHandlerTest.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/management/ManagedRouteRemoveRouteAndContextScopedErrorHandlerTest.java?rev=1296196&view=auto ============================================================================== --- camel/trunk/camel-core/src/test/java/org/apache/camel/management/ManagedRouteRemoveRouteAndContextScopedErrorHandlerTest.java (added) +++ camel/trunk/camel-core/src/test/java/org/apache/camel/management/ManagedRouteRemoveRouteAndContextScopedErrorHandlerTest.java Fri Mar 2 13:26:05 2012 @@ -0,0 +1,150 @@ +/** + * 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; + +import java.util.Iterator; +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; + +/** + * @version + */ +public class ManagedRouteRemoveRouteAndContextScopedErrorHandlerTest extends ManagementTestSupport { + + public void testRemoveFoo() throws Exception { + MBeanServer mbeanServer = getMBeanServer(); + ObjectName on = getRouteObjectName(mbeanServer, "foo"); + + MockEndpoint mock = getMockEndpoint("mock:result"); + mock.expectedBodiesReceived("Hello World"); + + template.sendBody("seda:foo", "Hello World"); + + assertMockEndpointsSatisfied(); + + // should be started + String state = (String) mbeanServer.getAttribute(on, "State"); + assertEquals("Should be started", ServiceStatus.Started.name(), state); + + // and 1 context scoped and 1 route scoped error handler + Set<ObjectName> set = mbeanServer.queryNames(new ObjectName("*:type=errorhandlers,*"), null); + assertEquals(2, set.size()); + + // stop + mbeanServer.invoke(on, "stop", null, null); + + state = (String) mbeanServer.getAttribute(on, "State"); + assertEquals("Should be stopped", ServiceStatus.Stopped.name(), state); + + // remove + mbeanServer.invoke(on, "remove", null, null); + + // should not be registered anymore + boolean registered = mbeanServer.isRegistered(on); + assertFalse("Route mbean should have been unregistered", registered); + + // and only the other route + set = mbeanServer.queryNames(new ObjectName("*:type=routes,*"), null); + assertEquals(1, set.size()); + + // and the route scoped error handler should be removed + set = mbeanServer.queryNames(new ObjectName("*:type=errorhandlers,*"), null); + assertEquals(1, set.size()); + // should be the context scoped logging error handler + assertTrue("Should be context scoped error handler: " + set, set.iterator().next().toString().contains("Logging")); + } + + public void testRemoveBar() throws Exception { + MBeanServer mbeanServer = getMBeanServer(); + ObjectName on = getRouteObjectName(mbeanServer, "bar"); + + MockEndpoint mock = getMockEndpoint("mock:result"); + mock.expectedBodiesReceived("Hello World"); + + template.sendBody("seda:bar", "Hello World"); + + assertMockEndpointsSatisfied(); + + // should be started + String state = (String) mbeanServer.getAttribute(on, "State"); + assertEquals("Should be started", ServiceStatus.Started.name(), state); + + // and 1 context scoped and 1 route scoped error handler + Set<ObjectName> set = mbeanServer.queryNames(new ObjectName("*:type=errorhandlers,*"), null); + assertEquals(2, set.size()); + + // stop + mbeanServer.invoke(on, "stop", null, null); + + state = (String) mbeanServer.getAttribute(on, "State"); + assertEquals("Should be stopped", ServiceStatus.Stopped.name(), state); + + // remove + mbeanServer.invoke(on, "remove", null, null); + + // should not be registered anymore + boolean registered = mbeanServer.isRegistered(on); + assertFalse("Route mbean should have been unregistered", registered); + + // and only the other route + set = mbeanServer.queryNames(new ObjectName("*:type=routes,*"), null); + assertEquals(1, set.size()); + + // should still be the context scoped error handler as its not removed when removing a route + set = mbeanServer.queryNames(new ObjectName("*:type=errorhandlers,*"), null); + assertEquals(2, set.size()); + } + + static ObjectName getRouteObjectName(MBeanServer mbeanServer, String name) throws Exception { + Set<ObjectName> set = mbeanServer.queryNames(new ObjectName("*:type=routes,*"), null); + assertEquals(2, set.size()); + + // return the foo route + Iterator<ObjectName> it = set.iterator(); + ObjectName on = it.next(); + if (on.toString().contains(name)) { + return on; + } else { + return it.next(); + } + } + + @Override + protected RouteBuilder createRouteBuilder() throws Exception { + return new RouteBuilder() { + @Override + public void configure() throws Exception { + // context scoped error handler + errorHandler(loggingErrorHandler("global")); + + from("seda:bar").routeId("bar") + .to("mock:result"); + + from("seda:foo").routeId("foo") + // route scoped error handler + .errorHandler(deadLetterChannel("mock:dead")) + .to("mock:result"); + } + }; + } + +} Added: camel/trunk/camel-core/src/test/java/org/apache/camel/management/ManagedRouteRemoveRouteScopedErrorHandlerTest.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/management/ManagedRouteRemoveRouteScopedErrorHandlerTest.java?rev=1296196&view=auto ============================================================================== --- camel/trunk/camel-core/src/test/java/org/apache/camel/management/ManagedRouteRemoveRouteScopedErrorHandlerTest.java (added) +++ camel/trunk/camel-core/src/test/java/org/apache/camel/management/ManagedRouteRemoveRouteScopedErrorHandlerTest.java Fri Mar 2 13:26:05 2012 @@ -0,0 +1,93 @@ +/** + * 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; + +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; + +/** + * @version + */ +public class ManagedRouteRemoveRouteScopedErrorHandlerTest extends ManagementTestSupport { + + public void testRemove() throws Exception { + MBeanServer mbeanServer = getMBeanServer(); + ObjectName on = getRouteObjectName(mbeanServer); + + MockEndpoint mock = getMockEndpoint("mock:result"); + mock.expectedBodiesReceived("Hello World"); + + template.sendBody("seda:foo", "Hello World"); + + assertMockEndpointsSatisfied(); + + // should be started + String state = (String) mbeanServer.getAttribute(on, "State"); + assertEquals("Should be started", ServiceStatus.Started.name(), state); + + // and one context scoped error handler + Set<ObjectName> set = mbeanServer.queryNames(new ObjectName("*:type=errorhandlers,*"), null); + assertEquals(1, set.size()); + + // stop + mbeanServer.invoke(on, "stop", null, null); + + state = (String) mbeanServer.getAttribute(on, "State"); + assertEquals("Should be stopped", ServiceStatus.Stopped.name(), state); + + // remove + mbeanServer.invoke(on, "remove", null, null); + + // should not be registered anymore + boolean registered = mbeanServer.isRegistered(on); + assertFalse("Route mbean should have been unregistered", registered); + + // and no more routes + set = mbeanServer.queryNames(new ObjectName("*:type=routes,*"), null); + assertEquals(0, set.size()); + + // and the route scoped error handler should be removed + set = mbeanServer.queryNames(new ObjectName("*:type=errorhandlers,*"), null); + assertEquals(0, set.size()); + } + + static ObjectName getRouteObjectName(MBeanServer mbeanServer) throws Exception { + Set<ObjectName> set = mbeanServer.queryNames(new ObjectName("*:type=routes,*"), null); + assertEquals(1, set.size()); + + return set.iterator().next(); + } + + @Override + protected RouteBuilder createRouteBuilder() throws Exception { + return new RouteBuilder() { + @Override + public void configure() throws Exception { + from("seda:foo") + // route scoped error handler + .errorHandler(deadLetterChannel("mock:dead")) + .to("mock:result"); + } + }; + } + +} Modified: camel/trunk/components/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiServiceRegistry.java URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiServiceRegistry.java?rev=1296196&r1=1296195&r2=1296196&view=diff ============================================================================== --- camel/trunk/components/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiServiceRegistry.java (original) +++ camel/trunk/components/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiServiceRegistry.java Fri Mar 2 13:26:05 2012 @@ -130,6 +130,10 @@ public class OsgiServiceRegistry impleme // noop } + public void onErrorHandlerRemove(RouteContext routeContext, Processor processor, ErrorHandlerFactory errorHandlerBuilder) { + // noop + } + public void onThreadPoolAdd(CamelContext camelContext, ThreadPoolExecutor threadPoolExecutor, String id, String sourceId, String routeId, String threadPoolProfileId) { // noop Modified: camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/DummyLifecycleStrategy.java URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/DummyLifecycleStrategy.java?rev=1296196&r1=1296195&r2=1296196&view=diff ============================================================================== --- camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/DummyLifecycleStrategy.java (original) +++ camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/DummyLifecycleStrategy.java Fri Mar 2 13:26:05 2012 @@ -66,6 +66,9 @@ public class DummyLifecycleStrategy impl public void onErrorHandlerAdd(RouteContext routeContext, Processor errorHandler, ErrorHandlerFactory errorHandlerBuilder) { } + public void onErrorHandlerRemove(RouteContext routeContext, Processor errorHandler, ErrorHandlerFactory errorHandlerBuilder) { + } + public void onRoutesRemove(Collection<Route> routes) { } Copied: camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/management/SpringManagedRouteRemoveContextScopedErrorHandlerTest.java (from r1296042, camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/management/SpringManagedNamePatternFixedTest.java) URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/management/SpringManagedRouteRemoveContextScopedErrorHandlerTest.java?p2=camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/management/SpringManagedRouteRemoveContextScopedErrorHandlerTest.java&p1=camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/management/SpringManagedNamePatternFixedTest.java&r1=1296042&r2=1296196&rev=1296196&view=diff ============================================================================== --- camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/management/SpringManagedNamePatternFixedTest.java (original) +++ camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/management/SpringManagedRouteRemoveContextScopedErrorHandlerTest.java Fri Mar 2 13:26:05 2012 @@ -17,17 +17,17 @@ package org.apache.camel.spring.management; import org.apache.camel.CamelContext; -import org.apache.camel.management.ManagedNamePatternFixedTest; +import org.apache.camel.management.ManagedRouteRemoveContextScopedErrorHandlerTest; import static org.apache.camel.spring.processor.SpringTestHelper.createSpringCamelContext; /** * @version */ -public class SpringManagedNamePatternFixedTest extends ManagedNamePatternFixedTest { +public class SpringManagedRouteRemoveContextScopedErrorHandlerTest extends ManagedRouteRemoveContextScopedErrorHandlerTest { protected CamelContext createCamelContext() throws Exception { - return createSpringCamelContext(this, "org/apache/camel/spring/management/SpringManagedNamePatternFixedTest.xml"); + return createSpringCamelContext(this, "org/apache/camel/spring/management/SpringManagedRouteRemoveContextScopedErrorHandlerTest.xml"); } } Added: camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/management/SpringManagedRouteRemoveRouteAndContextScopedErrorHandlerTest.java URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/management/SpringManagedRouteRemoveRouteAndContextScopedErrorHandlerTest.java?rev=1296196&view=auto ============================================================================== --- camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/management/SpringManagedRouteRemoveRouteAndContextScopedErrorHandlerTest.java (added) +++ camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/management/SpringManagedRouteRemoveRouteAndContextScopedErrorHandlerTest.java Fri Mar 2 13:26:05 2012 @@ -0,0 +1,33 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.spring.management; + +import org.apache.camel.CamelContext; +import org.apache.camel.management.ManagedRouteRemoveRouteAndContextScopedErrorHandlerTest; + +import static org.apache.camel.spring.processor.SpringTestHelper.createSpringCamelContext; + +/** + * @version + */ +public class SpringManagedRouteRemoveRouteAndContextScopedErrorHandlerTest extends ManagedRouteRemoveRouteAndContextScopedErrorHandlerTest { + + protected CamelContext createCamelContext() throws Exception { + return createSpringCamelContext(this, "org/apache/camel/spring/management/SpringManagedRouteRemoveRouteAndContextScopedErrorHandlerTest.xml"); + } + +} Added: camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/management/SpringManagedRouteRemoveRouteScopedErrorHandlerTest.java URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/management/SpringManagedRouteRemoveRouteScopedErrorHandlerTest.java?rev=1296196&view=auto ============================================================================== --- camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/management/SpringManagedRouteRemoveRouteScopedErrorHandlerTest.java (added) +++ camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/management/SpringManagedRouteRemoveRouteScopedErrorHandlerTest.java Fri Mar 2 13:26:05 2012 @@ -0,0 +1,33 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.spring.management; + +import org.apache.camel.CamelContext; +import org.apache.camel.management.ManagedRouteRemoveRouteScopedErrorHandlerTest; + +import static org.apache.camel.spring.processor.SpringTestHelper.createSpringCamelContext; + +/** + * @version + */ +public class SpringManagedRouteRemoveRouteScopedErrorHandlerTest extends ManagedRouteRemoveRouteScopedErrorHandlerTest { + + protected CamelContext createCamelContext() throws Exception { + return createSpringCamelContext(this, "org/apache/camel/spring/management/SpringManagedRouteRemoveRouteScopedErrorHandlerTest.xml"); + } + +} Copied: camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/management/SpringManagedRouteRemoveContextScopedErrorHandlerTest.xml (from r1296042, camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/management/SpringManagedNamePatternFixedTest.xml) URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/management/SpringManagedRouteRemoveContextScopedErrorHandlerTest.xml?p2=camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/management/SpringManagedRouteRemoveContextScopedErrorHandlerTest.xml&p1=camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/management/SpringManagedNamePatternFixedTest.xml&r1=1296042&r2=1296196&rev=1296196&view=diff ============================================================================== --- camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/management/SpringManagedNamePatternFixedTest.xml (original) +++ camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/management/SpringManagedRouteRemoveContextScopedErrorHandlerTest.xml Fri Mar 2 13:26:05 2012 @@ -27,15 +27,16 @@ <property name="domainName" value="org.apache.camel"/> </bean> - <!-- START SNIPPET: example --> - <camelContext managementNamePattern="cool" xmlns="http://camel.apache.org/schema/spring"> + <camelContext errorHandlerRef="dead" xmlns="http://camel.apache.org/schema/spring"> <jmxAgent id="agent"/> + <errorHandler id="dead" deadLetterUri="mock:dead" type="DeadLetterChannel"/> + <route> - <from uri="direct:start"/> + <from uri="seda:foo"/> <to uri="mock:result"/> </route> + </camelContext> - <!-- END SNIPPET: example --> </beans> Added: camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/management/SpringManagedRouteRemoveRouteAndContextScopedErrorHandlerTest.xml URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/management/SpringManagedRouteRemoveRouteAndContextScopedErrorHandlerTest.xml?rev=1296196&view=auto ============================================================================== --- camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/management/SpringManagedRouteRemoveRouteAndContextScopedErrorHandlerTest.xml (added) +++ camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/management/SpringManagedRouteRemoveRouteAndContextScopedErrorHandlerTest.xml Fri Mar 2 13:26:05 2012 @@ -0,0 +1,48 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + 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. +--> +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation=" + http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd + http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd + "> + + <bean id="naming" class="org.apache.camel.management.DefaultManagementNamingStrategy"> + <property name="hostName" value="localhost"/> + <property name="domainName" value="org.apache.camel"/> + </bean> + + <camelContext errorHandlerRef="logger" xmlns="http://camel.apache.org/schema/spring"> + <jmxAgent id="agent"/> + + <errorHandler id="dead" deadLetterUri="mock:dead" type="DeadLetterChannel"/> + <errorHandler id="logger" logName="global" type="LoggingErrorHandler"/> + + <route id="bar"> + <from uri="seda:bar"/> + <to uri="mock:result"/> + </route> + + <route id="foo" errorHandlerRef="dead"> + <from uri="seda:foo"/> + <to uri="mock:result"/> + </route> + + </camelContext> + +</beans> Added: camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/management/SpringManagedRouteRemoveRouteScopedErrorHandlerTest.xml URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/management/SpringManagedRouteRemoveRouteScopedErrorHandlerTest.xml?rev=1296196&view=auto ============================================================================== --- camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/management/SpringManagedRouteRemoveRouteScopedErrorHandlerTest.xml (added) +++ camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/management/SpringManagedRouteRemoveRouteScopedErrorHandlerTest.xml Fri Mar 2 13:26:05 2012 @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + 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. +--> +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation=" + http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd + http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd + "> + + <bean id="naming" class="org.apache.camel.management.DefaultManagementNamingStrategy"> + <property name="hostName" value="localhost"/> + <property name="domainName" value="org.apache.camel"/> + </bean> + + <camelContext xmlns="http://camel.apache.org/schema/spring"> + <jmxAgent id="agent"/> + + <errorHandler id="dead" deadLetterUri="mock:dead" type="DeadLetterChannel"/> + + <route errorHandlerRef="dead"> + <from uri="seda:foo"/> + <to uri="mock:result"/> + </route> + + </camelContext> + +</beans>