前言:我对Camel还很陌生,在尽可能好地消化了Camel之后,我正在调整它以适应我正在进行的一个项目。在这个项目中,我们有一些相当复杂的错误处理,我想确保我可以在驼峰化我们的代码时复制它。
在我们的项目中(就像大多数),有一组我们想重试的异常,还有一组我们不想重试的--但更具体地说,有一组我们比其他的更想重试(并不是所有可恢复的错误都可以被同等对待)。在本例中,我试图定义一个onException
块来更改重新传递策略。但是,Exchange似乎维护计数(Exchange.REDELIVERY_COUNTER
),并且此计数不依赖于引发哪个异常。有没有一种方法可以使这个计数对于给定的异常是特定的?
例如,我有两个例外:FooException
和BarException
。在我的路径中(或者实际上在整个上下文中),我想重试FooExceptions 10次,但BarException
s应该只重试2次。因此,上下文将包含:
<onException>
<exception>my.exception.FooException</exception>
<redeliveryPolicy maximumRedeliveries="10" redeliveryDelay="2000"
</onException>
<onException>
<exception>my.exception.BarException</exception>
<redeliveryPolicy maximumRedeliveries="2" redeliveryDelay="5000"
</onException>
现在,问题是-如果我的应用程序抛出一个FooException
并重试4次(每次都抛出FooException
),然后在第5次尝试时抛出一个BarException
,其工作方式似乎是交换的REDELIVERY_COUNTER
将为5,当我将策略重置为仅尝试两次时,它(逻辑上)得出不应该重试路由的结论,并抛出异常。但是,在我的应用程序中,无论抛出多少个FooExceptions
,BarExceptions
都应该重试两次。同样,如果它交替抛出Foo和Bar异常,我希望它只递增给定异常的计数器。
Camel in Action的末尾提倡使用retryWhile
--这是获得我想要的控制的唯一方法吗?我是否需要创建一个知道每个异常的计数的有状态bean?或者我忽略了一些简单的东西?我想确保当我接近这个重构时,我不会让我们走上一条丑陋的道路。
使用Camel 2.10.1
发布于 2012-12-07 23:49:10
我用下面的测试检查了你的案例:
import org.apache.camel.EndpointInject;
import org.apache.camel.Exchange;
import org.apache.camel.Produce;
import org.apache.camel.ProducerTemplate;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.component.mock.MockEndpoint;
import org.apache.camel.test.junit4.CamelTestSupport;
import org.junit.Test;
import java.util.concurrent.atomic.AtomicLong;
/**
* @author Illarion Kovalchuk
* Date: 12/7/12
* Time: 2:58 PM
*/
public class Test extends CamelTestSupport
{
private static final String MIDDLE_QUEUE = "seda:middle";
@EndpointInject(uri = "mock:result")
protected MockEndpoint resultEndpoint;
@Produce(uri = "direct:start")
protected ProducerTemplate template;
private Processor processor = new Processor();
@Test
public void shouldRedeliverOnErrors() throws Exception
{
resultEndpoint.expectedBodiesReceived("Body");
template.sendBodyAndHeader(MIDDLE_QUEUE, "Body", "Header", "HV");
resultEndpoint.assertIsNotSatisfied();
}
@Override
protected RouteBuilder createRouteBuilder()
{
return new RouteBuilder()
{
@Override
public void configure() throws Exception
{
onException(FooException.class)
.redeliveryDelay(2000)
.maximumRedeliveries(10);
onException(BarException.class)
.redeliveryDelay(5000)
.maximumRedeliveries(2);
from(MIDDLE_QUEUE)
.bean(Processor.class, "process")
.to(resultEndpoint)
.end();
}
};
}
public static class Processor
{
private static AtomicLong retryState = new AtomicLong(0L);
public static void process(Exchange e) throws FooException, BarException
{
long rs = retryState.getAndAdd(1L);
if (rs < 4)
{
System.err.println("Foo Attempt "+ rs);
throw new FooException();
}
if (rs == 4)
{
System.err.println("Bar Attempt "+ rs);
throw new BarException();
}
System.err.println("Normal Attempt "+ rs);
}
}
public static class FooException extends Throwable
{
}
private static class BarException extends Throwable
{
}
}
结果,您的concirn被批准了:即使我们只有4个FooExceptions和1个BarException,在BarException之后,传递尝试也会耗尽。
不幸的是,我现在不能完全回答你的问题,但我正在深入研究,如果有新的东西,我会更新我的unswer。
发布于 2013-01-05 23:36:05
尝试替换定义异常的顺序,例如:
<onException>
<exception>my.exception.BarException</exception>
<redeliveryPolicy maximumRedeliveries="2" redeliveryDelay="5000"
</onException>
<onException>
<exception>my.exception.FooException</exception>
<redeliveryPolicy maximumRedeliveries="10" redeliveryDelay="2000"
</onException>
https://stackoverflow.com/questions/13684775
复制相似问题