Completable先物。ビジネス「例外」を処理するための最良の方法は何ですか?

Yuliban:

私はJavaからCompletableFutureツールに慣れるために始めています。私は、ほぼすべてのDEVが直面するいくつかの再発のユースケースをモデル化するために小さなおもちゃのアプリケーションを作成しました。

この例では、私は単純にDBにものを保存したいのですが、その前に、私は事が既に保存されたかどうかを確認します。

事はDBにすでにある場合は、フロー(completable先物の連鎖)が停止していないものを保存する必要があります。私がやっていることはので、結局、私はそれを処理し、彼は何が起こったかを知ることができるようにサービスのクライアントに良いメッセージを与えることができる例外をスローです。

これは私がこれまで試したものです:

まず最初に保存したり、ものがテーブルにすでにある場合はエラーをスローするようにしようとコードは:

repository
        .query(thing.getId())
        .thenCompose(
            mayBeThing -> {
              if (mayBeThing.isDefined()) throw new CompletionException(new ThingAlreadyExists());
              else return repository.insert(new ThingDTO(thing.getId(), thing.getName()));

そして、これは私が実行しようとしているテストです。

    CompletableFuture<Integer> eventuallyMayBeThing =
        service.save(thing).thenCompose(i -> service.save(thing));
    try {
      eventuallyMayBeThing.get();
    } catch (CompletionException ce) {
      System.out.println("Completion exception " + ce.getMessage());
      try {
        throw ce.getCause();
      } catch (ThingAlreadyExist tae) {
        assert (true);
      } catch (Throwable t) {
        throw new AssertionError(t);
      }
    }

それを行うためのこの方法は、私は、この応答からそれを取った:CompletableFutureから例外を投げる(最も投票の答えの最初の部分)。

しかし、これは動作しません。ThingAlreadyExist確かにスローされますが、私のtry catchブロックによって処理されているありませんです。私は、この意味します:

catch (CompletionException ce) {
      System.out.println("Completion exception " + ce.getMessage());
      try {
        throw ce.getCause();
      } catch (ThingAlreadyExist tae) {
        assert (true);
      } catch (Throwable t) {
        throw new AssertionError(t);
      }

実行されることはありません。

私は2つの質問があり、

  1. より良い方法はありますか?

  2. そうでない場合、私は何かが足りないのですか?なぜ私は私のテストで例外を処理できないのですか?

ありがとう!

更新(06-06-2019)

おかげで、あなたが正しいですVGR。これは、コードの作業です:

try {
      eventuallyMayBeThing.get();
    } catch (ExecutionException ce) {
      assertThat(ce.getCause(), instanceOf(ThingAlreadyExists.class));
    }
ホルガー:

あなたは間の違いを意識する必要がget()join()

この方法は、get()から継承されたインタフェースとで例外をラップしますFutureExecutionException

この方法は、join()固有であるCompletableFutureとで例外をラップするCompletionExceptionチェック例外を宣言していない機能インタフェースのためのそれをより適切にするチェックされない例外であり、これは、。

ことでは、言っリンク解答アドレスが機能をご使用の場合は、関係のに対し、いずれかを実行値を返すか、チェックされない例外をスローしなければならない場合に使用compose関数は新しいを返します、CompletionStageこれは、のような代替ソリューションを可能に

.thenCompose(mayBeThing -> mayBeThing.isDefined()?
    CompletableFuture.failedFuture​(new ThingAlreadyExists()):
    repository.insert(new ThingDTO(thing.getId(), thing.getName())))

CompletableFuture.failedFuture Javaの9で追加されたあなたはまだJavaの8のサポートが必要な場合は、あなたのコードベースに追加します

public static <T> CompletableFuture<T> failedFuture(Throwable t) {
    final CompletableFuture<T> cf = new CompletableFuture<>();
    cf.completeExceptionally(t);
    return cf;
}

これは将来的に新しいJavaのバージョンに簡単に移行することができます。

おすすめ

転載: http://43.154.161.224:23101/article/api/json?id=201901&siteId=1