Mastering JavaServer Faces 2.2
上QQ阅读APP看书,第一时间看更新

The session scope

The session scope lives across multiple HTTP request-response cycles (theoretical unlimited).

The request scope is very useful in any web application when you need a single interaction per HTTP request-response cycle. However, when you need objects visible for any HTTP request-response cycle that belongs to a user session, then you need a session scope; in this case, the bean lives as long as the HTTP session lives. The session scope allows you to create and bind objects to a session. It gets created upon the first HTTP request involving this bean in the session and gets destroyed when the HTTP session is invalidated.

Note

The session scope is present in JSF and CDI and it functions the same way in both. Commonly, it is used for AJAX and non-AJAX requests that process user-specific data (such as credentials, shopping carts, and so on).

Therefore, the first HTTP request initializes the session and stores the objects, while the subsequent requests have access to these objects for further tasks. A session invalidation occurs when the browser is closed, a timeout is fired, the logout is clicked, or a programmatic subroutine forces it. Normally, each time you need to preserve data across the whole session (multiple requests and pages), the session scope is the right choice.

For example, you can add the session scope to the previous applications of this chapter for storing the list of randomly extracted players across multiple requests.

Note

The session scope annotation is @SessionScoped and is defined in the javax.enterprise.context package for CDI, and in the javax.faces.bean package for JSF.

The CDI bean is modified as follows:

import java.io.Serializable;
import javax.enterprise.context.SessionScoped;
import javax.inject.Named;

@Named
@SessionScoped
public class PlayersBean implements Serializable{
  ...
}

Alternatively, the JSF version is as follows:

import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;

@ManagedBean
@SessionScoped
public class PlayersBean implements Serializable{
  ...
}

Note

Notice that the session scope bean might get passivated by the container and should be capable of passivity, which means that the session beans should be serializable (implement the java.io.Serializable interface); refer to the capability to persist/restore session data to/from the hard disk.

The session objects lives across forward and redirect mechanisms. In the following screenshot, you can see the current extracted player and the list of extracted players after several requests belonging to the same session:

Now the list is not useless anymore! You can add methods for manipulating its content, such as order or delete.

Programmatically, you can access the session map as follows:

FacesContext context = FacesContext.getCurrentInstance();
Map<String, Object> sessionMap = context.getExternalContext().getSessionMap();

Also, you can invalidate a session as follows:

FacesContext.getCurrentInstance().getExternalContext().invalidateSession();

Obviously, data submitted through forms across the session scope will be available in subsequent requests.

Note

A method annotated with @PostConstruct will be called only once during a session, when the session bean is instantiated. Subsequent requests will use this instance, so it can be a good place to add initialization stuff.

The case of the CDI bean is wrapped into the application named ch3_2_1, while the case of the JSF bean is wrapped into the application named ch3_2_2.