diff --git a/spring-batch-integration/src/main/java/org/springframework/batch/integration/chunk/RemoteChunkingMasterStepBuilder.java b/spring-batch-integration/src/main/java/org/springframework/batch/integration/chunk/RemoteChunkingMasterStepBuilder.java
index a1d7cd921..cfd5b373b 100644
--- a/spring-batch-integration/src/main/java/org/springframework/batch/integration/chunk/RemoteChunkingMasterStepBuilder.java
+++ b/spring-batch-integration/src/main/java/org/springframework/batch/integration/chunk/RemoteChunkingMasterStepBuilder.java
@@ -33,8 +33,8 @@ import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.repeat.CompletionPolicy;
import org.springframework.batch.repeat.RepeatOperations;
import org.springframework.batch.repeat.exception.ExceptionHandler;
-import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.core.MessagingTemplate;
+import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.PollableChannel;
import org.springframework.retry.RetryPolicy;
import org.springframework.retry.backoff.BackOffPolicy;
@@ -47,12 +47,14 @@ import org.springframework.util.Assert;
* Builder for a master step in a remote chunking setup. This builder creates and
* sets a {@link ChunkMessageChannelItemWriter} on the master step.
*
- * If no messagingTemplate is provided through
+ *
If no {@code messagingTemplate} is provided through
* {@link RemoteChunkingMasterStepBuilder#messagingTemplate(MessagingTemplate)},
- * this builder will create one. The outputChannel set with
- * {@link RemoteChunkingMasterStepBuilder#outputChannel(DirectChannel)} will be
- * used as a default channel of the messaging template and will override any default
- * channel already set on the messaging template.
+ * this builder will create one and set its default channel to the {@code outputChannel}
+ * provided through {@link RemoteChunkingMasterStepBuilder#outputChannel(MessageChannel)}.
If a {@code messagingTemplate} is provided, it is assumed that it is fully configured + * and that its default channel is set to an output channel on which requests to workers + * will be sent.
* * @param type of input items * @paramUse either this setter or {@link RemoteChunkingMasterStepBuilder#messagingTemplate(MessagingTemplate)} + * to provide a fully configured messaging template.
* * @param outputChannel the output channel. * @return this builder instance for fluent chaining * * @see RemoteChunkingMasterStepBuilder#messagingTemplate(MessagingTemplate) */ - public RemoteChunkingMasterStepBuilder outputChannel(DirectChannel outputChannel) { + public RemoteChunkingMasterStepBuilder outputChannel(MessageChannel outputChannel) { Assert.notNull(outputChannel, "outputChannel must not be null"); this.outputChannel = outputChannel; return this; @@ -115,13 +118,14 @@ public class RemoteChunkingMasterStepBuilder extends FaultTolerantStepBuil /** * Set the {@link MessagingTemplate} to use to send data to workers. - * - *The default destination of the messaging template will be - * overridden by the output channel provided through - * {@link RemoteChunkingMasterStepBuilder#outputChannel(DirectChannel)}.
+ * The default channel of the messaging template must be set. + *Use either this setter to provide a fully configured messaging template or + * provide an output channel through {@link RemoteChunkingMasterStepBuilder#outputChannel(MessageChannel)} + * and a default messaging template will be created.
* * @param messagingTemplate the messaging template to use * @return this builder instance for fluent chaining + * @see RemoteChunkingMasterStepBuilder#outputChannel(MessageChannel) */ public RemoteChunkingMasterStepBuilder messagingTemplate(MessagingTemplate messagingTemplate) { Assert.notNull(messagingTemplate, "messagingTemplate must not be null"); @@ -164,13 +168,17 @@ public class RemoteChunkingMasterStepBuilder extends FaultTolerantStepBuil */ public TaskletStep build() { Assert.notNull(this.inputChannel, "An InputChannel must be provided"); - Assert.notNull(this.outputChannel, "An OutputChannel must be provided"); + Assert.state(this.outputChannel == null || this.messagingTemplate == null, + "You must specify either an outputChannel or a messagingTemplate but not both."); // configure messaging template if (this.messagingTemplate == null) { this.messagingTemplate = new MessagingTemplate(); + this.messagingTemplate.setDefaultChannel(this.outputChannel); + if (this.logger.isDebugEnabled()) { + this.logger.debug("No messagingTemplate was provided, using a default one"); + } } - this.messagingTemplate.setDefaultChannel(this.outputChannel); // configure item writer ChunkMessageChannelItemWriterIf no {@code messagingTemplate} is provided through * {@link RemotePartitioningMasterStepBuilder#messagingTemplate(MessagingTemplate)}, - * this builder will create one. The {@code outputChannel} set with - * {@link RemotePartitioningMasterStepBuilder#outputChannel(MessageChannel)} will be - * used as a default channel of the messaging template and will override any default - * channel already set on the messaging template. + * this builder will create one and set its default channel to the {@code outputChannel} + * provided through {@link RemotePartitioningMasterStepBuilder#outputChannel(MessageChannel)}.
+ * + *If a {@code messagingTemplate} is provided, it is assumed that it is fully configured + * and that its default channel is set to an output channel on which requests to workers + * will be sent.
* * @since 4.1 * @author Mahmoud Ben Hassine @@ -85,14 +87,14 @@ public class RemotePartitioningMasterStepBuilder extends PartitionStepBuilder { } /** - * Set the output channel on which requests to workers will be sent. - * The output channel will be set as a default channel on the provided - * {@link MessagingTemplate} trough - * {@link RemotePartitioningMasterStepBuilder#messagingTemplate(MessagingTemplate)} - * (or the one created by this builder if no messaging template is provided). + * Set the output channel on which requests to workers will be sent. By using + * this setter, a default messaging template will be created and the output + * channel will be set as its default channel. + *Use either this setter or {@link RemotePartitioningMasterStepBuilder#messagingTemplate(MessagingTemplate)} + * to provide a fully configured messaging template.
+ * * @param outputChannel the output channel. * @return this builder instance for fluent chaining - * * @see RemotePartitioningMasterStepBuilder#messagingTemplate(MessagingTemplate) */ public RemotePartitioningMasterStepBuilder outputChannel(MessageChannel outputChannel) { @@ -103,12 +105,14 @@ public class RemotePartitioningMasterStepBuilder extends PartitionStepBuilder { /** * Set the {@link MessagingTemplate} to use to send data to workers. - *The default destination of the messaging template will be - * overridden by the output channel provided through - * {@link RemotePartitioningMasterStepBuilder#outputChannel(MessageChannel)}.
+ * The default channel of the messaging template must be set. + *Use either this setter to provide a fully configured messaging template or + * provide an output channel through {@link RemotePartitioningMasterStepBuilder#outputChannel(MessageChannel)} + * and a default messaging template will be created.
* * @param messagingTemplate the messaging template to use * @return this builder instance for fluent chaining + * @see RemotePartitioningMasterStepBuilder#outputChannel(MessageChannel) */ public RemotePartitioningMasterStepBuilder messagingTemplate(MessagingTemplate messagingTemplate) { Assert.notNull(messagingTemplate, "messagingTemplate must not be null"); @@ -159,13 +163,17 @@ public class RemotePartitioningMasterStepBuilder extends PartitionStepBuilder { } public Step build() { - Assert.notNull(this.outputChannel, "An outputChannel must be provided"); + Assert.state(this.outputChannel == null || this.messagingTemplate == null, + "You must specify either an outputChannel or a messagingTemplate but not both."); // configure messaging template if (this.messagingTemplate == null) { this.messagingTemplate = new MessagingTemplate(); + this.messagingTemplate.setDefaultChannel(this.outputChannel); + if (this.logger.isDebugEnabled()) { + this.logger.debug("No messagingTemplate was provided, using a default one"); + } } - this.messagingTemplate.setDefaultChannel(this.outputChannel); // Configure the partition handler final MessageChannelPartitionHandler partitionHandler = new MessageChannelPartitionHandler(); diff --git a/spring-batch-integration/src/test/java/org/springframework/batch/integration/chunk/RemoteChunkingMasterStepBuilderTest.java b/spring-batch-integration/src/test/java/org/springframework/batch/integration/chunk/RemoteChunkingMasterStepBuilderTest.java index 83ab092a7..89c03c93d 100644 --- a/spring-batch-integration/src/test/java/org/springframework/batch/integration/chunk/RemoteChunkingMasterStepBuilderTest.java +++ b/spring-batch-integration/src/test/java/org/springframework/batch/integration/chunk/RemoteChunkingMasterStepBuilderTest.java @@ -176,13 +176,15 @@ public class RemoteChunkingMasterStepBuilderTest { } @Test - public void testMandatoryOutputChannel() { + public void eitherOutputChannelOrMessagingTemplateMustBeProvided() { // given RemoteChunkingMasterStepBuilder