Chapter 8. Handling Errors

Today you'll see how to handle the case when things don't go as planned. Errors are a fact of life for most programmers (perhaps not for you if you write perfect code, but for most programmers!) and both Java and JSP offer you a number of ways of dealing with them. There are two main kinds of errors—syntax and runtime, and you'll see how to handle both of them today:

  • Syntax errors are just what they sound like—errors in Java and JSP syntax. These are handled before your application is even released.

  • Runtime errors are harder to deal with. Here, your application is fine as far as syntax goes, but there is some problem with the code's logic, and an error occurs as the user is running your application.

Because you handle syntax errors before your code is even released, today's work is going to concentrate on runtime errors. Here are the topics you'll see:

  • Understanding runtime error messages from Tomcat

  • Understanding Java exceptions

  • Getting exception messages from exception objects

  • Handling exceptions with try/catch blocks

  • Handling specific exception types

  • Printing error messages on the server console

  • Throwing exceptions from methods

  • Nesting try/catch statements

  • Creating custom exception objects

  • Setting request object attributes

Error handling isn't the most glamorous topic, but it's an essential one to master—if your application crashes right before the user's eyes, that doesn't seem very professional. Handling errors is one of the aspects of real-world JSP programming that you need to have in your programming arsenal.

So that's the program—today's discussion starts with syntax errors and then moves on to runtime errors. It all starts with syntax errors.

Syntax Errors

Syntax errors are those errors that will stop Java or JSP from even running your code. Some of these are obvious (such as misspellings like out.prinbln("Hello!")), and some are not so obvious. For an example of the not-so-obvious kind, take a look at Listing 8.1. It's Listing 3.21 (ch03_21.jsp) from Day 3, “Branching, Looping, and Creating Methods,” with a subtle error introduced into the code. Can you find the error?

Example 8.1. Reading a Cookie (ch08_01.jsp)

<HTML>
  <HEAD>
    <TITLE>Passing Arrays to Methods</TITLE>
  </HEAD>

  <BODY>
    <H1>Passing Arrays to Methods</H1>
    <%!
    void doubler(int a)
    {
        for (int loopIndex = 0; loopIndex < a.length;
            loopIndex++) {
            a[loopIndex] *= 2;
        }
    }
    %>

    <%
        int array[] = {1, 2, 3, 4, 5};

        out.println("Before the call to doubler...<BR>");
        for (int loopIndex = 0; loopIndex < array.length;
            loopIndex++) {
            out.println("array[" + loopIndex + "] = " +
                array[loopIndex] + "<BR>");
        }

        doubler(array);

        out.println("After the call to doubler...<BR>");
        for (int loopIndex = 0; loopIndex < array.length;
            loopIndex++) {
            out.println("array[" + loopIndex + "] = " +
                array[loopIndex] + "<BR>");
        }
    %>
  </BODY>
</HTML>

Even if you don't see the error in Listing 8.1, Java will. You can see what happens when you try to take a look at this page in Tomcat in Figure 8.1.

A Tomcat error page.

Figure 8.1. A Tomcat error page.

As you can see by the bold message Apache Tomcat/4.0.3 - HTTP Status 500 - Internal Server Error in Figure 8.1, Tomcat is unhappy with the code in this example (this error message is a familiar one to nearly all JSP programmers).

Tomcat gives us a great deal of information about what the syntax error was, if you scroll down the error page. Here's an excerpt:

org.apache.jasper.JasperException: Unable to compile class for JSP 

An error occurred between lines: 8 and 16 in the jsp file: /ch08_01.jsp

Generated servlet error:
D:	omcatjakarta-tomcat-4.0.3worklocalhostch08ch08_0005f01$jsp.java:15: Attempt to
reference field length in a int.
                for (int loopIndex = 0; loopIndex < a.length;
                                                     ^


An error occurred between lines: 8 and 16 in the jsp file: /ch08_01.jsp

Generated servlet error:
D:	omcatjakarta-tomcat-4.0.3worklocalhostch08ch08_0005f01$jsp.java:17:
[] can only be applied to arrays. It can't be applied to int.
                    a[loopIndex] *= 2;
                     ^


An error occurred between lines: 18 and 36 in the jsp file: /ch08_01.jsp

Generated servlet error:
D:	omcatjakarta-tomcat-4.0.3worklocalhostch08ch08_0005f01$jsp.java:83:
Incompatible type for method. Can't convert int[] to int.
                        doubler(array);
                                ^
3 errors

    at org.apache.jasper.compiler.Compiler.compile(Compiler.java:285)
    at org.apache.jasper.servlet.JspServlet.loadJSP(JspServlet.java:552)
    at org.apache.jasper.servlet.JspServlet$JspServletWrapper.loadIfNecessary (JspServlet
A Tomcat error page..java:177)
    at org.apache.jasper.servlet.JspServlet$JspServletWrapper.service (JspServlet.java:189)
    at org.apache.jasper.servlet.JspServlet.serviceJspFile (JspServlet.java:382)
    at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:474)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:853)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter 
