'Firebase ApiFuture to CompletableFuture in a reactive stack

I am using the Firebase Admin Java SDK in a server side Spring WebFlux environment. The Firebase SDK provides two methods for each operation. A synchronous ".doOperation()" method which returns a result and a ".doOperationAsync()" method which returns an instance of ApiFuture.

The Javadoc for ApiFuture can be found here.

ApiFuture extends from java.util.concurrent.Future, which is no longer supported by Mono.fromFuture().

Is there a way to convert Googles ApiFuture into a Mono?



Solution 1:[1]

It's possible to convert ApiFuture to CompletableFuture, which can be used with Mono.fromFuture:

internal class ApiCompletableFuture<V>(
    private val future: ApiFuture<V>,
    executor: Executor = directExecutor(),
) : CompletableFuture<V>(), ApiFutureCallback<V> {
    init {
        ApiFutures.addCallback(future, this, executor)
    }

    override fun cancel(mayInterruptIfRunning: Boolean): Boolean {
        future.cancel(mayInterruptIfRunning)
        return super.cancel(mayInterruptIfRunning)
    }

    override fun onSuccess(result: V) {
        complete(result)
    }

    override fun onFailure(t: Throwable) {
        completeExceptionally(t)
    }
}

Solution 2:[2]

Some utility methods for you

    public static <T> CompletableFuture<T> toCompletableFuture(ApiFuture<T> apiFuture) {
        final CompletableFuture<T> cf = new CompletableFuture<>();
        ApiFutures.addCallback(apiFuture,
                new ApiFutureCallback<T>() {
                    @Override
                    public void onFailure(Throwable t) {
                        cf.completeExceptionally(t);
                    }

                    @Override
                    public void onSuccess(T result) {
                        cf.complete(result);
                    }
                },
                MoreExecutors.directExecutor());
        return cf;
    }

    public static <T> Mono<T> toMono(ApiFuture<T> apiFuture) {
        return Mono.create(sink -> ApiFutures.addCallback(apiFuture,
                new ApiFutureCallback<T>() {
                    @Override
                    public void onFailure(Throwable t) {
                        sink.error(t);
                    }

                    @Override
                    public void onSuccess(T result) {
                        sink.success(result);
                    }
                },
                MoreExecutors.directExecutor()));
    }

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Ruslan
Solution 2 sli