I recently inherited an application developed with bare servlets and JSPs (i.e.: no frameworks). I've been tasked with cleaning up the error-handling workflow. Currently, each <form> in the workflow submits to a servlet, and based on the result of the form submission, the servlet does one of two things:
If everything is OK, the servlet either forwards or redirects to the next page in the workflow.
If there's a problem, such as an invalid username or password, the servlet forwards to a page specific to the problem condition. For example, there are pages such as AccountDisabled.jsp, AccountExpired.jsp, AuthenticationFailed.jsp, SecurityQuestionIncorrect.jsp, etc.
I need to redesign this system to centralize how problem conditions are handled. So far, I've considered two possible solutions:
Exceptions
Create an exception class specific to my needs, such as AuthException. Inherit from this class to be more specific when necessary (e.g.: InvalidUsernameException, InvalidPasswordException, AccountDisabledException, etc.). Whenever there's a problem condition, throw an exception specific to the condition. Catch all exceptions via web.xml and route them to the appropriate page(s) with the <error-page> tag.
enums
Adopt an error code approach, with an enum keeping track of the error code and description. The descriptions can be read from a resource bundle in the finished product.
I'm leaning more toward the enum approach, as an authentication failure isn't really an "exceptional condition" and I don't see any benefit in adding clutter to the server logs. Plus, I'd just be replacing one maintenance headache with another. Instead of separate JSPs to maintain, I'd have separate Exception classes.
I'm planning on implementing "error" handling in a servlet that I'm writing specifically for this purpose. I'm also going to eliminate all of the separate error pages, instead setting an error request attribute with the error message to display to the user and forwarding back to the referrer. Each target servlet (Logon, ChangePassword, AnswerProfileQuestions, etc.) would add an error code to the request and redirect to my new servlet in the event of a problem. My new servlet would look something like this:
public enum Error {
INVALID_PASSWORD(5000, "You have entered an invalid password."),
ACCOUNT_DISABLED(5002, "Your account has been disabled."),
SESSION_EXPIRED(5003, "Your session has expired. Please log in again."),
INVALID_SECURITY_QUESTION(5004, "You have answered a security question incorrectly.");
private final int code;
private final String description;
Error(int code, String description) {
this.code = code;
this.description = description;
}
public int getCode() {
return code;
}
public String getDescription() {
return description;
}
};
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String sendTo = "UnknownError.jsp";
String message = "An unknown error has occurred.";
int errorCode = Integer.parseInt((String)request.getAttribute("errorCode"), 10);
Error errors[] = Error.values();
Error error = null;
for (int i = 0; error == null && i < errors.length; i++) {
if (errors[i].getCode() == errorCode) {
error = errors[i];
}
}
if (error != null) {
sendTo = request.getHeader("referer");
message = error.getDescription();
}
request.setAttribute("error", message);
request.getRequestDispatcher(sendTo).forward(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
Being fairly inexperienced with Java EE (this is my first real exposure to JSPs and servlets), I'm sure there's something I'm missing, or my approach is suboptimal. Am I on the right track, or do I need to rethink my strategy?