0

I'm making a scatter-gather flow here. In the end of the flow I want to printout the message from the reply channel to the console. Here I've 3 API calls out of which 2 are GET calls and 1 is POST call(POST call is doing some database operation). All the API's are running and getting result but I'm not able to print the message.

//Configuration class

package com.lbg.scattergather.configuration;

import com.lbg.scattergather.model.Company;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.integration.dsl.IntegrationFlow;
import org.springframework.integration.dsl.Transformers;
import org.springframework.integration.handler.LoggingHandler;
import org.springframework.integration.http.dsl.Http;
import org.springframework.integration.store.MessageGroup;

import java.util.List;
import java.util.Map;
import java.util.concurrent.Executors;


@Configuration
public class ScatterGatherConfig {
    @Bean
  public IntegrationFlow flow(){
        return flow -> flow
                .split().log().channel(c->c.executor(Executors.newCachedThreadPool()))
                .scatterGather(
                        scatterer -> scatterer
                                .applySequence(true)
                                .recipientFlow(flow1())
                                .recipientFlow(flow2())
                                .recipientFlow(flow3()),
                        gatherer -> gatherer
                                .releaseStrategy(group -> group.size()==3)


            );

}

@Bean
public IntegrationFlow flow1(){
    return integrationFlowDefinition -> integrationFlowDefinition
            .channel(c -> c.executor(Executors.newCachedThreadPool()))
            .handle(Http.outboundGateway("http://localhost:8888/name/101")
                    .httpMethod(HttpMethod.GET)
                    .expectedResponseType(String.class)
                    .get()).log();
}

@Bean
public IntegrationFlow flow2(){
    return integrationFlowDefinition -> integrationFlowDefinition
            .channel(c -> c.executor(Executors.newCachedThreadPool()))
            .handle(Http.outboundGateway("http://localhost:9091/name/101")
                    .httpMethod(HttpMethod.GET)
                    .expectedResponseType(String.class)
                    .get()).log();
}

@Bean
public IntegrationFlow flow3(){
    return integrationFlowDefinition -> integrationFlowDefinition
            .channel(c -> c.executor(Executors.newCachedThreadPool())).log()
            .split("payload.employee").log()
            .enrichHeaders(h->h.header("ContentType", "application/json")).log()
//                .transform(Transformers.fromJson(Map.class)).log()
//                .channel()
//                .enrich((enricher) -> enricher.<Map<String, ?>>requestPayload((message) ->
//                        ( message.getPayload().get("Name"))))
                .handle(Http.outboundGateway("http://localhost:8888/Employee")
                        .httpMethod(HttpMethod.POST)
                        .expectedResponseType(String.class)
                        .get()).log();
    }

}

//Gateway service
package com.lbg.scattergather;

import com.lbg.scattergather.model.Company;
import com.lbg.scattergather.model.Employee;
import org.springframework.integration.annotation.Gateway;
import org.springframework.integration.annotation.MessagingGateway;
import org.springframework.messaging.Message;

import java.util.List;

@MessagingGateway
public interface gatewayService {

    @Gateway(requestChannel = "flow.input")
    List<Message> messages(Company company);
}


//Main application
package com.lbg.scattergather;

import com.lbg.scattergather.model.Employee;
import com.lbg.scattergather.model.Company;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.util.StopWatch;

@SpringBootApplication
public class ScatterGatherApplication {


    public static void main(String[] args) {
        Employee employee = new Employee(114,"Abhinav",3000);
        Company company = new Company(employee, 122L,"C_01");
        StopWatch stopWatch = new StopWatch();
        ConfigurableApplicationContext ctx=
                SpringApplication.run(ScatterGatherApplication.class, args);
        stopWatch.start();
        System.out.println("Starting the Integration flow");
        System.out.println(ctx.getBean(gatewayService.class)
                .messages(company));
        System.out.println("Ending the Integration Flow");
        stopWatch.stop();
        System.out.println("Time taken : "+stopWatch.getTotalTimeMillis());
    }

}

if only two GET apis are being called then I can able to print the message.

  • Consider to use the message history to see how you message is traveling. Don’t use that `get()` for gateways: the framework does that for us plus some other useful stuff. – Artem Bilan Jun 19 '22 at 18:22
  • Hi @ArtemBilan, Thanks for your response. Actually I've traced the logs and it's working perfectly all right, it's just that the message is not getting printed. Also I've removed the get(). It's only happening for POST call(Flow 3). If I'm omitting the split("payload.employee") then it's printing the message. Regardless, it's showing correctly in logs. – Somnath Mukherjee Jun 20 '22 at 12:20

1 Answers1

0

You have a couple problems at the moment with your configuration:

  1. The log() is not relying operator in the end of the flow until currently in progress version 6.0: https://github.com/spring-projects/spring-integration/wiki/Spring-Integration-5.x-to-6.0-Migration-Guide#log-at-the-end-of-a-flow. Therefore it is not clear what you would expect to get as a result for your scatter-gather since none of your flow would reply back to the scatterer. Consider to add a bridge() in the end of those flows if you'd like to see an HTTP response logged.

  2. The split() is always a problem for request-reply scenario: the caller sends a request and waits for the reply. Only one reply. Typically splitter produces several messages, so only one of them can fulfill a reply expectations. The rest are going to be ignored ad dropped. If you still think that split() must be in your logic and you'd like to receive all the replies from those splitted items, consider to add in the end of that flow3 an aggregate().

Artem Bilan
  • 113,505
  • 11
  • 91
  • 118