Recommended: Sing it, brah! 5 fabulous songs for developers
JW's Top 5
Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs
Page 4 of 5
Case 3
Passenger getPassenger() throws TravelException
{
try
{
Passenger flier = object.searchPassengerFlightRecord("Gary Smith");
}
catch(MalformedURLException ume)
{
//do something
throw new TravelException("Search Failed", ume);
}
catch(SQLException sqle)
{
//do something
throw new TravelException("Search Failed", sqle);
}
}
Case 3 meets midway between the two extremes of Case 1 and 2 by using a custom exception class called TravelException. This class features a special characteristic that understands the actual exception thrown as an argument and transforms
a system-level message into a more relevant application-level one. Yet, you retain the flexibility of knowing what exactly
caused the exception by having the original exception as part of the new exception object instance, which is handy for debugging
purposes. This approach provides an elegant solution to designing APIs and applications that cross system boundaries.
The following code shows the TravelException class, which we used as our custom exception in Case 3. It takes two arguments. One is a message, which can be displayed
on the error stream; the other is the real exception, which caused the custom exception to be thrown. This code shows how
to package other information within a custom exception. The advantage of this packaging is that, if the calling method really
wants to know the underlying cause of the TravelException, all it has to do is call getHiddenException(). This allows the calling method to decide whether it wants to deal with specific exceptions or stick with TravelException.
public class TravelException extends Exception
{
private Exception hiddenException_;
public TravelException(String error, Exception excp)
{
super(error);
hiddenException_ = excp;
}
public Exception getHiddenException()
{
return(hiddenException_);
}
}
Exceptions come with a price, and in order to understand some of the issues involved, let's look at the mechanism for handling exceptions. The Java Virtual Machine maintains a method-invocation stack (or call stack) that features a list of the methods that have been invoked by a thread, starting with the first method the thread invoked and ending with the current method. A method-invocation stack illustrates the path of method invocations a thread made to arrive at the current method.

Figure 1. The Java method-invocation stack shows frames for the methods invoked.
Figure 1 shows a graphical representation of the method-invocation stack for our code. Inside the Java Virtual Machine, methods keep their state within the Java stack. Each method obtains a stack frame, which pushes onto the stack when the method invokes and pops from the stack when the method completes. (The stack frame stores the method's local variables, parameters, return value, and other key information needed by the Java VM). As methods continue to complete normally, their frames pop and the stack frame below turns into the currently executed method.