2012-12-03 30 views
4

前言:我是相當新的駱駝,並在行動中消化駱駝儘可能地後,我就適應一個項目,我在。在這個項目中,我們有一些相當複雜的錯誤處理,並且我們要確保我們可以在我們將代碼進行駝峯化時進行復制。駱駝重試控制與多個異常

在我們的項目中(大多數情況下)有一組我們想要重試的異常和一組我們沒有的 - 但更具體地說,有一組我們想要比其他人更重試(不是所有可恢復的錯誤可以被視爲相同)。在這種情況下,我試圖定義一個onException塊來更改重新傳送策略。然而,似乎交易所保持計數(Exchange.REDELIVERY_COUNTER),並且這個數量是不依賴於它拋出異常。有沒有辦法讓這個計數特定於特定的例外?

例如 - 我有兩個例外FooExceptionBarException。在我的路線(或者真的在整個上下文中),我要重新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,似乎這種工作方式是,交易所將有5 REDELIVERY_COUNTER,當我復位政策只嘗試了兩次,它(邏輯)的結論是,路線不應該重試,並拋出異常退了出去。然而,在我的應用BarExceptions應該重試兩次,不管有多少FooExceptions拋出。同樣,如果它交替拋出Foo和Bar異常,我希望它只增加給定異常的計數器。

駱駝在行動的最後一步促進使用retryWhile - 這是抓住我正在尋找的那種控制的唯一方法嗎?我是否需要創建一個有狀態的bean,以瞭解每個異常的計數?還是我忽略了簡單的事情?我想確保在我接近這個重構時,我不會在醜陋的道路上開始我們。

使用駱駝2.10.1

回答

1

我檢查與下面的測試你的情況:

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批准:傳遞嘗試被BarException耗盡後,即使我們只有4 FooExceptions和1 BarException。

不幸的是,我現在不能完全回答你的問題,但我正在深入研究它,如果有新的東西,我會更新我的unswer。如果您使用薩滿的測試用例

0

嘗試更換您定義例外的順序,例如:

<onException> 
     <exception>my.exception.BarException</exception> 
     <redeliveryPolicy maximumRedeliveries="2" redeliveryDelay="5000" 
</onException> 

<onException> 
    <exception>my.exception.FooException</exception> 
    <redeliveryPolicy maximumRedeliveries="10" redeliveryDelay="2000" 
</onException> 
+0

,重新排序似乎並沒有改變輸出。當我有機會時,我會試着在Spring配置中進行測試。 – RitterGT