Асинхронные задачи
Бин UiAsyncTasks
позволяет выполнить операцию в отдельном потоке с использованием контекста безопасности текущего пользователя, а затем обновить экран с результатом этой операции.
Бин UiAsyncTasks
использует под капотом CompletableFuture
.
Если необходимо показать прогресс операции и дать пользователям возможность прервать её, используйте более мощный механизм фоновых задач.
Асинхронные задачи с результатом
Чтобы выполнить задачу, возвращающую результат, используйте билдер supplierConfigurer()
и терминальный метод supplyAsync()
:
@Autowired
private UiAsyncTasks uiAsyncTasks;
private void loadCustomersAsync() {
uiAsyncTasks.supplierConfigurer(this::loadCustomers) (1)
.withResultHandler(customers -> {
customersDc.setItems(customers); (2)
notifications.create("Customers loaded").show();
})
.supplyAsync();
}
private List<Customer> loadCustomers() {
return customerService.loadCustomers();
}
1 | Supplier, переданный в метод supplierConfigurer() , будет выполнен с использованием контекста безопасности текущего пользователя. |
2 | Код, выполняемый внутри потребителя withResultHandler() , может безопасно обновлять компоненты экрана. |
Асинхронные задачи без результата
Чтобы выполнить задачу, не возвращающую результат, используйте билдер runnableConfigurer()
и терминальный метод runAsync()
:
private void synchronizeCustomersAsync() {
uiAsyncTasks.runnableConfigurer(this::synchronizeCustomers)
.withResultHandler(() -> {
resultField.setValue("Synchronization completed");
})
.runAsync();
}
private void synchronizeCustomers() {
customerService.synchronizeCustomers();
}
Обработка исключений
По умолчанию, если выполнение задачи завершится с исключением, оно будет записано в журнал приложения. Вы можете настроить это поведение, предоставив обработчик исключений:
private void loadCustomersAndHandleException() {
uiAsyncTasks.supplierConfigurer(this::loadCustomers)
.withResultHandler(customers -> {
//...
})
.withExceptionHandler(ex -> {
errorField.setValue(ex.getMessage());
})
.supplyAsync();
}
Обработка таймаутов
Используйте метод withTimeout()
, чтобы задать значение таймаута выполнения. Если время ожидания превышено, будет выброшено исключение TimeoutException
. Исключение TimeoutException
можно обработать в методе withExceptionHandler()
.
private void loadCustomersWithTimeout() {
uiAsyncTasks.supplierConfigurer(this::loadCustomers)
.withResultHandler(customers -> {
//...
})
.withTimeout(20, TimeUnit.SECONDS)
.withExceptionHandler(ex -> {
String errorText;
if (ex instanceof TimeoutException) {
errorText = "Timeout exceeded";
} else {
errorText = ex.getMessage();
}
errorField.setValue(errorText);
})
.supplyAsync();
}
Если явные значения таймаута не указаны, будет использоваться значение по умолчанию — 5 минут. Чтобы изменить это значение по умолчанию, используйте свойство приложения jmix.ui.async-task.default-timeout-sec.
Конфигурация ExecutorService
Бин UiAsyncTasks
использует собственный ExecutorService
для выполнения задач в отдельных потоках. Чтобы изменить размер пула по умолчанию для ExecutorService
, используйте свойство приложения jmix.ui.async-task.executor-service.maximum-pool-size.