/** * Populate the {@link MethodInvokingSplitter} to evaluate the discovered * {@code method} of the {@code service} at runtime. * @param service the service to use. * @return the current {@link IntegrationFlowDefinition}. * @see MethodInvokingSplitter */ public B split(Object service) { return split(service, null); }
/** * Populate the {@link MethodInvokingSplitter} to evaluate the provided * {@code method} of the {@code service} at runtime. * @param service the service to use. * @param methodName the method to invoke. * @return the current {@link IntegrationFlowDefinition}. * @see MethodInvokingSplitter */ public B split(Object service, String methodName) { return split(service, methodName, null); }
/** * Populate the {@link MethodInvokingSplitter} to evaluate the provided * {@code method} of the {@code bean} at runtime. * @param beanName the bean name to use. * @param methodName the method to invoke at runtime. * @return the current {@link IntegrationFlowDefinition}. */ public B split(String beanName, String methodName) { return split(beanName, methodName, null); }
/** * Populate the {@link DefaultMessageSplitter} with default options * to the current integration flow position. * @return the current {@link IntegrationFlowDefinition}. */ public B split() { return split((Consumer<SplitterEndpointSpec<DefaultMessageSplitter>>) null); }
/** * Populate the {@link ExpressionEvaluatingSplitter} with provided * SpEL expression. * @param expression the splitter SpEL expression. * and for {@link ExpressionEvaluatingSplitter}. * @return the current {@link IntegrationFlowDefinition}. * @see SplitterEndpointSpec */ public B split(String expression) { return split(expression, (Consumer<SplitterEndpointSpec<ExpressionEvaluatingSplitter>>) null); }
/** * Populate the provided {@link AbstractMessageSplitter} to the current integration * flow position. * @param splitterMessageHandlerSpec the {@link MessageHandlerSpec} to populate. * @param <S> the {@link AbstractMessageSplitter} * @return the current {@link IntegrationFlowDefinition}. * @see SplitterEndpointSpec */ public <S extends AbstractMessageSplitter> B split(MessageHandlerSpec<?, S> splitterMessageHandlerSpec) { return split(splitterMessageHandlerSpec, (Consumer<SplitterEndpointSpec<S>>) null); }
/** * Populate the provided {@link AbstractMessageSplitter} to the current integration * flow position. * @param splitter the {@link AbstractMessageSplitter} to populate. * @return the current {@link IntegrationFlowDefinition}. * @see SplitterEndpointSpec */ public B split(AbstractMessageSplitter splitter) { return split(splitter, (Consumer<SplitterEndpointSpec<AbstractMessageSplitter>>) null); }
/** * Populate the {@link MethodInvokingSplitter} to evaluate the * {@link org.springframework.integration.handler.MessageProcessor} at runtime * from provided {@link MessageProcessorSpec}. * <pre class="code"> * {@code * .split(Scripts.script("classpath:myScript.ruby")) * } * </pre> * @param messageProcessorSpec the splitter {@link MessageProcessorSpec}. * @return the current {@link IntegrationFlowDefinition}. * @see SplitterEndpointSpec */ public B split(MessageProcessorSpec<?> messageProcessorSpec) { return split(messageProcessorSpec, (Consumer<SplitterEndpointSpec<MethodInvokingSplitter>>) null); }
/** * Populate the {@link MethodInvokingSplitter} to evaluate the provided * {@link Function} at runtime. * Typically used with a Java 8 Lambda expression: * <pre class="code"> * {@code * .split(String.class, p -> * jdbcTemplate.execute("SELECT * from FOO", * (PreparedStatement ps) -> * new ResultSetIterator<Foo>(ps.executeQuery(), * (rs, rowNum) -> * new Foo(rs.getInt(1), rs.getString(2))))) * } * </pre> * @param payloadType the {@link Class} for expected payload type. It can also be * {@code Message.class} if you wish to access the entire message in the splitter. * Conversion to this type will be attempted, if necessary. * @param splitter the splitter {@link Function}. * @param <P> the payload type or {@code Message.class}. * @return the current {@link IntegrationFlowDefinition}. * @see LambdaMessageProcessor */ public <P> B split(Class<P> payloadType, Function<P, ?> splitter) { return split(payloadType, splitter, null); }
/** * Populate the {@link MethodInvokingSplitter} to evaluate the provided * {@link Function} at runtime. * In addition accept options for the integration endpoint using {@link GenericEndpointSpec}. * Typically used with a Java 8 Lambda expression: * <pre class="code"> * {@code * .<String>split(p -> * jdbcTemplate.execute("SELECT * from FOO", * (PreparedStatement ps) -> * new ResultSetIterator<Foo>(ps.executeQuery(), * (rs, rowNum) -> * new Foo(rs.getInt(1), rs.getString(2)))) * , e -> e.applySequence(false)) * } * </pre> * @param splitter the splitter {@link Function}. * @param endpointConfigurer the {@link Consumer} to provide integration endpoint options. * @param <P> the payload type. * @return the current {@link IntegrationFlowDefinition}. * @see LambdaMessageProcessor * @see SplitterEndpointSpec */ public <P> B split(Function<P, ?> splitter, Consumer<SplitterEndpointSpec<MethodInvokingSplitter>> endpointConfigurer) { return split(null, splitter, endpointConfigurer); }
/** * Populate the provided {@link AbstractMessageSplitter} to the current integration * flow position. * @param splitterMessageHandlerSpec the {@link MessageHandlerSpec} to populate. * @param endpointConfigurer the {@link Consumer} to provide integration endpoint options. * @param <S> the {@link AbstractMessageSplitter} * @return the current {@link IntegrationFlowDefinition}. * @see SplitterEndpointSpec */ public <S extends AbstractMessageSplitter> B split(MessageHandlerSpec<?, S> splitterMessageHandlerSpec, Consumer<SplitterEndpointSpec<S>> endpointConfigurer) { Assert.notNull(splitterMessageHandlerSpec, "'splitterMessageHandlerSpec' must not be null"); return split(splitterMessageHandlerSpec.get(), endpointConfigurer); }
/** * Populate the {@link DefaultMessageSplitter} with provided options * to the current integration flow position. * Typically used with a Java 8 Lambda expression: * <pre class="code"> * {@code * .split(s -> s.applySequence(false).delimiters(",")) * } * </pre> * @param endpointConfigurer the {@link Consumer} to provide integration endpoint options * and for {@link DefaultMessageSplitter}. * @return the current {@link IntegrationFlowDefinition}. * @see SplitterEndpointSpec */ public B split(Consumer<SplitterEndpointSpec<DefaultMessageSplitter>> endpointConfigurer) { return split(new DefaultMessageSplitter(), endpointConfigurer); }
/** * Populate the {@link ExpressionEvaluatingSplitter} with provided * SpEL expression. * @param expression the splitter SpEL expression. * @param endpointConfigurer the {@link Consumer} to provide integration endpoint options * and for {@link ExpressionEvaluatingSplitter}. * @return the current {@link IntegrationFlowDefinition}. * @see SplitterEndpointSpec */ public B split(String expression, Consumer<SplitterEndpointSpec<ExpressionEvaluatingSplitter>> endpointConfigurer) { Assert.hasText(expression, "'expression' must not be empty"); return split(new ExpressionEvaluatingSplitter(PARSER.parseExpression(expression)), endpointConfigurer); }
/** * Populate the {@link MethodInvokingSplitter} to evaluate the provided * {@code method} of the {@code bean} at runtime. * In addition accept options for the integration endpoint using {@link GenericEndpointSpec}. * @param service the service to use. * @param methodName the method to invoke. * @param endpointConfigurer the {@link Consumer} to provide integration endpoint options * and for {@link MethodInvokingSplitter}. * @return the current {@link IntegrationFlowDefinition}. * @see SplitterEndpointSpec * @see MethodInvokingSplitter */ public B split(Object service, String methodName, Consumer<SplitterEndpointSpec<MethodInvokingSplitter>> endpointConfigurer) { MethodInvokingSplitter splitter; if (StringUtils.hasText(methodName)) { splitter = new MethodInvokingSplitter(service, methodName); } else { splitter = new MethodInvokingSplitter(service); } return split(splitter, endpointConfigurer); }
/** * Populate the {@link MethodInvokingSplitter} to evaluate the * {@link org.springframework.integration.handler.MessageProcessor} at runtime * from provided {@link MessageProcessorSpec}. * In addition accept options for the integration endpoint using {@link GenericEndpointSpec}. * <pre class="code"> * {@code * .split(Scripts.script(myScriptResource).lang("groovy").refreshCheckDelay(1000), * , e -> e.applySequence(false)) * } * </pre> * @param messageProcessorSpec the splitter {@link MessageProcessorSpec}. * @param endpointConfigurer the {@link Consumer} to provide integration endpoint options * and for {@link MethodInvokingSplitter}. * @return the current {@link IntegrationFlowDefinition}. * @see SplitterEndpointSpec */ public B split(MessageProcessorSpec<?> messageProcessorSpec, Consumer<SplitterEndpointSpec<MethodInvokingSplitter>> endpointConfigurer) { Assert.notNull(messageProcessorSpec, "'messageProcessorSpec' must not be null"); MessageProcessor<?> processor = messageProcessorSpec.get(); return addComponent(processor) .split(new MethodInvokingSplitter(processor), endpointConfigurer); }
/** * Populate the {@link MethodInvokingSplitter} to evaluate the provided * {@code method} of the {@code bean} at runtime. * In addition accept options for the integration endpoint using {@link GenericEndpointSpec}. * @param beanName the bean name to use. * @param methodName the method to invoke at runtime. * @param endpointConfigurer the {@link Consumer} to provide integration endpoint options * and for {@link MethodInvokingSplitter}. * @return the current {@link IntegrationFlowDefinition}. * @see SplitterEndpointSpec */ public B split(String beanName, String methodName, Consumer<SplitterEndpointSpec<MethodInvokingSplitter>> endpointConfigurer) { return split(new MethodInvokingSplitter(new BeanNameMessageProcessor<Object>(beanName, methodName)), endpointConfigurer); }
@Bean public IntegrationFlow scriptSplitter() { return f -> f.split(Scripts.processor(this.splitterScript)).channel(results()); }
@Bean public IntegrationFlow routerTwoSubFlows() { return f -> f .split() .<Integer, Boolean>route(p -> p % 2 == 0, m -> m .subFlowMapping(true, sf -> sf.<Integer>handle((p, h) -> p * 2)) .subFlowMapping(false, sf -> sf.<Integer>handle((p, h) -> p * 3))) .aggregate() .channel(MessageChannels.queue("routerTwoSubFlowsOutput")); }
@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(); }
@Bean @SuppressWarnings("rawtypes") public IntegrationFlow splitResequenceFlow(MessageChannel executorChannel) { return f -> f.enrichHeaders(s -> s.header("FOO", "BAR")) .split("testSplitterData", "buildList", c -> c.applySequence(false)) .channel(executorChannel) .split(Message.class, Message::getPayload, c -> c.applySequence(false)) .channel(MessageChannels.executor(taskExecutor())) .split(s -> s .applySequence(false) .delimiters(",")) .channel(MessageChannels.executor(taskExecutor())) .<String, Integer>transform(Integer::parseInt) .enrichHeaders(h -> h.headerFunction(IntegrationMessageHeaderAccessor.SEQUENCE_NUMBER, Message::getPayload)) .resequence(r -> r.releasePartialSequences(true).correlationExpression("'foo'")) .headerFilter("foo", false); }