[ Team LiB ] Previous Section Next Section

Working with the pageContext Object

The pageContext object acts as a central repository for information that a JSP might need to obtain. A pageContext is associated with the "execution" of a page, which means that it is created at the beginning of the servlet that implements a JSP and is destroyed at the end. Typically, the system initializes the built-in variables by calling a method within the pageContext object. For example, if your JSP uses the session object, the generated servlet usually contains a line such as this:


HttpSession session = pageContext.getSession();

All of the implicit objects are available through the pageContext.

In addition to providing access to built-in objects, the pageContext object has the capability to scan for attributes and attribute names among all the possible scopes (page, request, session, and application).

Finally, the pageContext object contains convenience methods that make it easy to include or forward to another servlet or JSP.

Using PageContext Enhances Portability

graphics/bytheway_icon.gif

The PageContext class was created to enhance portability between JSP environments, including an environment based upon servlets. That's why the implicit objects are obtained using the pageContext object as outlined previously. As a JSP developer, you will most often use pageContext to store or retrieve attributes or for forwarding to or including JSP pages.


Accessing the Implicit Objects

The objects associated with built-in variables (request, response, out, session, and so on) are available from the pageContext object.

The implicit objects are initialized from the following methods in pageContext:


public ServletRequest getRequest()
public ServletResponse getResponse()
public JspWriter getOut()
public HttpSession getSession()
public ServletContext getServletContext()
public ServletConfig getServletConfig()
public Object getPage()
public Throwable getException()

Accessing Attributes from the PageContext Class

The PageContext class performs double duty when it comes to storing and retrieving attributes. First, you can store attributes in an instance of a PageContext explicitly. These attributes have a page scope, meaning that the attributes are only available for use within the lifecycle of a page. Every instance of every JSP page has its own separate PageContext for storing attributes. Also, any JavaBeans you create with a page scope are stored as attributes in PageContext as well.

The methods for storing, retrieving, and removing attributes in PageContext are similar to their counterparts in ServletRequest, HttpSession, and ServletContext:


public Object getAttribute(String name)
public void setAttribute(String name, Object ob)
public void removeAttribute(String name)

The most interesting aspect of PageContext is that it gives you access to attributes in any scope by adding an extra parameter to getAttribute, setAttribute, and removeAttribute:


Public Object getAttribute(String name, int scope)
Public void setAttribute(String name, Object object,
    int scope)
public void removeAttribute(String name, int scope)

JSP 2.0: More Than Just Features

graphics/bytheway_icon.gif

The JSP 2.0 specification has brought more than just great new JSP features. It's also decoupling JSPs from servlets. JSPs are capable of standing on their own, and the authors of the specification can see that future JSP containers may elect to work with JSPs in their own environment. Consequently, there are some design changes. For example, PageContext now extends JspContext—a new class that abstracts information that is not specific to servlets. It supports SimpleTags, which you'll learn about in Hour 16, "Extending JSP with New Tags." Along with other methods, JspContext also provides the methods for working with attributes we just covered.


The scope values are defined by the PageContext constants PAGE_SCOPE, REQUEST_SCOPE, SESSION_SCOPE, and APPLICATION_SCOPE. For example, to retrieve an object from a session, you can make the following call:


Object ob = pageContext.getAttribute("myObject",
    PageContext.SESSION_SCOPE);

You can locate all the attribute names in a given scope by calling getAttributeNamesInScope:


public Enumeration getAttributeNamesInScope(int scope)

You can search through all the scopes for a particular object by calling findAttribute:


public Object findAttribute(String name)

The pageContext object first searches within the page scope, then the request scope, the session scope, and finally the application scope. The search stops at the first scope in which it finds a match. If you have an attribute named myObject stored in the request object and also in the application object, findAttribute("myObject") returns the object stored in the request object.

The getAttributesScope method returns the scope in which it finds a particular name:


public int getAttributesScope(String name)

For example, if findAttribute finds myObject in the request object, getAttributeScope returns PageContext.REQUEST_SCOPE.

Listing 8.2 shows a JSP that dumps out all the objects it can see in the various scopes.

Listing 8.2 Source Code for DumpAttributes.jsp
<%@ page import="java.util.*" %>
<html>
<body>
This page has access to the following attributes:
<pre>
<%

// Create an array of the possible scopes.
    int scopes[] = new int[] {
        PageContext.PAGE_SCOPE,
        PageContext.REQUEST_SCOPE,
        PageContext.SESSION_SCOPE,
        PageContext.APPLICATION_SCOPE };

// Create names for each possible scope.
    String scopeNames[] = new String[] {
        "Page", "Request", "Session", "Application"
    };

// Loop through the possible scopes.
    for (int i=0; i < scopes.length; i++)
    {
        out.println("In the "+scopeNames[i]+" scope:");

// Get all the attribute names for the current scope.
Enumeration e = pageContext.getAttributeNamesInScope(scopes[i]);

        while (e.hasMoreElements())
        {
// Get the attribute name.
            Object nameOb = e.nextElement();

// The name should always be a string, but just in case someone put
// some bad data somewhere, you won't get a class cast exception this way.
            if (nameOb instanceof String)
            {
// Print out the attribute name and its value.
                String name = (String) nameOb;

                out.print(name+": ");
                out.println(pageContext.getAttribute(name, scopes[i]));
            }
            else
            {
                out.println("Oops, the attribute name isn't a string! It's "+
                    nameOb.getClass().getName());
            }
        }
        out.println();
    }
%>
</pre>
</body>
</html>

Figure 8.2 shows the output from the DumpAttributes JSP.

Figure 8.2. The get AttributeNames InScope method is useful for exploring the various scope objects.

graphics/08fig02.jpg

Forwarding and Including

Often, when designing a Web application, you will want a Web resource, such as a JSP, to interact with other resources. You may want to create a page that is an aggregation of pages that include a banner, menu, main section, and footer. Or you may want to continue on to another page after making a decision based upon a request parameter.

Normally you use the <jsp:include> and <jsp:forward> tags to include or forward to other pages. You will learn about these shortly. You have already learned how to handle the case when a resource has moved and you want to redirect the client to the new location by using the sendRedirect method of HttpServletResponse.

If you want to do an include or forward in a scriptlet, you can use ServletContext.getRequestDispatcher to get the request dispatcher for the page you want to include or forward to. The request dispatcher is a little messy, however. First, you must get the dispatcher for the page you want to call and then invoke either the include or the forward method in the dispatcher.

The PageContext class gives you a useful shortcut for forward and include. You can just call forward or include and pass the name of the page you are including or are forwarding to:


public void forward(String url)
    throws IOException, ServletException
public void include(String url)
    throws IOException, ServletException

You can prevent the content of the buffer from being flushed prior to processing the include by using


public void include(String url, boolean flush)
    throws IOException, ServletException

and setting the flush parameter to false.

In Case of Trouble

graphics/bytheway_icon.gif

If you are having trouble forwarding or including, see the "Q&A" section at the end of this hour.


    [ Team LiB ] Previous Section Next Section