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 2021/02/01 09:17:49 UTC

[camel] branch master updated: CAMEL-16070: CamelContext - Restart via stop/start is no longer supported (was not recommended before).

This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/master by this push:
     new dd17648  CAMEL-16070: CamelContext - Restart via stop/start is no longer supported (was not recommended before).
dd17648 is described below

commit dd17648e945e94581c5fce951cc9ee2b88348e0a
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Mon Feb 1 10:17:11 2021 +0100

    CAMEL-16070: CamelContext - Restart via stop/start is no longer supported (was not recommended before).
---
 .../main/java/org/apache/camel/CamelContext.java   |   8 +-
 .../camel/impl/engine/AbstractCamelContext.java    |  38 +++----
 ...rectVmTwoCamelContextDuplicateConsumerTest.java |   4 +-
 .../component/log/LogCustomFormatterTest.java      |  16 +--
 .../camel/component/timer/TimerRestartTest.java    |   4 +-
 .../vm/VmMultipleContextsStartStopTest.java        |   4 +-
 .../camel/impl/DefaultCamelContextRestartTest.java |  23 ++--
 ...melContextWithLifecycleStrategyRestartTest.java | 124 ---------------------
 .../camel/impl/engine/DefaultCamelContextTest.java |  22 ----
 .../management/mbean/ManagedCamelContextMBean.java |   3 -
 .../management/mbean/ManagedCamelContext.java      |   6 -
 .../management/ManagedCamelContextRestartTest.java | 119 --------------------
 .../ROOT/pages/camel-3x-upgrade-guide-3_8.adoc     |   5 +
 13 files changed, 40 insertions(+), 336 deletions(-)

