Search code examples
vaadin24

Vaadin 24 - Async render call seems to be "hang"


e.g. while current is UI. After some async service done, and we want to push relevant change to component. e.g. model

current.access(new Command() {
      @Override
      public void execute() {
          getElement().executeJs("this.widget.refresh(window.JSON.parse($0))", model);
      }
});

no change on screen until doing e.g. mouse click event on page. Tried to use the accessSynchronously also. same problem. Changes appear only after 'touching' the screen.

no error/exceptions in console or logs.

Use from component that created using the @JavaScript annotation. working synchronously works fine, but when trying to be asych, seems that render stack somewhere. tried with Vaadin 24.10.1 and 24.3.3


Solution

  • When you want to modify the UI from an async Thread* using ui.access(() -> {...}), then you need to have the @Push notification on your View (or one of its "parent" routerLayout-views).

    Otherwise that ui modification will show up only after your next server roundtrip (any user interaction in the UI -> button click, etc).

    You can use @Push(PushMode.MANUAL) if you intend to invoke ui.push() after each call of ui.access(..).
    Or you can simply use @Push which will default to PushMode.AUTOMATIC - automatically pushing any changes that were made when the ui-lock from a ui.access(..) call is lifted

    Sidenote: Even though I mostly use automatic pushmode, it has occurred to me that I'd still need to call ui.push() sometimes for it to work. I am not sure if that was a bug or an intentional edge-case.


    * or within e.g. a click listener of a Button if you want the modification to show before the whole clicklistener has completed (most common use case for me)


    PS: you can simplify your code with a lambda expression:

    current.access(() -> getElement().executeJs("this.widget.refresh(window.JSON.parse($0))", model));