From 28a23c90a00fef379de66d1ad54475d5ebe7cad3 Mon Sep 17 00:00:00 2001 From: Ilayaperumal Gopinathan Date: Thu, 3 Sep 2015 13:01:22 -0700 Subject: [PATCH] Start/Stop lifecycle components after bind/unbinding - Explicit call is needed to start/stop the non-smart lifecycle components after bind/unbinding Avoid recursive calls to applicationContext.start() --- .../binding/ChannelBindingLifecycle.java | 27 ++++++++++++------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/binding/ChannelBindingLifecycle.java b/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/binding/ChannelBindingLifecycle.java index c9b38ffb3..b11abd58d 100644 --- a/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/binding/ChannelBindingLifecycle.java +++ b/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/binding/ChannelBindingLifecycle.java @@ -17,6 +17,7 @@ package org.springframework.cloud.stream.binding; import java.util.Map; +import java.util.concurrent.atomic.AtomicBoolean; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; @@ -34,10 +35,10 @@ public class ChannelBindingLifecycle implements SmartLifecycle, ApplicationConte private volatile boolean running = false; - private final Object lifecycleMonitor = new Object(); - private ConfigurableApplicationContext applicationContext; + private final AtomicBoolean active = new AtomicBoolean(false); + @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { @@ -47,8 +48,8 @@ public class ChannelBindingLifecycle implements SmartLifecycle, ApplicationConte @Override public void start() { if (!running) { - synchronized (lifecycleMonitor) { - if (!running) { + if (!this.active.get()) { + if (this.active.compareAndSet(false, true)) { // retrieve the ChannelBindingService lazily, avoiding early initialization try { ChannelBindingService channelBindingService = this.applicationContext.getBean(ChannelBindingService.class); @@ -59,10 +60,13 @@ public class ChannelBindingLifecycle implements SmartLifecycle, ApplicationConte for (Bindable bindable : bindables.values()) { bindable.bindInputs(channelBindingService); } - } catch (BeansException e) { - throw new IllegalStateException("Cannot perform binding, no proper implementation found",e); + } + catch (BeansException e) { + throw new IllegalStateException("Cannot perform binding, no proper implementation found", e); } this.running = true; + this.applicationContext.start(); + this.active.set(false); } } } @@ -71,8 +75,8 @@ public class ChannelBindingLifecycle implements SmartLifecycle, ApplicationConte @Override public void stop() { if (running) { - synchronized (lifecycleMonitor) { - if (running) { + if (!this.active.get()) { + if (this.active.compareAndSet(false, true)) { try { // retrieve the ChannelBindingService lazily, avoiding early initialization ChannelBindingService channelBindingService = this.applicationContext.getBean(ChannelBindingService.class); @@ -83,9 +87,12 @@ public class ChannelBindingLifecycle implements SmartLifecycle, ApplicationConte for (Bindable bindable : bindables.values()) { bindable.unbindOutputs(channelBindingService); } - } catch (BeansException e) { - throw new IllegalStateException("Cannot perform binding, no proper implementation found",e); } + catch (BeansException e) { + throw new IllegalStateException("Cannot perform binding, no proper implementation found", e); + } + this.applicationContext.stop(); + this.active.set(false); this.running = false; } }