diff --git a/core/camel-api/src/main/java/org/apache/camel/CamelContext.java b/core/camel-api/src/main/java/org/apache/camel/CamelContext.java
index 44b31ed..31ea6c3 100644
--- a/core/camel-api/src/main/java/org/apache/camel/CamelContext.java
+++ b/core/camel-api/src/main/java/org/apache/camel/CamelContext.java
@@ -70,12 +70,8 @@ import org.apache.camel.support.jsse.SSLContextParameters;
  * <b>Notice:</b> {@link #stop()} and {@link #suspend()} will gracefully stop/suspend routes ensuring any messages in
  * progress will be given time to complete. See more details at {@link org.apache.camel.spi.ShutdownStrategy}.
  * <p/>
- * If you are doing a hot restart then it's advised to use the suspend/resume methods which ensure a faster restart but
- * also allows any internal state to be kept as is. The stop/start approach will do a <i>cold</i> restart of Camel,
- * where all internal state is reset.
- * <p/>
- * End users are advised to use suspend/resume. Using stop is for shutting down Camel and it's not guaranteed that when
- * it's being started again using the start method that Camel will operate consistently.
+ * If you are doing a restart then use the suspend/resume methods, it is not possible to start a CamelContext after it
+ * has been stopped.
  * <p/>
  * For more advanced APIs with {@link CamelContext} see {@link ExtendedCamelContext}, which you can obtain via the adapt
  * method.
diff --git a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java
index 6cb184d..0f8198b 100644
--- a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java
+++ b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java
@@ -231,9 +231,6 @@ public abstract class AbstractCamelContext extends BaseService
     private volatile RestConfiguration restConfiguration;
     private List<InterceptStrategy> interceptStrategies = new ArrayList<>();
     private List<RoutePolicyFactory> routePolicyFactories = new ArrayList<>();
-    // special flags to control the first startup which can are special
-    private volatile boolean firstStartDone;
-    private volatile boolean doNotStartRoutesOnFirstStart;
     private Initialization initialization = Initialization.Default;
     private Boolean autoStartup = Boolean.TRUE;
     private Boolean backlogTrace = Boolean.FALSE;
@@ -321,6 +318,7 @@ public abstract class AbstractCamelContext extends BaseService
     private long startDate;
     private SSLContextParameters sslContextParameters;
     private StartupSummaryLevel startupSummaryLevel = StartupSummaryLevel.Default;
+    private boolean closed;
 
     /**
      * Creates the {@link CamelContext} using {@link org.apache.camel.support.DefaultRegistry} as registry.
@@ -2775,6 +2773,11 @@ public abstract class AbstractCamelContext extends BaseService
 
     @Override
     protected void doStart() throws Exception {
+        if (closed) {
+            throw new IllegalStateException(
+                    "CamelContext cannot be started after it has previously been stopped. You can use suspend/resume instead.");
+        }
+
         StartupStep step = startupStepRecorder.beginStep(CamelContext.class, getName(), "Start CamelContext");
 
         try {
@@ -2808,25 +2811,9 @@ public abstract class AbstractCamelContext extends BaseService
         // Start the route controller
         ServiceHelper.startService(this.routeController);
 
-        doNotStartRoutesOnFirstStart = !firstStartDone && !isAutoStartup();
-
-        // if the context was configured with auto startup = false, and we
-        // are already started,
-        // then we may need to start the routes on the 2nd start call
-        if (firstStartDone && !isAutoStartup() && isStarted()) {
-            // invoke this logic to warm up the routes and if possible also
-            // start the routes
-            try {
-                internalRouteStartupManager.doStartOrResumeRoutes(routeServices, true, true, false, true);
-            } catch (Exception e) {
-                throw RuntimeCamelException.wrapRuntimeException(e);
-            }
-        }
-
         // super will invoke doStart which will prepare internal services
         // and start routes etc.
         try {
-            firstStartDone = true;
             doStartCamel();
         } catch (Exception e) {
             VetoCamelContextStartException veto = ObjectHelper.getException(VetoCamelContextStartException.class, e);
@@ -3124,14 +3111,14 @@ public abstract class AbstractCamelContext extends BaseService
         }
 
         // start routes
-        if (doNotStartRoutesOnFirstStart) {
+        if (!isAutoStartup()) {
             LOG.debug("Skip starting routes as CamelContext has been configured with autoStartup=false");
         }
 
         // invoke this logic to warmup the routes and if possible also start the routes
         StartupStep subStep = startupStepRecorder.beginStep(CamelContext.class, getName(), "Start Routes");
         EventHelper.notifyCamelContextRoutesStarting(this);
-        internalRouteStartupManager.doStartOrResumeRoutes(routeServices, true, !doNotStartRoutesOnFirstStart, false, true);
+        internalRouteStartupManager.doStartOrResumeRoutes(routeServices, true, isAutoStartup(), false, true);
         EventHelper.notifyCamelContextRoutesStarted(this);
         startupStepRecorder.endStep(subStep);
 
@@ -3307,6 +3294,15 @@ public abstract class AbstractCamelContext extends BaseService
         // Call all registered trackers with this context
         // Note, this may use a partially constructed object
         CamelContextTracker.notifyContextDestroyed(this);
+
+        closed = true;
+    }
+
+    @Override
+    protected void doFail(Exception e) {
+        // if we failed during start then dont mark as closed
+        closed = false;
+        super.doFail(e);
     }
 
     protected void logRouteStopSummary() {
diff --git a/core/camel-core/src/test/java/org/apache/camel/component/directvm/DirectVmTwoCamelContextDuplicateConsumerTest.java b/core/camel-core/src/test/java/org/apache/camel/component/directvm/DirectVmTwoCamelContextDuplicateConsumerTest.java
index 229ba8a..84204ca 100644
--- a/core/camel-core/src/test/java/org/apache/camel/component/directvm/DirectVmTwoCamelContextDuplicateConsumerTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/component/directvm/DirectVmTwoCamelContextDuplicateConsumerTest.java
@@ -43,8 +43,8 @@ public class DirectVmTwoCamelContextDuplicateConsumerTest extends AbstractDirect
                     e.getMessage());
         }
 
-        // stop first camel context then
-        context.stop();
+        // suspend first camel context then
+        context.suspend();
 
         // and start the 3rd which should work now
         third.start();
diff --git a/core/camel-core/src/test/java/org/apache/camel/component/log/LogCustomFormatterTest.java b/core/camel-core/src/test/java/org/apache/camel/component/log/LogCustomFormatterTest.java
index d8ebdc7..8514706 100644
--- a/core/camel-core/src/test/java/org/apache/camel/component/log/LogCustomFormatterTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/component/log/LogCustomFormatterTest.java
@@ -21,7 +21,6 @@ import org.apache.camel.Exchange;
 import org.apache.camel.ResolveEndpointFailedException;
 import org.apache.camel.spi.ExchangeFormatter;
 import org.apache.camel.support.processor.DefaultExchangeFormatter;
-import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 
 import static org.junit.jupiter.api.Assertions.*;
@@ -33,16 +32,13 @@ public class LogCustomFormatterTest extends ContextTestSupport {
 
     private TestExchangeFormatter exchangeFormatter;
 
-    @BeforeEach
     @Override
-    public void setUp() throws Exception {
-        super.setUp();
+    public boolean isUseRouteBuilder() {
+        return false;
     }
 
     @Test
     public void testCustomFormatterInComponent() throws Exception {
-        context.stop();
-
         LogComponent log = new LogComponent();
         exchangeFormatter = new TestExchangeFormatter();
         log.setExchangeFormatter(exchangeFormatter);
@@ -61,8 +57,6 @@ public class LogCustomFormatterTest extends ContextTestSupport {
 
     @Test
     public void testCustomFormatterInRegistry() throws Exception {
-        context.stop();
-
         exchangeFormatter = new TestExchangeFormatter();
         context.getRegistry().bind("logFormatter", exchangeFormatter);
 
@@ -79,8 +73,6 @@ public class LogCustomFormatterTest extends ContextTestSupport {
 
     @Test
     public void testCustomFormatterInRegistryOptions() throws Exception {
-        context.stop();
-
         exchangeFormatter = new TestExchangeFormatter();
         context.getRegistry().bind("logFormatter", exchangeFormatter);
         assertEquals("", exchangeFormatter.getPrefix());
@@ -97,8 +89,6 @@ public class LogCustomFormatterTest extends ContextTestSupport {
 
     @Test
     public void testCustomFormatterInRegistryUnknownOption() throws Exception {
-        context.stop();
-
         exchangeFormatter = new TestExchangeFormatter();
         context.getRegistry().bind("logFormatter", exchangeFormatter);
         assertEquals("", exchangeFormatter.getPrefix());
@@ -118,8 +108,6 @@ public class LogCustomFormatterTest extends ContextTestSupport {
 
     @Test
     public void testFormatterNotPickedUpWithDifferentKey() throws Exception {
-        context.stop();
-
         exchangeFormatter = new TestExchangeFormatter();
         context.getRegistry().bind("anotherFormatter", exchangeFormatter);
         context.getRegistry().bind("yetAnotherFormatter", new DefaultExchangeFormatter());
diff --git a/core/camel-core/src/test/java/org/apache/camel/component/timer/TimerRestartTest.java b/core/camel-core/src/test/java/org/apache/camel/component/timer/TimerRestartTest.java
index dbf4bc7..3a16f4a 100644
--- a/core/camel-core/src/test/java/org/apache/camel/component/timer/TimerRestartTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/component/timer/TimerRestartTest.java
@@ -33,11 +33,11 @@ public class TimerRestartTest extends ContextTestSupport {
         mock.reset();
         mock.expectedMessageCount(0);
 
-        context.stop();
+        context.suspend();
 
         mock.reset();
 
-        context.start();
+        context.resume();
 
         mock.expectedMinimumMessageCount(1);
 
diff --git a/core/camel-core/src/test/java/org/apache/camel/component/vm/VmMultipleContextsStartStopTest.java b/core/camel-core/src/test/java/org/apache/camel/component/vm/VmMultipleContextsStartStopTest.java
index 2339359..08997e2 100644
--- a/core/camel-core/src/test/java/org/apache/camel/component/vm/VmMultipleContextsStartStopTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/component/vm/VmMultipleContextsStartStopTest.java
@@ -32,8 +32,8 @@ public class VmMultipleContextsStartStopTest extends AbstractVmTestSupport {
         mock.reset();
 
         /* Restart the consumer Camel Context */
-        context2.stop();
-        context2.start();
+        context2.suspend();
+        context2.resume();
 
         /* Send a message again and assert that it's received */
         template.requestBody("direct:test", "Hello world!");
diff --git a/core/camel-core/src/test/java/org/apache/camel/impl/DefaultCamelContextRestartTest.java b/core/camel-core/src/test/java/org/apache/camel/impl/DefaultCamelContextRestartTest.java
index 4e97c7a..6ce47a5 100644
--- a/core/camel-core/src/test/java/org/apache/camel/impl/DefaultCamelContextRestartTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/impl/DefaultCamelContextRestartTest.java
@@ -22,9 +22,6 @@ import org.junit.jupiter.api.Test;
 
 import static org.junit.jupiter.api.Assertions.*;
 
-/**
- *
- */
 public class DefaultCamelContextRestartTest extends ContextTestSupport {
 
     @Test
@@ -44,18 +41,14 @@ public class DefaultCamelContextRestartTest extends ContextTestSupport {
         assertEquals(0, context.getRoutes().size());
 
         // now start
-        context.start();
-        assertTrue(context.getStatus().isStarted());
-        assertFalse(context.getStatus().isStopped());
-        assertEquals(1, context.getRoutes().size());
-
-        // must obtain a new template
-        template = context.createProducerTemplate();
-
-        // should still work
-        getMockEndpoint("mock:result").expectedMessageCount(1);
-        template.sendBody("direct:start", "Bye World");
-        assertMockEndpointsSatisfied();
+        try {
+            context.start();
+            fail("Should throw exception");
+        } catch (IllegalStateException e) {
+            assertEquals(
+                    "CamelContext cannot be started after it has previously been stopped. You can use suspend/resume instead.",
+                    e.getMessage());
+        }
     }
 
     @Override
diff --git a/core/camel-core/src/test/java/org/apache/camel/impl/DefaultCamelContextWithLifecycleStrategyRestartTest.java b/core/camel-core/src/test/java/org/apache/camel/impl/DefaultCamelContextWithLifecycleStrategyRestartTest.java
deleted file mode 100644
index 4167d65..0000000
--- a/core/camel-core/src/test/java/org/apache/camel/impl/DefaultCamelContextWithLifecycleStrategyRestartTest.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * 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.impl;
-
-import java.util.Collection;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import org.apache.camel.CamelContext;
-import org.apache.camel.ContextTestSupport;
-import org.apache.camel.Route;
-import org.apache.camel.VetoCamelContextStartException;
-import org.apache.camel.builder.RouteBuilder;
-import org.apache.camel.support.LifecycleStrategySupport;
-import org.junit.jupiter.api.Test;
-
-import static org.junit.jupiter.api.Assertions.*;
-
-/**
- *
- */
-public class DefaultCamelContextWithLifecycleStrategyRestartTest extends ContextTestSupport {
-
-    private MyStrategy strategy = new MyStrategy();
-
-    @Test
-    public void testRestart() throws Exception {
-        assertTrue(context.getStatus().isStarted());
-        assertFalse(context.getStatus().isStopped());
-        assertEquals(1, context.getRoutes().size());
-        assertEquals(1, strategy.getContextStartCounter());
-
-        getMockEndpoint("mock:result").expectedMessageCount(1);
-        template.sendBody("direct:start", "Hello World");
-        assertMockEndpointsSatisfied();
-
-        // now stop
-        context.stop();
-        assertFalse(context.getStatus().isStarted());
-        assertTrue(context.getStatus().isStopped());
-        assertEquals(0, context.getRoutes().size());
-
-        // now start
-        context.start();
-        assertTrue(context.getStatus().isStarted());
-        assertFalse(context.getStatus().isStopped());
-        assertEquals(1, context.getRoutes().size());
-        assertEquals(2, strategy.getContextStartCounter());
-
-        // must obtain a new template
-        template = context.createProducerTemplate();
-
-        // should still work
-        getMockEndpoint("mock:result").expectedMessageCount(1);
-        template.sendBody("direct:start", "Bye World");
-        assertMockEndpointsSatisfied();
-    }
-
-    @Test
-    public void testRouteStopped() throws Exception {
-        assertTrue(context.getRouteController().getRouteStatus("foo").isStarted());
-        assertEquals(0, strategy.getRemoveCounter());
-
-        context.getRouteController().stopRoute("foo");
-        assertEquals(0, strategy.getRemoveCounter());
-
-        context.removeRoute("foo");
-        assertEquals(1, strategy.getRemoveCounter());
-    }
-
-    @Override
-    protected CamelContext createCamelContext() throws Exception {
-        CamelContext context = super.createCamelContext();
-        context.addLifecycleStrategy(strategy);
-        return context;
-    }
-
-    @Override
-    protected RouteBuilder createRouteBuilder() throws Exception {
-        return new RouteBuilder() {
-            @Override
-            public void configure() throws Exception {
-                from("direct:start").routeId("foo").to("mock:result");
-            }
-        };
-    }
-
-    private class MyStrategy extends LifecycleStrategySupport {
-
-        private AtomicInteger contextStartCounter = new AtomicInteger();
-        private AtomicInteger removeCounter = new AtomicInteger();
-
-        @Override
-        public void onContextStart(CamelContext context) throws VetoCamelContextStartException {
-            contextStartCounter.incrementAndGet();
-        }
-
-        @Override
-        public void onRoutesRemove(Collection<Route> routes) {
-            removeCounter.incrementAndGet();
-        }
-
-        public int getContextStartCounter() {
-            return contextStartCounter.get();
-        }
-
-        public int getRemoveCounter() {
-            return removeCounter.get();
-        }
-    }
-}
diff --git a/core/camel-core/src/test/java/org/apache/camel/impl/engine/DefaultCamelContextTest.java b/core/camel-core/src/test/java/org/apache/camel/impl/engine/DefaultCamelContextTest.java
index 1b4e436..29725b5 100644
--- a/core/camel-core/src/test/java/org/apache/camel/impl/engine/DefaultCamelContextTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/impl/engine/DefaultCamelContextTest.java
@@ -196,28 +196,6 @@ public class DefaultCamelContextTest extends TestSupport {
     }
 
     @Test
-    public void testRestartCamelContext() throws Exception {
-        DefaultCamelContext ctx = new DefaultCamelContext(false);
-        ctx.disableJMX();
-        ctx.addRoutes(new RouteBuilder() {
-            @Override
-            public void configure() throws Exception {
-                from("direct:endpointA").to("mock:endpointB");
-            }
-        });
-        ctx.start();
-        assertEquals(1, ctx.getRouteServices().size(), "Should have one RouteService");
-        String routesString = ctx.getRoutes().toString();
-        ctx.stop();
-        assertEquals(1, ctx.getRouteServices().size(), "The RouteService should NOT be removed even when we stop");
-        ctx.start();
-        assertEquals(1, ctx.getRouteServices().size(), "Should have one RouteService");
-        assertEquals(routesString, ctx.getRoutes().toString(), "The Routes should be same");
-        ctx.stop();
-        assertEquals(1, ctx.getRouteServices().size(), "The RouteService should NOT be removed even when we stop");
-    }
-
-    @Test
     public void testName() {
         DefaultCamelContext ctx = new DefaultCamelContext(false);
         ctx.disableJMX();
diff --git a/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/ManagedCamelContextMBean.java b/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/ManagedCamelContextMBean.java
index 34a931f..292e2e6 100644
--- a/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/ManagedCamelContextMBean.java
+++ b/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/ManagedCamelContextMBean.java
@@ -143,9 +143,6 @@ public interface ManagedCamelContextMBean extends ManagedPerformanceCounterMBean
     @ManagedOperation(description = "Stop Camel (shutdown)")
     void stop() throws Exception;
 
-    @ManagedOperation(description = "Restart Camel (stop and then start)")
-    void restart() throws Exception;
-
     @ManagedOperation(description = "Suspend Camel")
     void suspend() throws Exception;
 
diff --git a/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedCamelContext.java b/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedCamelContext.java
index ef5facf..2aab316 100644
--- a/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedCamelContext.java
+++ b/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedCamelContext.java
@@ -307,12 +307,6 @@ public class ManagedCamelContext extends ManagedPerformanceCounter implements Ti
     }
 
     @Override
-    public void restart() throws Exception {
-        context.stop();
-        context.start();
-    }
-
-    @Override
     public void suspend() throws Exception {
         context.suspend();
     }
diff --git a/core/camel-management/src/test/java/org/apache/camel/management/ManagedCamelContextRestartTest.java b/core/camel-management/src/test/java/org/apache/camel/management/ManagedCamelContextRestartTest.java
deleted file mode 100644
index e02b320..0000000
--- a/core/camel-management/src/test/java/org/apache/camel/management/ManagedCamelContextRestartTest.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * 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 javax.management.MBeanServer;
-import javax.management.ObjectName;
-
-import org.apache.camel.builder.RouteBuilder;
-import org.apache.camel.component.mock.MockEndpoint;
-import org.apache.camel.spi.CamelEvent;
-import org.apache.camel.support.EventNotifierSupport;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
-public class ManagedCamelContextRestartTest extends ManagementTestSupport {
-
-    private int starts;
-    private int stops;
-
-    @Override
-    @BeforeEach
-    public void setUp() throws Exception {
-
-        super.setUp();
-
-        context.getManagementStrategy().addEventNotifier(new EventNotifierSupport() {
-            @Override
-            public void notify(CamelEvent event) throws Exception {
-                // Empty.
-            }
-
-            @Override
-            protected void doStart() throws Exception {
-                starts++;
-            }
-
-            @Override
-            protected void doStop() throws Exception {
-                stops++;
-            }
-        });
-    }
-
-    @Test
-    public void testManagedCamelContext() throws Exception {
-        // JMX tests dont work well on AIX CI servers (hangs them)
-        if (isPlatform("aix")) {
-            return;
-        }
-
-        MBeanServer mbeanServer = getMBeanServer();
-
-        ObjectName on = ObjectName.getInstance("org.apache.camel:context=camel-1,type=context,name=\"camel-1\"");
-
-        assertTrue(mbeanServer.isRegistered(on), "Should be registered");
-        String name = (String) mbeanServer.getAttribute(on, "CamelId");
-        assertEquals("camel-1", name);
-
-        String uptime = (String) mbeanServer.getAttribute(on, "Uptime");
-        assertNotNull(uptime);
-
-        long uptimeMillis = (Long) mbeanServer.getAttribute(on, "UptimeMillis");
-        assertTrue(uptimeMillis > 0);
-
-        String status = (String) mbeanServer.getAttribute(on, "State");
-        assertEquals("Started", status);
-
-        // invoke operations
-        MockEndpoint mock = getMockEndpoint("mock:result");
-        mock.expectedBodiesReceived("Hello World");
-
-        Object reply = mbeanServer.invoke(on, "requestBody", new Object[] { "direct:foo", "Hello World" },
-                new String[] { "java.lang.String", "java.lang.Object" });
-        assertEquals("Bye World", reply);
-
-        // restart Camel
-        assertEquals(0, starts);
-        assertEquals(0, stops);
-        mbeanServer.invoke(on, "restart", null, null);
-        assertEquals(1, starts);
-        assertEquals(1, stops);
-
-        status = (String) mbeanServer.getAttribute(on, "State");
-        assertEquals("Started", status);
-
-        reply = mbeanServer.invoke(on, "requestBody", new Object[] { "direct:foo", "Hello Camel" },
-                new String[] { "java.lang.String", "java.lang.Object" });
-        assertEquals("Bye World", reply);
-    }
-
-    @Override
-    protected RouteBuilder createRouteBuilder() throws Exception {
-        return new RouteBuilder() {
-            @Override
-            public void configure() throws Exception {
-                from("direct:foo").delay(10).transform(constant("Bye World"));
-            }
-        };
-    }
-
-}
diff --git a/docs/user-manual/modules/ROOT/pages/camel-3x-upgrade-guide-3_8.adoc b/docs/user-manual/modules/ROOT/pages/camel-3x-upgrade-guide-3_8.adoc
index 585bcf6..1215324 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-3x-upgrade-guide-3_8.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-3x-upgrade-guide-3_8.adoc
@@ -17,6 +17,11 @@ are also initialized. An affect of this change is that any custom Camel componen
 the constructors of `Consumer` or `Producer` should *not* do this, but move this logic to `doInit` or `doStart` where
 such logic correctly belongs.
 
+=== Restart CamelContext
+
+It is no longer possible to start `CamelContext` after it has been stopped. To restart a context, then use suspend/resume.
+The `restart` JMX operation on `CamelContextMBean` has been removed from `camel-management`.
+
 === API changes
 
 The following type names are renamed in `CamelEvent.Type` enum: