I have a SI DSL flow like
@Bean
public IntegrationFlow processRequest() {
return flow -> flow.channel(REQUEST_INPUT)
.transform(...)
.enrichHeaders(h -> h.<Storage>headerFunction(...)))
.enrich(this::...)
//.route(ifReplayIsNeeded(), routeToSameFlow())
.enrich(this::...)
.route(..., ...)
.route(..., ...)
.enrich(this::...)
.handle(...)
//.route(ifReplayWasNeeded(), routeBack())
.route(..., ...)
.enrich(this::...)
.transform(...)
.channel(REQUEST_OUTPUT);
}
So when a condition is fulfilled (see ifReplayIsNeeded()
) then the processRequest()
flow has to be called again. However not the whole flow has to be executed but nearly at the end (-> ifReplayWasNeeded()
) this internal flow has to go back to where it was called and process the original flow entirely.
The routeToSameFlow()
look like (the Storage
is used for store requests/responses and other data that are used in the flow)
Consumer<RouterSpec<Boolean, MethodInvokingRouter>> routeToSameFlow() {
return rs -> rs.resolutionRequired(false)
.subFlowMapping(true, sf -> sf
// 1. storing the current Storage
.enrichHeaders(h -> h.<Storage>headerFunction("store", s -> s))
// 2. creating the req for the internal flow
.transform(internalRequestMapper, "mapFrom")
// 3. routing to the beginning of the flow
.route(Message.class, (m) -> REQUEST_INPUT)
// 4. defining the channel where the internal flow will return to
.channel("RETURN_CHANNEL")
)
.defaultOutputToParentFlow();
}
and the routeBack()
Consumer<RouterSpec<Boolean, MethodInvokingRouter>> routeBack() {
return rs -> rs.resolutionRequired(false)
.subFlowMapping(true, sf ->
sf.route(Message.class, (m) -> "RETURN_CHANNEL")
)
.defaultOutputToParentFlow();
}
Definitely I am missing some concept as I got the following error:
Caused by: org.springframework.beans.factory.BeanCreationException: The 'currentComponent' (org.springframework.integration.router.MethodInvokingRouter@60a0f09f) is a one-way 'MessageHandler' and it isn't appropriate to configure 'outputChannel'. This is the end of the integration flow.
Could you please help me how to implement such a logic? Should I split the main flow to smaller IntegrationFlow?
I want to disrupt the main flow as less as possible so that's the reason why I just want to add a diversion route at the beginning and a return route at the end. Is it possible to do that?
Thank you!
Regards,
V.
You probably over complicate the logic with all those routers. Consider to have just only simple channel()
definitions in the middle of your main flow and as an output of that sub-flow you want to come back. There is no restrictions in Java DSL just to have channel()
definition in the beginning and the end: you free to add channel()
in the any point of the flow definition. For example:
.handle(...)
.channel("middleOfTheFlow")
.route(ifReplayWasNeeded(), routeBack())
Then your routeBack()
flow definition could just have .channel("middleOfTheFlow")
in the end and messages after processing here are going to be delivered to the middleOfTheFlow
channel of the main flow.
In other words an IntegrationFlow
is just logical components to keep endpoints regarding some business function in the same place, but this doesn't mean that all the endpoints in the flow are tied to each other very strictly. You always can have a channel in between and send messages to that channel from other places and the endpoint subscribed to this channel is going to process that message.
See more info in docs: https://docs.spring.io/spring-integration/docs/current/reference/html/dsl.html#java-dsl