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

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

commit ac64622f8d934648379543e6c773cebcafd76b6a
Author: Акинцев Валерий Андреевич <[email protected]>
AuthorDate: Wed Apr 21 22:28:03 2021 +0300

    CAMEL-16494: After VetoCamelContextStartException CamelContext instance 
broken forever
---
 .../apache/camel/support/service/BaseService.java  |   4 +
 .../camel/impl/engine/AbstractCamelContext.java    |  50 +++++---
 .../engine/VetoCamelContextStartExceptionTest.java | 139 +++++++++++++++++++++
 3 files changed, 176 insertions(+), 17 deletions(-)

diff --git 
a/core/camel-api/src/main/java/org/apache/camel/support/service/BaseService.java
 
b/core/camel-api/src/main/java/org/apache/camel/support/service/BaseService.java
index 8cfc17d..6ee434c 100644
--- 
a/core/camel-api/src/main/java/org/apache/camel/support/service/BaseService.java
+++ 
b/core/camel-api/src/main/java/org/apache/camel/support/service/BaseService.java
@@ -109,6 +109,10 @@ public abstract class BaseService {
                 return;
             }
             init();
+            if (status == FAILED) {
+                LOG.trace("Init failed");
+                return;
+            }
             try (AutoCloseable ignored = doLifecycleChange()) {
                 status = STARTING;
                 LOG.trace("Starting service: {}", this);
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 b73bb94..6f35049 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
@@ -2476,18 +2476,21 @@ public abstract class AbstractCamelContext extends 
BaseService
 
     @Override
     public void init() {
-        super.init();
+        try {
+            super.init();
+        } catch (RuntimeCamelException e) {
+            if (e.getCause() != null && e.getCause() instanceof 
VetoCamelContextStartException) {
+                vetoed = (VetoCamelContextStartException) e.getCause();
+            } else {
+                throw e;
+            }
+        }
 
         // was the initialization vetoed?
         if (vetoed != null) {
-            if (vetoed.isRethrowException()) {
-                throw RuntimeCamelException.wrapRuntimeException(vetoed);
-            } else {
-                LOG.info("CamelContext ({}) vetoed to not initialize due to 
{}", getName(), vetoed.getMessage());
-                // swallow exception and change state of this camel context to 
stopped
-                fail(vetoed);
-                return;
-            }
+            LOG.info("CamelContext ({}) vetoed to not initialize due to {}", 
getName(), vetoed.getMessage());
+            failOnStartup(vetoed);
+            return;
         }
     }
 
@@ -2502,14 +2505,10 @@ public abstract class AbstractCamelContext extends 
BaseService
 
         // did the start veto?
         if (vetoed != null) {
-            if (vetoed.isRethrowException()) {
-                throw RuntimeCamelException.wrapRuntimeException(vetoed);
-            } else {
-                LOG.info("CamelContext ({}) vetoed to not start due to {}", 
getName(), vetoed.getMessage());
-                // swallow exception and change state of this camel context to 
stopped
-                stop();
-                return;
-            }
+            LOG.info("CamelContext ({}) vetoed to not start due to {}", 
getName(), vetoed.getMessage());
+            failOnStartup(vetoed);
+            stop();
+            return;
         }
 
         for (LifecycleStrategy strategy : lifecycleStrategies) {
@@ -2624,6 +2623,8 @@ public abstract class AbstractCamelContext extends 
BaseService
     public void doInit() throws Exception {
         StopWatch watch = new StopWatch();
 
+        vetoed = null;
+
         StartupStep step = startupStepRecorder.beginStep(CamelContext.class, 
null, "Init CamelContext");
 
         // init the route controller
@@ -4847,6 +4848,21 @@ public abstract class AbstractCamelContext extends 
BaseService
         return "CamelContext(" + getName() + ")";
     }
 
+
+    protected void failOnStartup(Exception e) {
+        if (e instanceof VetoCamelContextStartException) {
+            VetoCamelContextStartException vetoException = 
(VetoCamelContextStartException) e;
+            if (vetoException.isRethrowException()) {
+                fail(e);
+            } else {
+                // swallow exception and change state of this camel context to 
stopped
+                status = FAILED;
+            }
+        } else {
+            fail(e);
+        }
+    }
+
     protected abstract ExchangeFactory createExchangeFactory();
 
     protected abstract ExchangeFactoryManager createExchangeFactoryManager();
diff --git 
a/core/camel-core/src/test/java/org/apache/camel/impl/engine/VetoCamelContextStartExceptionTest.java
 
b/core/camel-core/src/test/java/org/apache/camel/impl/engine/VetoCamelContextStartExceptionTest.java
new file mode 100644
index 0000000..9b27033
--- /dev/null
+++ 
b/core/camel-core/src/test/java/org/apache/camel/impl/engine/VetoCamelContextStartExceptionTest.java
@@ -0,0 +1,139 @@
+package org.apache.camel.impl.engine;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.ServiceStatus;
+import org.apache.camel.VetoCamelContextStartException;
+import org.apache.camel.impl.DefaultCamelContext;
+import org.apache.camel.support.LifecycleStrategySupport;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class VetoCamelContextStartExceptionTest {
+
+    @Test
+    public void testVetoOnStarting() {
+        CamelContext context = new DefaultCamelContext();
+        context.addLifecycleStrategy(
+                new LifecycleStrategySupport() {
+                    @Override
+                    public void onContextStarting(CamelContext context) throws 
VetoCamelContextStartException {
+                        throw new VetoCamelContextStartException("Veto on 
starting", context, true);
+                    }
+                });
+
+        Throwable throwable = assertThrows(Throwable.class, context::start);
+
+        assertTrue(context.isVetoStarted());
+        assertEquals(ServiceStatus.Stopped, context.getStatus());
+        assertEquals("org.apache.camel.VetoCamelContextStartException: Veto on 
starting", throwable.getMessage());
+    }
+
+    @Test
+    public void testVetoOnStartingWithoutRethrow() {
+        CamelContext context = new DefaultCamelContext();
+        context.addLifecycleStrategy(
+                new LifecycleStrategySupport() {
+                    @Override
+                    public void onContextStarting(CamelContext context) throws 
VetoCamelContextStartException {
+                        throw new VetoCamelContextStartException("Veto on 
starting", context, false);
+                    }
+                });
+        context.start();
+        assertTrue(context.isVetoStarted());
+        assertEquals(ServiceStatus.Stopped, context.getStatus());
+    }
+
+    @Test
+    public void testVetoOnInitializing() {
+        CamelContext context = new DefaultCamelContext();
+        context.addLifecycleStrategy(
+                new LifecycleStrategySupport() {
+                    @Override
+                    public void onContextInitializing(CamelContext context) 
throws VetoCamelContextStartException {
+                        throw new VetoCamelContextStartException("Veto on 
initializing", context, true);
+                    }
+                });
+
+        Throwable throwable = assertThrows(Throwable.class, context::start);
+        assertTrue(context.isVetoStarted());
+        assertEquals(ServiceStatus.Stopped, context.getStatus());
+        assertEquals("org.apache.camel.VetoCamelContextStartException: Veto on 
initializing", throwable.getMessage());
+    }
+
+    @Test
+    public void testVetoOnInitializingWithoutRethrow() {
+        CamelContext context = new DefaultCamelContext();
+        context.addLifecycleStrategy(
+                new LifecycleStrategySupport() {
+                    @Override
+                    public void onContextInitializing(CamelContext context) 
throws VetoCamelContextStartException {
+                        throw new VetoCamelContextStartException("Veto on 
initializing", context, false);
+                    }
+                });
+        context.start();
+        assertTrue(context.isVetoStarted());
+        assertEquals(ServiceStatus.Stopped, context.getStatus());
+    }
+
+    @Test
+    public void testVetoOnInitialized() {
+        CamelContext context = new DefaultCamelContext();
+        context.addLifecycleStrategy(
+                new LifecycleStrategySupport() {
+                    @Override
+                    public void onContextInitialized(CamelContext context) 
throws VetoCamelContextStartException {
+                        throw new VetoCamelContextStartException("Veto on 
initialized", context, true);
+                    }
+                });
+
+        Throwable throwable = assertThrows(Throwable.class, context::start);
+        assertTrue(context.isVetoStarted());
+        assertEquals(ServiceStatus.Stopped, context.getStatus());
+        assertEquals("org.apache.camel.VetoCamelContextStartException: Veto on 
initialized", throwable.getMessage());
+    }
+
+    @Test
+    public void testVetoOnInitializedWithoutRethrow() {
+        CamelContext context = new DefaultCamelContext();
+        context.addLifecycleStrategy(
+                new LifecycleStrategySupport() {
+                    @Override
+                    public void onContextInitialized(CamelContext context) 
throws VetoCamelContextStartException {
+                        throw new VetoCamelContextStartException("Veto on 
initialized", context, false);
+                    }
+                });
+        context.start();
+        assertTrue(context.isVetoStarted());
+        assertEquals(ServiceStatus.Stopped, context.getStatus());
+    }
+
+    @Test
+    public void testVetoReset() throws Exception {
+        try (CamelContext context = new DefaultCamelContext()) {
+            boolean[] needThrowVeto = new boolean[] { true };
+            context.addLifecycleStrategy(
+                    new LifecycleStrategySupport() {
+                        @Override
+                        public void onContextInitialized(CamelContext context) 
throws VetoCamelContextStartException {
+                            if (needThrowVeto[0]) {
+                                needThrowVeto[0] = false;
+                                throw new VetoCamelContextStartException("Veto 
on initialized", context, false);
+                            }
+                        }
+                    });
+
+            context.start();
+            assertTrue(context.isVetoStarted());
+            assertEquals(ServiceStatus.Stopped, context.getStatus());
+
+            context.start();
+            assertFalse(context.isVetoStarted());
+            assertEquals(ServiceStatus.Started, context.getStatus());
+        }
+
+    }
+}

Reply via email to