Closed sherter closed 2 years ago
I would appreciate if you could describe in more detail your actual use case and what kind of problem this produces to you.
However I noticed that your call stack goes thru findOrCreateVaadinSession, and in that method there was indeed a problem with locking, that could in some corner cases cause dead lock. Probably this is related. The problem has been fixed in Vaadin 8.14.0
This doesn't actually cause any problems for me (yet). I'm just trying to understand what "refreshing" means and if it could cause a problem that a thread might never see the "refreshed" values. Data races scare me, when I can't say for sure that they are not a problem 😨
If your concern is mainly concurrency with multithreaded environment, then it should be enough for you to know, that when you want to update Vaadin view or something that is "owned" by the http request thread (usual use case is that you have async data loading and updating UI when backend call has been completed), you should use ui.access(..) method to do that. ui.access(..) will wait for getting lock the session, locking the session, runs the update and frees the lock.
Check Vaadin Push training video: https://vaadin.com/learn/training/vaadin-push
And documentation: https://vaadin.com/docs/v8/framework/advanced/advanced-push
This doesn't really answer my question though. UI/VaadinSession.access()
makes the same racy read when calling getService()
. If this doesn't concern you, I guess we just have to make sure ourselves that we publish the VaadinSession
to other threads safely (i.e. ensure that the fields are non-null and establish happens-before) and then just hope that it's okay to work with potentially non-refreshed/stale values.
Thanks anyway for your help!
I guess we just have to make sure ourselves that we publish the VaadinSession to other threads
I would like to understand better what you mean by this and why you need to do it?
Maybe this example makes it a bit more clear: MyUI.java.txt
Or are you asking about the meaning of "safe publication" or "data race" in general?
Maybe this example makes it a bit more clear:
No, the code looks to me too fabricated and something that is not happening in real apps. So it does not reveal your actual use case and intention.
Why you need to publish the session to other threads? I have a feeling that you are trying to apply some design pattern that is very uncommon amongst Vaadin apps, but you are not able to clearly describe that. Thus probably you looking to this whole thing from a wrong angle.
Let me take a concrete example where you need cross-thread communication in application. Say I have separate REST end point the application, and certain calls need interaction with UI. I happen to have simplified example of this here
https://github.com/TatuLund/cdi-demo/tree/master/src/main/java/org/vaadin/cdidemo
The demo app has REST end point, where you can do GET with hello. The end point posts that as event to a event bus, which in turn is listened by main view of the application, and in case event is fired shows the hello message to the user. This app demonstrates that with sufficient separation of concern, all parties involved with this interaction are relatively agnostic to each other and e.g. no publishing of VaadinSession anywhere is needed.
(Your actual use case can be totally different, but I would assume that similar principles can and should be applied)
Side note, you do not need to override VaadinServletService in order to set session init listener, you can do it in servletInitializded directly, see
Use case: Iterate over all UI
s of a VaadinSession
and show some popup in every UI
, triggered by an external event (i.e. outside of any Vaadin request handling logic).
Are you saying that VaadinSession
is an internal API that only the framework is allowed to use? I'm not allowed to call VaadinSession#access
myself?
Use case: Iterate over all UIs of a VaadinSession and show some popup in every UI, triggered by an external event (i.e. outside of any Vaadin request handling logic).
Ok, that is actually fairly similar to what I have in the demo app, where REST module is triggering external event, which is subscribed by the view. I would recommend to use this pattern also for you.
I'm not allowed to call VaadinSession#access myself?
You can. Although there is seldomly need, as more often UI#access is used (like also in my demo app)
I wrap showing of the message in UI#access here, as the showMessage is called in event triggered in other thread (by EventBus)
I had a look at your example. If you would do the eventBus.post(event)
call asynchronously from a completely independent thread (i.e. remove the @RequestScoped
annotation from DemoEndpoint
), you would suffer from the same data race. Instead of the VaadinSession
, you capture the UI
in your eventListeners
, but ui.access()
just delegates to VaadinSession.access
, which then does the racy read of the service
field.
Then I would say you should not have real concern, as this kind of implementations are well battle proven.
session
,service
andlock
inVaadinSession
are notvolatile
and hence calling the getters from different threads without external synchronization can result in a data race (even though a comment ingetSession()
explicitly states that there is no need for having a lock when doing this.)If Vaadin is not going to prevent these data races internally, whats the recommended way to use
VaadinSession
instances from different threads? We would have to lock on the same monitor as the writes do when calling the getters, but thats kind of a chicken and egg problem then. Or is it expected to see random values (evennull
, when not published safely) when calling these getters?These races can also be detected with ThreadSanitizer, e.g.: