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()); + } + + } +}
