> Markdown version of [Futures](https://vaadin.com/docs/next/building-apps/business-logic/background-jobs/interaction/futures). Section index: [llms.txt](https://vaadin.com/docs/next/building-apps/llms.txt)

# Returning Futures

When using a Flow user interface, you can use a standard Java `CompletableFuture` to report results and errors to it, and to cancel the job. For reporting progress, however, you still need to use a callback.

Compared to [callbacks](https://vaadin.com/docs/next/building-apps/business-logic/background-jobs/interaction/callbacks.md), this approach is easier to implement in the application layer, but more difficult to implement in the UI layer. You should only use it if you’ve previously used `CompletableFuture`, and you need other features that it offers, like chaining completion stages together.

## <a id="returning-a-result"></a>Returning a Result

As on the [Callbacks](https://vaadin.com/docs/next/building-apps/business-logic/background-jobs/interaction/callbacks.md) page, the examples on this page are methods of a protected application service. They run the job with an injected `TaskExecutor` instead of using the `@Async` annotation. See [User Triggered Jobs](https://vaadin.com/docs/next/building-apps/business-logic/background-jobs/triggers.md#user-triggered-jobs) for why.

`CompletableFuture` can run a job on the `TaskExecutor` through its `supplyAsync()` method. The following example shows a background job that completes with either a string or an exception. If the job throws an exception, the `CompletableFuture` completes exceptionally:

```java
@PreAuthorize("hasAuthority('permission:startjob')")
public CompletableFuture<String> startBackgroundJob() {
    return CompletableFuture.supplyAsync(this::doSomethingThatTakesALongTime,
        taskExecutor);
}
```

To update the user interface, you have to add special completion stages that execute after the `CompletableFuture` completes. For more information about how to add these, see the [Consuming Futures](https://vaadin.com/docs/next/building-apps/server-push/futures.md) documentation page.

## <a id="cancelling"></a>Cancelling

You can cancel a Java `Future` by calling its `cancel()` method. The method has a `boolean` parameter that indicates whether the thread should be interrupted or not. However, `CompletableFuture`, which implements `Future`, doesn’t use this parameter. It doesn’t therefore make a difference whether you pass `true` or `false`.

When you cancel a `CompletableFuture`, it completes with a `CompletionException` caused by a `CancellationException`. However, the job continues to run silently in the background until it’s finished. If you want to notify the job itself that it has been cancelled, and it should stop running at the next suitable moment, you’ll have to make some changes.

`CompletableFuture` has an `isCancelled()` method that you can use to query whether the job has been cancelled or not. However, the job can’t reach the future that `supplyAsync()` returns. Instead, you have to create the `CompletableFuture` yourself, execute the job with the `TaskExecutor`, and manage the state of the future. The principle is the same as when using callbacks or handles.

The earlier example would look like this when implemented using a `CompletableFuture`:

```java
@PreAuthorize("hasAuthority('permission:startjob')")
public CompletableFuture<String> startBackgroundJob() {
    var future = new CompletableFuture<String>();
    taskExecutor.execute(() -> {
        try {
            var step1Result = performStep1();

            if (future.isCancelled()) {
                return;
            }
            var step2Result = performStep2(step1Result);

            if (future.isCancelled()) {
                return;
            }
            var step3Result = performStep3(step2Result);

            if (future.isCancelled()) {
                return;
            }
            var result = performStep4(step3Result);
            future.complete(result);
        } catch (Exception ex) {
            future.completeExceptionally(ex);
        }
    });
    return future;
}
```

You don’t need to do anything with the `future` after it has been cancelled, as it has already been completed. Returning is enough.
