【问题标题】:Vaadin: Cannot get progress dialog to receive/react when the task completesVaadin:任务完成时无法获取进度对话框以接收/做出反应
【发布时间】:2021-08-27 17:51:31
【问题描述】:

我编写了一个小型 Spring Boot/Vaadin 应用程序,它显示一个简单的 UI 以获取用户输入并调用另一个需要一些时间才能运行的服务。提交任务后,我将显示一个进度对话框,其中显示一个进度条、一条通知用户正在发生的事情的消息以及一个关闭按钮,允许他们在作业完成时关闭对话框。我使用ListenableFuture 在任务完成时收到通知。

我可以让对话框以“正在执行”的状态出现,并且进度条在做它的事情,但是当任务完成时(我有调试语句去控制台让我知道),它不会触发逻辑更新状态消息并启用关闭按钮。我不知道我做错了什么。

代码如下:

MainView1.java

@Route("rescheduleWorkOrders1")
@CssImport("./styles/shared-styles.css")
public class MainView1 extends VerticalLayout {
  ...
  private final BackendService service;

  public MainView1(BackendService service) {
    this.service = service;
    configureView();
    addSubmitButton();
    bindFields();
  }

  private void addSubmitButton() {
    Button submit = new Button("Submit", this::submit);
    add(submit);
  }

  private void submit(ClickEvent<?> event) {
    UserData data = binder.getBean();
    ListenableFuture<ResponseEntity<String>> future = service.executeTask(data);
    ProgressDialog dialog = new ProgressDialog(future);
    dialog.open();
  }

  private void configureView() {
    ...
  }

  private void bindFields() {
    ...
  }    
}

ProgressDialog.java

public class ProgressDialog extends Dialog {
  private final ListenableFuture<ResponseEntity<String>> future;

  private ProgressBar                                    bar;
  private Paragraph                                      message;
  private Button                                         close;

  public ProgressDialog(ListenableFuture<ResponseEntity<String>> future) {
    super();
    this.future = future;
    configureView();

    this.future.addCallback(new ListenableFutureCallback<>() {
      @Override
      public void onSuccess(ResponseEntity<String> result) {
        message.setText("Task complete. Status: " + result.getStatusCode());
        bar.setVisible(false);
        close.setEnabled(true);
      }

      @Override
      public void onFailure(Throwable ex) {
        message.setText(ex.getMessage());
        bar.setVisible(false);
        close.setEnabled(true);
      }
    });
  }

  private void configureView() {
    bar = new ProgressBar();
    bar.setIndeterminate(true);
    bar.setVisible(true);

    message = new Paragraph("Executing task ...");

    close = new Button("Close", this::close);
    close.setEnabled(false);

    add(bar, message, close);
  }

  private void close(ClickEvent<?> event) {
    this.close();
  }
}

BackendService.java

@Service
public class BackendService {

  @Async
  public ListenableFuture<ResponseEntity<String>> executeTask(UserData data) {
    ...
    RestTemplate template = new RestTemplate();
    ResponseEntity<String> response = template.postForEntity(uri, entity, String.class);

    System.out.println(response);
    return AsyncResult.forValue(response);
  }

}

注意:我确实在 @Configuration 注释类中指定了 @EnableAsync

【问题讨论】:

    标签: java spring-boot vaadin


    【解决方案1】:

    在 Vaadin 中处理异步代码时,您需要:

    • 在活动请求之外更新 UI 时使用 UI#access。这会在 UI 上获得一个锁,以防止它同时被两个线程更新。
    • 通过将@Push 注释添加到主布局或视图来启用服务器推送。这允许服务器将更新推送到客户端,即使没有处于活动状态的请求。

    没有前者,最好的情况是ConcurrentModificationExceptions,最坏的情况是非常微妙的错误。

    如果没有后者,更改将被应用(即对话框关闭),但更改只会在客户端下次发送请求时发送给客户端。我相信这是您的主要问题。

    更多信息可以在documentation找到。

    【讨论】:

      猜你喜欢
      • 2018-09-29
      • 2019-09-01
      • 2013-01-04
      • 2013-12-11
      • 1970-01-01
      • 1970-01-01
      • 2019-03-13
      • 2017-05-10
      • 1970-01-01
      相关资源
      最近更新 更多