Robert O'Neal
Robert O'Neal

Reputation: 43

How do I optionally chain another independent CompletableFuture if the first condition doesn't pass?

I have a method like this:

private CompletionStage<Void> example(final Resource resource) {
    return firstMatcher.match(resource)
        .whenComplete((op, t) -> {
            if (t != null || !op.isPresent()) {
                LOGGER.debug("resource doesn't match");
            }
        })
        .thenAccept(optMatch -> optMatch.ifPresent(match -> {
            LOGGER.debug("resource matches");

            // DONE
        }));

    // OR ELSE (Not sure how to chain this piece)

    return secondMatcher.match(resource)
        .whenComplete((op, t) -> {
            if (t != null || !op.isPresent()) {
                LOGGER.debug("resource doesn't match");
            }
        })
        .thenAccept(optMatch -> optMatch.ifPresent(match -> {
            LOGGER.debug("resource matches");

            // DONE
        }));

I would like to return a method that first matches my resource with the firstMatcher. If a match is found, it ends there. But if a match is not found, then it relies on the secondMatcher. Is it possible to chain this into a single method?

Upvotes: 1

Views: 285

Answers (1)

Davide D&#39;Alto
Davide D&#39;Alto

Reputation: 8206

You need something like this:

private CompletionStage<Void> example(final Resource resource) {
        return firstMatcher
                .match( resource )
                .thenCompose( firstMatch -> {
                    if ( firstMatch.isPresent() ) {
                        LOGGER.debug( "resource matches first" );
                        return CompletableFuture.completedFuture( null );
                    }
                    LOGGER.debug("resource doesn't match first");
                    return secondMatcher
                            .match( resource )
                            .thenCompose( secondMatch -> {
                                if ( secondMatch.isPresent() ) {
                                    LOGGER.debug( "resource matches second" );
                                    return CompletableFuture.completedFuture( null );
                                }
                                LOGGER.debug("resource doesn't match second");                       
                                // I'm returning a failed CompletionStage
                                // but you can add a third matcher or return something else.
                                // It depends on your requirements
                                return CompletableFuture.failed(new MatchNotFoundException());
                            });
                } );
}

Note that I've removed the whenComplete because they make the example more verbose, but you can add them back if you need to.

Upvotes: 1

Related Questions