enricher子流中Http.outboundGateway异常暴露及404自定义处理问题
URL配置错误被吞问题排查与解决方案
问题描述
遇到URL配置错误引发的异常被吞问题,初始配置代码如下:
@Bean ExpressionEvaluatingRequestHandlerAdvice notFoundAdvice() { final ExpressionEvaluatingRequestHandlerAdvice advice = new ExpressionEvaluatingRequestHandlerAdvice(); advice.setOnFailureExpressionString( "#exception.getCause()" + " instanceof T(org.springframework.web.client.HttpClientErrorException.NotFound)" + " ? '{ \"value\": null }' : payload" ); advice.setReturnFailureExpressionResult(true); return advice; } @Bean public IntegrationFlow myIntegrationFlow(final RestTemplate restTemplate) { return f -> f .enrich( e -> e.requestSubFlow( sf -> sf .handle( Http.outboundGateway(misconfiguredUrl, restTemplate) .httpMethod(HttpMethod.GET) .uriVariable("productId", "headers.productId") .mappedResponseHeaders() .expectedResponseType(String.class), ec -> ec.advice(notFoundAdvice()) ) ) .propertyExpression("productData", "#jsonPath(payload, '$.value')") ) ); }
问题现象:当misconfiguredUrl未包含http://host前缀时,会触发URL格式错误,但运行时没有直接抛出该错误,反而出现#jsonPath(...)报错提示$[value]不存在。
排查过程
- 初步排查发现两个问题:
- 遗漏了处理合法404错误的端点配置
- 错误配置了
setReturnFailureExpressionResult参数,移除该配置后异常可以正常暴露
- 后续测试发现该方案不完善,虽然异常能暴露,但无法实现仅捕获404异常返回默认值、其他异常正常抛出的需求,需要调整实现思路
- 最终实现自定义处理类解决问题,代码如下:
public class CustomNotFoundAdvice extends AbstractRequestHandlerAdvice { private static final Logger log = LoggerFactory.getLogger(CustomNotFoundAdvice.class); final Object defaultReturn; public CustomNotFoundAdvice(final Object defaultReturn) { this.defaultReturn = defaultReturn; } @Override protected Object doInvoke(ExecutionCallback callback, Object target, Message<?> message) { Object result; try { result = callback.execute(); } catch(RuntimeException ex) { final Exception realException = unwrapExceptionIfNecessary(ex); if( realException instanceof MessageHandlingException && realException.getCause() instanceof HttpClientErrorException.NotFound) { log.warn("Unable to locate object "+target); result = defaultReturn; } else { throw ex; } } return result; } }
方案说明
最终实现的自定义Advice是最优解决方案,既满足了仅对404异常返回默认值的业务需求,又不会吞掉其他异常,所有非404异常都会正常向上抛出,默认会被日志框架捕获打印,无需额外配置。如果需要更精细化的日志记录,可在自定义类的else分支抛出异常前添加对应的日志打印逻辑即可。
内容的提问来源于stack exchange,提问作者Dave G
相关产品推荐
相关产品推荐