A Tomcat error page.(ApplicationFilterChain.java:247)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter (ApplicationFilterChain
A Tomcat error page..java:193)
    at org.apache.catalina.core.StandardWrapperValve.invoke (StandardWrapperValve.java:243)
    at org.apache.catalina.core.StandardPipeline.invokeNext (StandardPipeline.java:566)
        .
        .
        .

At the top of this error report, you see the message org.apache.jasper.JasperException: Unable to compile class for JSP. Jasper is Tomcat's internal class for turning your JSP pages into servlets, so we know that there was a problem compiling the code into Java for use as a servlet.

Looking underneath this message, you see three error messages, which are shaded. The third error message says Incompatible type for method. Can't convert int[] to int., and refers you to this line of code:

doubler(array); 

This line occurs in Listing 8.1 where the code has created an array, and is passing that array to the doubler method, which is supposed to double each element in the array:

int array[] = {1, 2, 3, 4, 5}; 
    .
    .
    .
doubler(array);

What could be the problem with that? A quick look at the doubler method lets you know what the problem is—the argument passed to that method is mistakenly declared to be a simple integer, not an integer array:

void doubler(int a) 
{
    for (int loopIndex = 0; loopIndex < a.length;
        loopIndex++) {
        a[loopIndex] *= 2;
    }
}

When you fix this problem by changing this line to void doubler(int[] a), all works as it should. In this way, Tomcat pointed out the syntax error and made it relatively easy to fix.

You can also run into syntax errors when writing JavaBeans, of course. There, you'd see error messages from the Java compiler javac that would let you know what's going on.

In this way, you'll get feedback on syntax errors. However, the next kind of error, runtime errors, are harder to handle because they only occur when your application is running.

Runtime Errors

Take a look at the JSP page in Listing 8.2. This code calmly divides a number by zero, which is going to cause a numeric problem.

Example 8.2. Causing a Runtime Error (ch08_02.jsp)

<HTML>
    <HEAD>
        <TITLE>Causing a Runtime Error</TITLE>
    </HEAD>

    <BODY>
        <H1>Causing a Runtime Error</H1>
        <%
            int int1 = 1;
            int1 = int1 / 0;
            out.println("The answer is " + int1);
        %>
    </BODY>
</HTML>

You can see the results of this page in Figure 8.2, where Tomcat is indeed reporting a runtime error.

A runtime error.

Figure 8.2. A runtime error.

A runtime error.

Exceptions

Knowing Java, you might guess that exceptions are handled with a new class, and you'd be right. The class that handles exceptions is the Java Exception class (including its package name, it's the java.lang.Exception class), and it's based on the Throwable class (java.lang.Throwable). We'll get familiar with both classes today.

The Throwable class holds a sort of snapshot of what was going on in the code when the exception occurred. It can also contain a message string that gives more information about the error. You can see its methods in Table 8.1. Note especially the getMessage method, which returns a String object holding an error message that you can display to the user.

Table 8.1. The Methods of the java.lang.Throwable Class

Method

Does This

Throwable()

Constructs a new Throwable object.

Throwable(String message)

Constructs a new Throwable object with the given error message.

String getLocalizedMessage()

Creates a localized description of this object.

String getMessage()

Returns the error message string of this Throwable object.

void printStackTrace()

Prints this Throwable object and its stack trace to the server console.

void printStackTrace(PrintStream s)

Prints this object and its stack trace to the server console.

void printStackTrace(PrintWriter s)

Prints this object and its stack trace to the given print writer object.

String toString()

Returns a description of this Throwable object.

The Exception class is based on the Throwable class, and it's the one you normally use to work with exceptions. Because it's based on the Throwable class, it also includes all the methods of the Throwable class. You can see the methods of the Exception class in Table 8.2.

