UI.getCurrent() is null in ErrorHandler
See original GitHub issueThrowing an exception in the ui.access()
block from bg thread will call ErrorHandler.error()
with UI.getCurrent()
set to null. That will fail to show any notification from the ErrorHandler
with the following stacktrace:
[Thread-8] ERROR com.vaadin.flow.component.UI - UI instance is not available. It means that you are calling this method out of a normal workflow where it's always implicitly set. That may happen if you call the method from the custom thread without 'UI::access' or from tests without proper initialization.
java.lang.IllegalStateException: UI instance is not available. It means that you are calling this method out of a normal workflow where it's always implicitly set. That may happen if you call the method from the custom thread without 'UI::access' or from tests without proper initialization.
at com.vaadin.flow.component.notification.Notification.setOpened(Notification.java:426)
at com.vaadin.flow.component.notification.Notification.open(Notification.java:303)
at com.vaadin.flow.component.notification.Notification.show(Notification.java:227)
at com.vaadin.flow.component.notification.Notification.show(Notification.java:244)
at org.vaadin.example.Bootstrap.error(Bootstrap.java:20)
at com.vaadin.flow.component.UI$1.handleError(UI.java:520)
at com.vaadin.flow.server.FutureAccess.handleError(FutureAccess.java:76)
at com.vaadin.flow.server.VaadinService.runPendingAccessTasks(VaadinService.java:2045)
at com.vaadin.flow.server.VaadinSession.unlock(VaadinSession.java:681)
at com.vaadin.flow.server.VaadinService.ensureAccessQueuePurged(VaadinService.java:2005)
at com.vaadin.flow.server.VaadinService.accessSession(VaadinService.java:1972)
at com.vaadin.flow.server.VaadinSession.access(VaadinSession.java:969)
at com.vaadin.flow.component.UI.access(UI.java:506)
at com.vaadin.flow.component.UI.access(UI.java:489)
at org.vaadin.example.MainView$1.run(MainView.java:52)
The ErrorHandler
does not document whether it’s called in Vaadin UI thread or not. If it doesn’t, this needs to be clearly documented. If yes, then the Vaadin environment should be set properly - the UI.getCurrent() should not return null. In either case, this needs to be documented in the ErrorHandler
javadoc.
Minimal reproducible example
Attaching the skeleton starter app which demoes the issue. In short, this view demoes the issue:
public class MainView extends VerticalLayout {
public MainView() {
// Use TextField for standard text input
TextField textField = new TextField("Wait for it");
add(textField);
final UI ui = UI.getCurrent();
new Thread() {
@Override
public void run() {
try {
Thread.sleep(1000);
ui.access(() -> {
throw new RuntimeException("Simulated failure");
});
} catch (Throwable t) {
t.printStackTrace();
}
}
}.start();
}
}
Make sure to have the ErrorHandler set; wait for 1 second then check out the console log.
Expected behavior
The UI.getCurrent() should not be null.
Actual behavior
The UI.getCurrent() is null.
Versions:
- Vaadin / Flow version: 14.5.1 / 2.5.1
- Java version: 11
Issue Analytics
- State:
- Created 2 years ago
- Comments:9 (9 by maintainers)
This is not a bug, it just means that you need to setup your
ErrorHandler
to be thread aware, e.g. this worked for meThat is true, but Vaadin can simply remember the UI instance in the
ui.access()
itself, for example within thenew ErrorHandlingCommand()
when it is constructed. Or in theFutureAccess
class. If there is a will, there is a way 😉