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:
Artem Bilan
2017-05-25 14:21:40 -04:00
committed by Gary Russell
parent a800d9683a
commit f112ecbb7e
8 changed files with 371 additions and 70 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 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,9 +16,11 @@
package org.springframework.integration.xml.splitter;
import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertThat;
import java.util.List;
@@ -27,6 +29,7 @@ import org.junit.Test;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.springframework.integration.IntegrationMessageHeaderAccessor;
import org.springframework.integration.channel.QueueChannel;
import org.springframework.integration.handler.ReplyRequiredException;
import org.springframework.integration.xml.util.XmlTestUtil;
@@ -36,6 +39,7 @@ import org.springframework.messaging.support.GenericMessage;
/**
* @author Jonas Partner
* @author Artem Bilan
*/
public class XPathMessageSplitterTests {
@@ -47,58 +51,61 @@ public class XPathMessageSplitterTests {
@Before
public void setUp() {
String splittingXPath = "/orders/order";
splitter = new XPathMessageSplitter(splittingXPath);
splitter.setOutputChannel(replyChannel);
splitter.setRequiresReply(true);
this.splitter = new XPathMessageSplitter(splittingXPath);
this.splitter.setOutputChannel(replyChannel);
this.splitter.setRequiresReply(true);
}
@Test
public void splitDocument() throws Exception {
Document doc = XmlTestUtil.getDocumentForString("<orders><order>one</order><order>two</order><order>three</order></orders>");
splitter.handleMessage(new GenericMessage<Document>(doc));
this.splitter.handleMessage(new GenericMessage<>(doc));
List<Message<?>> docMessages = this.replyChannel.clear();
assertEquals("Wrong number of messages", 3, docMessages.size());
for (Message<?> message : docMessages) {
assertTrue("unexpected payload type" + message.getPayload().getClass().getName(), message.getPayload() instanceof Node);
assertFalse("unexpected payload type" + message.getPayload().getClass().getName(), message.getPayload() instanceof Document);
assertThat(message.getPayload(), instanceOf(Node.class));
assertThat(message.getPayload(), not(instanceOf(Document.class)));
assertThat(new IntegrationMessageHeaderAccessor(message).getSequenceSize(), greaterThan(0));
}
}
@Test(expected = ReplyRequiredException.class)
public void splitDocumentThatDoesNotMatch() throws Exception {
Document doc = XmlTestUtil.getDocumentForString("<wrongDocument/>");
splitter.handleMessage(new GenericMessage<Document>(doc));
this.splitter.handleMessage(new GenericMessage<>(doc));
}
@Test
public void splitDocumentWithCreateDocumentsTrue() throws Exception {
splitter.setCreateDocuments(true);
this.splitter.setCreateDocuments(true);
Document doc = XmlTestUtil.getDocumentForString("<orders><order>one</order><order>two</order><order>three</order></orders>");
splitter.handleMessage(new GenericMessage<Document>(doc));
this.splitter.handleMessage(new GenericMessage<>(doc));
List<Message<?>> docMessages = this.replyChannel.clear();
assertEquals("Wrong number of messages", 3, docMessages.size());
for (Message<?> message : docMessages) {
assertTrue("unexpected payload type" + message.getPayload().getClass().getName(), message.getPayload() instanceof Document);
assertThat(message.getPayload(), instanceOf(Document.class));
Document docPayload = (Document) message.getPayload();
assertEquals("Wrong root element name", "order", docPayload.getDocumentElement().getLocalName());
assertThat(new IntegrationMessageHeaderAccessor(message).getSequenceSize(), greaterThan(0));
}
}
@Test
public void splitStringXml() throws Exception {
String payload = "<orders><order>one</order><order>two</order><order>three</order></orders>";
splitter.handleMessage(new GenericMessage<String>(payload));
this.splitter.handleMessage(new GenericMessage<>(payload));
List<Message<?>> docMessages = this.replyChannel.clear();
assertEquals("Wrong number of messages", 3, docMessages.size());
for (Message<?> message : docMessages) {
assertTrue("unexpected payload type " + message.getPayload().getClass().getName(), message.getPayload() instanceof String);
assertThat(message.getPayload(), instanceOf(String.class));
assertThat(new IntegrationMessageHeaderAccessor(message).getSequenceSize(), greaterThan(0));
}
}
@Test(expected = MessageHandlingException.class)
public void invalidPayloadType() {
splitter.handleMessage(new GenericMessage<Integer>(123));
this.splitter.handleMessage(new GenericMessage<>(123));
}
}