Table 8.2. The Methods of the java.lang.Exception Class

Method

Does This

Exception()

Constructs an Exception object.

Exception(String s)

Constructs an Exception object with the given error message.

So how do you use Exception objects? You use Java try/catch blocks, and that's the next topic.

Using try/catch Blocks

Java supports both a try statement and a catch statement to handle exceptions. Here's how you use a try/catch block in general:

try { 
    // Sensitive code
}
catch (Exception1Type e1) {
    // Handle exception1 type
}
catch (Exception1Type e1) {
    // Handle exception1 type
}
    .
    .
    .
[finally {
    // Code to be executed before try block ends
}]

When some sensitive code inside a try block throws an exception, you can catch it with a catch block. You can also use a finally block to execute code after the try/catch block is complete, and the code in the finally block will be executed whether or not an exception occurred. You can use a finally block to handle exceptions not explicitly caught in a catch block. The finally block is optional, as is the catch block—but note that one or the other must be specified.

Here's an example to make this clearer. This code will surround the earlier code that divided by zero in a try/catch block. If an exception occurs, it is passed to the catch block just like passing an argument to a method, and here the exception object will be named e. This page displays a message in the catch block, using the exception object's getMessage method, as you can see in Listing 8.3.

Example 8.3. Using a try/catch Block (ch08_03.jsp)

<HTML>
    <HEAD>
        <TITLE>Using a try/catch Block</TITLE>
    </HEAD>

    <BODY>
        <H1>Using a try/catch Block</H1>
    <%
        try{
            int int1 = 1;
            int1 = int1 / 0;
            out.println("The answer is " + int1);
        }
        catch (Exception e){
            out.println("An exception occurred: " + e.getMessage());
        }
    %>
    </BODY>
</HTML>

