Camel:将异常翻译成另一个类

时间:2016-08-31 14:45:46

标签: apache-camel

在Camel中,如果在我的路由中抛出任何异常,我想将其转换为域异常并将其传递给mock:errors端点进行测试。但我似乎无法做到。

    errorHandler(deadLetterChannel("mock:errors").maximumRedeliveries(0));

    // even tried this alternative while debugging the processor below
    // to be sure it is not rethrown
      onException(Exception.class).process((Exchange e) -> {
          System.out.println(e.getException()); // breakpoint here
      });

    from("direct:createRequest")
            .onException(Exception.class)
                .handled(true)
                .process(toInvalidRequestException)
            .end()
            .unmarshal().json(Jackson, Request.class)
            .bean(validateRequest);

-------------

private static Processor toInvalidRequestException = exchange -> {
    Exception e = exchange.getProperty(Exchange.EXCEPTION_CAUGHT, Exception.class);
    throw new InvalidRequestException(format("Barcode request is not valid or has wrong format: %s",
            getRootCauseMessage(e)), e);
};

在上面的路由中,任何异常(例如验证异常或Jackson的解析异常)都可以在某个时刻抛出。我使用onException子句拦截它,并希望将其转换为带有消息详细信息的InvalidRequestException。这有效,但后来我想断言在我的测试中使用mock:errors端点实际抛出了这个异常。但是,该端点始终为空,因为异常不会从转换处理器传播。

我尝试了与handled(true)continued(true)的组合,但我似乎无法弄明白。

1 个答案:

答案 0 :(得分:0)

错误处理程序定义默认行为;每个错误处理程序都会有一个异常策略定义列表(通过onException DSL创建),它将首先尝试匹配。仅当未找到匹配项时,才会应用errorHandler的默认值。此外,由于您从onException管道中抛出异常,因此您基本上无法完成整个错误处理流程。

比包装和重新抛出异常更好的选择是在路由构建器中使用全局onException,将异常转换为适当类型的消息,然后执行基于消息类型/内容而不是异常类型的错误处理。

例如,这是我在当前项目中使用的有用错误消息的示例:

public class DeadLetterChannelMessage {
  private String timestamp = Times.nowInUtc().toString();
  private String exchangeId;
  private String originalMessageBody;
  private Map<String, Object> headers;
  private String fromRouteId;
  private String errorMessage;
  private String stackTrace;

  @RequiredByThirdPartyFramework("jackson")
  private DeadLetterChannelMessage() {
  }

  @SuppressWarnings("ThrowableResultOfMethodCallIgnored")
  public DeadLetterChannelMessage(Exchange e) {
    exchangeId = e.getExchangeId();
    originalMessageBody = e.getIn().getBody(String.class);
    headers = Collections.unmodifiableMap(e.getIn().getHeaders());
    fromRouteId = e.getFromRouteId();

    Optional.ofNullable(e.getProperty(Exchange.EXCEPTION_CAUGHT, Exception.class)).ifPresent(throwable -> {
      errorMessage = throwable.getMessage();
      stackTrace = ExceptionUtils.getStackTrace(throwable);
    });
  }

  // getters
}

至于为什么exchange.getException()为空 - 如果您将异常标记为已处理,则应该使用Exchange.EXCEPTION_CAUGHT属性来获取抛出的异常:

private static Processor toInvalidRequestException = exchange -> {
    Exception e = exchange.getProperty(Exchange.EXCEPTION_CAUGHT, Exception.class);
    throw new InvalidRequestException(
            format("Barcode request is not valid or has wrong format: %s",
                    getRootCauseMessage(e)), e);
};