2017-05-29 86 views
1

我有一個應用程序指定一個簡單的流,其中需要按特定順序調用一系列服務來執行某些功能。 Spring集成和它的DSL似乎適用於這種情況。爲鏈中的每個處理程序分配不同的錯誤處理程序

這些個別服務中的任何一個都可能失敗(這些服務是對外部應用程序的調用),此時鏈應該停止。不僅如此,控制流也需要重定向到其他地方,具體取決於失敗的服務。換句話說,我需要爲每個服務提供不同的錯誤處理程序。

問題是我很難找到如何做到這一點,如果有人能指出我正確的方向,我將非常感激。這就是我一直到目前爲止,標本兼治:

@Configuration 
@EnableAutoConfiguration 
@IntegrationComponentScan 
public class Application { 

public static void main(String[] args) throws InterruptedException { 
    ConfigurableApplicationContext ctx = 
      SpringApplication.run(Application.class, args); 

    System.out.println(ctx.getBean(MySource.class).send("foo")); 

    ctx.close(); 
} 

@MessagingGateway 
public interface MySource { 

    @Gateway(requestChannel = "flow.input") 
    String send(String string); 

} 

@Bean 
public IntegrationFlow flow() { 
    return f -> f 
      .handle(String.class, (i, map) -> { 
//    if (true){ 
//     throw new RuntimeException(); 
//    } 
       System.out.println(i); 
       return i + "a"; 
      }) 
      .handle(String.class, (i, map) -> { 
       System.out.println(i); 
       return i + "b"; 
      }) 
      .handle(String.class, (i, map) -> { 
       System.out.println(i); 
       return i + "c"; 
      }); 
    } 
} 

我一直在尋找如何設置爲每個處理程序的錯誤處理程序/信道,但我沒有發現任何有用的東西。

我幾乎在我的搜索放棄了,開始寫我自己的代碼(嘆息),它看起來是這樣的:

public class FlowHarness { 

    public static void main(String[] args) { 
     Flow flow = FlowBuilder.flow() 
      .nextStep(i -> ((Integer)i) + 1, e -> System.out.println("failed at step 1")) 
      .nextStep(i -> ((Integer)i) + 1, e -> System.out.println("failed at step 2")) 
      .nextStep(i -> ((Integer)i) + 1, e -> System.out.println("failed at step 3")) 
      .build(); 

     flow.execute(new Integer(1)); 
    } 
} 

.nextStep()的左手邊參數是處理程序而右側的參數是錯誤處理程序。這很簡單,但我希望它能說明這一點。

儘管現實生活中的所有流程都可以寫成一個大類,但我認爲將每個子流分解爲單獨的私有方法/類會更加方便。非常感謝。

回答

2

.handle()(以及任何其他消費終端)可以與ExpressionEvaluatingRequestHandlerAdvice提供:http://docs.spring.io/spring-integration/docs/4.3.9.RELEASE/reference/html/messaging-endpoints-chapter.html#expression-advice

@Bean 
public IntegrationFlow advised() { 
    return f -> f.handle((GenericHandler<String>) (payload, headers) -> { 
     if (payload.equals("good")) { 
      return null; 
     } 
     else { 
      throw new RuntimeException("some failure"); 
     } 
    }, c -> c.advice(expressionAdvice())); 
} 

@Bean 
public Advice expressionAdvice() { 
    ExpressionEvaluatingRequestHandlerAdvice advice = new ExpressionEvaluatingRequestHandlerAdvice(); 
    advice.setSuccessChannelName("success.input"); 
    advice.setOnSuccessExpressionString("payload + ' was successful'"); 
    advice.setFailureChannelName("failure.input"); 
    advice.setOnFailureExpressionString(
      "payload + ' was bad, with reason: ' + #exception.cause.message"); 
    advice.setTrapException(true); 
    return advice; 
} 

@Bean 
public IntegrationFlow success() { 
    return f -> f.handle(System.out::println); 
} 

@Bean 
public IntegrationFlow failure() { 
    return f -> f.handle(System.out::println); 
} 
+0

就是我想要的,謝謝 – edu

0

既然你想鏈上停止failure.I執行會建議你可以使用自定義異常,並適當處理

+0

問題是關於如何做到這一點...感謝無論如何:) Artem能夠提供一個例子 – edu