private MessageChannel obtainInputChannelFromFlow(IntegrationFlow flow) { Assert.notNull(flow, "'flow' must not be null"); MessageChannel messageChannel = flow.getInputChannel(); if (messageChannel == null) { messageChannel = new DirectChannel(); IntegrationFlowDefinition<?> flowBuilder = IntegrationFlows.from(messageChannel); flow.configure(flowBuilder); addComponent(flowBuilder.get()); } else { addComponent(flow); } return messageChannel; }
/** * 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); }
/** * Populate the {@code Wire Tap} EI Pattern specific * {@link org.springframework.messaging.support.ChannelInterceptor} implementation * to the current {@link #currentMessageChannel}. * It is useful when an implicit {@link MessageChannel} is used between endpoints: * <pre class="code"> * {@code * .transform("payload") * .wireTap(tapChannel(), wt -> wt.selector(m -> m.getPayload().equals("foo"))) * .channel("foo") * } * </pre> * This method can be used after any {@link #channel} for explicit {@link MessageChannel}, * but with the caution do not impact existing {@link org.springframework.messaging.support.ChannelInterceptor}s. * @param wireTapChannel the {@link MessageChannel} to wire-tap. * @param wireTapConfigurer the {@link Consumer} to accept options for the {@link WireTap}. * @return the current {@link IntegrationFlowDefinition}. */ public B wireTap(MessageChannel wireTapChannel, Consumer<WireTapSpec> wireTapConfigurer) { WireTapSpec wireTapSpec = new WireTapSpec(wireTapChannel); if (wireTapConfigurer != null) { wireTapConfigurer.accept(wireTapSpec); } addComponent(wireTapChannel); return wireTap(wireTapSpec); }
@SuppressWarnings("unchecked") private <S extends ConsumerEndpointSpec<S, ? extends MessageHandler>> B register(S endpointSpec, Consumer<S> endpointConfigurer) { if (endpointConfigurer != null) { endpointConfigurer.accept(endpointSpec); } MessageChannel inputChannel = this.currentMessageChannel; this.currentMessageChannel = null; if (inputChannel == null) { inputChannel = new DirectChannel(); this.registerOutputChannelIfCan(inputChannel); } Tuple2<ConsumerEndpointFactoryBean, ? extends MessageHandler> factoryBeanTuple2 = endpointSpec.get(); addComponents(endpointSpec.getComponentsToRegister()); if (inputChannel instanceof MessageChannelReference) { factoryBeanTuple2.getT1().setInputChannelName(((MessageChannelReference) inputChannel).getName()); } else { if (inputChannel instanceof FixedSubscriberChannelPrototype) { String beanName = ((FixedSubscriberChannelPrototype) inputChannel).getName(); inputChannel = new FixedSubscriberChannel(factoryBeanTuple2.getT2()); if (beanName != null) { ((FixedSubscriberChannel) inputChannel).setBeanName(beanName); } registerOutputChannelIfCan(inputChannel); } factoryBeanTuple2.getT1().setInputChannel(inputChannel); } return addComponent(endpointSpec).currentComponent(factoryBeanTuple2.getT2()); }
/** * Populate a {@link MessageFilter} with {@link MethodInvokingSelector} * for the {@link org.springframework.integration.handler.MessageProcessor} from * the provided {@link MessageProcessorSpec}. * In addition accept options for the integration endpoint using {@link FilterEndpointSpec}. * <pre class="code"> * {@code * .filter(Scripts.script(scriptResource).lang("ruby"), * e -> e.autoStartup(false)) * } * </pre> * @param messageProcessorSpec the {@link MessageProcessorSpec} to use. * @param endpointConfigurer the {@link Consumer} to provide integration endpoint options. * @return the current {@link IntegrationFlowDefinition}. */ public B filter(MessageProcessorSpec<?> messageProcessorSpec, Consumer<FilterEndpointSpec> endpointConfigurer) { Assert.notNull(messageProcessorSpec, "'messageProcessorSpec' must not be null"); MessageProcessor<?> processor = messageProcessorSpec.get(); return addComponent(processor) .filter(new MethodInvokingSelector(processor), endpointConfigurer); }
/** * Populate a {@link ServiceActivatingHandler} for the * {@link org.springframework.integration.handler.MessageProcessor} from the provided * {@link MessageProcessorSpec}. * In addition accept options for the integration endpoint using {@link GenericEndpointSpec}. * <pre class="code"> * {@code * .handle(Scripts.script("classpath:myScript.ruby"), e -> e.autoStartup(false)) * } * </pre> * @param messageProcessorSpec the {@link MessageProcessorSpec} to use. * @param endpointConfigurer the {@link Consumer} to provide integration endpoint options. * @return the current {@link IntegrationFlowDefinition}. */ public B handle(MessageProcessorSpec<?> messageProcessorSpec, Consumer<GenericEndpointSpec<ServiceActivatingHandler>> endpointConfigurer) { Assert.notNull(messageProcessorSpec, "'messageProcessorSpec' must not be null"); MessageProcessor<?> processor = messageProcessorSpec.get(); return addComponent(processor) .handle(new ServiceActivatingHandler(processor), endpointConfigurer); }
/** * Populate the {@link MessageTransformingHandler} instance for the * {@link org.springframework.integration.handler.MessageProcessor} from provided {@link MessageProcessorSpec}. * In addition accept options for the integration endpoint using {@link GenericEndpointSpec}. * <pre class="code"> * {@code * .transform(Scripts.script("classpath:myScript.py").variable("foo", bar()), * e -> e.autoStartup(false)) * } * </pre> * @param messageProcessorSpec the {@link MessageProcessorSpec} to use. * @param endpointConfigurer the {@link Consumer} to provide integration endpoint options. * @return the current {@link IntegrationFlowDefinition}. * @see MethodInvokingTransformer */ public B transform(MessageProcessorSpec<?> messageProcessorSpec, Consumer<GenericEndpointSpec<MessageTransformingHandler>> endpointConfigurer) { Assert.notNull(messageProcessorSpec, "'messageProcessorSpec' must not be null"); MessageProcessor<?> processor = messageProcessorSpec.get(); return addComponent(processor) .transform(new MethodInvokingTransformer(processor), 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 MethodInvokingRouter} for the {@link org.springframework.integration.handler.MessageProcessor} * from the provided {@link MessageProcessorSpec} with default options. * <pre class="code"> * {@code * .route(Scripts.script(myScriptResource).lang("groovy").refreshCheckDelay(1000), * m -> m.channelMapping("true", "evenChannel") * .subFlowMapping("false", f -> * f.<Integer>handle((p, h) -> p * 3))) * } * </pre> * @param messageProcessorSpec the {@link MessageProcessorSpec} to use. * @param routerConfigurer the {@link Consumer} to provide {@link MethodInvokingRouter} options. * @return the current {@link IntegrationFlowDefinition}. */ public B route(MessageProcessorSpec<?> messageProcessorSpec, Consumer<RouterSpec<Object, MethodInvokingRouter>> routerConfigurer) { Assert.notNull(messageProcessorSpec, "'messageProcessorSpec' must not be null"); MessageProcessor<?> processor = messageProcessorSpec.get(); addComponent(processor); return route(new RouterSpec<>(new MethodInvokingRouter(processor)), routerConfigurer); }
flowBuilder.channel(new FixedSubscriberChannel(bridgeHandler)); addComponent(flowBuilder.get());
/** * 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); }
/** * Populate the {@code Wire Tap} EI Pattern specific * {@link org.springframework.messaging.support.ChannelInterceptor} implementation * to the current {@link #currentMessageChannel}. * It is useful when an implicit {@link MessageChannel} is used between endpoints: * <pre class="code"> * {@code * .transform("payload") * .wireTap("tapChannel", wt -> wt.selector(m -> m.getPayload().equals("foo"))) * .channel("foo") * } * </pre> * This method can be used after any {@link #channel} for explicit {@link MessageChannel}, * but with the caution do not impact existing {@link org.springframework.messaging.support.ChannelInterceptor}s. * @param wireTapChannel the {@link MessageChannel} bean name to wire-tap. * @param wireTapConfigurer the {@link Consumer} to accept options for the {@link WireTap}. * @return the current {@link IntegrationFlowDefinition}. */ public B wireTap(String wireTapChannel, Consumer<WireTapSpec> wireTapConfigurer) { DirectChannel internalWireTapChannel = new DirectChannel(); addComponent(IntegrationFlows.from(internalWireTapChannel).channel(wireTapChannel).get()); return wireTap(internalWireTapChannel, wireTapConfigurer); }
/** * Populate a {@link FluxMessageChannel} to start a reactive processing for upstream data, * wrap it to a {@link Flux}, apply provided {@link Function} via {@link Flux#transform(Function)} * and emit the result to one more {@link FluxMessageChannel}, subscribed in the downstream flow. * @param fluxFunction the {@link Function} to process data reactive manner. * @param <I> the input payload type. * @param <O> the output type. * @return the current {@link IntegrationFlowDefinition}. */ @SuppressWarnings("unchecked") public <I, O> B fluxTransform(Function<? super Flux<Message<I>>, ? extends Publisher<O>> fluxFunction) { if (!(this.currentMessageChannel instanceof FluxMessageChannel)) { channel(new FluxMessageChannel()); } Publisher<Message<I>> upstream = (Publisher<Message<I>>) this.currentMessageChannel; Flux<Message<O>> result = Transformers.transformWithFunction(upstream, fluxFunction); FluxMessageChannel downstream = new FluxMessageChannel(); downstream.subscribeTo((Flux<Message<?>>) (Flux<?>) result); this.currentMessageChannel = downstream; return addComponent(this.currentMessageChannel); }
/** * Populate the {@link MessageTransformingHandler} instance for the provided {@link GenericTransformer} * for the specific {@code payloadType} to convert at runtime. * In addition accept options for the integration endpoint using {@link GenericEndpointSpec}. * @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 transformer. * Conversion to this type will be attempted, if necessary. * @param genericTransformer the {@link GenericTransformer} to populate. * @param endpointConfigurer the {@link Consumer} to provide integration endpoint options. * @param <P> the payload type - 'transform from', or {@code Message.class}. * @param <T> the target type - 'transform to'. * @return the current {@link IntegrationFlowDefinition}. * @see MethodInvokingTransformer * @see LambdaMessageProcessor * @see GenericEndpointSpec */ public <P, T> B transform(Class<P> payloadType, GenericTransformer<P, T> genericTransformer, Consumer<GenericEndpointSpec<MessageTransformingHandler>> endpointConfigurer) { Assert.notNull(genericTransformer, "'genericTransformer' must not be null"); Transformer transformer = genericTransformer instanceof Transformer ? (Transformer) genericTransformer : (isLambda(genericTransformer) ? new MethodInvokingTransformer(new LambdaMessageProcessor(genericTransformer, payloadType)) : new MethodInvokingTransformer(genericTransformer, ClassUtils.TRANSFORMER_TRANSFORM_METHOD)); return addComponent(transformer) .handle(new MessageTransformingHandler(transformer), endpointConfigurer); }
/** * Populate a {@link WireTap} for the {@link #currentMessageChannel} * with the {@link LoggingHandler} subscriber for the provided * {@link LoggingHandler.Level} logging level, logging category * and SpEL expression for the log message. * <p> When this operator is used in the end of flow, it is treated * as one-way handler without any replies to continue. * The {@link #logAndReply()} should be used for request-reply configuration. * @param level the {@link LoggingHandler.Level}. * @param category the logging category. * @param logExpression the {@link Expression} to evaluate logger message at runtime * against the request {@link Message}. * @return the current {@link IntegrationFlowDefinition}. * @see #wireTap(WireTapSpec) */ public B log(LoggingHandler.Level level, String category, Expression logExpression) { LoggingHandler loggingHandler = new LoggingHandler(level); if (StringUtils.hasText(category)) { loggingHandler.setLoggerName(category); } if (logExpression != null) { loggingHandler.setLogExpression(logExpression); } else { loggingHandler.setShouldLogFullMessage(true); } addComponent(loggingHandler); MessageChannel loggerChannel = new FixedSubscriberChannel(loggingHandler); return wireTap(loggerChannel); }
/** * Populate the {@code Wire Tap} EI Pattern specific * {@link org.springframework.messaging.support.ChannelInterceptor} implementation * to the current {@link #currentMessageChannel}. * <p> It is useful when an implicit {@link MessageChannel} is used between endpoints: * <pre class="code"> * {@code * .transform("payload") * .wireTap(new WireTap(tapChannel().selector(m -> m.getPayload().equals("foo"))) * .channel("foo") * } * </pre> * This method can be used after any {@link #channel} for explicit {@link MessageChannel}, * but with the caution do not impact existing {@link org.springframework.messaging.support.ChannelInterceptor}s. * @param wireTapSpec the {@link WireTapSpec} to use. * <p> When this EIP-method is used in the end of flow, it appends {@code nullChannel} to terminate flow properly, * Otherwise {@code Dispatcher has no subscribers} exception is thrown for implicit {@link DirectChannel}. * @return the current {@link IntegrationFlowDefinition}. */ public B wireTap(WireTapSpec wireTapSpec) { WireTap interceptor = wireTapSpec.get(); if (!(this.currentMessageChannel instanceof ChannelInterceptorAware)) { channel(new DirectChannel()); this.implicitChannel = true; } addComponent(wireTapSpec); ((ChannelInterceptorAware) this.currentMessageChannel).addInterceptor(interceptor); return _this(); }
private MessageChannel obtainInputChannelFromFlow(IntegrationFlow flow) { Assert.notNull(flow, "'flow' must not be null"); MessageChannel messageChannel = flow.getInputChannel(); if (messageChannel == null) { messageChannel = new DirectChannel(); IntegrationFlowDefinition<?> flowBuilder = IntegrationFlows.from(messageChannel); flow.configure(flowBuilder); addComponent(flowBuilder.get()); } else { addComponent(flow); } return messageChannel; }
/** * Populate the {@link MessageTransformingHandler} instance for the * {@link org.springframework.integration.handler.MessageProcessor} from provided {@link MessageProcessorSpec}. * In addition accept options for the integration endpoint using {@link GenericEndpointSpec}. * <pre class="code"> * {@code * .transform(Scripts.script("classpath:myScript.py").valiable("foo", bar()), * e -> e.autoStartup(false)) * } * </pre> * @param messageProcessorSpec the {@link MessageProcessorSpec} to use. * @param endpointConfigurer the {@link Consumer} to provide integration endpoint options. * @return the current {@link IntegrationFlowDefinition}. * @since 1.1 * @see MethodInvokingTransformer */ public B transform(MessageProcessorSpec<?> messageProcessorSpec, Consumer<GenericEndpointSpec<MessageTransformingHandler>> endpointConfigurer) { Assert.notNull(messageProcessorSpec, "'messageProcessorSpec' must not be null"); MessageProcessor<?> processor = messageProcessorSpec.get(); return addComponent(processor) .transform(new MethodInvokingTransformer(processor), endpointConfigurer); }
/** * Populate a {@link MessageFilter} with {@link MethodInvokingSelector} * for the {@link org.springframework.integration.handler.MessageProcessor} from * the provided {@link MessageProcessorSpec}. * In addition accept options for the integration endpoint using {@link FilterEndpointSpec}. * <pre class="code"> * {@code * .filter(Scripts.script(scriptResource).lang("ruby"), * e -> e.autoStartup(false)) * } * </pre> * @param messageProcessorSpec the {@link MessageProcessorSpec} to use. * @param endpointConfigurer the {@link Consumer} to provide integration endpoint options. * @return the current {@link IntegrationFlowDefinition}. */ public B filter(MessageProcessorSpec<?> messageProcessorSpec, Consumer<FilterEndpointSpec> endpointConfigurer) { Assert.notNull(messageProcessorSpec, "'messageProcessorSpec' must not be null"); MessageProcessor<?> processor = messageProcessorSpec.get(); return addComponent(processor) .filter(new MethodInvokingSelector(processor), endpointConfigurer); }
/** * Populate a {@link ServiceActivatingHandler} for the * {@link org.springframework.integration.handler.MessageProcessor} from the provided * {@link MessageProcessorSpec}. * In addition accept options for the integration endpoint using {@link GenericEndpointSpec}. * <pre class="code"> * {@code * .handle(Scripts.script("classpath:myScript.ruby"), e -> e.autoStartup(false)) * } * </pre> * @param messageProcessorSpec the {@link MessageProcessorSpec} to use. * @param endpointConfigurer the {@link Consumer} to provide integration endpoint options. * @return the current {@link IntegrationFlowDefinition}. */ public B handle(MessageProcessorSpec<?> messageProcessorSpec, Consumer<GenericEndpointSpec<ServiceActivatingHandler>> endpointConfigurer) { Assert.notNull(messageProcessorSpec, "'messageProcessorSpec' must not be null"); MessageProcessor<?> processor = messageProcessorSpec.get(); return addComponent(processor) .handle(new ServiceActivatingHandler(processor), endpointConfigurer); }