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:
Artem Bilan
2016-09-13 12:09:56 -04:00
parent 6790dbd03e
commit 6c6e1d319d
9 changed files with 49 additions and 32 deletions

View File

@@ -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);

View File

@@ -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);

View File

@@ -105,6 +105,7 @@ public class WatchServiceDirectoryScannerTests {
assertTrue(files.contains(top1));
assertTrue(files.contains(foo1));
assertTrue(files.contains(bar1));
fileReadingMessageSource.start();
File top2 = this.folder.newFile();
File foo2 = File.createTempFile("foo", ".txt", this.foo);
File bar2 = File.createTempFile("bar", ".txt", this.bar);
@@ -130,6 +131,7 @@ public class WatchServiceDirectoryScannerTests {
var1 = StandardWatchEventKinds.OVERFLOW;
}
*/
fileReadingMessageSource.start();
List<File> filesForOverflow = new ArrayList<File>(600);
for (int i = 0; i < 600; i++) {