INT-4269: Add Stream & Flux Support for Splitter
JIRA: https://jira.spring.io/browse/INT-4269 * Check if `outputChannel` is `ReactiveStreamsSubscribableChannel` to let back-pressure splitting * Build `Flux` or `Iterator` depending in the `reactive` state * Allow to get a size of the `iterator` if it is possible, for example `XPathMessageSplitter` Add tests Fix raw type and unused import * Add JavaDocs to the `AbstractMessageSplitter#obtainSizeIfPossible()` * Add asserts for the `sequenceSize` populataiton in the `XPathMessageSplitter` * Document `Stream` & `Flux` support in the splitter Minor doc polishing
This commit is contained in:
committed by
Gary Russell
parent
a800d9683a
commit
f112ecbb7e
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -16,29 +16,40 @@
|
||||
|
||||
package org.springframework.integration.splitter;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.reactivestreams.Subscriber;
|
||||
|
||||
import org.springframework.integration.IntegrationMessageHeaderAccessor;
|
||||
import org.springframework.integration.channel.DirectChannel;
|
||||
import org.springframework.integration.channel.FluxMessageChannel;
|
||||
import org.springframework.integration.channel.QueueChannel;
|
||||
import org.springframework.integration.endpoint.EventDrivenConsumer;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.integration.test.util.TestUtils;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.support.GenericMessage;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
* @author Iwein Fuld
|
||||
* @author Gunnar Hillert
|
||||
* @author Artem Bilan
|
||||
*/
|
||||
public class DefaultSplitterTests {
|
||||
|
||||
@@ -65,7 +76,7 @@ public class DefaultSplitterTests {
|
||||
|
||||
@Test
|
||||
public void splitMessageWithCollectionPayload() throws Exception {
|
||||
List<String> payload = Arrays.asList(new String[] { "x", "y", "z" });
|
||||
List<String> payload = Arrays.asList("x", "y", "z");
|
||||
Message<List<String>> message = MessageBuilder.withPayload(payload).build();
|
||||
QueueChannel replyChannel = new QueueChannel();
|
||||
DefaultMessageSplitter splitter = new DefaultMessageSplitter();
|
||||
@@ -108,4 +119,112 @@ public class DefaultSplitterTests {
|
||||
Message<?> output = replyChannel.receive(15);
|
||||
assertThat(output, is(nullValue()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void splitStream() {
|
||||
Message<?> message = new GenericMessage<>(
|
||||
Stream.generate(Math::random)
|
||||
.limit(10));
|
||||
QueueChannel outputChannel = new QueueChannel();
|
||||
DefaultMessageSplitter splitter = new DefaultMessageSplitter();
|
||||
splitter.setOutputChannel(outputChannel);
|
||||
splitter.handleMessage(message);
|
||||
for (int i = 0; i < 10; i++) {
|
||||
Message<?> reply = outputChannel.receive(0);
|
||||
assertEquals(message.getHeaders().getId(), new IntegrationMessageHeaderAccessor(reply).getCorrelationId());
|
||||
}
|
||||
assertNull(outputChannel.receive(10));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void splitFlux() {
|
||||
Message<?> message = new GenericMessage<>(
|
||||
Flux
|
||||
.generate(() -> 0,
|
||||
(state, sink) -> {
|
||||
if (state == 10) {
|
||||
sink.complete();
|
||||
}
|
||||
else {
|
||||
sink.next(state);
|
||||
}
|
||||
return ++state;
|
||||
}));
|
||||
QueueChannel outputChannel = new QueueChannel();
|
||||
DefaultMessageSplitter splitter = new DefaultMessageSplitter();
|
||||
splitter.setOutputChannel(outputChannel);
|
||||
splitter.handleMessage(message);
|
||||
for (int i = 0; i < 10; i++) {
|
||||
Message<?> reply = outputChannel.receive(0);
|
||||
assertEquals(message.getHeaders().getId(), new IntegrationMessageHeaderAccessor(reply).getCorrelationId());
|
||||
}
|
||||
assertNull(outputChannel.receive(10));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void splitArrayPayloadReactive() {
|
||||
Message<?> message = new GenericMessage<>(new String[] { "x", "y", "z" });
|
||||
FluxMessageChannel replyChannel = new FluxMessageChannel();
|
||||
DefaultMessageSplitter splitter = new DefaultMessageSplitter();
|
||||
splitter.setOutputChannel(replyChannel);
|
||||
|
||||
splitter.handleMessage(message);
|
||||
|
||||
Flux<String> testFlux =
|
||||
Flux.from(replyChannel)
|
||||
.map(Message::getPayload)
|
||||
.cast(String.class);
|
||||
|
||||
StepVerifier.create(testFlux)
|
||||
.expectNext("x", "y", "z")
|
||||
.then(() ->
|
||||
((Subscriber<?>) TestUtils.getPropertyValue(replyChannel, "subscribers", List.class).get(0))
|
||||
.onComplete())
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void splitStreamReactive() {
|
||||
Message<?> message = new GenericMessage<>(Stream.of("x", "y", "z"));
|
||||
FluxMessageChannel replyChannel = new FluxMessageChannel();
|
||||
DefaultMessageSplitter splitter = new DefaultMessageSplitter();
|
||||
splitter.setOutputChannel(replyChannel);
|
||||
|
||||
splitter.handleMessage(message);
|
||||
|
||||
Flux<String> testFlux =
|
||||
Flux.from(replyChannel)
|
||||
.map(Message::getPayload)
|
||||
.cast(String.class);
|
||||
|
||||
StepVerifier.create(testFlux)
|
||||
.expectNext("x", "y", "z")
|
||||
.then(() ->
|
||||
((Subscriber<?>) TestUtils.getPropertyValue(replyChannel, "subscribers", List.class).get(0))
|
||||
.onComplete())
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void splitFluxReactive() {
|
||||
Message<?> message = new GenericMessage<>(Flux.just("x", "y", "z"));
|
||||
FluxMessageChannel replyChannel = new FluxMessageChannel();
|
||||
DefaultMessageSplitter splitter = new DefaultMessageSplitter();
|
||||
splitter.setOutputChannel(replyChannel);
|
||||
|
||||
splitter.handleMessage(message);
|
||||
|
||||
Flux<String> testFlux =
|
||||
Flux.from(replyChannel)
|
||||
.map(Message::getPayload)
|
||||
.cast(String.class);
|
||||
|
||||
StepVerifier.create(testFlux)
|
||||
.expectNext("x", "y", "z")
|
||||
.then(() ->
|
||||
((Subscriber<?>) TestUtils.getPropertyValue(replyChannel, "subscribers", List.class).get(0))
|
||||
.onComplete())
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user