diff --git a/spring-integration-core/src/main/java/org/springframework/integration/endpoint/AbstractEndpoint.java b/spring-integration-core/src/main/java/org/springframework/integration/endpoint/AbstractEndpoint.java index 6744ea9649..9ed5547e13 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/endpoint/AbstractEndpoint.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/endpoint/AbstractEndpoint.java @@ -34,6 +34,7 @@ import org.springframework.scheduling.TaskScheduler; * to the {@link #setAutoStartup(boolean)} method. * * @author Mark Fisher + * @author Kris Jacyna */ public abstract class AbstractEndpoint extends IntegrationObjectSupport implements SmartLifecycle { @@ -84,7 +85,7 @@ public abstract class AbstractEndpoint extends IntegrationObjectSupport implemen this.lifecycleLock.lock(); try { if (!this.running) { - this.doStart(); + doStart(); this.running = true; if (logger.isInfoEnabled()) { logger.info("started " + this); @@ -100,7 +101,7 @@ public abstract class AbstractEndpoint extends IntegrationObjectSupport implemen this.lifecycleLock.lock(); try { if (this.running) { - this.doStop(); + doStop(); this.running = false; if (logger.isInfoEnabled()) { logger.info("stopped " + this); @@ -115,14 +116,23 @@ public abstract class AbstractEndpoint extends IntegrationObjectSupport implemen public final void stop(Runnable callback) { this.lifecycleLock.lock(); try { - this.stop(); - callback.run(); + doStop(callback); } finally { this.lifecycleLock.unlock(); } } + /** + * Subclasses may override this method to invoke the callback before + * or after the start behavior. + * @param callback the Runnable to invoke + */ + protected void doStop(Runnable callback) { + doStop(); + callback.run(); + } + /** * Subclasses must implement this method with the start behavior. * This method will be invoked while holding the {@link #lifecycleLock}. diff --git a/spring-integration-core/src/test/java/org/springframework/integration/endpoint/MessageProducerSupportTests.java b/spring-integration-core/src/test/java/org/springframework/integration/endpoint/MessageProducerSupportTests.java index c7f59ccc60..8443c167b5 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/endpoint/MessageProducerSupportTests.java +++ b/spring-integration-core/src/test/java/org/springframework/integration/endpoint/MessageProducerSupportTests.java @@ -17,10 +17,14 @@ package org.springframework.integration.endpoint; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; -import org.junit.Test; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; +import org.junit.Test; import org.springframework.beans.factory.BeanFactory; import org.springframework.integration.channel.DirectChannel; import org.springframework.integration.channel.PublishSubscribeChannel; @@ -37,6 +41,7 @@ import org.springframework.messaging.support.GenericMessage; * @author Oleg Zhurakousky * @author Mark Fisher * @author Gary Russell + * @author Kris Jacyna * @since 2.0.1 */ public class MessageProducerSupportTests { @@ -114,6 +119,22 @@ public class MessageProducerSupportTests { assertEquals(message, exception.getFailedMessage()); } + @Test + public void customDoStop() { + final CustomEndpoint endpoint = new CustomEndpoint(); + assertEquals(0, endpoint.getCount()); + assertTrue(endpoint.isStopped()); + endpoint.start(); + assertFalse(endpoint.isStopped()); + endpoint.stop(new Runnable() { + @Override + public void run() { + // Do nothing + } + }); + assertEquals(1, endpoint.getCount()); + assertTrue(endpoint.isStopped()); + } private static class SuccessfulErrorService { @@ -125,4 +146,35 @@ public class MessageProducerSupportTests { } } + private static class CustomEndpoint extends AbstractEndpoint { + + private final AtomicInteger count = new AtomicInteger(0); + private final AtomicBoolean stopped = new AtomicBoolean(true); + + public int getCount() { + return this.count.get(); + } + + public boolean isStopped() { + return this.stopped.get(); + } + + @Override + protected void doStop(final Runnable callback) { + this.count.incrementAndGet(); + super.doStop(callback); + } + + @Override + protected void doStart() { + this.stopped.set(false); + } + + @Override + protected void doStop() { + this.stopped.set(true); + } + + } + }