Spring integration 基于回复内容的Spring集成HTTP出站网关重试

Spring integration 基于回复内容的Spring集成HTTP出站网关重试,spring-integration,spring-integration-dsl,spring-integration-http,Spring Integration,Spring Integration Dsl,Spring Integration Http,我使用的API分为两个步骤: 它以异步方式开始处理文档,并向您提供用于步骤2的id 它提供了一个端点,您可以在该端点处获得结果,但只有在结果准备就绪时。所以基本上它会给你一个200的回复,包括一些细节,比如处理的状态 因此,问题是如何实现HTTP出站网关的自定义“成功”标准。我还想将它与我已经实现的RetryAdvice结合起来 我尝试了以下操作,但首先HandleMessageAdvice中提供的消息有效负载为空,其次不会触发重试: .handle(Http.outboundGateway(&

我使用的API分为两个步骤:

  • 它以异步方式开始处理文档,并向您提供用于步骤2的id
  • 它提供了一个端点,您可以在该端点处获得结果,但只有在结果准备就绪时。所以基本上它会给你一个200的回复,包括一些细节,比如处理的状态
  • 因此,问题是如何实现HTTP出站网关的自定义“成功”标准。我还想将它与我已经实现的RetryAdvice结合起来

    我尝试了以下操作,但首先HandleMessageAdvice中提供的消息有效负载为空,其次不会触发重试:

    .handle(Http.outboundGateway("https://northeurope.api.cognitive.microsoft.com/vision/v3" +
            ".0/read/analyzeResults/abc")
            .mappedRequestHeaders("Ocp-Apim-Subscription-Key")
            .httpMethod(HttpMethod.GET), c -> c.advice(this.advices.retryAdvice())
                  .handleMessageAdvice(new AbstractHandleMessageAdvice() {
        @Override
        protected Object doInvoke(MethodInvocation invocation, Message<?> message) throws Throwable {
            String body = (String) message.getPayload();
            if (StringUtils.isEmpty(body))
                throw new RuntimeException("Still analyzing");
            JSONObject document = new JSONObject(body);
            if (document.has("analyzeResult"))
                return message;
            else
                throw new RuntimeException("Still analyzing");
        }
    }))
    
    建议如下:

    @Bean
    public Advice verifyReplySuccess() {
        return new AbstractRequestHandlerAdvice() {
            @Override
            protected Object doInvoke(ExecutionCallback callback, Object target, Message<?> message) {
                try {
                    Object payload = ((MessageBuilder) callback.execute()).build().getPayload();
                    String body = (String) ((ResponseEntity) payload).getBody();
                    JSONObject document = new JSONObject(body);
                    if (document.has("analyzeResult"))
                        return message;
                } catch (JSONException e) {
                    throw new RuntimeException(e);
                }
                throw new RuntimeException("Still analyzing");
            }
        };
    }
    
    @Bean
    public Advice verifyReplySuccess() {
        return new AbstractRequestHandlerAdvice() {
            @Override
            protected Object doInvoke(ExecutionCallback callback, Object target, Message<?> message) {
                Object payload = ((MessageBuilder) callback.execute()).build().getPayload();
                if (((String) payload).contains("analyzeResult"))
                    return payload;
                else
                    throw new RuntimeException("Still analyzing");
            }
        };
    }
    
    以下是我使用回调从出站网关获得的有效负载:


    在Java DSL中确实没有
    请求
    回复
    通道选项,因为您只需将
    句柄()
    包装到
    通道()
    配置中,或者只是以流自然的方式链接端点,它们之间将使用隐式直接通道交换消息。您可以在XML配置中将Java DSL
    IntegrationFlow
    作为
    进行查看

    您的建议配置有点错误:您需要将自定义建议声明为链中的第一个,所以当从该链引发异常时,将由重试一次来处理它

    您还应考虑实现<代码> ActudiTrasththand Lead建议以将其与<代码> RequestHandlerRetryAdvice < /Cord>逻辑>


    您在那里实现了一个
    doInvoke()
    ,调用
    ExecutionCallback.execute()
    ,并分析结果以按原样返回或抛出所需的异常。调用
    HttpRequestExecutingMessageHandler
    的结果将是一个
    AbstractIntegrationMessageBuilder
    ,可能是一个
    ResponseEntity
    ,作为一个
    payload
    来检查进一步的逻辑(另外一个技巧是将expectedResponseType设置为String,否则使用ResponseEntity时,正文为空):

    建议如下:

    @Bean
    public Advice verifyReplySuccess() {
        return new AbstractRequestHandlerAdvice() {
            @Override
            protected Object doInvoke(ExecutionCallback callback, Object target, Message<?> message) {
                try {
                    Object payload = ((MessageBuilder) callback.execute()).build().getPayload();
                    String body = (String) ((ResponseEntity) payload).getBody();
                    JSONObject document = new JSONObject(body);
                    if (document.has("analyzeResult"))
                        return message;
                } catch (JSONException e) {
                    throw new RuntimeException(e);
                }
                throw new RuntimeException("Still analyzing");
            }
        };
    }
    
    @Bean
    public Advice verifyReplySuccess() {
        return new AbstractRequestHandlerAdvice() {
            @Override
            protected Object doInvoke(ExecutionCallback callback, Object target, Message<?> message) {
                Object payload = ((MessageBuilder) callback.execute()).build().getPayload();
                if (((String) payload).contains("analyzeResult"))
                    return payload;
                else
                    throw new RuntimeException("Still analyzing");
            }
        };
    }
    
    @Bean
    公共意见验证回复成功(){
    返回新的AbstractRequestHandlerAdvice(){
    @凌驾
    受保护对象doInvoke(ExecutionCallback回调、对象目标、消息){
    对象负载=((MessageBuilder)callback.execute()).build().getPayload();
    if(((字符串)有效负载).contains(“AnalyzerResult”))
    返回有效载荷;
    其他的
    抛出新的RuntimeException(“仍在分析”);
    }
    };
    }
    
    谢谢Artem。请看一下我的更新。您显示的不是
    响应的“主体”
    。所有这些都只是HTTP头和状态
    200 OK
    。据我所知,HTTP响应中没有主体。这是IntelliJ调试器的整个有效负载的副本。它不会显示主体,因为它是空的。我可以如果需要的话,请输入图像…那么body必须是什么?我认为null表示您仍然需要重试…我猜您谈论的是您的答案。问题是,这些建议相互包装成一个链。因此,下一个建议与上一个建议一起调用。因此,要使您的重试建议在另一个建议出现异常后工作,请ode>advices.retryuntilRequestCompletedAdvice()绝对应该是链中的第一位。
    .handle(Http.outboundGateway("https://northeurope.api.cognitive.microsoft.com/vision/v3" +
            ".0/read/analyzeResults/abc")
            .mappedRequestHeaders("Ocp-Apim-Subscription-Key")
            .httpMethod(HttpMethod.GET).expectedResponseType(String.class),
            c -> c.advice(advices.retryUntilRequestCompleteAdvice())
                  .advice(advices.verifyReplySuccess()))
    
    @Bean
    public Advice verifyReplySuccess() {
        return new AbstractRequestHandlerAdvice() {
            @Override
            protected Object doInvoke(ExecutionCallback callback, Object target, Message<?> message) {
                Object payload = ((MessageBuilder) callback.execute()).build().getPayload();
                if (((String) payload).contains("analyzeResult"))
                    return payload;
                else
                    throw new RuntimeException("Still analyzing");
            }
        };
    }