- Mastering JavaServer Faces 2.2
- Anghel Leonard
- 555字
- 2021-12-08 12:41:30
The view scope
The view scope lives as long as you are navigating in the same JSF view in the browser window/tab.
The view scope is useful when you need to preserve data over multiple requests without leaving the current JSF view by clicking on a link, returning a different action outcome, or any other interaction that dumps the current view. It gets created upon an HTTP request and gets destroyed when you postback to a different view; as long as you postback to the same view, the view scope is alive.
Note
Notice that the view scope bean might get passivated by the container and should be capable of passivity by implementing the java.io.Serializable
interface.
Since the view scope is particularly useful when you are editing some objects while staying in the same view, it can be the perfect choice for rich AJAX requests. Moreover, since the view scope is bounded to the current view, it does not reflect the stored information in another window or tab of a browser; this is an issue specific to the session scope!
Note
In order to keep the view active, the bean methods (actions/listeners) must return null
or void
.
The view scope is not available in CDI, but JSF 2.2 has introduced it through the new annotation, @ViewScoped
. This is defined in the javax.faces.view.ViewScoped
package and it is compatible with CDI. Do not confuse this @ViewScoped
with the one defined in the javax.faces.bean
package, which is JSF compatible!
Note
The view scope annotation is @ViewScoped
and is defined in the javax.faces.view
package for CDI, and in the javax.faces.bean
package for JSF.
You can see the view scope in action by modifying the PlayersBean
scope as follows:
import java.io.Serializable; import javax.faces.view.ViewScoped; import javax.inject.Named; @Named @ViewScoped public class PlayersBean implements Serializable{ ... }
Firing multiple HTTP requests by clicking on the button labeled Get Players In Same View will reveal something like the following screenshot. Notice the action method (newPlayer
) returns void and the button doesn't contain the action
attribute, which means that you are in the same JSF view during the execution of these requests.
The other two buttons contain the action
attribute and indicate an explicit navigation, which means that the current view is changed at every request and the data is lost.
You can easily adapt PlayersBean
(and any other bean) to use the JSF version of @ViewScoped
as follows:
import java.io.Serializable; import javax.faces.bean.ManagedBean; import javax.faces.bean.ViewScoped; @ManagedBean @ViewScoped public class PlayersBean implements Serializable{ ... }
Data submitted through forms across the view scope will be available in subsequent requests as long as you are in the same view.
Note
A method annotated with @PostConstruct
will be called only when the view scoped bean is instantiated. Subsequent requests, from this view, will use this instance. As long as you are in the same view, this method will not be called again; therefore, it can be a good place to add initialization stuff specific to the current view.
The case of the CDI bean is wrapped into the application named ch3_6_1
, while the case of the JSF bean is wrapped into the application named ch3_6_2
.
Note
Starting with JSF 2.2, we can use the UIViewRoot.restoreViewScopeState(FacesContext context, Object state)
method for restoring the view scope when it is not available. This will be exemplified in Chapter 12, Facelets Templating.