The request scope
The request scope is bound to the HTTP request-response life cycle.
The request scope is very useful in any web application, and an object defined in the request scope usually has a short lifespan; beans live as long as the HTTP request-response lives. When the container accepts an HTTP request from the client, the specified object is attached to the request scope and it is released when the container has finished transmitting the response to that request. A new HTTP request always comes in a new request scope object. In short, a request scope represents a user's interaction with a web application in a single HTTP request. Commonly, a request scope is useful for simple GET requests that expose some data to the user without requiring to store the data.
Note
The request scope is present in JSF and CDI and functions in the same way. It can be used for nonrich AJAX and non-AJAX requests. For JSF managed beans (@ManagedBean
), this is the default scope, when none is specified.
For example, let's suppose that we have a predefined list of tennis players, and we randomly extract them one-by-one from this list and store them in another list. The current generated player and the list of extracted players are managed bean's properties and their values are rendered in a JSF page.
Note
The request scope annotation is @RequestScoped
and is defined in the javax.enterprise.context
package for CDI, and in the javax.faces.bean
package for JSF.
The code for the CDI bean can be written as follows:
@Named @RequestScoped public class PlayersBean { final String[] players_list = {"Nadal, Rafael (ESP)","Djokovic, Novak (SRB)", "Ferrer, David (ESP)", "Murray, Andy (GBR)", "Del Potro, Juan Martin (ARG)"}; private ArrayList players = new ArrayList(); private String player; //getters and setters public void newPlayer() { int nr = new Random().nextInt(4); player = players_list[nr]; players.add(player); } }
The relevant part of the JSF page is as follows:
<h:body> Just generated: <h:outputText value="#{playersBean.player}"/><br/> List of generated players: <h:dataTable var="t" value="#{playersBean.players}"> <h:column> <h:outputText value="#{t}"/> </h:column> </h:dataTable> <h:form> <h:commandButton value="Get Players In Same View" actionListener="#{playersBean.newPlayer()}"/> <h:commandButton value="Get Players With Page Forward" actionListener="#{playersBean.newPlayer()}" action="index.xhtml"/> <h:commandButton value="Get Players With Page Redirect" actionListener="#{playersBean.newPlayer()}" action="index.xhtml?faces-redirect=true;"/> </h:form> </h:body>
When you click on the button labeled Get Players With Page Forward or Get Players In Same View, you will see something as shown in the following screenshot:
Since a request scope lives as long as the HTTP request-response lives and page forward implies a single HTTP request-response, you will see the player extracted at the current request and the list of extracted players, which will always only contain this player. The list is created for each request and filled with the current player, which makes the list useless.
Note
The request scope doesn't lose the object's state while forwarding, because the source page and the destination page (the forwarded page) are part of the same request-response cycle. This is not true in the case of redirect actions.
When you click on the button labeled Get Players With Page Redirect, you will see something as shown in the following screenshot:
The current extracted player and the list content is not available in this case, because a JSF redirect implies two requests, instead of one as in the forward case.
Programmatically, you can access the request map using the following code:
FacesContext context = FacesContext.getCurrentInstance(); Map<String, Object> requestMap = context.getExternalContext().getRequestMap();
Submitting a form defined in page 1 to page 2 via a bean, and then you have the following cases:
- If the same view or forward is used, then the data is available for display on page 2
- If redirect is used, then data will be lost and not available for display on page 2
The JSF version of the CDI beans is as follows:
import javax.faces.bean.ManagedBean; import javax.faces.bean.RequestScoped; @ManagedBean @RequestScoped public class PlayersBean { ... }
And it works the same as the CDI bean!
Note
A method annotated with @PostConstruct
will be called for each request, since each request requires a separate instance of the request scoped bean.
The case of the CDI bean is wrapped into the application named ch3_1_1
, while the case of the JSF bean is wrapped into application named ch3_1_2
.