2017-10-31 9 views
0

Java CompletableFutures을 사용하여 일련의 비동기 작업을 함께 연결했습니다. 코드는 다음과 같이 보입니다 :Java를`CompletablyFuture.exceptionally` 사용하여 선택적으로 예외를 계속합니다.

CompletableFuture<Result> doTasks(final TaskId id) { 
    return firstTask.workAsync(id) 
      .thenComposeAsync(__ -> secondTask.workAsync(id)) 
      .thenComposeAsync(__ -> thirdTask.workAsync(id)) 
      .thenApplyAsync(__ -> fourthTask.workAsync(id)); 
} 

그러나, firstTask.workAsync이 작품은 이미이 상황에서 OK 인 완료되었음을 나타내는 예외를 throw를, 그래서 그냥 무시하고 체인을 계속하고 싶습니다.

물론 예외를 처리 할 수있는 별도의 함수에서 해당 비트를 래핑 할 수 있지만 CompletableFuture 체인에서 직접 처리하고 다른 모든 예외를 throw하는 방법이 있습니까?

한 동료가 CompletableFuture.exceptionally을 사용하도록 제안했지만 온라인에서 볼 수있는 모든 예제는 완전히 쓸모가없고 단지 null을 반환합니다. 이는 체인을 죽이는 것처럼 보입니다. 이 경우 어떻게 사용합니까?

답변

0

CompletableFuture.exceptionallyCompletableFuture에서 예외가 발생할 때 계속 사용할 수 있습니다. 간단히 말해 예외 유형을 확인해야하며 계속 예외를 적용하려는 경우 새 CompletableFuture을 반환 할 수 있습니다.이 결과는 체인에서 사용되지 않으므로 비어있을 수 있습니다.

이 경우
CompletableFuture<Result> doTasks(final TaskId id) { 
    return firstTask.workAsync(id) 
      .exceptionally(t -> { 
       // Will continue down the chain if matches 
       if (t instanceof TotallyOkException) { 
        return null; 
       } 

       // This will throw an ExecutionException. I convert it to a RuntimeException here 
       // because I don't want to add throws statements up the chain. 
       throw new RuntimeException(t); 
      }) 
      .thenComposeAsync(__ -> secondTask.workAsync(id)) 
      .thenComposeAsync(__ -> thirdTask.workAsync(id)) 
      .thenApplyAsync(__ -> fourthTask.workAsync(id)); 
} 

, 모든 비 TotallyOkException 예외를 throw합니다.

+1

'return CompletableFuture.completedFuture (null)'보다는 'return null'을 사용한다고 생각하십니까? –

+0

@JoeC 체인을 죽이면 null이 반환되지 않습니까? 그것은 예상대로 작동하지만 2 ~ 4 작업을 계속 실행하려면 CompletableFuture를 반환 할 필요가 없습니까? – EmptyArsenal

+1

이것은 서명입니다 : 예외적으로 (Function fn). 이렇게하면'CompletableFuture >'이있는 경우에만 작동합니다. 'null'을 반환하면 체인을 중지해야하는 이유가 없습니다. –

0

함수에서 null을 반환해도 체인 자체가 종료되지 않습니다. 체인을 죽일 수있는 유일한 방법은 다운 스트림 함수에서 null 처리가 없어서 NullPointerException이 발생하는 것입니다.

exceptionally 함수는 일부 예외 유형을 처리하기 위해 설정할 수 있으며 다른 유형은 처리 할 수 ​​없습니다. 예를 들어

return firstTask.workAsync(id) 
     .thenComposeAsync(firstResult -> secondTask.workAsync(id)) 
     .exceptionally(t -> { 
          if (t instanceof TransientException) { 
           return getUsingBackupMethod(id); 
          } 
          throw new RuntimeException(t); 
         }); 

exceptionally이 함수는 (유효) 제 두 가지 작업 중 하나에서 발생 예외를 캐치한다.