异步任务

UiAsyncTasks Bean 支持使用当前用户的安全上下文在单独的线程中执行操作,并使用该操作的结果更新 UI。

UiAsyncTasks bean 的核心功能是通过 CompletableFuture 实现的。

如果需要显示操作的进度并为用户提供中止操作的功能,请使用更强大的 后台任务 机制。

带返回结果的异步任务

如需执行一个可返回结果的任务,请使用 supplierConfigurer() builder 以及 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 传递给 supplierConfigurer() 方法的 supplier 会使用当前用户的安全上下文执行。
2 在消费者 withResultHandler() 中执行的代码可以更新视图组件。

不带返回结果的异步任务

如需执行一个无返回结果的任务,请使用 runnableConfigurer() builder 以及 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 异常,可以通过 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 bean 使用 ExecutorService 在单独的线程中运行任务。如需修改 ExecutorService 线程池的默认大小,可以通过 jmix.ui.async-task.executor-service.maximum-pool-size 应用程序属性配置。