User Interface Interaction
Some background jobs execute business processes in the background. The end user may see the result of the job, but doesn’t have to interact directly with it. Scheduled and event triggered jobs are typically in this category.
Then there are jobs that need to interact with the user interface. For instance, a job may want to update a progress indicator while running, and notify the user when it’s finished or an error has occurred. Furthermore, the user may want to cancel a running job before it has completed. This page explains different options for allowing a user to interact with a background job, and vice versa.
Why Use a Background Job?
In a Flow application, Vaadin holds the lock of the user’s session while it handles a request from the browser. If a listener calls a slow operation directly, Vaadin can’t send the response until the operation has finished. Until then, the user interface doesn’t respond to the user — in any browser tab that belongs to the same session.
To keep the user interface responsive, run the slow operation as a background job, and let the job report back to the user interface.
Complete Example
The following Flow example shows all the parts together. An application service runs a job in a background thread. A view starts the job, shows its progress, and lets the user cancel it. The service uses callbacks to report back to the view, and the view stores the state of the job in signals.
The example only works with server push enabled. See Enabling Push for how to enable it.
Source code
ReportService.java
-
Protects the service with method security, as you should with all application services.
-
Runs the job in a background thread. The service uses the
TaskExecutorinstead of the@Asyncannotation, so that the security check runs in the thread of the user. See User Triggered Jobs for details. -
Stops at the next suitable moment if the job has been cancelled.
-
Returns a handle that the view can use to cancel the job.
Source code
ReportView.java
-
Allows any authenticated user to open the view, which matches the access rule of the service. See Protect Views for details.
-
Signals hold the state of the job. The job updates them from its background thread, and the bound components update automatically.
-
Derives a signal that disables the start button while the job is running.
-
Cancels the job if the user leaves the view.
-
Passes callbacks that update the signals, and stores the handle for cancelling the job.
-
Runs in the background thread. This is safe, because signals are thread-safe.
If the job can’t report its progress, call progressBar.setIndeterminate(true) instead of binding the value of the progress bar. The progress bar then shows that the job is running, without showing how far it has come.
Options
The example above is one way of letting the user interface and a background job interact. The following pages cover the different options in more detail:
- Callbacks
- How to use callbacks to interact with the user interface.
- Futures
- How to use CompletableFuture to interact with the user interface.
- Producing Reactive Streams
- How to use reactive streams to interact with the user interface.