Fix FluxMessageChannel for Multi Sources

* Rename `ReactiveConsumer` to `ReactiveStreamsConsumer`
* Rename `FluxSubscribableChannel` to `ReactiveStreamsSubscribableChannel`
* Remove the `processor` functionality from the `FluxMessageChannel`
in favor of internal `FluxSink` as it is recommended by the Project Reactor:
> Most of the time, you should try to avoid using a Processor.
They are harder to use correctly and prone to some corner cases.

* Make connectable, upstream publishers for the `FluxMessageChannel` as
bridges to the internal `sink` via `this::send`.
This way we are able to receive data from multi sources.
When the source is completed (e.g. `Mono` in case of WebFlux response),
the downstream flow isn't completed.
* Rework `MessageChannelReactiveUtils#PollableChannelPublisherAdapter`
to be based on the `Flux.create()` and `onRequest()` to poll channel for messages
* Add one more request to the `ReactiveHttpRequestExecutingMessageHandler`
to be sure that we consume different `Mono`s by the `FluxSubscribableChannel`
properly without completion
* Upgrade to the `spring-io-plugin:0.0.7.RELEASE`

Add `IntegrationConsumer` implementation to the `ReactiveStreamsConsumer`
This commit is contained in:
Artem Bilan
2017-05-04 16:09:51 -04:00
committed by Gary Russell
parent 7e919a4017
commit 9543877c0c
16 changed files with 128 additions and 189 deletions

View File

@@ -22,8 +22,8 @@ import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.BDDMockito.willAnswer;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.BDDMockito.willAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
@@ -46,28 +46,26 @@ import org.reactivestreams.Subscription;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.channel.QueueChannel;
import org.springframework.integration.channel.FluxMessageChannel;
import org.springframework.integration.channel.QueueChannel;
import org.springframework.integration.config.ConsumerEndpointFactoryBean;
import org.springframework.integration.endpoint.ReactiveConsumer;
import org.springframework.integration.endpoint.ReactiveStreamsConsumer;
import org.springframework.integration.handler.MethodInvokingMessageHandler;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageDeliveryException;
import org.springframework.messaging.MessageHandler;
import org.springframework.messaging.support.GenericMessage;
import reactor.core.publisher.EmitterProcessor;
/**
* @author Artem Bilan
*
* @since 5.0
*/
public class ReactiveConsumerTests {
public class ReactiveStreamsConsumerTests {
@Test
public void testReactiveConsumerReactiveChannel() throws InterruptedException {
FluxMessageChannel testChannel = new FluxMessageChannel(EmitterProcessor.create(false));
public void testReactiveStreamsConsumerFluxMessageChannel() throws InterruptedException {
FluxMessageChannel testChannel = new FluxMessageChannel();
List<Message<?>> result = new LinkedList<>();
CountDownLatch stopLatch = new CountDownLatch(2);
@@ -79,7 +77,7 @@ public class ReactiveConsumerTests {
MessageHandler testSubscriber = new MethodInvokingMessageHandler(messageHandler, (String) null);
ReactiveConsumer reactiveConsumer = new ReactiveConsumer(testChannel, testSubscriber);
ReactiveStreamsConsumer reactiveConsumer = new ReactiveStreamsConsumer(testChannel, testSubscriber);
reactiveConsumer.setBeanFactory(mock(BeanFactory.class));
reactiveConsumer.afterPropertiesSet();
reactiveConsumer.start();
@@ -103,7 +101,7 @@ public class ReactiveConsumerTests {
@Test
@SuppressWarnings("unchecked")
public void testReactiveConsumerDirectChannel() throws InterruptedException {
public void testReactiveStreamsConsumerDirectChannel() throws InterruptedException {
DirectChannel testChannel = new DirectChannel();
Subscriber<Message<?>> testSubscriber = (Subscriber<Message<?>>) Mockito.mock(Subscriber.class);
@@ -117,7 +115,7 @@ public class ReactiveConsumerTests {
.given(testSubscriber)
.onNext(any(Message.class));
ReactiveConsumer reactiveConsumer = new ReactiveConsumer(testChannel, testSubscriber);
ReactiveStreamsConsumer reactiveConsumer = new ReactiveStreamsConsumer(testChannel, testSubscriber);
reactiveConsumer.setBeanFactory(mock(BeanFactory.class));
reactiveConsumer.afterPropertiesSet();
reactiveConsumer.start();
@@ -163,7 +161,7 @@ public class ReactiveConsumerTests {
@Test
@SuppressWarnings("unchecked")
public void testReactiveConsumerPollableChannel() throws InterruptedException {
public void testReactiveStreamsConsumerPollableChannel() throws InterruptedException {
QueueChannel testChannel = new QueueChannel();
Subscriber<Message<?>> testSubscriber = (Subscriber<Message<?>>) Mockito.mock(Subscriber.class);
@@ -177,7 +175,7 @@ public class ReactiveConsumerTests {
.given(testSubscriber)
.onNext(any(Message.class));
ReactiveConsumer reactiveConsumer = new ReactiveConsumer(testChannel, testSubscriber);
ReactiveStreamsConsumer reactiveConsumer = new ReactiveStreamsConsumer(testChannel, testSubscriber);
reactiveConsumer.setBeanFactory(mock(BeanFactory.class));
reactiveConsumer.afterPropertiesSet();
reactiveConsumer.start();
@@ -223,7 +221,7 @@ public class ReactiveConsumerTests {
}
@Test
public void testReactiveConsumerViaConsumerEndpointFactoryBean() throws Exception {
public void testReactiveStreamsConsumerViaConsumerEndpointFactoryBean() throws Exception {
FluxMessageChannel testChannel = new FluxMessageChannel();
List<Message<?>> result = new LinkedList<>();

View File

@@ -32,7 +32,6 @@ import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import org.apache.log4j.Level;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.reactivestreams.Publisher;
@@ -49,7 +48,6 @@ import org.springframework.integration.dsl.IntegrationFlow;
import org.springframework.integration.dsl.IntegrationFlows;
import org.springframework.integration.dsl.channel.MessageChannels;
import org.springframework.integration.dsl.context.IntegrationFlowContext;
import org.springframework.integration.test.rule.Log4jLevelAdjuster;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.support.GenericMessage;
@@ -69,9 +67,6 @@ import reactor.core.publisher.Flux;
@DirtiesContext
public class ReactiveStreamsTests {
// @Rule
public Log4jLevelAdjuster adjuster = new Log4jLevelAdjuster(Level.DEBUG, "org.springframework.integration");
@Autowired
@Qualifier("reactiveFlow")
private Publisher<Message<String>> publisher;