question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

UI.getCurrent() is null in ErrorHandler

See original GitHub issue

Throwing 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.

skeleton-starter-flow.zip

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:open
  • Created 2 years ago
  • Comments:9 (9 by maintainers)

github_iconTop GitHub Comments

1reaction
TatuLundcommented, Mar 31, 2021

This is not a bug, it just means that you need to setup your ErrorHandler to be thread aware, e.g. this worked for me

public class InitListener implements VaadinServiceInitListener {

    @Override
    public void serviceInit(ServiceInitEvent serviceInitEvent) {
        serviceInitEvent.getSource().addUIInitListener(event -> {
            UI ui = event.getUI();
            VaadinSession session = ui.getSession();
            setErrorHandler(session, ui);
        }
    }

    private void setErrorHandler(VaadinSession session, UI ui) {
        session.setErrorHandler(error -> {
            ui.access(() -> {
                ConfirmDialog confirmDialog = new ConfirmDialog("Error",
                        "Internal Error: " + error.getThrowable().getMessage(),
                        "Do Something", confirmFire -> {
                        });
                String trace = "";
                for (StackTraceElement s : error.getThrowable()
                        .getStackTrace()) {
                    trace = trace + "  at " + s.getClassName() + ".java line "
                            + s.getLineNumber() + " " + s.getMethodName()
                            + "\n";
                }
                confirmDialog.add(new Pre(trace));
                confirmDialog.setWidth("500px");
                confirmDialog.setHeight("500px");
                confirmDialog.open();
                error.getThrowable().printStackTrace();
            });
        });
    }
}
0reactions
mvysnycommented, Sep 17, 2021

Sevice - UI is one to many mapping when there are multiple browser tabs.

That is true, but Vaadin can simply remember the UI instance in the ui.access() itself, for example within the new ErrorHandlingCommand() when it is constructed. Or in the FutureAccess class. If there is a will, there is a way 😉

Read more comments on GitHub >

github_iconTop Results From Across the Web

Vaadin 8 UI.getCurrent() returns null on non-request-threads
Hello community, I´m currently testing out vaadin 8 (8.0.0) and discovered a change in behavior compared to Vaadin 7 (tested with 7.7.6).
Read more >
javascript - Vaadin22 dosen't return value for expression
When i call UI.getCurrent(). ... scrollTop") the PendingJavaScriptResult always returns null. No error is given through the error handler.
Read more >
Vaadin 14+ Error/Exception Handling - Martin Vysny
Asynchronous blocks run via UI.access() - however beware that the UI.getCurrent() will be null in the ErrorHandler because of Vaadin bug ...
Read more >
com.vaadin.flow.component.UI.getCurrent java code ...
private UI getCurrentUI() { UI ui = UI.getCurrent(); if (ui == null) { throw new IllegalStateException("UI instance is not available.
Read more >
VaadinSession (vaadin-server 8.9.3 API)
Sets this session to be closed and all UI state to be discarded at the end ... ErrorHandler · getErrorHandler() ... public static...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found