Rely on MProducerSupport.active for Flux (#3423)

* Rely on `MProducerSupport.active` for `Flux`

* Fix `MessageProducerSupport` to extract an `active` flag and set it before
`isRunning` - the `Flux` subscription relies on the `takeWhile()`
where in case of `autoStartup = false` we will never start consume because
it is set to `true` already after `doStart()`
* Refactor all the `MessageProducerSupport` implementation with similar
`active` state to use already one from the super class

**Cherry-pick to 5.3.x**

* * Remove `MessageProducerSupport.setActive()`
to not let to mutate it from the implementations
* Set `active` to `false` in the `destroy()`
* Clean up and fix typos in the affected `JmsMessageDrivenEndpoint`

* * Pull `active` flag down to the `AbstractEndpoint`
* Set `active = true` in the `start()` before calling `doStart()`
* Do same for `active = false` in the `stop()`
* Clean up `AbstractEndpoint` impls to not call `doStart/doStop` for nothing
* Refactor endpoints to rely on the `active` state from the `AbstractEndpoint`
not their own
This commit is contained in:
Artem Bilan
2020-11-06 13:51:03 -05:00
committed by Gary Russell
parent 27b464ad27
commit 002382e647
23 changed files with 1167 additions and 253 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2019 the original author or authors.
* Copyright 2002-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,7 +19,6 @@ package org.springframework.integration.ip;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
@@ -32,6 +31,8 @@ import org.springframework.util.Assert;
*
* @author Mark Fisher
* @author Gary Russell
* @author Artem Bilan
*
* @since 2.0
*/
public abstract class AbstractInternetProtocolReceivingChannelAdapter
@@ -56,8 +57,6 @@ public abstract class AbstractInternetProtocolReceivingChannelAdapter
private int poolSize = 5;
private volatile boolean active;
private volatile boolean listening;
@@ -108,48 +107,6 @@ public abstract class AbstractInternetProtocolReceivingChannelAdapter
return this.receiveBufferSize;
}
/**
* Protected by lifecycleLock
*/
@Override
protected void doStart() {
if (!this.active) {
this.active = true;
String beanName = this.getComponentName();
checkTaskExecutor((beanName == null ? "" : beanName + "-") + this.getComponentType());
this.taskExecutor.execute(this);
}
}
/**
* Creates a default task executor if none was supplied.
*
* @param threadName The thread name.
*/
protected void checkTaskExecutor(final String threadName) {
if (this.active && this.taskExecutor == null) {
Executor executor = Executors.newFixedThreadPool(this.poolSize, new ThreadFactory() {
@Override
public Thread newThread(Runnable runner) {
Thread thread = new Thread(runner);
thread.setName(threadName);
thread.setDaemon(true);
return thread;
}
});
this.taskExecutor = executor;
}
}
@Override
protected void doStop() {
this.active = false;
if (!this.taskExecutorSet && this.taskExecutor != null) {
((ExecutorService) this.taskExecutor).shutdown();
this.taskExecutor = null;
}
}
public boolean isListening() {
return this.listening;
}
@@ -197,10 +154,39 @@ public abstract class AbstractInternetProtocolReceivingChannelAdapter
}
/**
* @return the active
* Protected by lifecycleLock
*/
public boolean isActive() {
return this.active;
@Override
protected void doStart() {
String beanName = getComponentName();
checkTaskExecutor((beanName == null ? "" : beanName + "-") + getComponentType());
this.taskExecutor.execute(this);
}
/**
* Creates a default task executor if none was supplied.
*
* @param threadName The thread name.
*/
protected void checkTaskExecutor(final String threadName) {
if (isActive() && this.taskExecutor == null) {
this.taskExecutor =
Executors.newFixedThreadPool(this.poolSize,
(runner) -> {
Thread thread = new Thread(runner);
thread.setName(threadName);
thread.setDaemon(true);
return thread;
});
}
}
@Override
protected void doStop() {
if (!this.taskExecutorSet && this.taskExecutor != null) {
((ExecutorService) this.taskExecutor).shutdown();
this.taskExecutor = null;
}
}
}

View File

