5.5.6. Background Tasks
Background tasks mechanism is designed for performing tasks at the client tier asynchronously without blocking the user interface.
In order to use background tasks, do the following:
-
Define a task as an inheritor of the
BackgroundTask
abstract class. Pass a link to a screen controller which will be associated with the task and the task timeout to the task constructor.Closing the screen will interrupt the tasks associated with it. Additionally, the task will be interrupted automatically after the specified timeout.
Actual actions performed by the task are implemented in the run() method.
-
Create an object of
BackgroundTaskHandler
class controlling the task by passing the task instance to thehandle()
method of theBackgroundWorker
bean. A link toBackgroundWorker
can be obtained by an injection in a screen controller, or through theAppBeans
class. -
Run the task by invoking the
execute()
method ofBackgroundTaskHandler
.
Warning
|
UI components' state and datasources must not be read/updated from |
Example:
@Inject
protected BackgroundWorker backgroundWorker;
@Override
public void init(Map<String, Object> params) {
// Create task with 10 sec timeout and this screen as owner
BackgroundTask<Integer, Void> task = new BackgroundTask<Integer, Void>(10, this) {
@Override
public Void run(TaskLifeCycle<Integer> taskLifeCycle) throws Exception {
// Do something in background thread
for (int i = 0; i < 5; i++) {
TimeUnit.SECONDS.sleep(1); // time consuming computations
taskLifeCycle.publish(i); // publish current progress to show it in progress() method
}
return null;
}
@Override
public void canceled() {
// Do something in UI thread if the task is canceled
}
@Override
public void done(Void result) {
// Do something in UI thread when the task is done
}
@Override
public void progress(List<Integer> changes) {
// Show current progress in UI thread
}
};
// Get task handler object and run the task
BackgroundTaskHandler taskHandler = backgroundWorker.handle(task);
taskHandler.execute();
}
Detailed information about methods is provided in JavaDocs for BackgroundTask
, TaskLifeCycle
, BackgroundTaskHandler
classes.
Please note the following:
-
BackgroundTask<T, V>
is a parameterized class:-
T
− the type of objects displaying task progress. Objects of this type are passed to the task’sprogress()
method during an invocation ofTaskLifeCycle.publish()
in the working thread. -
V
− task result type passed to thedone()
method. It can also be obtained by invokingBackgroundTaskHandler.getResult()
method, which will wait for a task to complete.
-
-
canceled()
method is invoked only during a controlled cancellation of a task, i.e. whencancel()
is invoked in theTaskHandler
. -
handleTimeoutException()
is invoked when the task timeout expires. If the window where the task is running closes, the task is stopped without a notification.
-
run()
method of a task should support external interruptions. To ensure this, we recommend checking theTaskLifeCycle.isInterrupted()
flag periodically during long processes and stopping execution when needed. Additionally, you should not silently discardInterruptedException
(or any other exception) - instead you should either exit the method correctly or not handle the exception at all.-
isCancelled()
method returnstrue
if a task was interrupted by calling thecancel()
method.public String run(TaskLifeCycle<Integer> taskLifeCycle) { for (int i = 0; i < 9_000_000; i++) { if (taskLifeCycle.isCancelled()) { log.info(" >>> Task was cancelled"); break; } else { log.info(" >>> Task is working: iteration #" + i); } } return "Done"; }
-
-
BackgroundTask
objects are stateless. If you did not create fields for temporary data when implementing task class, you can start several parallel processes using a single task instance. -
BackgroundHandler
object (itsexecute()
method) can only be started once. If you need to restart a task frequently, useBackgroundTaskWrapper
class. -
Use
BackgroundWorkWindow
orBackgroundWorkProgressWindow
classes with a set of static methods to show a modal window with progress indicator and Cancel button. You can define progress indication type and allow or prohibit cancellation of the background task for the window. -
If you need to use certain values of visual components in the task thread, you should implement their acquisition in
getParams()
method, which runs in the UI thread once, when a task starts. In the run() method, these parameters will be accessible via thegetParams()
method of theTaskLifeCycle
object. -
If any exception occurs, the framework invokes
BackgroundTask.handleException()
method in the UI thread, which can be used to display the error. -
Background tasks are affected by cuba.backgroundWorker.maxActiveTasksCount and cuba.backgroundWorker.timeoutCheckInterval application properties.
Warning
|
In Web Client, background tasks are implemented using HTTP push provided by the Vaadin framework. See https://vaadin.com/wiki/-/wiki/Main/Working+around+push+issues for information on how to set up your web servers for this technology. |
Tip
|
If you don’t use background tasks, but want to update UI state from a non-UI thread, use methods of the |