Book: JavaServer Pages™, 2nd Edition
Section: Chapter 9.  Error Handling and Debugging



9.1 Dealing with Syntax Errors

The first type of error you will encounter is the one you, or your coworkers, create by simple typos; in other words, syntax errors. The JSP container needs every JSP element to be written exactly as it's defined in the specification in order to process the JSP page. When it finds something that's not right, it tells you. How easy it is to understand what it tells you depends on the type of error, the JSP container implementation, and sometimes, on how fluent you are in computer gibberish.

9.1.1 Element Syntax Errors

All container implementations report syntax errors, but details such as the wording of the messages, how much information the message contains, and where the message is written differ between them. In this chapter, I show examples only of the messages produced by Tomcat.

Let's first look at how Tomcat reports some typical syntax errors in JSP directives and action elements. Example 9-1 shows a version of the easy.jsp page from Chapter 5 with a syntax error.

Example 9-1. Improperly terminated directive (error1.jsp)
<%@ page contentType="text/html" >
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>
<html>
  <head>
    <title>JSP is Easy</title>
  </head>
  <body bgcolor="white">
  
    <h1>JSP is as easy as ...</h1>
  
    1 + 2 + 3 = <c:out value="${1 + 2 + 3}" />
  
  </body>
</html>

The syntax error here is that the page directive on the first line isn't closed properly with %>; the percent sign is missing. Figure 9-1 shows what Tomcat has to say about it.

Figure 9-1. Error message about an unterminated JSP directive
figs/Jsp2_0901.gif

Tomcat reports the error by sending an error message to the browser. This is the default behavior for Tomcat, but it's not mandated by the JSP specification. The specification requires only that a response with the HTTP status code for a severe error (500) is returned, but how a JSP container reports the details is vendor-specific. For instance, the error message can be written to a file instead of the browser. If you use a container other than Tomcat, check the container documentation to see how it reports these types of errors.

The actual error message in Figure 9-1 is what is called an exception stack trace. When something goes really wrong in a Java method, it typically throws an exception. An exception is a special Java object, and throwing an exception is the method's way of saying it doesn't know how to handle a problem. Sometimes another part of the program can take care of the problem in a graceful manner, but in many cases the best that can be done is to tell the user about it and move on. That's what the Tomcat container does when it finds a problem with a JSP page during the translation phase; it sends the exception stack trace to the browser. The stack trace contains a message about what went wrong and where the problem occurred. The message is intended to be informative enough for a user to understand, but the actual trace information is of value only to a programmer. As you can see in Figure 9-1, the message is:

/ch9/error1.jsp(0,33) Unterminated <%@ tag

The first part of the message is the name of the JSP page. The numbers within parentheses indicate on which line and character position in the file the error was found (both the line and the position are numbered from 0), and then the message states what the problem is. So this message tells us that a directive (an element starting with <%@) on the first line isn't terminated as expected at position 33. In this case it's both the correct diagnosis and the right location.

It's not always this easy to interpret the error message. Example 9-2 shows another version of easy.jsp with a different syntax error.

Example 9-2. Improperly terminated action (error2.jsp)
<%@ page contentType="text/html" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>
<html>
  <head>
    <title>JSP is Easy</title>
  </head>
  <body bgcolor="white">
  
    <h1>JSP is as easy as ...</h1>
  
    1 + 2 + 3 = <c:out value="${1 + 2 + 3}" >
  
  </body>
</html>

