Spring集成中的重试和建议

时间:2015-03-19 23:33:20

标签: spring-integration

我已经创建了一个简单的例子来了解重试和建议。以下是示例配置:

@Configuration
@EnableIntegration
@IntegrationComponentScan
@ComponentScan
public class SimpleConfiguration2 {
  @Bean
  public DirectChannel requestChannel() {
   return new DirectChannel();
  }

  @Bean
  public DirectChannel aChannel() {
   return new DirectChannel();
  }

  @Bean
  public DirectChannel retryLaterChannel() {
   return new DirectChannel();
  }

  @Bean
  public DirectChannel tapChannel() {
   return new DirectChannel();
  }

  @Bean
  public DirectChannel endChannel() {
   return new DirectChannel();
  }

  @Bean
  public ExceptionThrowingTransformer exceptionThrowingTransformer() {
    return new ExceptionThrowingTransformer();
  }

  @Bean
  public IntegrationFlow initFlow() {
    return IntegrationFlows.from(requestChannel())
                           .gateway(aChannel(), e -> e.advice(retryAdvice())
                                                      .errorChannel(retryLaterChannel()))
                           .get();
  }

  @Bean
  public Advice retryAdvice() {
    final RequestHandlerRetryAdvice advice = new RequestHandlerRetryAdvice();
    advice.setRetryTemplate(retryTemplate());
    return advice;
  }

  @Bean
  public RetryTemplate retryTemplate() {
    final RetryTemplate ret = new RetryTemplate();
    ret.setRetryPolicy(retryPolicy());
    ret.setThrowLastExceptionOnExhausted(false);
    return ret;
  }

  @Bean
  public RetryPolicy retryPolicy() {
    final Map<Class<? extends Throwable>, Boolean> map = new HashMap<Class<? extends Throwable>, Boolean>() {{
        put(RuntimeException.class, true);
      }
      private static final long serialVersionUID = -1L;
    };
    final RetryPolicy ret = new SimpleRetryPolicy(3, map, true);
    return ret;
  }

  @Bean
  public IntegrationFlow aChannelFlow() {
    return IntegrationFlows.from(aChannel())
                           .transform("C: "::concat)
                           .transform(exceptionThrowingTransformer())
                           .channel(endChannel())
                           .get();
  }

  @Bean
  public IntegrationFlow endFlow() {
    return IntegrationFlows.from(endChannel())
                           .handle(String.class, (p, h) -> p)
                           .get();
  }

  @Bean
  public IntegrationFlow retryLaterFlow() {
    return IntegrationFlows.from(retryLaterChannel())
                           .wireTap(tapChannel())
//                           .bridge(null)
//                           .handle(String.class, (p, h) -> p)
                           .get();
  }

  @Bean
  public IntegrationFlow tapFlow() {
    return IntegrationFlows.from(tapChannel())
                           .handle(m -> System.err.println("tap [" + Thread.currentThread().getName() + "] " + m.getPayload() ))
                           .get();
  }
}

这里是ExceptionThrowingTransformer:

public class ExceptionThrowingTransformer implements GenericTransformer<String, String> {
  @Override
  public String transform(final String source) {
    printAndThrow();
    return Thread.currentThread().getName() + " " + source;
  }

  private void printAndThrow() {
    if(numFail > 0) {
      numFail--;
      final String msg = numFail > 0 ? " will fail " + numFail + " more times"
                                     : "last failure";
      System.out.println(Thread.currentThread().getName() + " ExceptionThrowingTransformer " + msg);
      throw new RuntimeException();
    }
  }
  private static int numFail = 2;
}

以下是单元测试:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = SimpleConfiguration2.class)
public class DependenciesApplicationTests {
  @Test
  public void t1() {
    System.out.println(gw.echo("MSG1"));
  }

  @Autowired
  private EchoGateway gw;
}

和echo网关:

@MessagingGateway(defaultReplyTimeout=600)
public interface EchoGateway {
  @Gateway(requestChannel = "requestChannel")
  String echo(String message);
}

问题1: 如果我按原样运行代码,输入&#34; MSG1&#34;放在requestChannel上,我得到以下输出:

main ExceptionThrowingTransformer will fail 1 more times
tap [main] org.springframework.integration.transformer.MessageTransformationException: ; nested exception is org.springframework.messaging.MessageHandlingException: ; nested exception is java.lang.RuntimeException
main ExceptionThrowingTransformer last failure
tap [main] org.springframework.integration.transformer.MessageTransformationException: ; nested exception is org.springframework.messaging.MessageHandlingException: ; nested exception is java.lang.RuntimeException
main C: MSG1

虽然我希望看到类似的东西:

main ExceptionThrowingTransformer will fail 1 more times
main ExceptionThrowingTransformer last failure
main C: MSG1

重试发生,但原始异常仍然传播到initFlow网关中指定的errorChannel。有没有办法防止这种情况?

问题2: 当numFail更改为3时,除问题1中的输出外,还会向调用者返回异常:

org.springframework.messaging.MessagingException: failure occurred in error-handling flow; nested exception is org.springframework.messaging.MessageDeliveryException: Dispatcher has no subscribers for channel 'application:-1.retryLaterChannel'.; nested exception is org.springframework.integration.MessageDispatchingException: Dispatcher has no subscribers

如果仅取消注释retryLaterFlow中的第一个注释,则将exceptionThrowingTransformer抛出的异常返回给调用者。 为什么这样,假设retryTemplate有setThrowLastExceptionOnExhausted(false)?

问题3: 如果仅取消注释retryLaterFlow中的第二个注释,则输出如下所示:

main ExceptionThrowingTransformer  will fail 2 more times
tap [main] org.springframework.integration.transformer.MessageTransformationException: ; nested exception is org.springframework.messaging.MessageHandlingException: ; nested exception is java.lang.RuntimeException
org.springframework.integration.transformer.MessageTransformationException: ; nested exception is org.springframework.messaging.MessageHandlingException: ; nested exception is java.lang.RuntimeException

为什么重试没有生效? (对问题1的回答也可以回答这个问题)

1 个答案:

答案 0 :(得分:0)

你有两个网关(初始和中间流),你建议中流网关,以便它按预期工作。

您应该建议变压器获得您期望的结果。