You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When the user's session times out or is killed by 3 missed heartbeats, or by spring security's logout URL we see an exception in the logs about the session already being invalidated.
There's quite a bit of setup before this can be tried out as it needs many moving parts but based on the stack traces and some investigation it seems that the v8 VaadinService tries to access the session during the fireSessionDestroy part, which will throw if the session is already invalidated.
There's basically a couple of different paths were we've observed this:
For sanity sake, we set:
vaadin.heartbeatInterval=15
vaadin.closeIdleSessions=true
server.servlet.session.timeout=60s
Login to the application and land on a view that mixes v14 and v8 components (i.e. both runtimes are enabled)
close the browser
Use another browser (like Safari if you used Chrome earlier) to generate some small traffic on the server
After about 45-60 seconds you'll see a stacktrace:
2019-10-24 15:32:10.322 WARN 59167 --- [alina-utility-1] o.apache.catalina.core.StandardContext : Exception processing manager [StandardManager[StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]]] background process
java.lang.IllegalStateException: getAttribute: Session already invalidated
at org.apache.catalina.session.StandardSession.getAttribute(StandardSession.java:1145)
at org.apache.catalina.session.StandardSessionFacade.getAttribute(StandardSessionFacade.java:103)
at com.vaadin.server.WrappedHttpSession.getAttribute(WrappedHttpSession.java:54)
at com.vaadin.mpr.core.MprServletService.getFlowSession(MprServletService.java:183)
at com.vaadin.mpr.core.MprServletService.accessSession(MprServletService.java:158)
at com.vaadin.server.VaadinSession.access(VaadinSession.java:1417)
at com.vaadin.server.VaadinService.fireSessionDestroy(VaadinService.java:529)
at com.vaadin.server.VaadinSession.valueUnbound(VaadinSession.java:313)
at org.apache.catalina.session.StandardSession.removeAttributeInternal(StandardSession.java:1784)
at org.apache.catalina.session.StandardSession.expire(StandardSession.java:856)
at org.apache.catalina.session.StandardSession.isValid(StandardSession.java:659)
at org.apache.catalina.session.ManagerBase.processExpires(ManagerBase.java:573)
at org.apache.catalina.session.ManagerBase.backgroundProcess(ManagerBase.java:558)
at org.apache.catalina.core.StandardContext.backgroundProcess(StandardContext.java:5539)
at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1353)
at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1357)
at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1357)
at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.run(ContainerBase.java:1335)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)
Tracing the stacktrace down, you'll see that com.vaadin.server.VaadinService#fireSessionDestroy() will call ".access()" on the session which tries to get the Flow session (through MprVaadinService) which eventually ends up in "StandardSession.getAttribute()" which is not allowed if the session "is not valid"...
Second case:
Configure SpringSecurity to have a "logout url"
open a browser
logon and land on a page that mixes v14 and v8
change the URL to the SpringSecurity logout url
You'll notice a stacktrace like:
2019-10-24 16:22:50.641 ERROR 68576 --- [nio-8080-exec-4] o.a.c.c.C.[.[.[/].[springServlet] : Servlet.service() for servlet [springServlet] in context with path [] threw exception
java.lang.IllegalStateException: getAttribute: Session already invalidated
at org.apache.catalina.session.StandardSession.getAttribute(StandardSession.java:1145)
at org.apache.catalina.session.StandardSessionFacade.getAttribute(StandardSessionFacade.java:103)
at com.vaadin.server.WrappedHttpSession.getAttribute(WrappedHttpSession.java:54)
at com.vaadin.mpr.core.MprServletService.getFlowSession(MprServletService.java:183)
at com.vaadin.mpr.core.MprServletService.accessSession(MprServletService.java:158)
at com.vaadin.server.VaadinSession.access(VaadinSession.java:1417)
at com.vaadin.server.VaadinService.fireSessionDestroy(VaadinService.java:529)
at com.vaadin.server.VaadinSession.valueUnbound(VaadinSession.java:313)
at org.apache.catalina.session.StandardSession.removeAttributeInternal(StandardSession.java:1784)
at org.apache.catalina.session.StandardSession.expire(StandardSession.java:856)
at org.apache.catalina.session.StandardSession.expire(StandardSession.java:743)
at org.apache.catalina.session.StandardSession.invalidate(StandardSession.java:1229)
at org.apache.catalina.session.StandardSessionFacade.invalidate(StandardSessionFacade.java:171)
at org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler.logout(SecurityContextLogoutHandler.java:66)
at org.springframework.security.web.authentication.logout.CompositeLogoutHandler.logout(CompositeLogoutHandler.java:54)
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:109)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:74)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:215)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:358)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:271)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:94)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.filterAndRecordMetrics(WebMvcMetricsFilter.java:114)
at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:104)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
at org.apache.catalina.core.StandardContextValve.__invoke(StandardContextValve.java:96)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:41002)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:526)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
at org.apache.catalina.valves.RemoteIpValve.invoke(RemoteIpValve.java:747)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:860)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1589)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)
Tracing this one back, it is apparent that in this case Spring is invalidating the session, which causes the same kind of exception as the Tomcat session timeout case above.
A third case:
logon to the application and land on a v14 v8 mixed view
leave the browser idling and let the "closeIdleSesssions" do its thing
observe that you again have a stacktrace, which one depends on who/what triggered it
a) the next heartbeat
b) tomcats internal processing (this one is hard to reproduce with a short heartbeat interval but essentially the same as closing the browser)
The text was updated successfully, but these errors were encountered:
In a project running:
Vaadin 14.0.10, Vaadin 8.9.1
MPR 2.0.0
SpringSecurity
Tomcat
Original ticket in Vaadin internal repo: https://github.com/vaadin/multiplatform-runtime-internal/issues/340
When the user's session times out or is killed by 3 missed heartbeats, or by spring security's logout URL we see an exception in the logs about the session already being invalidated.
There's quite a bit of setup before this can be tried out as it needs many moving parts but based on the stack traces and some investigation it seems that the v8 VaadinService tries to access the session during the fireSessionDestroy part, which will throw if the session is already invalidated.
There's basically a couple of different paths were we've observed this:
For sanity sake, we set:
vaadin.heartbeatInterval=15
vaadin.closeIdleSessions=true
server.servlet.session.timeout=60s
Login to the application and land on a view that mixes v14 and v8 components (i.e. both runtimes are enabled)
close the browser
Use another browser (like Safari if you used Chrome earlier) to generate some small traffic on the server
After about 45-60 seconds you'll see a stacktrace:
Tracing the stacktrace down, you'll see that com.vaadin.server.VaadinService#fireSessionDestroy() will call ".access()" on the session which tries to get the Flow session (through MprVaadinService) which eventually ends up in "StandardSession.getAttribute()" which is not allowed if the session "is not valid"...
Second case:
Configure SpringSecurity to have a "logout url"
open a browser
logon and land on a page that mixes v14 and v8
change the URL to the SpringSecurity logout url
You'll notice a stacktrace like:
2019-10-24 16:22:50.641 ERROR 68576 --- [nio-8080-exec-4] o.a.c.c.C.[.[.[/].[springServlet] : Servlet.service() for servlet [springServlet] in context with path [] threw exception
Tracing this one back, it is apparent that in this case Spring is invalidating the session, which causes the same kind of exception as the Tomcat session timeout case above.
A third case:
logon to the application and land on a v14 v8 mixed view
leave the browser idling and let the "closeIdleSesssions" do its thing
observe that you again have a stacktrace, which one depends on who/what triggered it
a) the next heartbeat
b) tomcats internal processing (this one is hard to reproduce with a short heartbeat interval but essentially the same as closing the browser)
The text was updated successfully, but these errors were encountered: