| [ directory ] |
All Java errors are subclasses of the java.lang.Throwable class. When an error occurs within a running program, an appropriate instance of this class is created and said to be thrown. The same code can then catch the exception and handle it or let the JVM handle the problem, which usually results in terminating the current program. In some cases Java enforces code to try and handle exceptions, and in others the exceptions are left to freely pass to a JVM.
There are three main subclasses of the Throwable class that divide all errors into three main categories. As shown in Figure 4-1, errors in Java are grouped as either instances of the Error, Exception, or RuntimeException class.

Of the three primary Throwable subclasses, the most well-known branch is instances of Exception. The Exception object represents a problem that a program must be able to catch. If code neglects to properly catch all instances of Exception objects, a Java compiler will refuse to compile the delinquent code. Complementing Exception classes, instances of the RuntimeException class represent a runtime error that does not need to be caught by code. However, just because the error does not need to be caught does not mean it is not a serious problem. Instances of RuntimeException objects are used when an error should not be handled by local code and would only clutter things up if declared as an Exception. While helpful, RuntimeExceptions are inherently dangerous since they do not require code to account for them. RuntimeException objects are not as commonly used as Exception objects because of this risk. The third branch of Throwable objects is subclasses of Error. An instance of the Error class represents something abnormally wrong that applications should not try to catch. If an instance of an Error object is thrown, it is almost always catastrophic to the executing program.
When programming a Web Application, it is common to use code that throws Exception objects, and in many cases, it is also helpful to design code for throwing and catching RuntimeException objects. Both Exception and RuntimeException objects are further covered by this chapter. Instances of the Error class are assumed to never occur and are considered outside the scope of this book.
Exceptions are thrown by use of the throw keyword followed by the Throwable object to be thrown. An exception may be thrown at any time, but the intended purpose of the throw keyword is to allow an exception to be thrown when a problem is detected at runtime. There are many good uses for throwing exceptions. One of the most common uses of exceptions is to verify correct parameters are passed into a function call. An exception can be thrown with a good explanation of what went wrong instead of using a convoluted system of return values. Listing 4-1 resembles code that accomplishes this.
public void fooMethod(String value1, String value2) {
if (value1 == null)
throw new Exception("Value 1 can't be null!");
if (value2 == null)
throw new Exception("Value 2 can't be null!");
// method's code...
}
Accompanying the throw keyword is the throws clause. The throws clause extends the signature of a method to reflect the fact that an exception might be thrown. Each method that uses the throw keyword and does not catch the exception must use the throws clause to declare Exception objects that are uncaught. To apply the throws clause to the preceding code, you would need to change the code to resemble Listing 4-2.
public void fooMethod(String value1, String value2) throws Exception { if (value1 == null) throw new Exception("Value 1 can't be null!"); if (value2 == null) throw new Exception("Value 2 can't be null!"); // method's code... }
It is always good to code with exceptions in mind. The Java exception handling mechanism is incredibly helpful for keeping code running smoothly and debugging a problem when something goes wrong. While valid, the previously given examples of exception throwing are skewed for the purposes of illustrating how the functionality works. In real use exceptions are almost never thrown as a direct instance of the Exception class. Exceptions are best thrown as a specific subclass of Exception that better relates to the nature of the exception.
A custom exception can easily be made by subclassing Exception. In general, code for a custom error is usually nothing more than a class that extends Exception with a call to the Exception constructor in its own, as shown in Listing 4-3.
package com.jspbook.foo;
public class CustomException extends Exception {
public CustomException(String message) {
super(message);
}
}
The CustomException code is to appear in an upcoming example, so it is placed in the com.jspbook.foo package. Save and compile CustomException.java in the /WEB-INF/classes/com/jspbook/foo directory of the jspbook Web Application.
In most cases it is impractical to throw every single type of exception that occurs. Cluttering up a method declaration only to include countless types of Throwable classes is not good practice in Java programming. A better solution is to consolidate types of Throwable classes by wrapping them with custom-categorized Throwable classes. If two or more types of exceptions really mean the same thing and are meant to be handled identically by catching code, then there is reason to consolidate them.
A good method of consolidating Throwable classes with a Web Application is to break exceptions into two categories, user-related exceptions and critical application exceptions. These two exceptions represent the general type of problems that might occur during runtime: either a user makes a mistake or the application fails to work as expected. In the case of a user mistake it is helpful to catch the problem and inform the user what they did wrong. In the case of an application mistake there is little a user can do. Instead an application mistake should display a polite error page to a user while simultaneously notifying the administrators.
The user and application types of exceptions are encouraged for use and followed throughout this book. For future examples save the following two classes. Listing 4-4 displays the custom Throwable class representing a user exception. The exception should immediately raise an alarm and so is made a "checked" exception by subclassing Exception.
package com.jspbook;
public class UserException extends Exception {
// A constructor to set the description of the exception
public UserException(String description) {
super(description);
}
}
The second class represents unforeseen application exceptions, as displayed in Listing 4-5. Any exception of this type is completely unexpected and represents a potentially serious problem with the Web Application. This exception is not made "checked", but assumed to be caught by one consolidated mechanism that appropriately logs the problem and notifies administrators. By extending the RuntimeException class, the code is not cluttered needlessly handling the problem since it should never occur.
package com.jspbook;
public class AdminException extends RuntimeException {
// A constructor to set the description of the exception
public AdminException(String description) {
super(description);
}
}
Save and compile both of the preceding classes in the /WEB-INF/classes/com/jspbook directory of the jspbook Web Application. Appropriately handling the preceding two exceptions is something that is developed throughout this chapter. There are many good methods, some with advantages compared to others, but before introducing anything complex, let's start the discussion at the basic level.
Throwing exceptions is good, but catching them is just as important. Throwing an exception straight to the JVM is never good practice because it can result in stopping your application. When possible it is best to keep exception handling local. The Java specification uses the try statement with a catch clause to respectively attempt to execute possible exception throwing code and to handle any exceptions that might be thrown. The general format is to surround exception throwing code with a try statement and follow with one or more catch clauses to handle the different types of Throwable objects that might arise.
Before giving an example of the try-catch functionality, some code is needed that throws exceptions. Because this code is purely educational, it will accompany CustomException.java in the foo package. Save and compile Listing 4-6 in the /WEB-INF/classes/com/jspbook/foo directory of the jspbook Web Application.
package com.jspbook.foo;
public class ExceptionThrower {
public static void throwException(String message) throws Exception{
throw new Exception(message);
}
public static void throwCustomException(String message)
throws CustomException{
throw new CustomException(message);
}
}
The ExceptionThrower.java only exists to throw Exception and CustomException objects. Its purpose is to provide a mock setup in which differing exceptions are thrown so the try-catch statement can be demonstrated. The JSP in Listing 4-7 uses the ExceptionThrower class to randomly throw an instance of either a CustomException or Exception object. A try statement surrounds the code with catch clauses to handle both types of exceptions.
<%@ page import="com.jspbook.foo.*" %>
<html>
<head>
<title>ExceptionThrower</title>
</head>
<body>
<%
try {
double rand = Math.random();
if (rand <.5) {
ExceptionThrower.throwException("foo");
}
ExceptionThrower.throwCustomException("foo");
}
catch (CustomException e) {
out.println("Caught a CustomException: " + e.getMessage());
}
catch (Exception e) {
out.println("Caught a Exception: " + e.getMessage());
}
%>
</body>
</html>
Save ExceptionThrower.jsp in the base directory of the jspbook Web Application and browse to http://127.0.0.1/jspbook/ExceptionThrower.jsp. Each visit to the page causes either an Exception or CustomException to be thrown. Instead of seeing an error page (as shown later in Figure 4-3), the JSP catches the error and displays a little information about it. Figure 4-2 shows a browser rendering of the output.


In many situations code is going to be throwing various types of exceptions. Some exceptions might be caused from a user error, while others could be a critical bug in an application. Being able to catch, distinguish, and appropriately handle these exceptions is a necessity in keeping a Web Application running smoothly. The try-catch mechanism appears quite often throughout this book, and it is important to be familiar with it.
When an exception is thrown, the offending code is stopped and control is passed to the code responsible for catching the exception. Stopping executing code in this manner is not always safe. Resources initially declared by the offending code are ignored, and there is no guarantee that they are properly cleaned up. With local variables and object references, the garbage collector still works, but in cases where non-local objects are in use, then a fall-back mechanism is needed to ensure the resource is properly terminated.
The finally clause complements the try-catch statement to provide this form of functionality. Whenever a block of code needs to be executed, regardless if an exception is thrown or not, then it should be included in a finally clause. Blocks of code appearing in a finally clause are always executed even if an executing of code in the try block is halted due to an exception.
| [ directory ] |