NPE in VaadinSession.getState during startup (when spring-security is involved)

Since we applied spring-security to our application, sometimes we’re getting this in the startup logs of our application. Unsure if it’s harmless or not, but the fact that it’s happening seems to indicate somewhere a condition is being triggered that was not foreseen in the framework.

Caused by: com.vaadin.flow.server.ServiceException: java.lang.NullPointerException: Cannot invoke “com.vaadin.flow.server.VaadinSession.getState()” because the return value of “com.vaadin.flow.component.UI.getSession()” is null
at com.vaadin.flow.server.VaadinService.handleExceptionDuringRequest(VaadinService.java:1635) ~[flow-server-24.3.5.jar:24.3.5]
at com.vaadin.flow.server.VaadinService.handleRequest(VaadinService.java:1586) ~[flow-server-24.3.5.jar:24.3.5]
at com.vaadin.flow.server.VaadinServlet.service(VaadinServlet.java:398) ~[flow-server-24.3.5.jar:24.3.5]
… 141 common frames omitted
Caused by: java.lang.NullPointerException: Cannot invoke “com.vaadin.flow.server.VaadinSession.getState()” because the return value of “com.vaadin.flow.component.UI.getSession()” is null

Here is the more helpful, bottom part of the stacktrace:

Caused by: java.lang.NullPointerException: Cannot invoke “com.vaadin.flow.server.VaadinSession.getState()” because the return value of “com.vaadin.flow.component.UI.getSession()” is null
at com.vaadin.flow.server.communication.MetadataWriter.createMetadata(MetadataWriter.java:69) ~[flow-server-24.3.5.jar:24.3.5]
at com.vaadin.flow.server.communication.UidlWriter.createUidl(UidlWriter.java:162) ~[flow-server-24.3.5.jar:24.3.5]
at com.vaadin.flow.server.communication.UidlWriter.createUidl(UidlWriter.java:215) ~[flow-server-24.3.5.jar:24.3.5]
at com.vaadin.flow.server.BootstrapHandler.getInitialUidl(BootstrapHandler.java:1503) ~[flow-server-24.3.5.jar:24.3.5]
at com.vaadin.flow.server.communication.JavaScriptBootstrapHandler.getInitialJson(JavaScriptBootstrapHandler.java:284) ~[flow-server-24.3.5.jar:24.3.5]
at com.vaadin.flow.server.communication.JavaScriptBootstrapHandler.synchronizedHandleRequest(JavaScriptBootstrapHandler.java:205) ~[flow-server-24.3.5.jar:24.3.5]
at com.vaadin.flow.server.SynchronizedRequestHandler.handleRequest(SynchronizedRequestHandler.java:40) ~[flow-server-24.3.5.jar:24.3.5]
at com.vaadin.flow.server.VaadinService.handleRequest(VaadinService.java:1574) ~[flow-server-24.3.5.jar:24.3.5]
… 142 common frames omitted

Relevant code block, maybe ui.getSession could use another null guard ?


        // meta instruction for client to enable auto-forward to
        // sessionExpiredURL after timer expires.
        if (messages != null && messages.getSessionExpiredMessage() == null
                && messages.getSessionExpiredCaption() == null
                && messages.isSessionExpiredNotificationEnabled()
69 -->          && ui.getSession().getSession() != null) {
            int newTimeoutInterval = ui.getSession().getSession()
                    .getMaxInactiveInterval();
            if (repaintAll || (timeoutInterval != newTimeoutInterval)) {

Is this an older application that you just added spring security, or a fairly fresh one?
You can try exporting an starter project from https://start.vaadin.com/ it will come with spring security if you modify a single page view access. You can compare configuration there with yours, maybe there’s something missing.
image.png

It’s an app that is under development for 8 months. We just added spring-security now. Regardless of what is going on, i feel that an extra null guard is warranted there. If not, and the code expects to only run when there is a session available then this should be checked upfront in a precondition and a different exception thrown indicating that this code path must not be run outside of a valid session.

The code that currently fails is runnìng in a SynchronizedRequestHandler that performs a VaadinSessionn lock and unlock around the execution,
In addition the UI instance is created in the BootstrapHandler and the VaadinSession is assigned to it.

So, the fact that the session is null there is completely unexpected :thinking:

The only way to nullify VaadinSession for a UI is to remove the UI itself from the VaadinSession.
This usually happens when the VaadinSession is destroyed (e.g, HTTP session expired or VaadinSession is inactive and gets cleaned up)
Another option is that application code is nullifying the UI session in some init listener, but I’m confident your application has not such things.
Is there any part of your code that is manually closing UIs or VaadinSession?
How does your Spring Security configuration look like?

I have logged an issue here https://github.com/vaadin/flow/issues/18796 . We don’t have code to nullify the UI session, nor closing UIs or VaadinSession. The spring security config is very minimal:

@EnableWebSecurity
@EnableMethodSecurity
@Configuration
class MyVaadinWebSecurity extends VaadinWebSecurity {

  @Autowired
  MyAuthenticationFilter myAuthenticationFilter;

  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http.authorizeHttpRequests(
        registry ->
            registry.requestMatchers(new AntPathRequestMatcher("/actuator/**")).permitAll());
    super.configure(http);
    http.addFilter(myAuthenticationFilter);
  }
}

Out of curiosity, what does MyAuthenticationFilter do?

Nothing (at least in my view) special, it extends AbstractPreAuthenticatedProcessingFilter and has this in constructor:

    setCheckForPrincipalChanges(true);
    setAuthenticationDetailsSource(new MyAuthenticationDetailsSource(properties));
    setAuthenticationManager(new ProviderManager(myAuthenticationProvider));

That filter seems to invalidate session under some circumstances. Can you try to remove ti and see if the issue is still there?

I cannot remove it as our application does not work without any security enabled :\