Notify User from Background Thread

I know there are millions of questions like this, but they all come to having to call UI.getCurrent().access(…) and in my case UI.getCurrent() returns null. The same goes for VaadinSesscion.getCurrent() - also null. I am calling it from a Spring AsyncUncaughtExceptionHandler.

Basically, this is a bean that comes to life every time an exception occurs in an @Async annotated method (such as sending a mail). The handler thread is instantiated by Spring, so I have no way of passing it a Vaadin UI or Component.

So, is it possible to display any kind of error message to the user from a non-Vaadin thread?

There should at least be a way with JavaScript or such.

Yes, UI.getCurrent() returns null when called from background thread for a reason.

Instead of using UI.getCurrent() you should rely on getUI() method the component. This is available both Vaadin 8 as well as in Vaadin 14+

I have example here: https://github.com/TatuLund/cdi-demo/blob/master/src/main/java/org/vaadin/cdidemo/views/admin/AdminViewImpl.java#L56

The component knows to which UI it has been attached to. A background thread is not attached to anything, thus UI.getCurrent() or VaadinSession.getCurrent() do not work there.

I have found that the best pattern is to delegate the background thread calls to presenter which then uses excutor service, future etc. like in this example https://github.com/TatuLund/cdi-demo/blob/master/src/main/java/org/vaadin/cdidemo/views/admin/AdminPresenter.java#L48

My code example is Java EE based. However with Spring @Async the principle is the same. @Async itself uses excutor service behind the scenes.

Thank you very much for your comment. I am not 100% sure I understand your example, but I cannot use getUI(), because my background thread has no access to the component it needs to be called on.

My question was meant to be specifically about using Spring’s @Async mechanism, where I have no control over the instantiation of the background thread.

I was wondering, maybe I could throw a custom DOM event from the background thread and catch that in the UI thread?

Why don’t you pass the UI element to the @Async method?

You then can call

component.getUI().ifPresent(ui -> ui.access(() -> {
    // do the UI update here
});

Yes, that is the correct answer for those many questions very similar to mine :slight_smile:

But in this case Spring calls the method and its signature is:

handleUncaughtException(Throwable ex, Method method, Object... params)

So there is no way to pass a UI component, unless one were to fiddle with the Reflection API…

oh I’m sorry I didn’t read you question good enough. will think about

I solved this by using @Push on my view and adding a method:

@Override
protected void onAttach(AttachEvent attachEvent) {
	this.ui = attachEvent.getUI();
}

So when the user clicks the button that starts the @Async thread I can do something like this:

myService.doAsyncStuff(ui, ...);

And in MyService:

@Async
public void doAsyncStuff(UI ui, ...) {
	[...]

	catch (Exception ex) {
		ui.access(() -> {
			// show error dialog or change UI in another way
		});
	}