|
JSP 2.0: The New Deal, Part 2by Hans Bergsten, author of JavaServer Pages, 3rd Edition12/03/2003 |
This article is the second in a series of articles describing the features added in the JavaServer Pages (JSP) 2.0 specification. In part one, I described the new Expression Language (EL), but there's a lot more. This installment discusses the improvements made in the area of error handling and the new deployment descriptor features. I have assumed that you're familiar with JSP 1.2 and have at least heard about the JSP Standard Tag Library (JSTL).
If you've ever tried to use a JSP error page for both JSP
and servlet errors and wanted it to display or log information about
the exception that caused the page to be invoked, you know that it's
not so easy with JSP 1.2. The reason for the difficulties is that
while both servlets and JSP pages with an errorPage
declaration pass on the exception as a request attribute, they use
different attribute names; only the exception passed on with the
JSP attribute name is automatically exposed to the JSP error page
(through the exception scripting variable and the
${pageContext.exception} EL expression).
JSP 2.0 fixes this problem by switching to the same
attribute name as the servlet specification: javax.servlet.error.exception. In addition, a new
property of the implicit EL pageContext variable, named
errorData, exposes other information about the problem.
The errorData property is an instance of the
javax.servlet.jsp.ErrorData class that can be used as
a bean with the following properties:
| Property | Java Type | Description |
|---|---|---|
requestURI |
String |
The URI for the request that failed. |
servletName |
String |
The name of the servlet or JSP page that failed. |
statusCode |
int |
The failure status code. |
throwable |
Throwable |
The exception that caused the error page to be invoked. |
Here's an example of a JSP error page that uses some of these properties:
<%@ page isErrorPage="true" contentType="text/html" %>
<%@ taglib prefix="log" uri="http://jakarta.apache.org/taglibs/log-1.0" %>
Sorry, but things didn't work out as planned. I've logged as much as
I know about the problem, so rest assured that my master will look
into what's wrong as soon as he's sober.
<jsp:useBean id="now" class="java.util.Date" />
<log:fatal>
-----
${now}
Request that failed: ${pageContext.errorData.requestURI}
Status code: ${pageContext.errorData.statusCode}
Exception: ${pageContext.errorData.throwable}
-----
</log:fatal>
This page shows the user a somewhat reassuring message and logs the details using the Apache Jakarta Taglib project's Log tag library.
You can use the <error-page> element in the
web.xml file to declare that this is as an error page for
both servlets and JSP pages:
...
<error-page>
<exception-type>java.lang.Throwable</exception-type>
<location>/error.jsp</location>
</error-page>
<error-page>
<exception-code>500</exception-code>
<location>/error.jsp</location>
</error-page>
...
If you need to use a different error page for some
specific JSP pages, you can use the page directive's
errorPage attribute to selectively override the
web.xml declaration in those pages:
<%@ page errorPage="/other_error.jsp" contentType="text/html" %>
|
Related Reading
JavaServer Pages |
A subtle but important difference between JSP 1.2 and JSP
2.0 is that JSP 2.0 requires that the JSP container support the
jsp:id feature, while this was just a recommendation in
JSP 1.2. What does this mean to you as JSP developer? It means that
you have a much better chance of getting useful error messages for
JSTL and custom tag library syntax errors.
This is how it works. When the container translates a JSP page into an executable form (a servlet class), it looks at all tag libraries declared in the page. If one or more of them include a Tag Library Validator (TLV), it gives the TLV a chance to validate the page before the container accepts it. It gives the TLV an XML View of the page to analyze. The XML View is, as the name implies, a version of the page where all regular JSP elements and the template text have been converted into a well-formed XML document. The XML View is easy for the TLV to parse to ensure that all custom actions are used correctly (e.g., that they are appropriately nested and that mutually exclusive attributes aren't used for the same action element).
This is where jsp:id comes in. The container assigns
an ID to each custom action element in the page and maintains a map
between the ID and the element's location (file, line, and column). It
adds a jsp:id attribute with this ID as the
value to all custom action elements in the XML View, so that the TLV
can read it. If the TLV finds an error, it includes the
jsp:id attribute value for the invalid action element in
the error message it returns to the container. The container can then
use its mapping and add information about the location of the faulty
custom action element to the error message it displays to you, making it
easy to find and correct the problem.
All JSTL libraries have TLVs. I strongly recommend that you develop TLVs for the custom libraries you write, and insist that the developer of any third-party library you use do the same.
If you're unfamiliar with the XML View and TLVs, I included a brief introduction in my 2001 article about JSP 1.2 ("JSP 1.2: Great News for the JSP Community").
JSP 2.0 uses the deployment descriptor (web.xml) file format defined by the servlet specification, just as in earlier versions of the JSP spec. There are, however, two important changes for JSP 2.0: the rules for the web.xml file are now defined by an XML Schema, and most of the JSP-specific configuration items have been moved to a new XML element, which is under the control of the JSP specification (to minimize the coupling between the servlet and JSP specifications).
XML Schema is an XML language for describing the syntax rules for an XML document (i.e., things like how elements can be nested, what values an element can hold, value uniqueness requirements, and a lot more). It's a complex specification, but fortunately, you don't need to understand the XML Schema rule syntax to write the web.xml file, because the servlet and JSP specifications provide easier-to-understand diagrams (my JavaServer Pages, 3rd Edition book contains easy-to-read syntax charts). If you still want to learn more about XML Schema, see the W3C web site.
The main benefit of declaring the rules with XML Schema instead of the older Document Type Definition (DTD) language that was used for previous versions is that XML Schema is more expressive, so more errors can be found when parsing of the web.xml file, hopefully resulting in better portability between containers.
Another benefit, which I'm sure you'll appreciate, is that using XML
Schema makes it easier to allow the top-level elements in the
web.xml file to be listed in any order. With previous versions
of the servlet and JSP specifications, you get an error if you, for
instance, have an <error-page> element ahead of the
<welcome-file-list> element; with new version, this
is perfectly okay. The order of the elements within a top-level
element must still be written in a strict order, though, but at least
you now have free reign over the top-level elements.
All JSP-specific elements, except the <jsp-file>
element nested within the <servlet> element, are
now grouped together under a new top-level element named
<jsp-config>. Nested within <jsp-config>, you can have
<taglib> elements with the same syntax and meaning
as in JSP 1.2, even though they are typically not needed with
containers that implement JSP 1.2 or later, because they pick up tag
library definitions automatically from all deployed JAR files.
The new <jsp-property-group> subelement is much
more interesting. This element lets you apply configuration settings
to a set of JSP pages that matches a specified URL pattern. For
instance:
...
<jsp-config>
<jsp-property-group>
<url-pattern>*.jsp</url-pattern>
<scripting-invalid>true</scripting-invalid>
</jsp-property-group>
</jsp-config>
...
The <url-pattern> element identifies the set of
JSP pages to which the configuration setting applies. The other nested
elements define the configuration options. In this example, the
<scripting-invalid> element makes it invalid to use
JSP scripting elements (i.e., Java code) in all regular JSP pages.
All in all, you can use the following configuration elements within
a <jsp-property-group> in the same way as the
<scripting-invalid> element:
| Element | Description |
|---|---|
<el-ignored> |
If set to true, EL expressions in the JSP pages
matching the URL pattern are treated as regular text instead of
as EL expressions. This is useful if you slowly migrate JSP 1.2
pages with text that looks like EL expressions to JSP 2.0. You
can use a new elIgnored page
directive attribute to selectively enable EL in the pages
you've converted to JSP 2.0.
|
<scripting-invalid> |
If set to true, using scripting elements in a JSP
page matched by the URL pattern results in translation-time
errors.
|
<page-encoding> |
The specified page encoding is used for all JSP pages matching the URL pattern. This is an alternative to specifying the page encoding in every JSP page, and is the only way to use some file encodings (like EBCDIC) for JSP pages. |
<include-coda> |
Specifies the context-relative path for a file to be
automatically included at the end of all JSP pages matching the
URL pattern. You can use multiple elements, within one
<jsp-property-group> element or across
multiple <jsp-property-group> elements.
|
<include-prelude> |
Specifies the context-relative path for a file to be
automatically included at the beginning of all JSP pages matching
the URL pattern. You can use multiple elements, within one
<jsp-property-group> element or across
multiple <jsp-property-group> elements.
|
<is-xml> |
If set to true, specifies that all JSP pages that
match the URL pattern use the JSP XML syntax (i.e., they are JSP
Documents).
|
In this installment, I've described the JSP 2.0 error-handling improvements and the new deployment descriptor features. Upcoming articles in this series will cover how JSP 2.0 makes it easier to use JSP for XML content and the new features related to custom tag libraries.
If you want to try out the new JSP 2.0 features, I recommend that you use Apache Tomcat 5, one of the first JSP containers to implement the new specification. A version labeled as "stable" can't be released until the final version of the specification is published, but the latest Beta versions have proved to be very stable, regardless of the Beta label. Tomcat 5 is available at the Jakarta Project site.
Hans Bergsten is the founder of Gefion Software and author of O'Reilly's JavaServer Pages, 3rd Edition.
Return to ONJava.com.
Copyright © 2009 O'Reilly Media, Inc.