GH-3797: Improve batch processing in the framework (#3820)
* GH-3797: Improve batch processing in the framework Fixes https://github.com/spring-projects/spring-integration/issues/3797 * Handle `Message` items of the `Iterable` payload properly in the `JdbcMessageHandler`. Otherwise, they've been wrapped into an extra `Message` * Produce a single message with a `Collection<Message<?>>` payload in the `AggregatingMessageHandler` when the `getOutputProcessor()` is not an instance of `SimpleMessageGroupProcessor` * Mention these changes in docs * Point to the error handling sample from docs * * Fix language in docs Co-authored-by: Gary Russell <grussell@vmware.com> Co-authored-by: Gary Russell <grussell@vmware.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2022 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.
|
||||
@@ -72,6 +72,21 @@ public class AggregatingMessageHandler extends AbstractCorrelatingMessageHandler
|
||||
return this.expireGroupsUponCompletion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check an {@link Iterable} result for split possibility on the output production:
|
||||
* the items of the collection have to be instances of {@link Message}
|
||||
* or {@link org.springframework.integration.support.AbstractIntegrationMessageBuilder}
|
||||
* and {@link #getOutputProcessor()} has to be a {@link SimpleMessageGroupProcessor}.
|
||||
* Otherwise, a single reply message is emitted with the whole {@link Iterable} as its payload.
|
||||
* @param reply the {@link Iterable} result to check for split possibility.
|
||||
* @return true if the {@link Iterable} result has to be split into individual messages.
|
||||
* @since 6.0
|
||||
*/
|
||||
@Override
|
||||
protected boolean shouldSplitOutput(Iterable<?> reply) {
|
||||
return getOutputProcessor() instanceof SimpleMessageGroupProcessor && super.shouldSplitOutput(reply);
|
||||
}
|
||||
|
||||
/**
|
||||
* Complete the group and remove all its messages.
|
||||
* If the {@link #expireGroupsUponCompletion} is true, then remove group fully.
|
||||
|
||||
@@ -44,7 +44,6 @@ import org.springframework.integration.MessageRejectedException;
|
||||
import org.springframework.integration.aggregator.AggregatingMessageHandler;
|
||||
import org.springframework.integration.aggregator.ExpressionEvaluatingCorrelationStrategy;
|
||||
import org.springframework.integration.aggregator.ExpressionEvaluatingReleaseStrategy;
|
||||
import org.springframework.integration.aggregator.SimpleMessageGroupProcessor;
|
||||
import org.springframework.integration.annotation.BridgeFrom;
|
||||
import org.springframework.integration.annotation.BridgeTo;
|
||||
import org.springframework.integration.annotation.Filter;
|
||||
@@ -69,6 +68,7 @@ import org.springframework.integration.endpoint.SourcePollingChannelAdapter;
|
||||
import org.springframework.integration.filter.ExpressionEvaluatingSelector;
|
||||
import org.springframework.integration.history.MessageHistory;
|
||||
import org.springframework.integration.splitter.DefaultMessageSplitter;
|
||||
import org.springframework.integration.store.MessageGroup;
|
||||
import org.springframework.integration.transformer.ExpressionEvaluatingTransformer;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
@@ -178,12 +178,11 @@ public class MessagingAnnotationsWithBeanAnnotationTests {
|
||||
MessageHistory messageHistory = MessageHistory.read(message);
|
||||
assertThat(messageHistory).isNotNull();
|
||||
String messageHistoryString = messageHistory.toString();
|
||||
assertThat(messageHistoryString).contains("routerChannel")
|
||||
.contains("filterChannel")
|
||||
.contains("aggregatorChannel")
|
||||
.contains("splitterChannel")
|
||||
.contains("serviceChannel")
|
||||
.doesNotContain("discardChannel");
|
||||
assertThat(messageHistoryString)
|
||||
.contains("routerChannel", "filterChannel", "aggregatorChannel", "serviceChannel")
|
||||
.doesNotContain("discardChannel")
|
||||
// history header is not overridden in splitter for individual message from message group emitted before
|
||||
.doesNotContain("splitterChannel");
|
||||
}
|
||||
|
||||
assertThat(this.skippedServiceActivator).isNull();
|
||||
@@ -248,10 +247,10 @@ public class MessagingAnnotationsWithBeanAnnotationTests {
|
||||
this.reactiveMessageHandlerChannel.send(new GenericMessage<>("test"));
|
||||
|
||||
StepVerifier.create(
|
||||
this.contextConfiguration.messageMono
|
||||
.asMono()
|
||||
.map(Message::getPayload)
|
||||
.cast(String.class))
|
||||
this.contextConfiguration.messageMono
|
||||
.asMono()
|
||||
.map(Message::getPayload)
|
||||
.cast(String.class))
|
||||
.expectNext("test")
|
||||
.verifyComplete();
|
||||
}
|
||||
@@ -332,7 +331,7 @@ public class MessagingAnnotationsWithBeanAnnotationTests {
|
||||
@Bean
|
||||
@ServiceActivator(inputChannel = "aggregatorChannel")
|
||||
public MessageHandler aggregator() {
|
||||
AggregatingMessageHandler handler = new AggregatingMessageHandler(new SimpleMessageGroupProcessor());
|
||||
AggregatingMessageHandler handler = new AggregatingMessageHandler(MessageGroup::getMessages);
|
||||
handler.setCorrelationStrategy(new ExpressionEvaluatingCorrelationStrategy("1"));
|
||||
handler.setReleaseStrategy(new ExpressionEvaluatingReleaseStrategy("size() == 10"));
|
||||
handler.setOutputChannelName("splitterChannel");
|
||||
@@ -346,7 +345,7 @@ public class MessagingAnnotationsWithBeanAnnotationTests {
|
||||
|
||||
@Bean
|
||||
public CountDownLatch reactiveCustomizerLatch() {
|
||||
return new CountDownLatch(10);
|
||||
return new CountDownLatch(1);
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
||||
Reference in New Issue
Block a user