如何处理Jackson与Camel REST DSL绑定的异常?

时间:2015-02-17 17:36:28

标签: java json rest jackson apache-camel

我正在使用Camel 2.14.1构建一些RESTful服务,这些服务使用Camel REST DSL的Jackson json绑定功能。这很有效,但我希望能够在绑定过程中出现问题时向客户端发送自定义响应。

例如,如果在将输入字符串值转换为整数时抛出NumberFormatException,则因为客户端错误地发送了不是数字的字符。此异常不是杰克逊特定的异常,因此我无法通过绑定失败消息来回复客户端,因为它可能是合法的内部错误。

同样,我想捕获在json到POJO的入站绑定期间抛出的任何其他异常,并以类似的方式处理它们,至少通知客户端它们的有效负载是无效的。

由于这一切都在我的代码“上方”处理,我无法看到如何轻松处理这些错误,因为它在我无法控制的库中处理。 我使用Camel的onException子句来处理我自己的异常,所以我知道这一点,只是不确定如何实现我需要的......

最糟糕的情况是,我想我可以将每个客户输入作为一个字符串并自己绑定,但这似乎相当于击败杰克逊。

TL; DR: Camel中是否有一个模式允许我使用REST DSL在POJO绑定失败时返回自定义响应?

修改 - 这里有一些伪代码来说明我正在尝试做什么:

class errorHandler {

  void handleException(Exchange exchange, @ExchangeException Exception exception) {

    if (myException.class.isAssignableFrom(exception.getClass())) {
      // Set exchange body and response code header
      // This works as expected, though could probably do this more nicely
    }

    else if (camelBindingOrJacksonBindingException) {
      // Some other custom handling like above, but specific for these exception types
    }

    else {
      // Generic catch all with generic error response body
      // This also works fine
    }
  }
}

目前我最终在最后的其他块中捕获绑定/ Jackson异常,这就是我想要避免的,因为对客户端来说知道他们的输入无效是更有用的。这似乎相当于下面isaac.hazan的答案。

这样做的问题是我无法找到Jackson绑定异常是否具有我可以捕获的父类,所有这些可能的异常的列表,或者告诉它来自绑定的方式。

第二个问题是当Camel期望来自类似NumberFormatException之类的方法的绑定注释中的int时,我无法判断camel绑定异常,例如@Header int number,是真的来自Camel,还是来自我的自己的代码。非常不愿意捕获任何旧的NumberFormatException,因为如果进一步的内部更改可能会引发这种情况,我最终会返回错误的响应。是否有某种方法可以找出异常的来源(是否在绑定时)?

2 个答案:

答案 0 :(得分:1)

我的一个应用程序中有类似的问题。我通过为每种类型的异常提供专用处理器来解决它。

例如,您可以拥有以下2个处理程序,一个作为特定异常,另一个作为任何其他异常:

    <onException id="handleAmazonServiceException">
        <exception>com.amazonaws.AmazonServiceException</exception>
        <handled><constant>true</constant></handled>
        <bean ref="errorHandlerProcessor" method="handleAmazonServiceException" />
        <setHeader headerName="CamelFileName">
            <simple>{{local.failed.records.dir}}/${header.S3Prefix}/${date:now:yyyy-MM-dd}/${header.failedRecordFileName}</simple>
        </setHeader>
        <to id="failedRecordsFile" uri="ref:s3FailedRecordsEndpoint" />
    </onException>

    <onException id="handleGeneralException">
        <exception>org.apache.camel.CamelExecutionException</exception>
        <exception>java.lang.Exception</exception>
        <handled><constant>true</constant></handled>
        <bean ref="errorHandlerProcessor" method="handleGeneralException" />
        <setHeader headerName="CamelFileName">
            <simple>{{local.failed.records.dir}}/${header.S3Prefix}/${date:now:yyyy-MM-dd}/${header.failedRecordFileName}</simple>
        </setHeader>
        <to id="failedRecordsFile" uri="ref:s3FailedRecordsEndpoint" />
    </onException>

上面的关键是&#34; errorHandlerProcessor&#34;负责处理任何异常的bean。这是一种从一个地方处理所有错误的简单方法。

看起来像这样:

@Service(value = "errorHandlerProcessor")
public class ErrorHandlerProcessor
{
// General handler
public void handleGeneralException(Exchange exchange)
{
    Throwable caused = exchange.getProperty(Exchange.EXCEPTION_CAUGHT, Throwable.class);
    logger.error("An unexpected error camel error occurred:" + caused.getMessage());
    logger.debug("Caught exception within the camel engine:", caused);
    ...
}

//AmazonClientException handler
public void handleAmazonClientException(Exchange exchange)
{
    AmazonClientException caused = exchange.getProperty(Exchange.EXCEPTION_CAUGHT, AmazonClientException.class);
    StringBuffer errorMessage = new StringBuffer();
    errorMessage.append("AmazonClientException,AWS communication problem, Error Message: " + caused.getMessage());
    ...
}
}

答案 1 :(得分:0)

最后,我最终使用了Camel onException条款,用于我在Jackson的javadoc中找到的任何内容。这些是JsonMappingExceptionJsonParseException(尽管你可以更进一步,然后选择其他子类)。

为了处理Camel绑定问题,我最终通过Camel Headers绑定了@Header属性作为字符串,并进行了我自己的输入验证,解析等。这让我抛出自己的自定义异常,因此在onException条款中处理它们。

不确定是否有更好的方法,很高兴知道是否有!