Null pointer exception in UI.getCurrent().getSession().lock();

I think this is a bug.

@SpringComponent
public class Cron {
    public static void setVaadinSession(VaadinSession session) {
        vaadinSession = session;
    }

 @Scheduled(cron = "0 0 * * * ?")
    public void hourly() {
        String userTimezone = null;
        if (vaadinSession != null) {
            vaadinSession.lock();
            try {
                userTimezone = (String) vaadinSession.getAttribute(USER_TIMEZONE);
            } finally {
                vaadinSession.unlock();
            }
        }
        if (userTimezone != null) {
            ZoneId zoneId = ZoneId.of(userTimezone);
            ZonedDateTime zonedDateTime = ZonedDateTime.ofInstant(Instant.now(), zoneId);
            if (zonedDateTime.getHour() == 0)
                wodView.displayWod(zonedDateTime); //line 64
        }
    }
@SpringComponent
@UIScope
public class WodView extends VerticalLayout {
    public void displayWod(ZonedDateTime zonedDateTime) {
        UI.getCurrent().getSession().lock(); //line 44
		 try {
            removeAll();
        } finally {
            UI.getCurrent().getSession().unlock();
        }
public class MainLayout extends AppLayout {
    @Override
    protected void onAttach(AttachEvent attachEvent) {
        Cron.setVaadinSession(VaadinSession.getCurrent());
java.lang.NullPointerException: null
	at com.wodiq.ui.views.WodView.displayWod(WodView.java:44) ~[classes/:na]

	at com.wodiq.logic.Cron.hourly(Cron.java:64) ~[classes/:na]

	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]

	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]

	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]

	at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]

	at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:84) ~[spring-context-5.1.9.RELEASE.jar:5.1.9.RELEASE]

	at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54) ~[spring-context-5.1.9.RELEASE.jar:5.1.9.RELEASE]

	at org.springframework.scheduling.concurrent.ReschedulingRunnable.run(ReschedulingRunnable.java:93) ~[spring-context-5.1.9.RELEASE.jar:5.1.9.RELEASE]

	at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515) ~[na:na]

	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) ~[na:na]

	at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:304) ~[na:na]

	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) ~[na:na]

	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) ~[na:na]

	at java.base/java.lang.Thread.run(Thread.java:834) ~[na:na]

Hi Brian,

If you’re updating the UI from another thread you need to call ui.access() to get access to the UI.

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

Since your cronjob is not part of Vaadin but an external thread I guess UI.getCurrent() returns null.

Please have a look at

https://vaadin.com/docs/v14/flow/advanced/tutorial-push-access.html
=> PushyView

to see how asynchronous updates are handled.
You should save the UI reference and call ui.access() to get it working.
If your background code runs quick you could even put everything into ui.access()

Ah, that makes perfect sense. Thanks guys!

Actually, wouldn’t this be the simplest thing to do…

public void hourly() {
        if (vaadinSession != null) {
            vaadinSession.lock();
            try {
                String userTimezone = (String) vaadinSession.getAttribute(USER_TIMEZONE);
                ZoneId zoneId = ZoneId.of(userTimezone);
                ZonedDateTime zonedDateTime = ZonedDateTime.ofInstant(Instant.now(), zoneId);
                if (zonedDateTime.getHour() == 0)
                    wodView.displayWod(zonedDateTime);
            } finally {
                vaadinSession.unlock();
            }
        }
    }

No, because in a custom thread Vaadin does not know where to push your UI changes to.

https://vaadin.com/docs/v14/flow/advanced/tutorial-push-access.html => PushyView

Got it. Thanks again!