You can see this page at work in Figure 8.3, where again you see the terse message / by zero (you'll see how to make this message more readable in a few pages).

Catching an exception.

Figure 8.3. Catching an exception.

Now you've been able to handle an exception. Even though the message displayed is very terse, it's better than the Tomcat error page you saw in Figure 8.2. Besides the getMessage method of an Exception object, you can also simply call out.println with the Exception object itself, as you see in Listing 8.4. As with all Java objects, doing so calls the object's toString method, which results in a slightly different exception message as you see in Figure 8.4.

Using an Exception object's toString method.

Figure 8.4. Using an Exception object's toString method.

Example 8.4. Using the Exception Object (ch08_04.jsp)

<HTML>
    <HEAD>
        <TITLE>Using a try/catch Block</TITLE>
    </HEAD>

    <BODY>
        <H1>Using a try/catch Block</H1>
    <%
        try{
            int int1 = 1;
            int1 = int1 / 0;
            out.println("The answer is " + int1);
        }
        catch (Exception e){
            out.println("An exception occurred: " + e);
        }
    %>
    </BODY>
</HTML>

Note in Figure 8.4 that this error message specifies what looks like a Java class—java.lang.ArithmeticException. What's that all about?

Handling Specific Exception Types

There are many, many different types of exceptions in Java, and they're all based on the Java Exception class. To handle specific problems, you can work with specific types of exceptions. The following is a list of some of the most common exception classes:

  • AclNotFoundException

  • ActivationException

  • AlreadyBoundException

  • ApplicationException

  • ArithmeticException

  • ArrayIndexOutOfBoundsException

  • AWTException

  • BadLocationException

  • ClassNotFoundException

  • CloneNotSupportedException

  • DataFormatException

  • ExpandVetoException

  • FileException

  • GeneralSecurityException

  • IllegalAccessException

  • InstantiationException

  • InterruptedException

  • IntrospectionException

  • InvocationTargetException

  • IOException

  • LastOwnerException

  • NoninvertibleTransformException

  • NoSuchFieldException

  • NoSuchMethodException

  • NotBoundException

  • NotOwnerException

  • ParseException

  • PrinterException

  • PrivilegedActionException

  • PropertyVetoException

  • RemarshalException

  • RuntimeException

  • ServerNotActiveException

  • SQLException

  • TooManyListenersException

  • UnsupportedFlavorException

  • UnsupportedLookAndFeelException

  • UserException

You can catch any type of exception by specifying the Exception object in a catch block, but you can also be more selective by specifying a particular type of exception—such as one from the previous list—to catch. Here is one example of catching an exception—in this case, the code catches an array-out-of-bounds exception using the appropriately named ArrayIndexOutOfBoundsException class:

try { 
    .
    .
    .
} catch (ArrayIndexOutOfBoundsException e) {
    out.println("Array index out of bounds");
}

You can see this code at work in Listing 8.5, where the code creates an array of 100 elements—array[0] to array[99]—and then tries to assign a value to the nonexistent element array[100], which Java isn't going to like.

Example 8.5. Catching an ArrayIndexOutOfBoundsException Exception (ch08_05.jsp)

<HTML>
    <HEAD>
        <TITLE>Catching an ArrayIndexOutOfBoundsException Exception</TITLE>
    </HEAD>
    <BODY>
        <H1>Catching an ArrayIndexOutOfBoundsException Exception</H1>
    <%
    try {
        int array[] = new int[100];
        array[100] = 100;
    } catch (ArrayIndexOutOfBoundsException e) {
        out.println("Array index out of bounds.");
    }
    %>
    </BODY>
</HTML>

You can see this page in Figure 8.5, where the code is catching an ArrayIndexOutOfBoundsException exception.

Catching an ArrayIndexOutOfBoundsException exception.

Figure 8.5. Catching an ArrayIndexOutOfBoundsException exception.

As you see, it's possible to catch specific exceptions by specifying the class of exception you want to catch. In fact, you can do more—you can catch multiple exceptions by specifying their type, which is what's coming up next.

Catching Multiple Exceptions

Now that you know you can catch exceptions of specific types, it's important to know that you can use multiple catch blocks in the same try/catch statement. One catch block can handle one type of exception, another can handle another, and so on, making for very specific error handlers.

You can see an example of this in Listing 8.6, where the code catches array-index-out-of-bounds exceptions if there were any, and if not, checks for arithmetic exceptions. If neither one of those exceptions occurred, the catch block that catches any Exception objects will catch any other type of exception, letting you pick out the exceptions you want to specifically handle, but also to provide general error-handling code for any other exception. It's a great advantage that Java enables you to do this—not only does your code not bomb in front of the user, but by knowing what went wrong, you can take specific action to fix it.

Tip

If an exception occurs and Java can't find a catch block in your code to handle it, it will use its default exception handler—which in Tomcat will display an error page.

Example 8.6. Catching Multiple Exceptions (ch08_06.jsp)

<HTML>
    <HEAD>
        <TITLE>Catching an ArrayIndexOutOfBoundsException Exception</TITLE>
    </HEAD>
    <BODY>
        <H1>Catching an ArrayIndexOutOfBoundsException Exception</H1>
    <%
    try {
        int array[] = new int[100];
        array[100] = 100;
    } catch (ArrayIndexOutOfBoundsException e) {
        out.println("Array index out of bounds.");
    } catch(ArithmeticException e) {
        out.println("Arithmetic exception: " + e);
    } catch(Exception e) {
        out.println("An error occurred: " + e);
    }
    %>
    </BODY>
</HTML>

Besides using multiple catch statements, you can also nest try/catch statements.

Nesting try/catch Statements

You can nest try blocks inside other try blocks, and if one try block doesn't have a corresponding catch block that handles an exception, Java will search the next outer try block for a catch block that will handle the exception, back through successive nestings. If Java can't find a catch block for the exception, it will pass the exception to its default exception handler. You can see an example of nested try blocks in Listing 8.7.

Example 8.7. Nesting try/catch Statements (ch08_07.jsp)

<HTML>
    <HEAD>
        <TITLE>Nesting try/catch Statements</TITLE>
    </HEAD>

    <BODY>
        <H1>Nesting try/catch Statements</H1>
        <%
        try {
            try {
                int c[] = {0, 1, 2, 3};
                c[4] = 4;
            } catch(ArrayIndexOutOfBoundsException e) {
                out.println("Array index out of bounds: " + e);
            }

        } catch(ArithmeticException e) {
            out.println("Divide by zero: " + e);
        }
        %>
    </BODY>
</HTML>

You can see this page at work in Figure 8.6.

Using nested try/catch statements.

Figure 8.6. Using nested try/catch statements.

Using nested try/catch statements.

Throwing Exceptions Yourself

Say that some error condition happens that Java doesn't want to treat as an exception—but you do. In that case, you can cause a Java exception by throwing an Exception object. You can throw your own exceptions with the throw statement. You can see an example in Listing 8.8. In this case, the code throws an exception that will be caught in a catch block, which displays a message. Note that when you create an Exception object, like the ArithmeticException object created here, you can pass text to the object's constructor to specify the error message it will contain.

Example 8.8. Throwing an Exception (ch08_08.jsp)

<HTML>
    <HEAD>
        <TITLE>Throwing an Exception</TITLE>
    </HEAD>

    <BODY>
        <H1>Throwing an Exception</H1>
        <%
        try {
            throw new ArithmeticException("Math Exception!");
        } catch(ArithmeticException e) {
            out.println("Exception message: " + e);
        }
        %>
    </BODY>
</HTML>

Tip

Throwing exceptions is a good idea if you don't want to handle an exception in a certain exception handler—when you throw the exception, Java looks for an enclosing or following catch statement for the exception. And as we're about to see, you can throw an exception in a method that is handled in the code that called the method, which is good if you don't want to place all your exception-handling code in the method itself.

Throwing Exceptions from Methods

You might remember that in Day 3, you saw this code to pass the out object to a method:

<HTML> 
  <HEAD>
    <TITLE>Passing the out Object to a Method</TITLE>
  </HEAD>

  <BODY>
    <H1>Passing the out Object to a Method</H1>
    <%!
    void printem(javax.servlet.jsp.JspWriter out) throws java.io.IOException
    {
        out.println("Hello from JSP!");
    }
    %>
    <%
        printem(out);
    %>
  </BODY>
</HTML>

This code passed the out object to the printem method. The out object is a complex and large one, and it can throw objects of the java.io.IOException class (which, as you can guess from its name, handles I/O exceptions). Java noticed that the code had no way of handling this exception if it was thrown, and will insist that you handle it (and will cause a syntax error otherwise). This code handled the error simply by adding a throws clause to the method definition.

In practice, that means that if an exception occurred, it would be passed to Java's default exception handler, and the user would be left looking at an error page. On the other hand, you can handle exceptions that occur in a called method in the calling code.

For example, say you have a method, doWork, that causes an ArrayIndexOutOfBoundsException:

<%! 
    void doWork() throws ArrayIndexOutOfBoundsException
    {
        int array[] = new int[100];
        array[100] = 100;
    }
%>

You can handle this exception by calling doWork from inside a try block, and handling the error in a catch block this way:

<% 
    try {
        doWork();
    } catch (ArrayIndexOutOfBoundsException e) {
        out.println("Array out of bounds exception");
    }
%>

You can see this code in a sample Web page in Listing 8.9.

Example 8.9. Reading a Cookie (ch08_09.jsp)

<HTML>
    <HEAD>
        <TITLE>Throwing Exceptions From Methods</TITLE>
    </HEAD>

    <BODY>
        <H1>Throwing Exceptions From Methods</H1>
        <%!
            void doWork() throws ArrayIndexOutOfBoundsException
            {
                int array[] = new int[100];
                array[100] = 100;
            }
        %>

        <%
            try {
                doWork();
            } catch (ArrayIndexOutOfBoundsException e) {
                out.println("Array out of bounds exception");
            }
        %>
    </BODY>
</HTML>

You can see this page at work in Figure 8.7, where the exception thrown in the doWork method was caught back in the calling code.

Throwing exceptions from methods.

Figure 8.7. Throwing exceptions from methods.

Note that you don't have to throw any of the predefined Java exceptions—you can define your own exceptions.

Creating a Custom Exception Object

You can create your own exception classes by basing them on the Exception class. You haven't seen how that works in this book yet—it's coming up in Day 11, “Creating More Powerful JavaBeans”—but it's worth getting a preview here.

Creating a Custom Exception Object
class NewException extends Exception 
{
        .
        .
        .
}

As you'll see in Day 11, this gives the NewException class the functionality of the Exception class. To customize this new class, you can provide a constructor and a new version of the methods you plan to use, like getMessage or toString. Here's what that looks like—the toString method is called automatically if you pass an object of this class to out.println:

class NewException extends Exception 
{
    int value;

    public String toString()
    {
        return "NewException " + value;
    }

    NewException(int v)
    {
        value = v;
    }
}

You can see this class at work in Listing 8.10 in a method called doWork—if the value passed to that method is 0, doWork will throw an exception of the NewException class, which is caught in the calling code, and the error message is displayed.

Example 8.10. Creating a Custom Exception Object (ch08_10.jsp)

<HTML>
    <HEAD>
        <TITLE>Creating a Custom Exception Object</TITLE>
    </HEAD>

    <BODY>
        <H1>Creating a Custom Exception Object</H1>
        <%!
            class NewException extends Exception
            {
                int value;

                public String toString()
                {
                    return "NewException " + value;
                }

                NewException(int v)
                {
                    value = v;
                }
            }

            void doWork(int value) throws NewException
            {
                if(value == 0){
                    throw new NewException(value);
            }
        }
    %>

    <%
        try {
            doWork(3);
            doWork(2);
            doWork(1);
            doWork(0);
        }
        catch (NewException e) {
            out.println("Exception: " + e);
        }
    %>
    </BODY>
</HTML>

You can see this code at work in Figure 8.8—now you've created and caught a custom exception.

Catching a custom exception.

Figure 8.8. Catching a custom exception.

Printing to the Server Console

Here's another technique to know that's helpful in handling errors—you can send text directly to the server console. For example, in Windows, that's the DOS session that opens when you start Tomcat. To do so, you use the System.out.println method instead of out.println.

You can see an example using the System.out.println method in Listing 8.11, where the code sends an exception's error message to the server console if an exception occurs (and the code makes sure one does).

Example 8.11. Printing to the Server Console (ch08_11.jsp)

<HTML>
    <HEAD>
        <TITLE>Printing to the Server Console</TITLE>
    </HEAD>

    <BODY>
        <H1>Printing to the Server Console</H1>
        <%
            try{
                int value = 1;
                value = value / 0;
            }
            catch (Exception e){
                System.out.println(e.getMessage());
            }
        %>
    </BODY>
</HTML>

You can see the results in the server console in Windows in Figure 8.9, where the terse Java error message / by zero appears.

Writing to the server console.

Figure 8.9. Writing to the server console.

Note that displaying text on the server console isn't just useful for handling errors—you can send any type of message to the console you like.

Writing to the server console.

Example 8.12. Printing a Stack Trace to the Server Console (ch08_12.jsp)

<HTML>
    <HEAD>
        <TITLE>Printing a Stack Trace to the Server Console</TITLE>
    </HEAD>

    <BODY>
        <H1>Printing a Stack Trace to the Server Console</H1>
        <%
            try{
                int value = 1;
                value = value / 0;
            }
            catch (Exception e){
                e.printStackTrace();
            }
        %>
    </BODY>
</HTML>

In fact, you can see what a stack trace looks like in the next topic, where you'll learn how to use Tomcat log files.

Using Log Files

Tomcat itself keeps track of the errors that occur, but it can be hard to find out where tracking information goes. Here's an example of tracking down the error-tracking files. Tomcat comes with a number of examples in its examples directory (http://localhost:8080/examples/), and it makes provision for handling errors created by those examples. To find out how the error logging works, take a look at the server.xml file in the jakarta-tomcat-4.0.3conf directory. You'll find a section like the following in that file, which indicates how to handle logging for errors in the examples:

<!-- Tomcat Examples Context --> 
<Context path="/examples" docBase="examples" debug="0"
    reloadable="true" crossContext="true">
<Logger className="org.apache.catalina.logger.FileLogger"
    prefix="localhost_examples_log." suffix=".txt"
    timestamp="true"/>

From this, you learn that log files for errors in the example directory will go into files with names like (note that the filename includes the date) localhost_examples_log.2003-03-29.txt. The following is the kind of data you'll find in such a log file, where the code has thrown an arithmetic divide-by-zero exception—the rest of this data is a stack trace, showing what methods Java called to get to the error-causing code:

2003-05-10 10:54:22 StandardWrapperValve[jsp]: Servlet.service() for servlet jsp threw
Using Log Files exception
java.lang.ArithmeticException: / by zero
    at org.apache.jsp.simple_0005ferror$jsp._jspService(simple_0005ferror$jsp. java:60)
    at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:107)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:853)
    at org.apache.jasper.servlet.JspServlet$JspServletWrapper. service(JspServlet.java
Using Log Files:202)
    at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet. java:382)
    at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:474)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:853)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter  
