Catching the AppException
Jakob Jenkov |
Somewhere in your application you will need to catch your application specific exception, and react to it.
As mentioned in the text Catching Exceptions, the reaction to an exception typically falls into two categories:
- Notifying users.
- Notifying non-users.
Remember, that at the point of catching the exception, any potential local exception handling has already been carried out earlier in the call stack. That is why no local exception handling techniques are listed here.
Let's jump right into a code example:
try{ startTheWholeThing(); } catch(Throwable e) { notifyUser(e); notifyNonUsers(e); }
First, the method startTheWholeThing()
is called. This method declares that it can throw
AppException
's, but even if it is not declared, it may throw unchecked exceptions too
(in Java). That is why the catch clause catches Throwable
intead of AppException
The catch clause calls two methods. The first method is notifyUsers()
. This method is supposed
to send a message to the user, saying that an error occurred. The second method is notifyNonUsers()
.
This method is supposed to notify all other relevant parties.
I'll go into a little more detail with these two methods, in the following sections.
notifyUsers()
The notifyUsers()
method should show an error message to the user, telling that an error occurred.
How this is done depends a little bit on what kind of application you are developing.
Web Applications
If you are developing a web application, and an exception is thrown and caught on the server, your web application should show a nice error message to the user. You will do that by either showing the error message inside the page that fails, or by redirecting the user to an error page.
If your web application uses AJAX, and it is an AJAX call that fails, then somehow your AJAX protocol must be able to signal to the JavaScript on the client, that an error occurred. The error message could either be embedded in the HTML page / JavaScript, or you could send it back from the server, included in the error signal in the AJAX call.
Desktop Applications
In a desktop application you would often show the error message to the user in a popup window.
That is, the notifyUsers()
method would pop up a new window showing the error message.
Web Services
If you are developing a web service, or some other kind of remote accessible service, your users are other programs. For instance, a web service client. If an exception occurs in such a service, the access protocol should send an error message across to the client too.
Do not give the client more information than necessary. Of course, if the error is caused by the client, give the client enough information to correct the error.
Background Services
Background services or batch jobs, often don't have direct users. They just execute autonomously in the background. Such applications will typically only notify non-users.
notifyNonUsers()
The notifyNonUsers()
method will typically log the error to some application log.
Any relevant party that needs to know about the error, will be notified via the application log.
How you log the exception depends on what language you are programming in, and what logging tools you are using.
Method Templates for notifyUsers() and notifyNonUsers()
Exactly how the notifyUsers()
and notifyNonUsers()
methods will look in your
application, depends on your application, and your language and platform. Nevertheless, I will try to
give you a little more detail about their internals here.
Here are the two templates:
protected void notifyUsers(Throwable e){ if(e instanceof AppException) { AppException ae = (AppException) e; if(ae.getErrorType() == ErrorInfo.ERROR_TYPE_CLIENT) { // The error was caused by the user / client, // show the cause and how to correct it. } else { // The error was not caused by user / client. // Just show a standard error message. } } else { //An unknown exception occurred. Show a standard error message. } }
protected void notifyNonUsers(Throwable e){ if(e instanceof AppException) { AppException ae = (AppException) e; if(ae.getErrorType() == ErrorInfo.ERROR_TYPE_CLIENT) { // The error was caused by the user / client. // It may not be necessary to log it, or just log // it as info or warning. The app is working fine. // It is the user that is malfunctioning. } else if(ae.getErrorType() == ErrorInfo.ERROR_TYPE_SERVICE) { // The error was caused by a failure in an external service. // Notify operations about the external failure (log it). // Also tell if this appliation will survive the failure, // and continue working once the external service works again. } else if(ae.getErrorType() == ErrorInfo.ERROR_TYPE_INTERNAL) { // An internal error occurred. This is serious, and may need // both operations and developers attention, as it may be a // sign of a bug in the application. Log the error. } } else { // The exception was not an AppException. This should be fixed, // so that exception is caught and wrapped in an AppException // in the future. Log the error. // This kind of error is also serious, and should get the attention // of both operations and developers, as the cause of the exception // is unknown. } }
Tweet | |
Jakob Jenkov |