@@ -75,8 +75,6 @@ public class TcpInboundGateway extends MessagingGatewaySupport implements
private long retryInterval = DEFAULT_RETRY_INTERVAL;
private volatile boolean active;
private volatile ClientModeConnectionManager clientModeConnectionManager;
private volatile ScheduledFuture<?> scheduledFuture;
@@ -210,8 +208,7 @@ public class TcpInboundGateway extends MessagingGatewaySupport implements
protected void onInit() {
super.onInit();
if (this.isClientMode) {
Assert.notNull(this.clientConnectionFactory,
"For client-mode, connection factory must be type='client'");
Assert.notNull(this.clientConnectionFactory, "For client-mode, connection factory must be type='client'");
Assert.isTrue(!this.clientConnectionFactory.isSingleUse(),
"For client-mode, connection factory must have single-use='false'");
}
@@ -220,40 +217,34 @@ public class TcpInboundGateway extends MessagingGatewaySupport implements
@Override // protected by super#lifecycleLock
protected void doStart() {
super.doStart();
if (!this.active) {
this.active = true;
this.shuttingDown = false;
if (this.serverConnectionFactory != null) {
this.serverConnectionFactory.start();
}
if (this.clientConnectionFactory != null) {
this.clientConnectionFactory.start();
}
if (this.isClientMode) {
ClientModeConnectionManager manager =
new ClientModeConnectionManager(this.clientConnectionFactory);
this.clientModeConnectionManager = manager;
Assert.state(getTaskScheduler() != null, "Client mode requires a task scheduler");
this.scheduledFuture = getTaskScheduler().scheduleAtFixedRate(manager, this.retryInterval);
}
this.shuttingDown = false;
if (this.serverConnectionFactory != null) {
this.serverConnectionFactory.start();
}
if (this.clientConnectionFactory != null) {
this.clientConnectionFactory.start();
}
if (this.isClientMode) {
ClientModeConnectionManager manager =
new ClientModeConnectionManager(this.clientConnectionFactory);
this.clientModeConnectionManager = manager;
Assert.state(getTaskScheduler() != null, "Client mode requires a task scheduler");
this.scheduledFuture = getTaskScheduler().scheduleAtFixedRate(manager, this.retryInterval);
}
}
@Override // protected by super#lifecycleLock
protected void doStop() {
super.doStop();
if (this.active) {
this.active = false;
if (this.scheduledFuture != null) {
this.scheduledFuture.cancel(true);
}
this.clientModeConnectionManager = null;
if (this.clientConnectionFactory != null) {
this.clientConnectionFactory.stop();
}
if (this.serverConnectionFactory != null) {
this.serverConnectionFactory.stop();
}
if (this.scheduledFuture != null) {
this.scheduledFuture.cancel(true);
}
this.clientModeConnectionManager = null;
if (this.clientConnectionFactory != null) {
this.clientConnectionFactory.stop();
}
if (this.serverConnectionFactory != null) {
this.serverConnectionFactory.stop();
}
}
@@ -301,7 +292,7 @@ public class TcpInboundGateway extends MessagingGatewaySupport implements
@Override
public void retryConnection() {
if (this.active && this.isClientMode && this.clientModeConnectionManager != null) {
if (isActive() && this.isClientMode && this.clientModeConnectionManager != null) {
this.clientModeConnectionManager.run();
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2019 the original author or authors.
* Copyright 2002-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -31,6 +31,7 @@ import org.springframework.integration.ip.tcp.connection.ConnectionFactory;
import org.springframework.integration.ip.tcp.connection.TcpListener;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.ErrorMessage;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.util.Assert;
/**
@@ -40,11 +41,13 @@ import org.springframework.util.Assert;
* a client factory, the sender owns the connection.
*
* @author Gary Russell
* @author Artem Bilan
*
* @since 2.0
*
*/
public class TcpReceivingChannelAdapter
extends MessageProducerSupport implements TcpListener, ClientModeCapable, OrderlyShutdownCapable {
extends MessageProducerSupport implements TcpListener, ClientModeCapable, OrderlyShutdownCapable {
private AbstractConnectionFactory clientConnectionFactory;
@@ -60,8 +63,6 @@ public class TcpReceivingChannelAdapter
private volatile ClientModeConnectionManager clientModeConnectionManager;
private volatile boolean active;
private volatile boolean shuttingDown;
private final AtomicInteger activeCount = new AtomicInteger();
@@ -71,9 +72,7 @@ public class TcpReceivingChannelAdapter
boolean isErrorMessage = message instanceof ErrorMessage;
try {
if (this.shuttingDown) {
if (logger.isInfoEnabled()) {
logger.info("Inbound message ignored; shutting down; " + message.toString());
}
logger.info(() -> "Inbound message ignored; shutting down; " + message.toString());
}
else {
if (isErrorMessage) {
@@ -123,41 +122,33 @@ public class TcpReceivingChannelAdapter
@Override // protected by super#lifecycleLock
protected void doStart() {
super.doStart();
if (!this.active) {
this.active = true;
this.shuttingDown = false;
if (this.serverConnectionFactory != null) {
this.serverConnectionFactory.start();
}
if (this.clientConnectionFactory != null) {
this.clientConnectionFactory.start();
}
if (this.isClientMode) {
ClientModeConnectionManager manager = new ClientModeConnectionManager(
this.clientConnectionFactory);
this.clientModeConnectionManager = manager;
Assert.state(this.getTaskScheduler() != null, "Client mode requires a task scheduler");
this.scheduledFuture = this.getTaskScheduler().scheduleAtFixedRate(manager, this.retryInterval);
}
this.shuttingDown = false;
if (this.serverConnectionFactory != null) {
this.serverConnectionFactory.start();
}
if (this.clientConnectionFactory != null) {
this.clientConnectionFactory.start();
}
if (this.isClientMode) {
ClientModeConnectionManager manager = new ClientModeConnectionManager(this.clientConnectionFactory);
this.clientModeConnectionManager = manager;
TaskScheduler taskScheduler = getTaskScheduler();
Assert.state(taskScheduler != null, "Client mode requires a task scheduler");
this.scheduledFuture = taskScheduler.scheduleAtFixedRate(manager, this.retryInterval);
}
}
@Override // protected by super#lifecycleLock
protected void doStop() {
super.doStop();
if (this.active) {
this.active = false;
if (this.scheduledFuture != null) {
this.scheduledFuture.cancel(true);
}
this.clientModeConnectionManager = null;
if (this.clientConnectionFactory != null) {
this.clientConnectionFactory.stop();
}
if (this.serverConnectionFactory != null) {
this.serverConnectionFactory.stop();
}
if (this.scheduledFuture != null) {
this.scheduledFuture.cancel(true);
}
this.clientModeConnectionManager = null;
if (this.clientConnectionFactory != null) {
this.clientConnectionFactory.stop();
}
if (this.serverConnectionFactory != null) {
this.serverConnectionFactory.stop();
}
}
@@ -165,7 +156,6 @@ public class TcpReceivingChannelAdapter
* Sets the client or server connection factory; for this (an inbound adapter), if
* the factory is a client connection factory, the sockets are owned by a sending
* channel adapter and this adapter is used to receive replies.
*
* @param connectionFactory the connectionFactory to set
*/
public void setConnectionFactory(AbstractConnectionFactory connectionFactory) {
@@ -217,8 +207,7 @@ public class TcpReceivingChannelAdapter
}
/**
* @param isClientMode
* the isClientMode to set
* @param isClientMode the isClientMode to set
*/
public void setClientMode(boolean isClientMode) {
this.isClientMode = isClientMode;
@@ -232,8 +221,7 @@ public class TcpReceivingChannelAdapter
}
/**
* @param retryInterval
* the retryInterval to set
* @param retryInterval the retryInterval to set
*/
public void setRetryInterval(long retryInterval) {
this.retryInterval = retryInterval;
@@ -251,7 +239,7 @@ public class TcpReceivingChannelAdapter
@Override
public void retryConnection() {
if (this.active && this.isClientMode && this.clientModeConnectionManager != null) {
if (isActive() && this.isClientMode && this.clientModeConnectionManager != null) {
this.clientModeConnectionManager.run();
}
}
@@ -264,7 +252,8 @@ public class TcpReceivingChannelAdapter
@Override
public int afterShutdown() {
this.stop();
stop();
return this.activeCount.get();
}
}