Using Log Files(ApplicationFilterChain.java:247)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter  (ApplicationFilterChain
Using Log Files.java:193)
    at org.apache.catalina.core.StandardWrapperValve.invoke  (StandardWrapperValve.java:243)
    at org.apache.catalina.core.StandardPipeline.invokeNext(StandardPipeline. java:566)
    at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline. java:472)
    at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:943)
    at org.apache.catalina.core.StandardContextValve.invoke  (StandardContextValve.java:190)
    at org.apache.catalina.core.StandardPipeline.invokeNext(StandardPipeline. java:566)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke  (AuthenticatorBase.java
Using Log Files:475)
    at org.apache.catalina.core.StandardPipeline.invokeNext(StandardPipeline. java:564)
    at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline. java:472)
    at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:943)
    at org.apache.catalina.core.StandardContext.invoke(StandardContext. java:2343)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve. java:180)
    at org.apache.catalina.core.StandardPipeline.invokeNext(StandardPipeline. java:566)
    at org.apache.catalina.valves.ErrorDispatcherValve.invoke  (ErrorDispatcherValve.java
Using Log Files:170)
    at org.apache.catalina.core.StandardPipeline.invokeNext(StandardPipeline. java:564)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve. java:170)
    at org.apache.catalina.core.StandardPipeline.invokeNext(StandardPipeline. java:564)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve. java:468)
    at org.apache.catalina.core.StandardPipeline.invokeNext(StandardPipeline. java:564)
    at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline. java:472)
    at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:943)
    at org.apache.catalina.core.StandardEngineValve.invoke  (StandardEngineValve.java:174)
    at org.apache.catalina.core.StandardPipeline.invokeNext(StandardPipeline. java:566)
    at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline. java:472)
    at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:943)
    at org.apache.catalina.connector.http.HttpProcessor.process(HttpProcessor. java:1012)
    at org.apache.catalina.connector.http.HttpProcessor.run(HttpProcessor. java:1107)
    at java.lang.Thread.run(Thread.java:484)

