INT-4108: Fix idempotency for some Lifecycles
JIRA: https://jira.spring.io/browse/INT-4108 Some `Lifecycle.start()/stop()` usage doesn't ensure robustness for components causing unexpected and difficulty tracing issues * Fix `Lifecycle.start()/stop()` for `FileReadingMessageSource`, `FileWritingMessageHandler`, `AbstractMqttMessageHandler` * In the `DefaultHeaderChannelRegistry`, `LockRegistryLeaderInitiator`, `MqttPahoMessageHandler` rework logic for shared variables to avoid `NPE` * Increase receive timeouts in the `PayloadDeserializingTransformerParserTests` and `UdpChannelAdapterTests` * Prove with the `WatchServiceDirectoryScannerTests` changes that several invocation for `FileReadingMessageSource.start()` are idempotent **Cherry-pick to 4.3.x**
This commit is contained in:
@@ -38,6 +38,7 @@ import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.PriorityBlockingQueue;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
@@ -87,6 +88,8 @@ public class FileReadingMessageSource extends IntegrationObjectSupport implement
|
||||
|
||||
private static final Log logger = LogFactory.getLog(FileReadingMessageSource.class);
|
||||
|
||||
private final AtomicBoolean running = new AtomicBoolean();
|
||||
|
||||
/*
|
||||
* {@link PriorityBlockingQueue#iterator()} throws
|
||||
* {@link java.util.ConcurrentModificationException} in Java 5.
|
||||
@@ -104,8 +107,6 @@ public class FileReadingMessageSource extends IntegrationObjectSupport implement
|
||||
|
||||
private volatile boolean scanEachPoll = false;
|
||||
|
||||
private volatile boolean running;
|
||||
|
||||
private FileListFilter<File> filter;
|
||||
|
||||
private FileLocker locker;
|
||||
@@ -281,7 +282,7 @@ public class FileReadingMessageSource extends IntegrationObjectSupport implement
|
||||
public void setWatchEvents(WatchEventType... watchEvents) {
|
||||
Assert.notEmpty(watchEvents, "'watchEvents' must not be empty.");
|
||||
Assert.noNullElements(watchEvents, "'watchEvents' must not contain null elements.");
|
||||
Assert.state(!this.running, "Cannot change watch events while running.");
|
||||
Assert.state(!this.running.get(), "Cannot change watch events while running.");
|
||||
|
||||
this.watchEvents = Arrays.copyOf(watchEvents, watchEvents.length);
|
||||
}
|
||||
@@ -293,23 +294,21 @@ public class FileReadingMessageSource extends IntegrationObjectSupport implement
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
if (this.scanner instanceof Lifecycle) {
|
||||
if (!this.running.getAndSet(true) && this.scanner instanceof Lifecycle) {
|
||||
((Lifecycle) this.scanner).start();
|
||||
}
|
||||
this.running = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
if (this.scanner instanceof Lifecycle) {
|
||||
((Lifecycle) this.scanner).start();
|
||||
if (this.running.getAndSet(false) && this.scanner instanceof Lifecycle) {
|
||||
((Lifecycle) this.scanner).stop();
|
||||
}
|
||||
this.running = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRunning() {
|
||||
return this.running;
|
||||
return this.running.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -444,6 +443,7 @@ public class FileReadingMessageSource extends IntegrationObjectSupport implement
|
||||
try {
|
||||
this.watcher.close();
|
||||
this.watcher = null;
|
||||
this.pathKeys.clear();
|
||||
}
|
||||
catch (IOException e) {
|
||||
logger.error("Failed to close watcher for " + FileReadingMessageSource.this.directory, e);
|
||||
|
||||
@@ -364,7 +364,7 @@ public class FileWritingMessageHandler extends AbstractReplyProducingMessageHand
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
if (FileExistsMode.APPEND_NO_FLUSH.equals(this.fileExistsMode)) {
|
||||
if (this.flushTask == null && FileExistsMode.APPEND_NO_FLUSH.equals(this.fileExistsMode)) {
|
||||
TaskScheduler taskScheduler = getTaskScheduler();
|
||||
Assert.state(taskScheduler != null, "'taskScheduler' is required for FileExistsMode.APPEND_NO_FLUSH");
|
||||
this.flushTask = taskScheduler.scheduleAtFixedRate(new Flusher(), this.flushInterval / 3);
|
||||
|
||||
Reference in New Issue
Block a user