This week's book giveaway is in the OCAJP 8 forum. We're giving away four copies of OCA Java SE 8 Programmer I Study Guide and have Edward Finegan & Robert Liguori on-line! See this thread for details.
Within a servlet I throw a Business Exception, catch it and then throw a ServletException. In the deployment descriptors I define an error page for the Business Exception. When I call the servlet that throws the ServletException I am redirected to the error page defined for the Business Exception. Why and how does it do this? I have also discovered that if I define a error page for the ServletException I am shown its error page instead. I am sure that this is desired behaviour. I wondered if someone with more experience could tell me something about this. I have not found other questions on this forum like this nor did I find any clues in the servlet specs. Thank you in advance for anything you can say regarding this.
The Business Exception is a checked exception which means that it must be either caught or propagated. It cannot be propagated as it does not form one of a subset of exceptions that are thrown by the doGet() method that it overrides, so it must be caught otherwise an unhandled exception error occurs. I am seeking an explanation as to why and how the error page associated with the business exception (defined in the deployment descriptor) is shown when the catch clause of the try that caught the business exception throws a ServletException. I believe that this behaviour is correct and desirable, just not what I expected. I am hoping that someone with knowledge of this can shed some light on it.
As a test, create another exception which is a runtime exception:
Amend your deployment descriptor to include a different re-direct for this exception:
Now test these scenarios:
1) In your doGet method, throw a MyRuntimeException. Which page does the user get re-directed to?
2) In your doGet method, throw a ServletException. Which page does the user get re-directed to?
I haven't tried your suggestion but I think that I have an answer.
I wanted to know why the error page defined for the business exception was shown when the exception thrown was ServletException. The reason is that the business exception is passed as a parameter to the ServletException as the root cause of the exception and I am assuming that the container attempts to match this root cause exception to an exception mapped to an error page in the deployment descriptor and that if there is an error page defined for the ServletException that this page is chosen over the other.
Thanks for attempting to help me with this issue. As is often the case a good nights sleep results in the solution being found.
I think ultimately the container will look to match the "closest" exception in the class hierarchy. I have read a little of the Java Servlet Specification, section 10.9.2:
The Web application may have declared error pages using the exception-type
element. In this case the container matches the exception type by comparing the
exception thrown with the list of error-page definitions that use the exception-type
element. A match results in the container returning the resource indicated in the
location entry. The closest match in the class hierarchy wins.