2002-05-10 10:56:13 SessionListener: contextDestroyed()
2002-05-10 10:56:13 ContextListener: contextDestroyed()

Using JSP Error Pages

Using JSP Error Pages

Example 8.13. Using an Error Page (ch08_13.jsp)

<%@ page errorPage="ch08_14.jsp" %>
<HTML>
    <HEAD>
        <TITLE>Using an Error Page</TITLE>
    </HEAD>

    <BODY>
        <H1>Using an Error Page</H1>
        <%
            int value = 1;
            value = value / 0;
        %>
    </BODY>
</HTML>

You can see the error page itself in Listing 8.14. Note that you can specify that a page is an error page by setting the page directive's isErrorPage attribute to "true" (the default is "false").

Example 8.14. An Error Page (ch08_14.jsp)

<%@ page isErrorPage="true" %>
<HTML>
    <HEAD>
        <TITLE>An Error Page</TITLE>
    </HEAD>

    <BODY>
        <H1>An Error Page</H1>
        There was an error! Don't Panic!!!
        <BR>
        Consult your physician immediately.
    </BODY>
</HTML>

You can see the results in Figure 8.10. As soon as you load ch08_13.jsp, an error occurs because of the division by zero in the JSP code. That makes Tomcat display the error page, as you see in Figure 8.10.

