简体   繁体   English

如何在 Spring 集成中处理 http 响应异常并继续流程直到聚合

[英]How to handle http response exception and continue the flow till aggregate in Spring integration

I'm using Spring-integration in my project and the pattern used is scatter-gather.我在我的项目中使用 Spring-integration,使用的模式是分散聚集。 Here three parallel processes are being carried out.这里正在执行三个并行过程。 The flow2 is a outbound gateway method and if that service is down then I want to handle the Httpstatus exception and want to send null. flow2 是一个出站网关方法,如果该服务关闭,那么我想处理 Httpstatus 异常并希望发送 null。 Actually if that service is down then the whole flow is getting stopped.实际上,如果该服务关闭,那么整个流程就会停止。 But I want to handle that exception and send null and then want to continue with the aggregate method and end the flow.但我想处理该异常并发送 null,然后想继续使用聚合方法并结束流程。

Below is the code - -下面是代码——

//Config file //配置文件

 @Configuration
        public class IntegrationConfiguration {
          @Autowired LionsServiceImpl lionsService;
        
          long dbId = new SequenceGenerator().nextId();
      //   Main flow
      @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(flow2())
                        .recipientFlow(flow3()),
                gatherer ->
                    gatherer
                        .releaseLockBeforeSend(true)
                        .releaseStrategy(group -> group.size() == 2))
            .aggregate(prepareSomeRequest())
            .to(getDec());
  }

  //   Saving the request to the database
  @Bean
  public IntegrationFlow flow1() {
    return integrationFlowDefinition ->
        integrationFlowDefinition
            .channel(c -> c.executor(Executors.newCachedThreadPool()))
            .handle(
                (payload, header) -> {
                  ObjectMapper mapper = new ObjectMapper();
                  try {
                    String jsonString = mapper.writeValueAsString(payload);
                    JsonNode request = mapper.readTree(jsonString);
                    JsonNode csID = request.get("ApplicationDetails").get("CustomerId");
                    int customerID = mapper.treeToValue(csID, Integer.class);

                    return lionService.saveRequest(
                        payload,
                        String.valueOf(dbId),
                        customerID,
                        ((SourceSystem) Objects.requireNonNull(header.get("sourceSystem")))
                            .getSourceSystemCode());
                  } catch (JsonProcessingException e) {
                    throw new RuntimeException(e);
                  }
                }
                )
            .nullChannel();
  }

  // 
  @Bean
  public IntegrationFlow flow3() {
    return integrationFlowDefinition ->
        integrationFlowDefinition
            .channel(c -> c.executor(Executors.newCachedThreadPool()))
            .transform(
                message ->
                    loansService.someMethod(
                        (LionRequest) message));
  }

 //Here I'm calling a service through HTTPOUTBOUNDGATEWAY and if that called service is down then it throws HTTP STAtus error so I want to handle that and want to send null from this flow.
  @Bean
  public IntegrationFlow flow2() {
    return integrationFlowDefinition ->
        integrationFlowDefinition
            .channel(c -> c.executor(Executors.newCachedThreadPool()))
            .handle(
                (payload, header) ->
                    loansService.someMethod2(
                        (LionRequest) payload,
                        (SourceSystem) (Objects.requireNonNull(header.get("sourceSystem")))))
            .handle(
                Http.outboundGateway(someurl)
                    .httpMethod(HttpMethod.POST)
                    .expectedResponseType(String.class)
                       );
  }


  @Bean
  public IntegrationFlow getDec() {
    return flow ->
        flow.handle(
            Http.outboundGateway(ServiceURL)
                .httpMethod(HttpMethod.POST)
                .expectedResponseType(CrResponse.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;
  }


//here I want to take out null from messages which is sent by flow2 if the called service is down and then I want to send null to someMethod2 method.

  public MessageGroupProcessor prepareSomeRequest() {
    return group -> {
      String cData;
      Object CDReq;

      List<Message<?>> messages = group.streamMessages().collect(Collectors.toList());

      ArrayList<Object> payloads = (ArrayList<Object>) messages.get(0).getPayload();

      if (payloads.get(0).toString().contains("tribv")) {
        cData= payloads.get(0).toString();
        logger.atInfo().log("Customer data from Data Sourcing Service : " + cData);
        CDReq= payloads.get(1);
      } else {
        cData= payloads.get(1).toString();
        logger.atInfo().log("Customer data from Data Sourcing Service : " + cData);
        CDReq = payloads.get(0);
      }

      Object fReq =
          lionservice.someMethod2(cData, CDReq);

      SomeRequest somreq= new SomeRequest();

      ObjectMapper mapper = new ObjectMapper();

      JsonNode req = mapper.valueToTree(freq);
      creditDecisionRequest.setfsfgg(req);
      creditDecisionRequest.setR("234565432");
      creditDecisionRequest.setD(String.valueOf(dbId));
      creditDecisionRequest.setCID("33333333");
      creditDecisionRequest.setSourceSystemCode(SourceSystem.ONE.getSourceSystemCode());

      return somreq;
    };
  }

Gateway网关

    @Gateway(requestChannel = "flow.input")
  void processLionRequest(
      @Payload Message lionRequest, @Header("sourceSystem") SourceSystem sourceSystem);

Can I use something like .errorHandler() in the outboundgateway?我可以在出站网关中使用类似.errorHandler()的东西吗? But how do I use that?但是我该如何使用呢?

 @Bean
  public IntegrationFlow flow2() {
    return integrationFlowDefinition ->
        integrationFlowDefinition
            .channel(c -> c.executor(Executors.newCachedThreadPool()))
            .handle(
                (payload, header) ->
                    lionService.prepareSomeRequest(
                        (LionRequest) payload,
                        (SourceSystem) (Objects.requireNonNull(header.get("sourceSystem")))))
            .handle(
                Http.outboundGateway(someurl)
                    .httpMethod(HttpMethod.POST)
                    .expectedResponseType(String.class),
                c -> c.advice(expressionAdvice()));
  }

  @Bean
  public Advice expressionAdvice() {
    ExpressionEvaluatingRequestHandlerAdvice advice =
        new ExpressionEvaluatingRequestHandlerAdvice();
    advice.setFailureChannelName("failure.input");
    advice.setTrapException(true);
    return advice;
  }

  @Bean
  public IntegrationFlow success() {
    return f -> f.handle(System.out::println);
  }

  @Bean
  public IntegrationFlow failure() {
    return f -> f.handle(adviceOnFailure());
  }

  public String adviceOnFailure() {
    return "Failed";
  }

I'm doing something like that but getting error as below -我正在做类似的事情,但出现如下错误 -

Caused by: java.lang.IllegalArgumentException: Found ambiguous parameter type [class java.lang.String] for method match: [public byte[] java.lang.String.getBytes(java.nio.charset.Charset), public static java.lang.String java.lang.String.valueOf(double), public boolean java.lang.String.contains(java.lang.CharSequence), public static java.lang.String java.lang.String.copyValueOf(char[]), public java.lang.String[] java.lang.String.split(java.lang.String), public native java.lang.String java.lang.String.intern(), public java.lang.String java.lang.String.repeat(int), public static java.lang.String java.lang.String.valueOf(char), public static java.lang.String java.lang.String.valueOf(boolean), public static java.lang.String java.lang.String.valueOf(java.lang.Object), public static java.lang.String java.lang.String.valueOf(float), public static java.lang.String java.lang.String.valueOf(long), public java.lang.String java.lang.String.toUpperCase(java.util.Locale), public boolean java.lang.String.contentEquals(java.lang.StringBuffer)]

please help.请帮忙。

There is no null payload concept in messaging, so even if you handle an error, you definitely cannot return null as a reply from that Outbound Gateway call.消息传递中没有null payload概念,因此即使您处理错误,也绝对不能返回null作为该出站网关调用的回复。

See Request Handler Advice pattern in the framework, in particular an ExpressionEvaluatingRequestHandlerAdvice implementation.请参阅框架中的请求处理程序建议模式,特别是ExpressionEvaluatingRequestHandlerAdvice实现。 It does handle error for the specific message handler and may return a compensation reply which you then can aggregator and process respectively.它确实处理特定消息处理程序的错误,并可能返回补偿回复,然后您可以分别聚合和处理。

The doc is here: https://docs.spring.io/spring-integration/docs/current/reference/html/messaging-endpoints.html#message-handler-advice-chain文档在这里: https ://docs.spring.io/spring-integration/docs/current/reference/html/messaging-endpoints.html#message-handler-advice-chain

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM