Are JSF 2.x @ViewScoped managed beans thread safe?
I've been googling for a couple hours on this issue to no eval.
WELD docs and the CDI spec are pretty clear regarding thread safety of the scopes provided.
For example:
Application Scope - not safe
Session Scope - not safe
Request Scope - safe, always bound to a single thread
Conversation Scope - safe (due to the WELD proxy serializing access from multiple request threads)
I can't find anything on the View Scope defined by JSF 2.x.
It is in roughly the same bucket as the Conversation Scope in that it is very possible for multiple requests to hit the scope concurrently despite it being bound to a single view / user. What I don't know is if the JSF implementation serializes access to the bean from multiple requests.
Anyone have knowledge of the spec or of the Morr开发者_C百科aja/MyFaces implementations that could clear this up?
The view scope is with normal usage thread safe. It can be used by only one browser window/tab. Namely, it's keyed by an unique hidden input field which is set on the initial GET request. Every postback on the same view will use the one and same view scoped bean. The browser itself already "synchronizes" postback requests in the same window/tab. A new browser window/tab is effectively a new GET request and will therefore create a new and completely independent view.
As to ajax postbacks, they are by specification queued. This is mentioned in chapter 13.3.2 of the JSF 2 specification:
13.3.2 Ajax Request Queueing
All Ajax requests must be put into a client side request queue before they are sent to the server to ensure Ajax requests are processed in the order they are sent. The request that has been waiting in the queue the longest is the next request to be sent. After a request is sent, the Ajax request callback function must remove the request from the queue (also known as dequeuing). If the request completed successfully, it must be removed from the queue. If there was an error, the client must be notified, but the request must still be removed from the queue so the next request can be sent. The next request (the oldest request in the queue) must be sent. Refer to the
jsf.ajax.request
JavaScript documentation for more specifics about the Ajax request queue.
Only when using PrimeFaces, queueing can be disabled with <p:ajax async="true">
. When using this in combination with view scoped beans, threadsafety must be reconsidered the same way as for session scoped beans.
See also:
- Concurrency of @ApplicationScoped JSF managed beans
- Help me to understand JSF managed bean scope from concurrency view
- How to choose the right bean scope?
ViewScoped
beans are stored in a "view" Map
that is created for every UIViewRoot
. When two concurrent requests are processed by a JSF runtime, usually, it is unlikely that the same UIViewRoot
instance is created/restored for these requests, as the javax.faces.ViewState
form parameter in the HTTP request is used to determine whether an existing UIViewRoot
instance should be restored or not (on postback). As BalusC has indicated, two different browser windows will result in two different view scoped beans being created, as the underlying ViewStates parameters are different for both the browser tabs (if you are issuing two different HTTP requests and the browser is using the response of each to display the individual tabs, instead of using a cached copy).
The part about thread-safety however goes beyond browser tabs/windows. There is no inherent mechanism within the JSF runtime (atleast within Mojarra) that will synchronize access to the UIViewRoot
and the view map, if two HTTP requests (and hence, two threads) present the same javax.faces.ViewState
value in the request to be processed by the container. Hence, view scoped beans are not threadsafe by nature, and neither are they accessed in a thread safe manner. You could confirm this by replaying requests with the same javax.faces.ViewState
values and observe the behavior of the container/JVM when multiple such requests are received by the container in a short duration (resulting in the possibility of concurrent access to the same UIViewRoot
instance by multiple threads).
精彩评论