Updated Branches: refs/heads/master 7b995ad9a -> abba6b312
CAMEL-6576: Improved initializaiton logic of ManagementStrategy to avoid contention as well a potential NPE. Project: http://git-wip-us.apache.org/repos/asf/camel/repo Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/c6620dba Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/c6620dba Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/c6620dba Branch: refs/heads/master Commit: c6620dbace9ae1e15981f4c31b1a97b4c396cde6 Parents: 7b995ad Author: Claus Ibsen <davscl...@apache.org> Authored: Tue Jul 30 12:18:53 2013 +0200 Committer: Claus Ibsen <davscl...@apache.org> Committed: Tue Jul 30 16:27:59 2013 +0200 ---------------------------------------------------------------------- .../java/org/apache/camel/CamelContext.java | 10 ++++-- .../apache/camel/impl/DefaultCamelContext.java | 29 ++++++---------- .../management/DefaultManagementAgent.java | 3 ++ .../management/DefaultManagementStrategy.java | 24 ++++++++------ .../management/ManagedManagementStrategy.java | 6 ++++ .../management/ManagementStrategyFactory.java | 17 +++------- .../management/CamelContextDisableJmxTest.java | 35 ++++++++++++++++++++ .../xml/AbstractCamelContextFactoryBean.java | 3 -- 8 files changed, 80 insertions(+), 47 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/camel/blob/c6620dba/camel-core/src/main/java/org/apache/camel/CamelContext.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/CamelContext.java b/camel-core/src/main/java/org/apache/camel/CamelContext.java index 6db32ba..839b00d 100644 --- a/camel-core/src/main/java/org/apache/camel/CamelContext.java +++ b/camel-core/src/main/java/org/apache/camel/CamelContext.java @@ -18,7 +18,9 @@ package org.apache.camel; import java.io.IOException; import java.io.InputStream; -import java.util.*; +import java.util.Collection; +import java.util.List; +import java.util.Map; import java.util.Properties; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; @@ -1019,8 +1021,12 @@ public interface CamelContext extends SuspendableService, RuntimeConfiguration { /** * Disables using JMX as {@link org.apache.camel.spi.ManagementStrategy}. + * <p/> + * <b>Important:</b> This method must be called <b>before</b> the {@link CamelContext} is started. + * + * @throws IllegalStateException is thrown if the {@link CamelContext} is not in stopped state. */ - void disableJMX(); + void disableJMX() throws IllegalStateException; /** * Gets the inflight repository http://git-wip-us.apache.org/repos/asf/camel/blob/c6620dba/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java b/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java index fdd238a..385a920 100644 --- a/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java +++ b/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java @@ -34,7 +34,6 @@ import java.util.Set; import java.util.TreeMap; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import javax.naming.Context; import javax.xml.bind.JAXBContext; @@ -74,6 +73,7 @@ import org.apache.camel.impl.converter.BaseTypeConverterRegistry; import org.apache.camel.impl.converter.DefaultTypeConverter; import org.apache.camel.impl.converter.LazyLoadingTypeConverter; import org.apache.camel.management.DefaultManagementMBeanAssembler; +import org.apache.camel.management.DefaultManagementStrategy; import org.apache.camel.management.JmxSystemPropertyKeys; import org.apache.camel.management.ManagementStrategyFactory; import org.apache.camel.model.Constants; @@ -167,7 +167,6 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon private List<LifecycleStrategy> lifecycleStrategies = new ArrayList<LifecycleStrategy>(); private ManagementStrategy managementStrategy; private ManagementMBeanAssembler managementMBeanAssembler; - private final AtomicBoolean managementStrategyInitialized = new AtomicBoolean(false); private final List<RouteDefinition> routeDefinitions = new ArrayList<RouteDefinition>(); private List<InterceptStrategy> interceptStrategies = new ArrayList<InterceptStrategy>(); @@ -242,6 +241,10 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon packageScanClassResolver = new DefaultPackageScanClassResolver(); } + // setup management strategy first since end users may use it to add event notifiers + // using the management strategy before the CamelContext has been started + this.managementStrategy = createManagementStrategy(); + Container.Instance.manage(this); } @@ -2436,26 +2439,11 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon } public ManagementStrategy getManagementStrategy() { - synchronized (managementStrategyInitialized) { - if (!managementStrategyInitialized.get()) { - if (managementStrategyInitialized.compareAndSet(false, true)) { - managementStrategy = createManagementStrategy(); - } - } - } - return managementStrategy; } public void setManagementStrategy(ManagementStrategy managementStrategy) { - synchronized (managementStrategyInitialized) { - if (managementStrategyInitialized.get()) { - log.warn("Resetting ManagementStrategy for CamelContext: " + getName()); - } - - this.managementStrategy = managementStrategy; - managementStrategyInitialized.set(true); - } + this.managementStrategy = managementStrategy; } public InterceptStrategy getDefaultTracer() { @@ -2492,7 +2480,10 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon } public void disableJMX() { - disableJMX = true; + if (isStarting() || isStarted()) { + throw new IllegalStateException("Disabling JMX can only be done when CamelContext has not been started"); + } + managementStrategy = new DefaultManagementStrategy(this); } public InflightRepository getInflightRepository() { http://git-wip-us.apache.org/repos/asf/camel/blob/c6620dba/camel-core/src/main/java/org/apache/camel/management/DefaultManagementAgent.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/management/DefaultManagementAgent.java b/camel-core/src/main/java/org/apache/camel/management/DefaultManagementAgent.java index d2e57fb..eeda9c9 100644 --- a/camel-core/src/main/java/org/apache/camel/management/DefaultManagementAgent.java +++ b/camel-core/src/main/java/org/apache/camel/management/DefaultManagementAgent.java @@ -265,6 +265,9 @@ public class DefaultManagementAgent extends ServiceSupport implements Management protected void doStart() throws Exception { ObjectHelper.notNull(camelContext, "CamelContext"); + // must add management lifecycle strategy + camelContext.getLifecycleStrategies().add(0, new DefaultManagementLifecycleStrategy(camelContext)); + // create mbean server if is has not be injected. if (server == null) { finalizeSettings(); http://git-wip-us.apache.org/repos/asf/camel/blob/c6620dba/camel-core/src/main/java/org/apache/camel/management/DefaultManagementStrategy.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/management/DefaultManagementStrategy.java b/camel-core/src/main/java/org/apache/camel/management/DefaultManagementStrategy.java index f71f9ba..63aa132 100644 --- a/camel-core/src/main/java/org/apache/camel/management/DefaultManagementStrategy.java +++ b/camel-core/src/main/java/org/apache/camel/management/DefaultManagementStrategy.java @@ -32,8 +32,11 @@ import org.apache.camel.spi.ManagementAgent; import org.apache.camel.spi.ManagementNamingStrategy; import org.apache.camel.spi.ManagementObjectStrategy; import org.apache.camel.spi.ManagementStrategy; +import org.apache.camel.support.ServiceSupport; import org.apache.camel.util.ObjectHelper; import org.apache.camel.util.ServiceHelper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * A default management strategy that does <b>not</b> manage. @@ -48,8 +51,9 @@ import org.apache.camel.util.ServiceHelper; * @see ManagedManagementStrategy * @version */ -public class DefaultManagementStrategy implements ManagementStrategy, CamelContextAware { +public class DefaultManagementStrategy extends ServiceSupport implements ManagementStrategy, CamelContextAware { + private static final transient Logger LOG = LoggerFactory.getLogger(DefaultManagementStrategy.class); private List<EventNotifier> eventNotifiers = new CopyOnWriteArrayList<EventNotifier>(); private EventFactory eventFactory = new DefaultEventFactory(); private ManagementNamingStrategy managementNamingStrategy; @@ -198,7 +202,12 @@ public class DefaultManagementStrategy implements ManagementStrategy, CamelConte this.loadStatisticsEnabled = loadStatisticsEnabled; } - public void start() throws Exception { + protected void doStart() throws Exception { + LOG.info("JMX is disabled"); + doStartManagementStrategy(); + } + + protected void doStartManagementStrategy() throws Exception { ObjectHelper.notNull(camelContext, "CamelContext"); if (eventNotifiers != null) { @@ -215,7 +224,7 @@ public class DefaultManagementStrategy implements ManagementStrategy, CamelConte } if (managementAgent != null) { - managementAgent.start(); + ServiceHelper.startService(managementAgent); // set the naming strategy using the domain name from the agent if (managementNamingStrategy == null) { setManagementNamingStrategy(new DefaultManagementNamingStrategy(managementAgent.getMBeanObjectDomainName())); @@ -226,13 +235,8 @@ public class DefaultManagementStrategy implements ManagementStrategy, CamelConte } } - public void stop() throws Exception { - if (managementAgent != null) { - managementAgent.stop(); - } - if (eventNotifiers != null) { - ServiceHelper.stopServices(eventNotifiers); - } + protected void doStop() throws Exception { + ServiceHelper.stopServices(managementAgent, eventNotifiers); } } http://git-wip-us.apache.org/repos/asf/camel/blob/c6620dba/camel-core/src/main/java/org/apache/camel/management/ManagedManagementStrategy.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/management/ManagedManagementStrategy.java b/camel-core/src/main/java/org/apache/camel/management/ManagedManagementStrategy.java index c16e5c1..f89ffb4 100644 --- a/camel-core/src/main/java/org/apache/camel/management/ManagedManagementStrategy.java +++ b/camel-core/src/main/java/org/apache/camel/management/ManagedManagementStrategy.java @@ -182,4 +182,10 @@ public class ManagedManagementStrategy extends DefaultManagementStrategy { return objectName; } + @Override + protected void doStart() throws Exception { + LOG.info("JMX is enabled"); + doStartManagementStrategy(); + } + } http://git-wip-us.apache.org/repos/asf/camel/blob/c6620dba/camel-core/src/main/java/org/apache/camel/management/ManagementStrategyFactory.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/management/ManagementStrategyFactory.java b/camel-core/src/main/java/org/apache/camel/management/ManagementStrategyFactory.java index 44b7602..50d55fa 100644 --- a/camel-core/src/main/java/org/apache/camel/management/ManagementStrategyFactory.java +++ b/camel-core/src/main/java/org/apache/camel/management/ManagementStrategyFactory.java @@ -18,7 +18,6 @@ package org.apache.camel.management; import org.apache.camel.CamelContext; import org.apache.camel.spi.ManagementStrategy; -import org.apache.camel.util.ServiceHelper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -29,27 +28,19 @@ public class ManagementStrategyFactory { private final transient Logger log = LoggerFactory.getLogger(getClass()); public ManagementStrategy create(CamelContext context, boolean disableJMX) { - ManagementStrategy answer = null; + ManagementStrategy answer; if (disableJMX || Boolean.getBoolean(JmxSystemPropertyKeys.DISABLED)) { - log.info("JMX is disabled."); + answer = new DefaultManagementStrategy(context); } else { try { answer = new ManagedManagementStrategy(context, new DefaultManagementAgent(context)); - // must start it to ensure JMX works and can load needed Spring JARs - ServiceHelper.startService(answer); - // prefer to have it at first strategy - context.getLifecycleStrategies().add(0, new DefaultManagementLifecycleStrategy(context)); - log.info("JMX enabled."); } catch (Exception e) { - answer = null; log.warn("Cannot create JMX lifecycle strategy. Will fallback and disable JMX.", e); + answer = new DefaultManagementStrategy(context); } } - - if (answer == null) { - answer = new DefaultManagementStrategy(context); - } return answer; } + } http://git-wip-us.apache.org/repos/asf/camel/blob/c6620dba/camel-core/src/test/java/org/apache/camel/management/CamelContextDisableJmxTest.java ---------------------------------------------------------------------- diff --git a/camel-core/src/test/java/org/apache/camel/management/CamelContextDisableJmxTest.java b/camel-core/src/test/java/org/apache/camel/management/CamelContextDisableJmxTest.java new file mode 100644 index 0000000..2946e3c --- /dev/null +++ b/camel-core/src/test/java/org/apache/camel/management/CamelContextDisableJmxTest.java @@ -0,0 +1,35 @@ +/** + * 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 junit.framework.TestCase; +import org.apache.camel.CamelContext; +import org.apache.camel.impl.DefaultCamelContext; + +public class CamelContextDisableJmxTest extends TestCase { + + public void testDisableJmx() throws Exception { + CamelContext context = new DefaultCamelContext(); + context.disableJMX(); + context.start(); + + // JMX should be disabled and therefore not a ManagedManagementStrategy instance + assertFalse(context.getManagementStrategy() instanceof ManagedManagementStrategy); + + context.stop(); + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/c6620dba/components/camel-core-xml/src/main/java/org/apache/camel/core/xml/AbstractCamelContextFactoryBean.java ---------------------------------------------------------------------- diff --git a/components/camel-core-xml/src/main/java/org/apache/camel/core/xml/AbstractCamelContextFactoryBean.java b/components/camel-core-xml/src/main/java/org/apache/camel/core/xml/AbstractCamelContextFactoryBean.java index 05e6568..76b0c69 100644 --- a/components/camel-core-xml/src/main/java/org/apache/camel/core/xml/AbstractCamelContextFactoryBean.java +++ b/components/camel-core-xml/src/main/java/org/apache/camel/core/xml/AbstractCamelContextFactoryBean.java @@ -370,9 +370,6 @@ public abstract class AbstractCamelContextFactoryBean<T extends ModelCamelContex ManagementStrategy managementStrategy = new ManagedManagementStrategy(getContext(), agent); getContext().setManagementStrategy(managementStrategy); - // clear the existing lifecycle strategies define by the DefaultCamelContext constructor - getContext().getLifecycleStrategies().clear(); - getContext().addLifecycleStrategy(new DefaultManagementLifecycleStrategy(getContext())); // set additional configuration from camelJMXAgent boolean onlyId = agent.getOnlyRegisterProcessorWithCustomId() != null && agent.getOnlyRegisterProcessorWithCustomId(); getContext().getManagementStrategy().onlyManageProcessorWithCustomId(onlyId);