tigu
tigu

Reputation: 751

Vaadin Spring Boot: "Cannot access state in VaadinSession or UI without locking the session" when multiple users access UI

I have a vaadin flow (13) application with spring boot. I have a VerticalLayout, annotated with @UIScope with multiple sub-layouts. The sub layouts are annotated with @Scope("prototype") and created via ctx.getBean(SubUI.class, ...). Depending on selections and button clicks on the parent UI (VerticalLayout), the sub layouts are added or removed.

That all works fine as long as I use the application alone (that's the reason why I found the error right now, after delivering the application to my customer for acceptantce test). They tested with multiple users. As long as one user works with the appliaction, everything works but as soon as a second user enters the UI (VerticalLayout), the following exception is thrown:

java.util.concurrent.ExecutionException: java.lang.IllegalStateException: Cannot access state in VaadinSession or UI without locking the session.
    at java.util.concurrent.FutureTask.report(FutureTask.java:122) ~[na:1.8.0_202]
    at java.util.concurrent.FutureTask.get(FutureTask.java:192) ~[na:1.8.0_202]
    ...

I tried different annotations for my parent layout (@UIScope, @Scope("prototype"), @VaadinSessionScope) but non solves my error.

I googled about the problem and found some threads, but none of them helped me to solve my problem. I am not really sure if the problem is caused by the scoping of my UIs/layouts or maybe by the data binding. In my sub layouts, data is bound using Binder<MyEntity> binder = new Binder<>(MyEntity.class); and binder.forField(xxx).bind(MyEntity::getXY,MyEntity::setXY);.

Can someone maybe explain me, what my problem is? I would be really happy, because I need to deliver a fixed version for my customers test.

Kind regards

Upvotes: 3

Views: 4435

Answers (2)

Tatu Lund
Tatu Lund

Reputation: 10623

You have some logic in your app that attempts to modify UI state, components etc. from a background thread. That should be done guarded by locking. So you need to encapsulate the logic in your view that is called from background method with

getUI().ifPresent(ui -> ui.access(() -> {
    ...
}));

Also, Server Push should be enabled.

Documentation: https://vaadin.com/docs/latest/advanced/server-push

Upvotes: 11

Martin Wunderlich
Martin Wunderlich

Reputation: 1884

FWIW, I was facing a similar issue with the exact same error message in a Vaadin-based MVC application (not using Spring MVC in addition to what Vaadin provides ootb). The root cause was the way the application was architected: The controllers in the MVC application were constructed as stateless singletons, similar to Spring MVC, which is fine.

However, the views were instantiated and registered not per user/session, but globally. This worked alright during local development when only one user was accessing the application, but failed as soon as more than one user was logged in, because the Vaadin application tried to access the same view instance from different sessions. This lead to the error stated by the OP.

The solution then was to disentangle the MVC architecture and make sure that different view instances get created per user session.

Upvotes: 1

Related Questions