Using an error page.

Figure 8.10. Using an error page.

The text in the error page you see in Figure 8.10 is not very specific—but it turns out that you can get more information on the error.

Using JSP Error Pages: The exception Object

The HTTP request sent to the original page is forwarded to the error page, and you have access to it in the error page as the request object. In addition, you have access to the built-in exception object. This is an object of the Java java.lang.Throwable class (see Table 8.1), so you can use methods like toString on this object to get the object's error message. For example, you can see a new error-prone page in Listing 8.15, which uses ch08_16.jsp as an error page.

Example 8.15. Using the exception Object (ch08_15.jsp)

<%@ page errorPage="ch08_16.jsp" %>
<HTML>
    <HEAD>
        <TITLE>Using the exception Object</TITLE>
    </HEAD>

    <BODY>
        <H1>Using the exception Object</H1>
        <%
            int value = 1;
            value = value / 0;
        %>
    </BODY>
</HTML>

In ch06_16.jsp, you can use the exception object to display the error message for the exception, as you see in Listing 8.16.

Example 8.16. Using the exception Object in an Error Page (ch08_16.jsp)

<%@ page isErrorPage="true" %>
<HTML>
    <HEAD>
        <TITLE>An Error Page Using the exception Object</TITLE>
    </HEAD>

    <BODY>
        <H1>An Error Page Using the exception Object</H1>
        An error occurred: <%= exception.toString() %>
    </BODY>
