私は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つの質問があり、
より良い方法はありますか?
そうでない場合、私は何かが足りないのですか?なぜ私は私のテストで例外を処理できないのですか?
ありがとう!
更新(06-06-2019)
おかげで、あなたが正しいですVGR。これは、コードの作業です:
try {
eventuallyMayBeThing.get();
} catch (ExecutionException ce) {
assertThat(ce.getCause(), instanceOf(ThingAlreadyExists.class));
}
この方法は、get()
から継承されたインタフェースとで例外をラップします。Future
ExecutionException
この方法は、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のバージョンに簡単に移行することができます。