|
|
|
Contents: |
|
|
|
Related content: |
|
|
|
Subscriptions: |
|
|
| Meet the hardest working objects in JSP
technology
Kyle
Gabhart (mailto:kyle@gabhart.com?cc=&subject=The
many uses of implicit objects) Consultant, Gabhart Consulting 26
August 2003
In this follow-up to last month's
introduction to session scopes, Java enterprise expert Kyle Gabhart
delves into the many uses of JSP implicit objects. Follow along as he
introduces the nine implicit objects, explains the purpose (and multiple
purposes) of each one, and closes with a list of best practices for
using these handy little workers in your JSP programming efforts. Share
your thoughts on this article or any article in the J2EE
pathfinder series in the accompanying discussion forum.
This installment of J2EE pathfinder is a follow-up to last
month's introduction
to the proper handling of session scopes. In addition to accessing
session scopes, JSP implicit objects can be used to handle HTML
parameters, forward a request to a Web component, include the content of a
component, log data through the JSP container, control the output stream,
handle exceptions, and more.
This month, you'll learn about using implicit objects in your JSP
pages. We'll start with a brief overview of the JSP architecture,
including implicit objects. After that, I'll introduce each object and
describe its core capabilities. We'll close with a list of best practices
for using each type of object and the container-managed services it
provides.
Introduction to implicit
objects The concept behind the JSP architecture is to
provide a Web component that allows developers to focus on the
presentation of Web content without getting sucked into the details of
parsing, programming, and data manipulation. JSP applications are
essentially special Web components that a J2EE Web container converts into
servlets prior to handling user requests. Within each JSP application is
the complete set of implicit objects.
Implicit objects let developers access container-provided services and
resources. These objects are defined as implicit because you do not
have to explicitly declare them. They are defined in every JSP page and
used behind the scenes by the container whether you declare them or not --
although you cannot redeclare them. Because implicit objects are
declared automatically, we need only use the reference variable associated
with a given object to begin calling methods on it.
The nine implicit objects, with a brief description of each one's
function, are:
Application is the broadest context state available. It
allows the JSP page's servlet and any Web components contained in the
same application to share information.
Config allows initialization data to be passed to a JSP
page's servlet.
Exception houses exception data to be accessed only by
designated JSP "error pages."
Out provides access to the servlet's output
stream.
Page is the instance of the JSP page's servlet
processing the current request. Not typically used by JSP page
authors.
PageContext is the context for the JSP page itself. It
provides a single API to manage the various scoped attributes. This API
is used extensively when implementing JSP custom tag handlers.
Request provides access to HTTP request data, as well
as providing a context for associating request-specific data.
Response enables direct access to the
HTTPServletResponse object and is rarely used by JSP
authors.
Session is perhaps the most commonly used of the state
management contexts. The concept of a "session" is that of a single user
interacting with a Web application over several requests.
Although some implicit objects address a single function, several of
them provide multiple categories of functionality. In the sections that
follow, we'll review implicit objects according to functional
categories:
- Session management:
application ,
session , request , pageContext
- Flow control:
application , config ,
pageContext , request , session
- Logging and exceptions:
application ,
config , exception , pageContext ,
request , session
- Input/output control:
request ,
response , out
- Initialization parameters:
config
Session management As
mentioned last month, four of the implicit objects defined for JSP pages
can be used to associate stateful data within a particular context, or
scope. Those four objects are application ,
session , request , and pageContext .
The following table identifies the four objects and the stateful context
each one defines, and also gives a brief description of what each context
entails.
Table 1. JSP state management
Implicit object |
Scope |
Description |
javax.servlet.ServletContext |
Application |
Represents the entire runtime Web module (application). Data
that is scoped to an application is shared among all the Web
components within a single application module. This is the closest
that J2EE offers to "global" data. |
javax.servlet.http.HttpSession |
Session |
Represents the current HTTP session. Next to page
scope, session scope is the most commonly used context.
This is the most commonly used context for providing a persistent,
stateful user experience spanning multiple requests. |
javax.servlet.http.HttpServletRequest |
Request |
Represents the current HTTP request. This context can span
multiple Web components (servlets and JSP pages) that are still a
part of the same atomic request. Request-specific data (request
methods, URI, HTTP parameters, and so on) provided by the client is
automatically stored in a request context. Data can
also be programmatically scoped to a request by one servlet or JSP
page to be retrieved by another within the same request
scope. |
javax.servlet.jsp.PageContext |
Page |
Represents the current JSP page's context. Because the context
for a JSP page includes the current request, session, and
application, a pageContext instance provides access to
all the namespaces associated with a JSP page. It is the default
scope for all objects, including JavaBeans components. Objects with
page scope will typically be bound to a local variable
to be accessed within scriptlets, expressions, JavaBeans tags, and
custom tags. |
From a best-practices standpoint, page scope should be
used whenever possible. It's simple, and is also the default scope for JSP
data. request scope is excellent for sharing data between
components at run time in order to process a particular request.
session scope is designed to provide a persistent, stateful
experience for a unique user, spanning multiple requests.
application scope should be used only when you need to share
data between components and across user sessions. See Resources
to learn more about session scopes.
Flow control One of
the big advantages of object-oriented design is reuse. J2EE systems, in
particular, lend themselves to a modular style of development, where
components can be rearranged, repackaged, and reused in other
applications. Even if you aren't interested in designing reusable Web
modules, you will most likely find that your J2EE applications break down
into several Web components. Any time that you use multiple servlets or
JSP pages (that is, components) to fulfill a request, you will need to use
some type of flow-control technique. The Servlet architecture provides two
such techniques: forwards and includes.
In J2EE Web development, a forward transfers control for
processing the user's request to another Web component. This can be useful
if you need one component to set up some JavaBeans, open or close
resources, authenticate the user, or otherwise perform some prep work
prior to passing control to the next component. A wide variety of tasks
can be performed prior to performing a forward, but no response headers
can be set by the forwarding component and no content can be sent to the
output buffer. All tasks directly related to sending content to the client
must be done by the component that the request is forwarded to.
The second flow control technique available in J2EE is an
include. Rather than transferring control, as you do with a
forward, the component performing the include maintains control of the
request and simply requests that the output of another component be
included at a particular point within the page. This is an excellent way
to handle common design elements such as headers, footers, and navigation
panes.
Both forwards and includes are accomplished through a special object,
java.servlet.RequestDispatcher . In order to obtain a
RequestDispatcher you simply call
getRequestDispatcher() on a ServletContext
object. There are several ways to get a reference to a
ServletContext object. We can:
- Use the implicitly declared
application variable,
because it is already of type ServletContext
- Call
getServletContext() , which will return a reference
to the implicitly declared application variable
- Call
getServletContext() on the implicitly declared
config variable
- Call
getServletContext() on the implicitly declared
pageContext variable
- Call
getServletContext() on the implicitly declared
request variable
- Call
getServletContext() on the implicitly declared
session variable
Listing 1 shows a code sample for the forward flow control mechanism,
using the implicit application variable: Listing 1. Forwarding flow control example
javax.servlet.RequestDispatcher rd;
/* Obtain a reference to a RequestDispatcher object via the implicit
application variable*/
rd = application.getRequestDispatcher( "/NextPage.jsp" );
/* Perform the forward specified by the RequestDispatcher
and pass along a reference to the current request and
response objects */
rd.forward( request, response );
|
Listing 2 shows a code example for the include flow control mechanism,
using the same application variable: Listing 2. Include flow control example
javax.servlet.RequestDispatcher rd;
/* Obtain a reference to a RequestDispatcher object via the implicit
application variable*/
rd = application.getRequestDispatcher( "/Header.jsp" );
/* Perform the include specified by the RequestDispatcher
and pass along a reference to the current request and
response objects */
rd.include( request, response );
|
Forwards and includes are excellent techniques to add to your J2EE Web
development toolbox. There are a couple of other ways to perform includes
in a JSP page, and there's also a lot of literature that addresses the
subject of J2EE design patterns that incorporate both of these techniques.
See Resources
to learn more.
Logging and
exceptions If you need to store information related to your
Web application in a log, there is one built-in method available to you.
The ServletContext interface declares two methods for passing
data to a log. One accepts a simple text message: log(
java.lang.String ) , and the other accepts exception information and
a text message: log(java.lang.Throwable, java.lang.String
) .
After both logging methods are made available through the
ServletContext interface, the key is to obtain a reference to
an object of type ServletContext . As we discussed in the
previous section on flow control objects, there are several ways to do
this. After you have a reference, simply call either of the
log() methods and pass the necessary data into the method.
Once you have done this, you will no doubt want to be able to view your
application log to view the messages. ServletContext is
simply an interface, and does not dictate how to implement the methods it
declares. Consequently, the actual implementation of the log methods is
handled by the vendor. They can store your log messages in a text file,
binary file, database, or any other format that the vendor considers
appropriate. You'll want to check your server's documentation to discover
where and how your application's log can be located.
Although sending messages to a log file can be quite useful, there are
often times when you would also like to display a user-friendly error
message in the event of an unrecoverable exception. To do this, you can
declare that your JSP page uses a separate page to handle error messages.
This is accomplished by including the following page directive anywhere in
your JSP page:
<%@ page errorPage="ErrorMessage.jsp"%>
|
Whenever an exception is thrown while processing your JSP page, the
exception object will immediately be thrown to the designated error page
by means of the implicitly declared exception variable.
In order for a JSP page to function as an error page, it must include a
directive that declares the page to be a special page designed to handle
errors, as follows:
<%@ page isErrorPage="true"%>
|
In order for the ErrorMessage.jsp page to be able to act as an error
page, this directive must appear somewhere in the page. The error page can
then display a friendly error message to the user, and then perhaps log
the relevant exception information for the system administrator to review
at a later time.
Input and output
control Because JSP pages are simply an abstraction of an
HTTP servlet, it makes sense that you would have access to the
HttpServletRequest and HttpServletResponse
objects. If you have a need for request-specific information such as the
client's browser type, content type of an HTTP post, client capabilities,
cookie data, or request parameters, simply call the appropriate method
directly on the implicitly declared request variable.
Likewise, if you need to set response headers such as browser type,
content type, content length, and so on, simply call the necessary methods
on the implicit response variable.
If you need direct access to the JSP page's output stream, it would be
tempting to call getWriter() or
getOutputStream() through the implicit response
variable. Due to the special nature of JSP pages, however, you must not do
this. If you need direct access to the output stream, you must go through
a special buffered PrintWriter object of type
javax.servlet.jsp.JSPWriter . How do you locate a reference
for such an object? The JSP container will implicitly declare one for you
and make it available through the out variable. In order to
use it, simply call out.print() or out.println()
from within a JSP scriptlet.
Typically you will not need to use the JSPWriter directly
like this, but simply place your content as plain text or through JSP
expressions, and allow the container to translate this information into
JSPWriter calls. There are, however, two cases in which you
will want to use the out variable directly. One case is when
you are defining the handler classes for a JSP custom tag, which we'll
talk about more in next month's column. The other case is when you would
like more direct control over the output that your JSP creates. If you
have a section of HTML that is littered with JSP scriptlets and
expressions, you may find it to be much cleaner and easier to create one
large JSP scriptlet and then simply use out.println()
statements whenever you want to push content out to the client.
Initialization
parameters If you have some static data that you want to
make available to your JSP page and that data does not change frequently,
initialization parameters may do the trick. Sometimes called environment
variables or "init" parameters, these parameters are specified through a
Web application's web.xml file on a per-servlet/JSP basis, and they
are read only once during the life cycle of the servlet, at initialization
time.
Listing 3 is an example of an initialization parameter
declaration: Listing 3. Initialization parameter
declaration
<webapp>
<servlet>
<servlet-name>MyServlet</servlet-name>
<servlet-class>com.gabhart.MyTestServlet</servlet-class>
<init-param>
<param-name>contactEmail</param-name>
<param-value>kyle@gabhart.com</param-value>
</init-param>
</servlet>
</webapp>
|
In order to access this parameter value, use the implicit
config variable which references the JSP page's
ServletConfig object. There are two methods available through
the ServletConfig interface for working with init parameters.
You can either perform a lookup on a particular parameter by name
(getInitParameter( java.lang.String) ), or you can retrieve an
enumeration of all the parameter names defined for the JSP page
(getInitParameterNames() ). After you have the enumeration,
you can then loop through and look up each value. All init parameters are
treated as String objects. If you need another data type such
as integer, floating point, or boolean value, you will have to parse the
string using the appropriate wrapper class.
Conclusion JSP
technology provides a very useful abstraction on top of the Servlet
architecture, letting Web designers focus more on content presentation,
and less on programming details. In this article, you've seen how implicit
objects can be used to enable faster, easier, and simpler Web development.
Next month, we'll start talking about JSP custom tags and the JSP
Standard Tag Library (JSTL). Tune in then to learn how custom tags can
facilitate the separation between presentation and business logic, while
also letting you incorporate dynamic data into the presentation layer. In
the meantime, happy pathfinding!
Resources
About the
author Kyle Gabhart is an independent consultant and subject
matter expert with J2EE, XML, and Web services technologies. Kyle is
a popular public speaker, recognized for his enthusiasm and dynamic
analysis and presentation of emerging technologies. For information
on his recent and upcoming presentations or industry publications,
visit Gabhart.com. Kyle can be reached at kyle@gabhart.com. |
|
|