Here I'm using Scatter-gather pattern using spring integration and calling 3 sub-flows parallelly. this same parallel process needs to be run for other requirements because the whole process is similar for the other few requirements it's just that for flow1 and flow2 I need I need to pass different parameter for different requirements. Here in flow1 I'm passing SourceSystem.ONEto the save method. So SourceSystem is an enum which is requirement specific. For different requirement that value is only needs to be changed, i.e., SourceSystem.TWO, SourceSystem.THREE etc.
I tried passing this as header to the gateway but not sure how do I use it to pass to the flow1 and flow 2 method.
//codebase
@Configuration
public class SpringIntegrationConfiguration {
@Autowired LoansServiceImpl loansService;
@Value("${someservice.url}")
private String someURL;
long dbId = new SequenceGenerator().nextId();
// Main flow
@Bean
public IntegrationFlow flow() {
return flow ->
flow.split()
.log()
.channel(c -> c.executor(Executors.newCachedThreadPool()))
.convert(LionRequest.class)
.scatterGather(
scatterer ->
scatterer
.applySequence(true)
.recipientFlow(flow1())
.recipientFlow(flow2())
.recipientFlow(flow3()),
gatherer ->
gatherer
.releaseLockBeforeSend(true)
.releaseStrategy(group -> group.size() == 2))
.aggregate(a -> a.outputProcessor(MessageGroup::getMessages))
.channel("output-flow");
}
@Bean
public IntegrationFlow flow1() {
return integrationFlowDefinition ->
integrationFlowDefinition
.channel(c -> c.executor(Executors.newCachedThreadPool()))
.transform(
message -> {
try {
return lionService.saveRequest(
(LionRequest) message,
String.valueOf(dbId),
Integer.valueOf(
((LoanRequest) message)
.getLionDetails()
.getId()),
SourceSystem.ONE.getSourceSystemCode());
} catch (JsonProcessingException e) {
return e.getMessage();
}
})
.nullChannel();
}
@Bean
public IntegrationFlow flow2() {
return integrationFlowDefinition ->
integrationFlowDefinition
.channel(c -> c.executor(Executors.newCachedThreadPool()))
.transform(
message ->
loansService.prepareSomething(
(LionRequest) message));
}
// Calling data sourcing service
@Bean
public IntegrationFlow flow3() {
return integrationFlowDefinition ->
integrationFlowDefinition
.channel(c -> c.executor(Executors.newCachedThreadPool()))
.transform(
payload ->
lionService.prepareRequest(
(LionRequest) payload, SourceSystem.ONE))
.handle(
Http.outboundGateway(someURL)
.httpMethod(HttpMethod.POST)
.expectedResponseType(String.class));
}
@Bean
public MessageChannel replyChannel() {
return MessageChannels.executor("output-flow", outputExecutor()).get();
}
@Bean
public ThreadPoolTaskExecutor outputExecutor() {
ThreadPoolTaskExecutor pool = new ThreadPoolTaskExecutor();
pool.setCorePoolSize(4);
pool.setMaxPoolSize(4);
return pool;
}
}
I tried to pass it onto the header but not sure how to pass it onto the methods. Because in transformer I'm not able to access the header only the payload is available it seems. And I can't use handle() method because it's throwing error as - "this component is a one-way 'MessageHandler' and it isn't appropriate to configure 'outputChannel'".
//Gateway
@Gateway(requestChannel = "flow.input", replyChannel = "output-flow")
List<Object> triggerParallelTasks(
@Payload LionRequest lionRequest,
@Header("sourceSystem") SourceSystem sourceSystem);
I'm trying to invoke the gateway like this -
gateway(lionrequest, SourceSystem.ONE);
gateway(lionrequest, SourceSystem.TWO);
gateway(lionrequest, SourceSystem.THREE);
If I should follow any other approach that also kindly suggest.