我正在使用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
,因为如果进一步的内部更改可能会引发这种情况,我最终会返回错误的响应。是否有某种方法可以找出异常的来源(是否在绑定时)?
答案 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中找到的任何内容。这些是JsonMappingException
和JsonParseException
(尽管你可以更进一步,然后选择其他子类)。
为了处理Camel绑定问题,我最终通过Camel Headers绑定了@Header
属性作为字符串,并进行了我自己的输入验证,解析等。这让我抛出自己的自定义异常,因此在onException
条款中处理它们。
不确定是否有更好的方法,很高兴知道是否有!