INT-2480: Add aggregate headers strategy
JIRA: https://jira.spring.io/browse/INT-2480 * Introduce `headers-function` option into the `aggregator` for merging and computing headers for the output message based on the completed group * Implement a `DefaultAggregateHeadersFunction` and use it in the `AbstractAggregatingMessageGroupProcessor` for default behavior with possible injection for any other implementation * Add `DelegatingMessageGroupProcessor` to wrap any other `MessageGroupProcessor` implementations with possible usage of the `headersFunction` if result is not a `Message` or `MessageBuilder` * Make `AbstractCorrelatingMessageHandler.getOutputProcessor()` as `public` rto give access to this option from the `AggregatorSpec` to be able to inject a `headersFunction` in Java DSL configuration * Add `AbstractIntegrationMessageBuilder.getHeader()` to get access to some underlying header avoiding extra `Map` in case of `getHeaders()` * Change a logic in the `AbstractMessageProducingHandler.produceOutput()` to consult a `reply` for the `replyChannel` as well `routingSlip` header if the `reply` is a `Message` or `MessageBuilder` * Introduce a `AbstractMessageProducingHandler.messageBuilderForReply()` and use it in `AbstractMessageSplitter` to avoid duplication * Validate a new functionality in tests * Fix `FileOutboundGatewayParserTests` to rely on the `TemporaryFolder` to clean up test files after using * JavaDocs for `DefaultAggregateHeadersFunction` * Some `router.adoc` polishing * Fix link to Reactor in the `router.adoc` * Add docs for new `Function<MessageGroup, Map<String, Object>>` strategy * Doc polishing.
This commit is contained in:
committed by
Gary Russell
parent
09c4f03d7c
commit
5a1846cfe5
@@ -3,21 +3,26 @@
|
||||
xmlns:int-file="http://www.springframework.org/schema/integration/file"
|
||||
xmlns:beans="http://www.springframework.org/schema/beans"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xmlns:util="http://www.springframework.org/schema/util"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
https://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/context
|
||||
https://www.springframework.org/schema/context/spring-context.xsd
|
||||
http://www.springframework.org/schema/integration/file
|
||||
https://www.springframework.org/schema/integration/file/spring-integration-file.xsd">
|
||||
https://www.springframework.org/schema/integration/file/spring-integration-file.xsd
|
||||
http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd">
|
||||
|
||||
<context:property-placeholder/>
|
||||
|
||||
<util:constant id="temporaryFolder"
|
||||
static-field="org.springframework.integration.file.config.FileOutboundGatewayParserTests.tempFolder"/>
|
||||
|
||||
<int-file:outbound-gateway id="ordered"
|
||||
request-channel="someChannel" reply-timeout="777" directory="${java.io.tmpdir}"
|
||||
request-channel="someChannel" reply-timeout="777" directory="#{temporaryFolder.root}"
|
||||
auto-startup="false" order="777" filename-generator-expression="'foo.txt'"/>
|
||||
|
||||
<int-file:outbound-gateway id="gatewayWithDirectoryExpression"
|
||||
request-channel="someChannel" directory-expression="'build/foo'"
|
||||
request-channel="someChannel" directory-expression="temporaryFolder.root"
|
||||
auto-startup="false" order="777" filename-generator-expression="'foo.txt'"
|
||||
requires-reply="false">
|
||||
<int-file:request-handler-advice-chain>
|
||||
@@ -28,32 +33,32 @@
|
||||
<int-file:outbound-gateway id="gatewayWithReplaceMode"
|
||||
request-channel="gatewayWithReplaceModeChannel"
|
||||
filename-generator-expression="'fileToAppend.txt'" mode="REPLACE"
|
||||
directory="test" requires-reply="false"/>
|
||||
directory="#{temporaryFolder.root}" requires-reply="false"/>
|
||||
|
||||
<int-file:outbound-gateway id="gatewayWithAppendMode"
|
||||
request-channel="gatewayWithAppendModeChannel"
|
||||
filename-generator-expression="'fileToAppend.txt'" mode="APPEND"
|
||||
directory="test"/>
|
||||
directory="#{temporaryFolder.root}"/>
|
||||
|
||||
<int-file:outbound-gateway id="gatewayWithFailMode"
|
||||
request-channel="gatewayWithFailModeChannel"
|
||||
filename-generator-expression="'fileToAppend.txt'" mode="FAIL"
|
||||
directory="test"/>
|
||||
directory="#{temporaryFolder.root}"/>
|
||||
|
||||
<int-file:outbound-gateway id="gatewayWithIgnoreMode"
|
||||
request-channel="gatewayWithIgnoreModeChannel"
|
||||
filename-generator-expression="'fileToAppend.txt'" mode="IGNORE"
|
||||
directory="test"/>
|
||||
directory="#{temporaryFolder.root}"/>
|
||||
|
||||
<int-file:outbound-gateway id="gatewayWithFailModeLowercase"
|
||||
request-channel="gatewayWithFailModeLowercaseChannel"
|
||||
filename-generator-expression="'fileToAppend.txt'" mode="fail"
|
||||
directory="test"/>
|
||||
directory="#{temporaryFolder.root}"/>
|
||||
|
||||
<int-file:outbound-gateway id="gatewayWithAppendNewLine"
|
||||
request-channel="gatewayWithAppendNewLineChannel"
|
||||
filename-generator-expression="'fileToAppend.txt'"
|
||||
append-new-line="true"
|
||||
directory="test"/>
|
||||
directory="#{temporaryFolder.root}"/>
|
||||
|
||||
</beans:beans>
|
||||
|
||||
@@ -17,11 +17,14 @@
|
||||
package org.springframework.integration.file.config;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.fail;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.DirectFieldAccessor;
|
||||
@@ -39,8 +42,8 @@ import org.springframework.messaging.MessageChannel;
|
||||
import org.springframework.messaging.MessageHandler;
|
||||
import org.springframework.messaging.MessageHandlingException;
|
||||
import org.springframework.messaging.support.GenericMessage;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.util.FileCopyUtils;
|
||||
|
||||
/**
|
||||
@@ -49,10 +52,13 @@ import org.springframework.util.FileCopyUtils;
|
||||
* @author Artem Bilan
|
||||
* @author Tony Falabella
|
||||
*/
|
||||
@ContextConfiguration
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@RunWith(SpringRunner.class)
|
||||
@DirtiesContext
|
||||
public class FileOutboundGatewayParserTests {
|
||||
|
||||
@ClassRule
|
||||
public static final TemporaryFolder tempFolder = new TemporaryFolder();
|
||||
|
||||
@Autowired
|
||||
private EventDrivenConsumer ordered;
|
||||
|
||||
@@ -83,6 +89,11 @@ public class FileOutboundGatewayParserTests {
|
||||
|
||||
private static volatile int adviceCalled;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
tempFolder.delete();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkOrderedGateway() {
|
||||
DirectFieldAccessor gatewayAccessor = new DirectFieldAccessor(ordered);
|
||||
@@ -109,7 +120,7 @@ public class FileOutboundGatewayParserTests {
|
||||
FileWritingMessageHandler handler =
|
||||
TestUtils.getPropertyValue(gatewayWithDirectoryExpression, "handler", FileWritingMessageHandler.class);
|
||||
assertThat(TestUtils.getPropertyValue(handler, "destinationDirectoryExpression", Expression.class)
|
||||
.getExpressionString()).isEqualTo("'build/foo'");
|
||||
.getExpressionString()).isEqualTo("temporaryFolder.root");
|
||||
handler.handleMessage(new GenericMessage<>("foo"));
|
||||
assertThat(adviceCalled).isEqualTo(1);
|
||||
}
|
||||
@@ -129,11 +140,7 @@ public class FileOutboundGatewayParserTests {
|
||||
messagingTemplate.setDefaultDestination(this.gatewayWithIgnoreModeChannel);
|
||||
|
||||
final String expectedFileContent = "Initial File Content:";
|
||||
final File testFile = new File("test/fileToAppend.txt");
|
||||
|
||||
if (testFile.exists()) {
|
||||
testFile.delete();
|
||||
}
|
||||
final File testFile = new File(tempFolder.getRoot(), "fileToAppend.txt");
|
||||
|
||||
messagingTemplate.sendAndReceive(new GenericMessage<>("Initial File Content:"));
|
||||
|
||||
@@ -165,29 +172,16 @@ public class FileOutboundGatewayParserTests {
|
||||
|
||||
String expectedFileContent = "Initial File Content:";
|
||||
|
||||
File testFile = new File("test/fileToAppend.txt");
|
||||
|
||||
if (testFile.exists()) {
|
||||
testFile.delete();
|
||||
}
|
||||
File testFile = new File(tempFolder.getRoot(), "fileToAppend.txt");
|
||||
|
||||
messagingTemplate.sendAndReceive(new GenericMessage<>("Initial File Content:"));
|
||||
|
||||
final String actualFileContent = new String(FileCopyUtils.copyToByteArray(testFile));
|
||||
assertThat(actualFileContent).isEqualTo(expectedFileContent);
|
||||
|
||||
try {
|
||||
|
||||
messagingTemplate.sendAndReceive(new GenericMessage<>("String content:"));
|
||||
|
||||
}
|
||||
catch (MessageHandlingException e) {
|
||||
assertThat(e.getMessage()).startsWith("The destination file already exists at '");
|
||||
return;
|
||||
}
|
||||
|
||||
fail("Was expecting a MessageHandlingException to be thrown.");
|
||||
|
||||
assertThatExceptionOfType(MessageHandlingException.class)
|
||||
.isThrownBy(() -> messagingTemplate.sendAndReceive(new GenericMessage<>("String content:")))
|
||||
.withMessageStartingWith("The destination file already exists at '");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -200,35 +194,21 @@ public class FileOutboundGatewayParserTests {
|
||||
*/
|
||||
@Test
|
||||
public void gatewayWithFailModeLowercase() throws Exception {
|
||||
|
||||
final MessagingTemplate messagingTemplate = new MessagingTemplate();
|
||||
messagingTemplate.setDefaultDestination(this.gatewayWithFailModeLowercaseChannel);
|
||||
|
||||
String expectedFileContent = "Initial File Content:";
|
||||
|
||||
File testFile = new File("test/fileToAppend.txt");
|
||||
|
||||
if (testFile.exists()) {
|
||||
testFile.delete();
|
||||
}
|
||||
File testFile = new File(tempFolder.getRoot(), "fileToAppend.txt");
|
||||
|
||||
messagingTemplate.sendAndReceive(new GenericMessage<>("Initial File Content:"));
|
||||
|
||||
final String actualFileContent = new String(FileCopyUtils.copyToByteArray(testFile));
|
||||
assertThat(actualFileContent).isEqualTo(expectedFileContent);
|
||||
|
||||
try {
|
||||
|
||||
messagingTemplate.sendAndReceive(new GenericMessage<>("String content:"));
|
||||
|
||||
}
|
||||
catch (MessageHandlingException e) {
|
||||
assertThat(e.getMessage()).startsWith("The destination file already exists at '");
|
||||
return;
|
||||
}
|
||||
|
||||
fail("Was expecting a MessageHandlingException to be thrown.");
|
||||
|
||||
assertThatExceptionOfType(MessageHandlingException.class)
|
||||
.isThrownBy(() -> messagingTemplate.sendAndReceive(new GenericMessage<>("String content:")))
|
||||
.withMessageStartingWith("The destination file already exists at '");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -243,17 +223,12 @@ public class FileOutboundGatewayParserTests {
|
||||
*/
|
||||
@Test
|
||||
public void gatewayWithAppendMode() throws Exception {
|
||||
|
||||
final MessagingTemplate messagingTemplate = new MessagingTemplate();
|
||||
messagingTemplate.setDefaultDestination(this.gatewayWithAppendModeChannel);
|
||||
|
||||
String expectedFileContent = "Initial File Content:String content:";
|
||||
|
||||
File testFile = new File("test/fileToAppend.txt");
|
||||
|
||||
if (testFile.exists()) {
|
||||
testFile.delete();
|
||||
}
|
||||
File testFile = new File(tempFolder.getRoot(), "fileToAppend.txt");
|
||||
|
||||
messagingTemplate.sendAndReceive(new GenericMessage<>("Initial File Content:"));
|
||||
Message<?> m = messagingTemplate.sendAndReceive(new GenericMessage<>("String content:"));
|
||||
@@ -280,7 +255,6 @@ public class FileOutboundGatewayParserTests {
|
||||
*/
|
||||
@Test
|
||||
public void gatewayWithReplaceMode() throws Exception {
|
||||
|
||||
assertThat(TestUtils.getPropertyValue(this.gatewayWithReplaceModeHandler, "requiresReply", Boolean.class))
|
||||
.isFalse();
|
||||
|
||||
@@ -289,11 +263,7 @@ public class FileOutboundGatewayParserTests {
|
||||
|
||||
String expectedFileContent = "String content:";
|
||||
|
||||
File testFile = new File("test/fileToAppend.txt");
|
||||
|
||||
if (testFile.exists()) {
|
||||
testFile.delete();
|
||||
}
|
||||
File testFile = new File(tempFolder.getRoot(), "fileToAppend.txt");
|
||||
|
||||
messagingTemplate.sendAndReceive(new GenericMessage<>("Initial File Content:"));
|
||||
Message<?> m = messagingTemplate.sendAndReceive(new GenericMessage<>("String content:"));
|
||||
|
||||
Reference in New Issue
Block a user