0

Here I've three subflows and out of which one is HTTP outbound call. I want that HTTP call should try to get response till a mentioned time. If times out then the main flow should break and it should show a Error message in Json format as output.

Below is the code -

     @Bean
      public IntegrationFlow flow() {
        return flow ->
            flow.handle(validatorService, "validateRequest")
                .split()
                .channel(c -> c.executor(Executors.newCachedThreadPool()))
                .scatterGather(
                    scatterer ->
                        scatterer
                            .applySequence(true)
                            .recipientFlow(flow1())
                            .recipientFlow(
                                f ->
                                    f.gateway(
                                        flow2(), gateway -> gateway.replyTimeout(3000L).errorChannel("errorChannel")))
                            .recipientFlow(flow3()),
                    gatherer ->
                        gatherer
                            .releaseLockBeforeSend(true)
                            .releaseStrategy(group -> group.size() == 2))
                .aggregate(someMethod1())
                .to(someMethod2());
      }

  private IntegrationFlow returnError() {
    return IntegrationFlows.from("errorChannel").handle(System.out::println).get();
  }

I've added the errorChannel but how do I send a customized message to the user?

1 Answers1

1

See documentation for error handling in the messaging gateway: https://docs.spring.io/spring-integration/docs/current/reference/html/messaging-endpoints.html#gateway-no-response.

Consider to add an errorChannel() along side with that replyTimeout() on the gateway definition to build an error reply you'd like. However you also may consider to add something like a request timeout for the RestTemplate you use for that HTTP call to prevent the long wait for HTTP response.

UPDATE

First of all you need to understand that request-reply is a bit of block-n-then-wait approach. We send a request and if the process consuming that message is blocking - performed immediately in a thread producing the message, then we don't reach "wait" part until that process lets go. In most cases (by default) a DirectChannel is used, so it is blocked because it is performed in the calling thread. This process might be your HTTP call which is also request-response pattern. So, we don't reach that "wait" part until this HTTP call returns, or timeout, or fail with error. Only after that a replyTimeout takes its effect to wait for the reply from the underlying process. This can be changes if an input channel of that process is not direct. See an ExecutorChannel or QueueChannel. This way a sending part exits immediately because there is nothing to block it and it goes to the "wait" part to observe a CountDownLatch.

So, you need to think again if that replyTimeout() option is appropriate for your or not. Perhaps the mentioned requestTimeout for the RestTemplate is better option for you, than rework your flow to the async solution to leverage that replyTimeout() feature. Again: see the documentation I've mentioned about that replyTimeout feature.

The error handling is described here: https://docs.spring.io/spring-integration/docs/current/reference/html/error-handling.html#error-handling.

It is really not recommended to rely on the global errorChannel bean. This is one which is used everywhere in async processes where there is no an explicit error channel configured.

You said in your question "send a customized message to the user", but your error handling flow is one-way - System.out::println. If you want to return anything from the error handling flow, the endpoint must be replying one, e.g.:

.handle((p, h) -> "The error during HTTP call: " + p)

Also see if you declare that returnError() correctly. It really cannot be just plain private method. The IntegrationFlow must be declared as a bean this or other way to initiate wiring process for endpoints and channels. Right now that one is just a plain, unused private method. The framework does not see that method to do anything. See basics of the Java DSL in docs: https://docs.spring.io/spring-integration/docs/current/reference/html/dsl.html#java-dsl

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