The syntax error here is almost the same as the "unterminated tag" in Example 9-1, but now it's the <c:out> action element that's not terminated properly (it's missing the closing slash required for an empty element). The message reported by Tomcat in this case is:

End of content reached while more parsing required: tag nesting error?

This message isn't really helpful, because the line and position information is missing, and it gives no clue about which action element is in error. The error in this case is that, since the action element doesn't have a body, a single tag ending with /> should be used, but in Example 9-2 it's terminated with just >. Because that's valid syntax for a JSP action that contains a body, the JSP container can't tell that it's a syntax error at this point. Instead, it treats it as the opening tag for an element with a body and complains that it can't find the closing tag before the file ends. The error message could be a lot more informative, for instance include the name of the action element that is missing the closing tag, and maybe even the position of the opening tag. Let's hope this is fixed in the Tomcat version you use.

Another common error is a typo in an attribute name. The value attribute for the <c:out> action is misspelled in Example 9-3.

Example 9-3. Mistyped attribute name (error3.jsp)
<%@ page contentType="text/html" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>
<html>
  <head>
    <title>JSP is Easy</title>
  </head>
  <body bgcolor="white">
  
    <h1>JSP is as easy as ...</h1>
  
    1 + 2 + 3 = <c:out valu="${1 + 2 + 3}" />
  
  </body>
</html>

Tomcat reports the problem like this:

/ch9/error3.jsp(10,16) According to the TLD attribute value is mandatory 
for tag out

In this case, the typo is in the name of a mandatory attribute, so Tomcat reports it as missing. If the typo is in the name of an optional attribute, Tomcat reports it as an invalid attribute name.

Example 9-4 shows a type of error that results in a message that is hard to figure out unless you know what's going on.

Example 9-4. Missing end quote in attribute value (error4.jsp)
<%@ page contentType="text/html" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>
<html>
  <head>
    <title>JSP is Easy</title>
  </head>
  <body bgcolor="white">
  
    <h1>JSP is as easy as ...</h1>
  
    1 + 2 + 3 = <c:out value="${1 + 2 + 3} default="Doh!" />
  
  </body>
</html>

If you look carefully at the <c:out> element, you see that the closing quote for the value attribute is missing. If another attribute is specified for the same element, like the default attribute used here, Tomcat reports the problem like this:

/ch9/error4.jsp(10,56) Attribute Doh! has no value

What's happening is that Tomcat includes everything up to the second quote as the value of the value attribute. It then assumes that the next word (Doh! in this example) is an attribute, and because it's not followed by an equal sign, it reports that it doesn't have a value.

Let's close this section with one of the most frustrating scenarios of all, namely forgetting to include a taglib directive for the tag library used in the page. This doesn't result in an error message at all, but all custom action elements are treated as template text and just added to the response without being executed. Before pulling all your hair trying to understand why none of your actions are being executed, make sure you have included the taglib directive. An easy way to see if this is the problem is to use the browser's View Source function: if the source for the response sent to the browser includes action elements, they where not processed by the web container, most likely due to a missing or incorrect taglib directive.

The examples here are the most common ones for JSP element syntax errors. Tomcat can give you pretty good information about what's wrong in most of these cases, but this is still an area where I expect many improvements to be implemented in later versions of Tomcat as well as in other JSP containers. The JSP authoring tools that emerge now may also help. By providing GUI-based interfaces that generate the action elements automatically, they can eliminate this type of syntax problem.

9.1.2 JSTL Expression Language Syntax Errors

How well JSTL EL syntax errors are reported varies between JSTL implementations and web containers, because the EL isn't yet part of the JSP specification. The JSTL Reference Implementation (RI) is doing a pretty good of job of reporting EL syntax errors. In a web container that implements an optional JSP feature (described in Chapter 21), it even includes information about the exact line and column in the JSP source file. Unfortunately, Tomcat 4 doesn't implement this feature yet, but will hopefully do so in a future version.

We look at a few EL syntax error examples in this section so you can see what to expect when you use the JSTL RI and Tomcat 4.0.4. Later versions, and other implementations may do better (or worse), but these examples illustrate what to look for.

Example 9-5 shows a page with a subtle syntax error: the curly braces are missing in the EL expression.

Example 9-5. Missing both curly braces (error5.jsp)
<%@ page contentType="text/html" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>
<html>
  <head>
    <title>JSP is Easy</title>
  </head>
  <body bgcolor="white">
  
    <h1>JSP is as easy as ...</h1>
  
    1 + 2 + 3 = <c:out value="$1 + 2 + 3" />
  
  </body>
</html>

This is an easy mistake to make, but it's not recognized as a syntax error at all. To the EL, this means that the value is a plain-text value, not an expression. When used with the <c:out> action, it's easy to figure out what's wrong because the text value is added to the response as-is instead of the being evaluated: $1 + 2 + 3. But if you make this mistake with an attribute value that should provide the action with input to process in some way, the problem may not be so easy to spot. For instance, if you forget the curly braces for the <c:forEach> items attribute, it takes it as a text value and loops once over its body with the text as a single element.

Let's see what happens if you forget only the end curly brace, as shown in Example 9-6.

Example 9-6. Missing end curly brace (error6.jsp)
<%@ page contentType="text/html" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>
<html>
  <head>
    <title>JSP is Easy</title>
  </head>
  <body bgcolor="white">
  
    <h1>JSP is as easy as ...</h1>
  
    1 + 2 + 3 = <c:out value="${1 + 2 + 3" />
  
  </body>
</html>

Tomcat 4 and the JSTL RI report this error as shown in Figure 9-2.

Figure 9-2. JSTL EL syntax error message
figs/Jsp2_0902.gif

The error message is produced by the JSTL RI translation-phase validator and contains four pieces of information:

  • The action name:

     tag = 'out'
  • The attribute name:

    attribute = 'value'
  • A generic message that includes the complete EL expression:

    An error occurred while parsing custom action attribute "value" with value "${1 + 2 + 3"
  • A more detailed message about the problem:

     Encountered "", expected one of ..."). 

This isn't so bad. The first three pieces of information make it fairly easy to find the attribute value that's in error. And the fourth message; well, it makes more and more sense when you've seen messages like this a few times. What's missing is the actual line number for the error. Hopefully Tomcat will implement the optional feature I mentioned earlier in a future version, so that the error location can also be included in the report.

Figure 9-2 is a good example of how all true syntax errors are reported by the JSTL RI (only the detailed messages differ), but some types of errors can't be found until the request-time phase, even though they may be regarded as syntax errors. Example 9-7 illustrates one such case.

Example 9-7. Misspelled property name (error7.jsp)
<%@ page contentType="text/html" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>
<html>
  <head>
    <title>Looking for information</title>
  </head>
  <body bgcolor="white">
  
    <h1>Looking for information</h1>
  
    The Current URI: <c:out value="${pageContext.request.requestUri}" />
  
  </body>
</html>

The problem here is that the property name is misspelled: it should be requestURI ("URI" in all caps) instead of requestUri. In this particular example, the EL could actually figure this out at translation time, because pageContext is an implicit variable, so all its properties are known. But the type of an application variable is known only at request time, so it's not possible to notice a misspelled property name for the general case. The JSTL RI has opted for consistency in how to handle this type of error. The way this error is reported is by throwing an exception with this message:

An error occurred while evaluating custom action attribute "value" with 
value "${pageContext.request.requestUri}": Unable to find a value for
"requestUri" in object of class "org.apache.catalina.connector.HttpRequestFacade" 
using operator "."

It contains enough details about the error, such as the attribute name and value, to make it feasible to match it with its source in the page. Because it's not caught until request time, it's unfortunately impossible to include the line number in a JSP 1.2 container.

Example 9-8 shows an almost identical error, but it results in a completely different result.

Example 9-8. Misspelled parameter name (error8.jsp)
<%@ page contentType="text/html" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>
<html>
  <head>
    <title>Looking for information</title>
  </head>
  <body bgcolor="white">
  
    <h1>Looking for information</h1>
  
    The missing parameter: <c:out value="${param.misspelled}" />
  
  </body>
</html>

Here it's the name of a request parameter that is misspelled, and it's not reported as an error. Instead the expression evaluates to null, which the <c:out> action converts to an empty string. This is by design, and it makes it easier to handle the typical case in which a missing parameter should be handled the same as a parameter with an empty string as the value. If a missing parameter resulted in an exception, you would have to do a lot more testing in all JSP pages, with <c:if> actions and expressions like this all over the place:

<c:if test="${!empty param.someParam}">
  <!-- Here it's safe to use the parameter -->
</c:if>

The downside is that it makes it harder to find parameter-name spelling errors. The EL handles all types of name/value pair collections, such as the implicit variables representing scopes (pageScope, requestScope, sessionScope, and applicationScope) as well as any application variable of type java.util.Map, the same way.

    [http://safari.oreilly.com/059600317X/jserverpages2-CHP-9-SECT-1]


    Copyright © 2002 O'Reilly & Associates, Inc. All rights reserved.
    1005 Gravenstein Highway North
    Sebastopol, CA 95472