@SpringUI lock

Hi,

I have a Spring-based Vaadin 8 app. There’s a @SpringUI in this app which is quite “heavy”: it takes ~20 seconds to load it. The problem which I noticed is that while it is loading, I can’t open the same UI in a parallel tab. In fact, all other UIs are also kind of “locked”. So, basically, if one UI is being loaded, no other UI can be opened in any other parallel session.

I’m a bit confused, because if we are talking about plain Spring app without Vaadin, even if one request is handled a lot of time, other requests can still be served in parallel, because Tomcat operates with multiple threads. Why it doesn’t work the same way with Vaadin’s @SpringUI’s?

Is it possible to configure Vaadin somehow in a way that parallel requests are processed in a parallel Tomcat threads?

It’s because all of the UIs will share the VaadinSession and the lock is on the session. One way around this issue would be using @Push for asynchronous updates. In a nutshell, you should move all of the slow server activities (whether it means slow backend queries or complicated UI construction logic) into a background thread and just return a skeleton UI into the browser. Then, once the slow processing thread is done, use UI.access() to update the UI instance and Push will update the browser for you. You might want to put some kind of loading indicator into the first response to let the user know that they need to wait for the complete view to appear; it could be something as simple as a Label that says “Loading, please wait…”. You can read more about Push here: https://vaadin.com/docs/v8/framework/advanced/advanced-push.html

This sounds very confusing, to be honest. I didn’t quite get why there’s a session lock in the first place? If we take a look at simple Spring example:

@RequestMapping("/api")
@RestController
@SessionScope
public class TestController {

    @GetMapping(path = "/test")
    public String test() throws InterruptedException {
        Thread.sleep(10000L);
        return "test";
    }

    @GetMapping(path = "/test2")
    public String test2() {
        return "test2";
    }
	
}

The controller above is also session-scoped, but if you call /test (slow endpoint) and /test2 at the same time, the second one will be processed immediately, because it will be executed in parallel, despite the fact that the whole bean is bound to the same session.

And, what’s even more surprising for me, is that not only the “slow” UI becomes unaccessible: all other UI’s (separate ones) also can’t be loaded. Why do they interfere with each other? I mean, the scope itself shouldn’t require things to be locked on this scope, if this things are independent…

Any update on this?

Nothing new. Vaadin UI requests should respond quickly and slow server side operations should be processed in threads that update the UI asynchronously; implementation of the threading is left for the application developer. You can think of like this: instead of “one browser tab can be very slow”, the experience needs to be “no browser tab should be very slow”.

But could you, please, elaborate why is it like that? Sorry for being annoying, but I need to explain somehow to my team why our “heavy” Spring REST endpoints can be executed in parallel (in multiple browser tabs simultaneously), the Angular synchronous UI, that uses these endpoints, also can be opened in multiple tabs in parallel, but when it comes to Vaadin UI (which uses the same Spring services), everything gets locked, regardless of the session (because tabs are being opened on different computers, so, to my understanding, separate sessions should be spawned in this case)… I have provided a Spring example above with a slow dummy endpoint, and apart from Vaadin, it can be handled in parallel, so I wonder why conceptually adding @SpringUI, that will use the same method, will be blocking? Is there some single entry-point on the edge between Vaadin and Spring that can process incoming requests only one at a time? And, if so, is there a way of paralellizing it? You have mentioned that Vaadin UIs are locked on VaadinSession, but I wonder why this session is global (per whole application instead of being per HTTP session)?

Let me explain this like I understand it (albeit simplifying a bit):

The problem is: there is a UI that is taking a really long time to respond to a request in one browser tab

A consequence of this problem is that, due to session locking, you can’t work on other tabs with the same browser on the same app either

Your proposed solution is: you should be able to keep using the other tabs, like you can with e.g. a HTML+JS app conected to stateless Spring REST services, by having some kind of mechanism that creates a new thread per request or bypasses the session locking or something.

But your proposed solution doesn’t address original problem, which is the really slow UI request in the first tab. There is a solution to this problem, which is returning from UI requests quickly and using asynchronous updates to push the results of slower operations to the browser. This is the standard approach in Vaadin applications and having a UI that’s not stuck unresponsive sounds like a good choice to me.

Why session locking in Vaadin works like it does, I honestly don’t know well enough to explain it in detail. Maybe it’s just legacy (unlikely) or maybe there’s a valid architectural reason for it. Stateful server-side UIs are not directly comparable to stateless services, after all. Could some session-lock-ignoring mode be implemented? Would it take a lot of effort? I don’t know the answer to either, but I do know that this would not fix the problem.

Now, with Vaadin 15, you will start getting features for creating stateless TypeScript views which changes things from this respect a bit, with some caveats. Again, this doesn’t change the original problem that you should not have browser tabs that lock up because the server is taking a long time to respond. That is bad UX and there’s no need to have it because you can use asynchronous updates with Push.

Also,

I wonder why this session is global (per whole application instead of being per HTTP session)?

This is just not true. If you’re experiencing your whole application locking up with one slow Vaadin request, then the problem is not with session locking.