/** * Configure the handler with {@link org.springframework.integration.aggregator.MethodInvokingCorrelationStrategy} * and {@link org.springframework.integration.aggregator.MethodInvokingReleaseStrategy} using the target * object which should have methods annotated appropriately for each function. * Also set the output processor. * @param target the target object. * @return the handler spec. */ public AggregatorSpec processor(Object target) { return processor(target, null); }
/** * An expression to determine the output message from the released group. Defaults to a message * with a payload that is a collection of payloads from the input messages. * @param expression the expression. * @return the aggregator spec. */ public AggregatorSpec outputExpression(String expression) { return this.outputProcessor(new ExpressionEvaluatingMessageGroupProcessor(expression)); }
/** * Populate a {@link ScatterGatherHandler} to the current integration flow position * based on the provided {@link MessageChannel} for scattering function * and {@link AggregatorSpec} for gathering function. * @param scatterChannel the {@link MessageChannel} for scatting requests. * @param gatherer the {@link Consumer} for {@link AggregatorSpec} to configure gatherer. * Can be {@code null}. * @param scatterGather the {@link Consumer} for {@link ScatterGatherSpec} to configure * {@link ScatterGatherHandler} and its endpoint. Can be {@code null}. * @return the current {@link IntegrationFlowDefinition}. */ public B scatterGather(MessageChannel scatterChannel, Consumer<AggregatorSpec> gatherer, Consumer<ScatterGatherSpec> scatterGather) { AggregatorSpec aggregatorSpec = new AggregatorSpec(); if (gatherer != null) { gatherer.accept(aggregatorSpec); } AggregatingMessageHandler aggregatingMessageHandler = aggregatorSpec.get().getT2(); addComponent(aggregatingMessageHandler); ScatterGatherHandler messageHandler = new ScatterGatherHandler(scatterChannel, aggregatingMessageHandler); return register(new ScatterGatherSpec(messageHandler), scatterGather); }
/** * @param expireGroupsUponCompletion the expireGroupsUponCompletion. * @return the aggregator spec. * @see AggregatingMessageHandler#setExpireGroupsUponCompletion(boolean) */ public AggregatorSpec expireGroupsUponCompletion(boolean expireGroupsUponCompletion) { this.handler.setExpireGroupsUponCompletion(expireGroupsUponCompletion); return _this(); }
/** * Populate the {@link AggregatingMessageHandler} with provided options from {@link AggregatorSpec}. * In addition accept options for the integration endpoint using {@link GenericEndpointSpec}. * Typically used with a Java 8 Lambda expression: * <pre class="code"> * {@code * .aggregate(a -> a.correlationExpression("1") * .releaseStrategy(g -> g.size() == 25) * .phase(100)) * } * </pre> * @param aggregator the {@link Consumer} to provide {@link AggregatingMessageHandler} options. * @return the current {@link IntegrationFlowDefinition}. * @see AggregatorSpec */ public B aggregate(Consumer<AggregatorSpec> aggregator) { return register(new AggregatorSpec(), aggregator); }
@Bean public IntegrationFlow fileReadingFlow() { return IntegrationFlows .from(Files.inboundAdapter(tmpDir.getRoot()) .patternFilter("*.sitest") .useWatchService(true) .watchEvents(FileReadingMessageSource.WatchEventType.CREATE, FileReadingMessageSource.WatchEventType.MODIFY), e -> e.poller(Pollers.fixedDelay(100) .errorChannel("filePollingErrorChannel"))) .filter(File.class, p -> !p.getName().startsWith("a"), e -> e.throwExceptionOnRejection(true)) .transform(Files.toStringTransformer()) .aggregate(a -> a.correlationExpression("1") .releaseStrategy(g -> g.size() == 25)) .channel(MessageChannels.queue("fileReadingResultChannel")) .get(); }
@Test public void testFluxMessageChannelCleanUp() throws InterruptedException { FluxMessageChannel flux = MessageChannels.flux().get(); CountDownLatch finishLatch = new CountDownLatch(1); IntegrationFlow testFlow = f -> f .<String>split(__ -> Flux.fromStream(IntStream.range(0, 100).boxed()), null) .channel(flux) .aggregate(a -> a.releaseStrategy(m -> m.size() == 100)) .handle(__ -> finishLatch.countDown()); IntegrationFlowContext.IntegrationFlowRegistration flowRegistration = this.integrationFlowContext.registration(testFlow) .register(); flowRegistration.getInputChannel().send(new GenericMessage<>("foo")); assertTrue(finishLatch.await(10, TimeUnit.SECONDS)); assertTrue(TestUtils.getPropertyValue(flux, "publishers", Map.class).isEmpty()); flowRegistration.destroy(); }
/** * A processor to determine the output message from the released group. Defaults to a message * with a payload that is a collection of payloads from the input messages. * @param outputProcessor the processor. * @return the aggregator spec. */ public AggregatorSpec outputProcessor(MessageGroupProcessor outputProcessor) { this.handler.setOutputProcessor(outputProcessor); return _this(); }
/** * Populate the {@link AggregatingMessageHandler} with provided options from {@link AggregatorSpec}. * In addition accept options for the integration endpoint using {@link GenericEndpointSpec}. * Typically used with a Java 8 Lambda expression: * <pre class="code"> * {@code * .aggregate(a -> a.correlationExpression("1") * .releaseStrategy(g -> g.size() == 25) * .phase(100)) * } * </pre> * @param aggregator the {@link Consumer} to provide {@link AggregatingMessageHandler} options. * @return the current {@link IntegrationFlowDefinition}. * @since 1.1 * @see AggregatorSpec */ public B aggregate(Consumer<AggregatorSpec> aggregator) { return register(new AggregatorSpec(), aggregator); }
@Bean public IntegrationFlow fileReadingFlow() { return IntegrationFlows .from(s -> s.file(tmpDir.getRoot()) .patternFilter("*.sitest") .useWatchService(true) .watchEvents(FileReadingMessageSource.WatchEventType.CREATE, FileReadingMessageSource.WatchEventType.MODIFY), e -> e.poller(Pollers.fixedDelay(100) .errorChannel("filePollingErrorChannel"))) .filter(File.class, p -> !p.getName().startsWith("a"), e -> e.throwExceptionOnRejection(true)) .transform(Transformers.fileToString()) .aggregate(a -> a.correlationExpression("1") .releaseStrategy(g -> g.size() == 25)) .channel(MessageChannels.queue("fileReadingResultChannel")) .get(); }
/** * Populate a {@link ScatterGatherHandler} to the current integration flow position * based on the provided {@link RecipientListRouterSpec} for scattering function * and {@link AggregatorSpec} for gathering function. * @param scatterer the {@link Consumer} for {@link RecipientListRouterSpec} to configure scatterer. * @param gatherer the {@link Consumer} for {@link AggregatorSpec} to configure gatherer. * @param scatterGather the {@link Consumer} for {@link ScatterGatherSpec} to configure * {@link ScatterGatherHandler} and its endpoint. Can be {@code null}. * @return the current {@link IntegrationFlowDefinition}. */ public B scatterGather(Consumer<RecipientListRouterSpec> scatterer, Consumer<AggregatorSpec> gatherer, Consumer<ScatterGatherSpec> scatterGather) { Assert.notNull(scatterer, "'scatterer' must not be null"); RecipientListRouterSpec recipientListRouterSpec = new RecipientListRouterSpec(); scatterer.accept(recipientListRouterSpec); AggregatorSpec aggregatorSpec = new AggregatorSpec(); if (gatherer != null) { gatherer.accept(aggregatorSpec); } RecipientListRouter recipientListRouter = recipientListRouterSpec.get().getT2(); addComponent(recipientListRouter) .addComponents(recipientListRouterSpec.getComponentsToRegister()); AggregatingMessageHandler aggregatingMessageHandler = aggregatorSpec.get().getT2(); addComponent(aggregatingMessageHandler); ScatterGatherHandler messageHandler = new ScatterGatherHandler(recipientListRouter, aggregatingMessageHandler); return register(new ScatterGatherSpec(messageHandler), scatterGather); }
StandardIntegrationFlow standardIntegrationFlow = IntegrationFlows .from(this.inputChannel) .aggregate(aggregatorSpec -> aggregatorSpec.processor(partitionHandler)) .channel(replies) .get();
/** * Configure the handler with {@link org.springframework.integration.aggregator.MethodInvokingCorrelationStrategy} * and {@link org.springframework.integration.aggregator.MethodInvokingReleaseStrategy} using the target * object which should have methods annotated appropriately for each function. * Also set the output processor. * @param target the target object. * @param methodName The method name for the output processor (or 'null' in which case, the * target object must have an {@link org.springframework.integration.annotation.Aggregator} annotation). * @return the handler spec. */ public AggregatorSpec processor(Object target, String methodName) { super.processor(target); return this.outputProcessor(methodName != null ? new MethodInvokingMessageGroupProcessor(target, methodName) : new MethodInvokingMessageGroupProcessor(target)); }
/** * @param expireGroupsUponCompletion the expireGroupsUponCompletion. * @return the aggregator spec. * @see AggregatingMessageHandler#setExpireGroupsUponCompletion(boolean) */ public AggregatorSpec expireGroupsUponCompletion(boolean expireGroupsUponCompletion) { this.handler.setExpireGroupsUponCompletion(expireGroupsUponCompletion); return _this(); }
/** * Populate the {@link AggregatingMessageHandler} with provided options from {@link AggregatorSpec}. * In addition accept options for the integration endpoint using {@link GenericEndpointSpec}. * Typically used with a Java 8 Lambda expression: * <pre class="code"> * {@code * .aggregate(a -> a.correlationExpression("1") * .releaseStrategy(g -> g.size() == 25) * .phase(100)) * } * </pre> * @param aggregator the {@link Consumer} to provide {@link AggregatingMessageHandler} options. * @return the current {@link IntegrationFlowDefinition}. * @see AggregatorSpec */ public B aggregate(Consumer<AggregatorSpec> aggregator) { return register(new AggregatorSpec(), aggregator); }
/** * Populate the {@link AggregatingMessageHandler} with provided options from {@link AggregatorSpec}. * In addition accept options for the integration endpoint using {@link GenericEndpointSpec}. * Typically used with a Java 8 Lambda expression: * <pre class="code"> * {@code * .aggregate(a -> a.correlationExpression("1").releaseStrategy(g -> g.size() == 25), * e -> e.applySequence(false)) * } * </pre> * @param aggregatorConfigurer the {@link Consumer} to provide {@link AggregatingMessageHandler} options. * @param endpointConfigurer the {@link Consumer} to provide integration endpoint options. * @return the current {@link IntegrationFlowDefinition}. * @see GenericEndpointSpec * @deprecated since 1.1 in favor of {@link #aggregate(Consumer)} */ @Deprecated public B aggregate(Consumer<AggregatorSpec> aggregatorConfigurer, Consumer<GenericEndpointSpec<AggregatingMessageHandler>> endpointConfigurer) { Assert.notNull(aggregatorConfigurer, "'aggregatorConfigurer' must not be null"); AggregatorSpec spec = new AggregatorSpec(); aggregatorConfigurer.accept(spec); return this.handle(spec.get().getT2(), endpointConfigurer); }
/** * Configure the handler with {@link org.springframework.integration.aggregator.MethodInvokingCorrelationStrategy} * and {@link org.springframework.integration.aggregator.MethodInvokingReleaseStrategy} using the target * object which should have methods annotated appropriately for each function. * Also set the output processor. * @param target the target object. * @return the handler spec. */ public AggregatorSpec processor(Object target) { return processor(target, null); }
@Bean public IntegrationFlow publishSubscribeAggregateFlow() { return flow -> flow .aggregate(a -> a.outputProcessor(g -> g.getMessages() .stream() .map(m -> (String) m.getPayload()) .collect(Collectors.joining(" ")))) .channel(MessageChannels.queue("subscriberAggregateResult")); }
/** * A processor to determine the output message from the released group. Defaults to a message * with a payload that is a collection of payloads from the input messages. * @param outputProcessor the processor. * @return the aggregator spec. */ public AggregatorSpec outputProcessor(MessageGroupProcessor outputProcessor) { this.handler.setOutputProcessor(outputProcessor); return _this(); }
/** * Populate the {@link AggregatingMessageHandler} with provided options from {@link AggregatorSpec}. * In addition accept options for the integration endpoint using {@link GenericEndpointSpec}. * Typically used with a Java 8 Lambda expression: * <pre class="code"> * {@code * .aggregate(a -> a.correlationExpression("1") * .releaseStrategy(g -> g.size() == 25) * .phase(100)) * } * </pre> * @param aggregator the {@link Consumer} to provide {@link AggregatingMessageHandler} options. * @return the current {@link IntegrationFlowDefinition}. * @since 1.1 * @see AggregatorSpec */ public B aggregate(Consumer<AggregatorSpec> aggregator) { return register(new AggregatorSpec(), aggregator); }