ui.navigate not work outside of an event handler - vaadin 14.2.1

I have 2 pages:

  • Login page with login button.
  • Result Page (ResultView.java).

when user click on Login Button, inside the button event handler, I navigate:

void buttonLoginHandler(ClickEvent<Button> event){

  ui.access(()->{ (ui.getUI().ifPresent(uii -> {
  uii.navigate(ResultView.class, data);
   }); };)
}

It works fine.

But if i navigate outside the button event handler (in other thread as a Timer after button event handler completed execution) then the “Result Page” will not show. Need to click again in page, then “Result Page” will only show.

void buttonLoginHandler(ClickEvent<Button> event){

}

void myTimerThread(){
  // this will not work, ResultView does not show, there is no exception.
   ui.access(()->{ (ui.getUI().ifPresent(uii -> {
  uii.navigate(ResultView.class, data);
   }); };)
}

In Threads you must use ui.access() for every Vaadin UI related code.

See
https://vaadin.com/docs/v14/flow/advanced/tutorial-push-access.html
for more info

yes, we used ui.access() but still not work

Do you use
@Push? If not please enable it.

See https://vaadin.com/docs/flow/advanced/tutorial-push-configuration.html
“The automatic mode pushes changes to the browser automatically after access() finishes.”

That should work.

yes we enabled PUSH

If the code is run asynchronously (for example new Thread, etc), then you need ui.access(..) to push any changes to the ui.
Inside a ClickListener (or any Listener based on user action) however, you don’t need that. That’s why it worked there.

In your code sample, you don’t show how ui is defined. You need to save the ui instance of the view when the view is attached, to be able to reuse it later for a call of ui.access in a background thread.

PS: you don’t need ui.getUI.ifPresent part, it gets an optional of itself.

public class MyLoginView extends VerticalLayout {
	private UI ui;
	private String data = "";
	
	public MyLoginView(){
		// save ui instance when view is attached
		addAttachListener(event -> this.ui = UI.getCurrent());
		
		add(new Button("Navigate in 5 seconds", click -> {
			new Thread(() -> {
				Thread.sleep(5000);
				this.ui.access(() -> ui.navigate(ResultView.class, data));
			}).start();
		}));
	}
}

INPUTsys Chris Peter:
Do you use
@Push? If not please enable it.

See https://vaadin.com/docs/flow/advanced/tutorial-push-configuration.html
“The automatic mode pushes changes to the browser automatically after access() finishes.”

That should work.

thanks for advise. I only add PUSH to mainview. we need enable PUSH at the view we need to navigate. now it worked. thanks