</HTML>

You can see the results in Figure 8.11—note that although you've navigated to ch08_15.jsp, the actual page you see is the error page, ch08_16.jsp, because there was an exception in ch08_15.jsp.

Using the exception object in an error page.

Figure 8.11. Using the exception object in an error page.

Using JSP Error Pages: request Object Attributes

Using JSP Error Pages: request Object Attributes

Example 8.17. Using request Object Attributes (ch08_17.jsp)

<%@ page errorPage="ch08_18.jsp" %>
<HTML>
    <HEAD>
        <TITLE>Using request Object Attributes</TITLE>
    </HEAD>

    <BODY>
        <H1>Using request Object Attributes</H1>
        <%
            request.setAttribute("message", "Divide by zero.");
            int value = 1;
            value = value / 0;
        %>
    </BODY>
</HTML>

In the page that the request is forwarded to, you can use the getAttribute method to get the object associated with the attribute, simply by passing the attribute's name to this method, as you see in Listing 8.18.

Example 8.18. Using the exception Object in an Error Page (ch08_18.jsp)

<%@ page isErrorPage="true" %>
<HTML>
    <HEAD>
        <TITLE>An Error Page Using Request Attributes</TITLE>
    </HEAD>

    <BODY>
        <H1>An Error Page Using the exception Object</H1>
        An error occurred: <%= request.getAttribute("message") %>
    </BODY>
</HTML>

The result is that you can place an object in an attribute and retrieve it in an error page, as you see in Figure 8.12.

Using request object attributes.

Figure 8.12. Using request object attributes.

Summary

Today you learned about handling errors. You saw that syntax errors prevent your code from being compiled, and that exceptions are runtime errors that Tomcat lets you handle.

To handle exceptions, you use try/catch blocks. You place the sensitive code in try blocks and the error-handling code in catch blocks. Code that you want to run after the code in try/catch blocks can go into finally blocks.

Using try/catch blocks, you can handle not just general exceptions by catching exceptions of the Exception class, but specific exception objects, such as exceptions of the ArrayIndexOutOfBoundsException class.

You can use multiple catch blocks to catch exceptions of different classes from the same try block. If the last catch block catches general exceptions of the Exception class, you'll be sure to catch all possible exception objects. You can also nest try/catch statements.You can even create your own exceptions, and throw exceptions with the throw statement.

JSP also provides a mechanism for working with errors—you can specify an error page with the page directive. The error page is forwarded the original request object sent to the error-causing page, as well as an exception object to let you know what exception occurred. You can add attributes to the request object before it's forwarded to the error page, which lets you pass data to the error page.

Q&A

Q1:

Are there runtime errors that I can't handle with try/catch blocks?

A1:

Yes. Those kinds of errors are internal to Java, to Tomcat, and to JSP itself. Because they are internal errors, there is no provision to handle them with the try/catch mechanism. But these kinds of errors are rare. Sometimes, Java will run across errors so severe that it can't continue, in which case the try/catch mechanism is not called—the program just ends.

Q2:

What about using a debugger?

A2:

The support for debuggers is very limited at this time—that's one of the things being planned for the next version of the JSP and servlet specifications.

Workshop

This workshop tests whether you understand all the concepts you learned today. It's a good idea to master today's concepts by honing your knowledge here before starting tomorrow's material. You can find the answers to the quiz questions in Appendix A.

Quiz

1:

What's the difference between a syntax error and an exception?

2:

What's the base class of the Exception class?

3:

What is the finally block used for in a try/catch statement?

4:

What Exception object method is automatically called when you pass that object to out.println?

5:

What methods do you use to set and get attributes with request objects?

Exercises

1:

Create a simple Web page and make sure that the code creates an exception at runtime. Catch the exception using a try/catch block and report it. Then convert the Web page to use an error page to do the same thing, moving from the Java way of doing things to the JSP way.

2:

Build a simple calculator that lets the user add, subtract, divide, and multiply. Use any layout you want (Suggestion: Start with a text field for the first operand, four submit buttons labeled +, -, *, and / under that text field, another text field under the buttons for the second operand, then another text field for the answer). Make sure to add an error page to handle ArithmeticException exceptions.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.117.137.12