I would like to do some custom logic anytime there is an uncaught exception in my application. Normally I would do something like:
Thread.setDefaultUncaughtExceptionHandler(myCustomHandler);
However, Thread is locked down on Google App Engine. The above code raises a security exception. Is there anyway to achieve similar functionality on Google App Engine?
EDIT: I have implemented my approach as a Servlet Filter. My experience with Java web programming is fairly limited. Can someone comment on such an approach? Since all requests in AppEngine originate as HTTP requests, I think this is a comprehensive solution.
#Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
try {
chain.doFilter(request, response);
} catch (RuntimeException ex) {
// Work my magic here...
throw ex;
}
}
Servlets handle threads on their own so you should not mess with it in this way.
Instead, install a servlet Error Handler:
<error-page>
<error-type>com.package.YourException</error-type>
<location>/errors/handler</location>
</error-page>
then have /errors/handler map to servlet that handles the error and returns the appropriate response.
Related
I have a web-app developed with servlet & JSP. I configured my app to throw an IllegalArgumentException if I insert bad parameters.
Then I configured my web.xml file in this way:
<error-page>
<error-code>404</error-code>
<location>/error.jsp</location>
</error-page>
<error-page>
<exception-type>java.lang.Throwable</exception-type>
<location>/error.jsp</location>
</error-page>
When I rise a 404 error, then it works and calls error.jsp, but when I rise a java.lang.IllegalArgumentException, then it does not work and I've a blank page instead of error.jsp. Why?
The server is Glassfish, and logs show really IllegalArgumentException rised.
You should not catch and suppress it, but just let it go.
I.e. do not do:
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
doSomethingWhichMayThrowException();
} catch (IllegalArgumentException e) {
e.printStackTrace(); // Or something else which totally suppresses the exception.
}
}
But rather just let it go:
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doSomethingWhichMayThrowException();
}
Or, if you actually intented to catch it for logging or so (I'd rather use a filter for that, but ala), then rethrow it:
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
doSomethingWhichMayThrowException();
} catch (IllegalArgumentException e) {
e.printStackTrace();
throw e;
}
}
Or, if it's not an runtime exception, then rethrow it wrapped in ServletException, it will be automatically unwrapped by the container:
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
doSomethingWhichMayThrowException();
} catch (NotARuntimeException e) {
throw new ServletException(e);
}
}
See also:
How does server prioritize which type of web.xml error page to use?
Submitting form to Servlet which interacts with database results in blank page
Another (simplified) approach is not to declare multiple handlers for various <error-code> and <exception-type> situations but rather have one, sort of catch-all sink, e.g.
<error-page>
<location>/error-page.jsp</location>
</error-page>
Inside your error-page.jsp you can determine the cause, be it a return status code or an exception as described here: https://www.tutorialspoint.com/servlets/servlets-exception-handling.htm These constants are a part of the standard Servlet 3.0 API.
For instance a primitive error-page.jsp response handler placed into the root of your webapp can look like this:
Server encountered a situation
Status code: <%=(Integer) request.getAttribute(javax.servlet.RequestDispatcher.ERROR_STATUS_CODE)%>
<br>
Exception: <%=(Throwable) request.getAttribute(javax.servlet.RequestDispatcher.ERROR_EXCEPTION)%>
For security reasons I wouldn't recommend sending the exact exception type to the client; this is just an example of how to handle different types of errors and response statuses inside a JSP handler; a servlet can be used instead of JSP.
One common catch-all handler vs one per status code is certainly dependent on the situation and requirements.
I have today the same issue. (JavaEE 7 and Glassfish 4.0)
The problem seems that the framework check it as String instead with the Class.
String based check (the hypothesis)
When a Exception is twrown, e.getClass() is compared with <exception-type> as string.
So you can't use inheritance.
Note that nested classes must be pointed as '$' instead '.' (same as getClass() method).
Class based check
The framework create an instance of the class, and <exception-type> text refer to it, and the class.isInstance() is used to check.
This will need reflection and policy file could break it.
I hope that this response solves future issues.
The javax.servlet.Filter object can be used both for authentication (where the Filter needs to catch the request before any servlet work needs to be done) and for XSLT translation (where the servlet needs to be completely finished generating content). When does it actually get executed?
I know this is implementation dependent (on the web container), but this seems to be problem that needs to be solved by all of them.
Maybe there is a configuration option set somewhere for each Filter registration with the web container?
Additional:
Also, what governs the order of Filter execution? Why would FooFilter get executed before BarFilter?
The filter chain in essence wraps the servlet invocation. The chain will process all links until it hits the "bottom", then allow the servlet to run, and then return up the chain in reverse. For example, if you have a new "example filter", your doFilter() method may look like this:
public void doFilter(ServletRequest request,
ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// do pre-servlet work here
chain.doFilter(request, response);
// do post servlet work here
}
According to the servlet2.3 specification filter is performed according to web.xml configuration of filter- mapping sequence Ref-http://www.programering.com/a/MTMyADOwATI.html
Problem description
Tomcat is logging a SEVERE message including a stacktrace when my HttpServlet is throwing a ServletException, although it is properly re-directed to another HttpServlet in the web.xml.
Tomcat logs the following message with stacktrace:
21-Mar-2015 15:24:57.521 SEVERE [http-nio-8080-exec-28] org.apache.catalina.core.StandardWrapperValve.invoke Servlet.service() for servlet [MyHttpServlet] in context with path [/HttpServletExceptionHandler] threw exception [CustomException] with root cause CustomException
at MyHttpServlet.doGet(MyHttpServlet.java:20)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:618)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:725)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:610)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:516)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1086)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:659)
at org.apache.coyote.http11.Http11NioProtocol$Http11ConnectionHandler.process(Http11NioProtocol.java:223)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1558)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1515)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
What did I do?
First, MyHttpServlet throws a ServletException wrapping a CustomException (subclass of Exception) in it's doGet() method:
public class MyHttpServlet extends HttpServlet {
#Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doGet(req, resp);
throw new ServletException(new CustomException());
}
}
Then, the thrown CustomException is re-directed to MyServletExceptionHandler (mapped to location '/MyServletExceptionHandler'. This re-direction is defined in the following manner in the web.xml:
<error-page>
<exception-type>CustomException</exception-type>
<location>/MyServletExceptionHandler</location>
</error-page>
Finally, MyServletExceptionHandler receives the thrown exception and prints it:
public class MyServletExceptionHandler extends HttpServlet {
#Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doGet(req, resp);
final Throwable throwable = (Throwable) req.getAttribute("javax.servlet.error.exception");
System.out.println("MyServletExceptionHandler caught Throwable: " + throwable.toString());
}
}
This results in the expected 'MyServletExceptionHandler caught Throwable: CustomException' print so this does work, but somehow Tomcat also logs the SEVERE message mentioned above, including that stacktrace. This messes up my logging.
Why do I want it this way?
According to Java Beat's OCEJWCD 6 Mock Exam – 4 the above mentioned method is the proper way to deal with Exception handling in Servlets. Question 29 states (spoiler alert: bold are correct answers):
Which of the following is a sensible way of sending an error page to the client in case of a business exception that extends from java.lang.Exception?
Catch the exception and use RequestDispatcher to forward the request to the error page
Don’t catch the exception and define the ‘exception to error-page’ mapping in web.xml
Catch the exception, wrap it into ServletException and define the ‘business exception to error-page’ mapping in web.xml
Catch the exception, wrap it into ServletException, and define the ‘ServletException to error-page’ mapping in web.xml
Don’t do anything, the servlet container will automatically send a default error page
The third answer (which is marked as correct) clearly states that my way of re-directing the exceptions is a sensible solution.
Further discussion material
I found the following quote on this page (from 10-2-2012 by Tom Holloway at CodeRanch.com)
Actually, a ServletException has nowhere to go uphill in a webapp, and therefore having it appear on the master console isn't really that unreasonable, because it indicates that the application isn't handling the problem itself.
In fact, the Javadocs say this about the ServletException constructor:
"Constructs a new servlet exception with the specified message. The message can be written to the server log and/or displayed for the user."
Note that it explicitly says server log.
The server can get involved in a number of ways here. First, you should be able to define a general exception handler in web.xml to permit the app to deal with the exception, where that handler can not only log to the application log, but can determine what, if any, recovery action should be taken (something that the more generic server code cannot do). Secondly, you can define a custom error page, in which case Tomcat will catch the ServletException and dispatch that page. Note, however that the operative word is page. Like login screens, these pages are invoked directly from Tomcat, and therefore cannot be routed through servlets. In other words, use HTML or JSP, not Struts or JSF.
Bottom line, though, is that throwing ServletExceptions is a sign of bad application design. It means that someone was too lazy or too rushed to properly deal with a problem. Compared to that, the location where the error is logged is of secondary importance.
This statement makes me question the Java Beat's OCEJWCD Mock Exam (mentioned above) and my own solution as good practice. Do you think business exceptions should be handled by another Servlet? And if so, do you think that the Servlet Container (Tomcat) should log the stacktrace of these Exceptions or not? If not, what would then be the best practice?
Final remarks
Throwing RuntimeExceptions instead of ServletExceptions results in the same SEVERE log.
A working example of the problem is provided via this Bitbucket repository.
It seems your basic problem is that you want to centralize your error handling but without using a mechanism that causes Tomcat to log the errors as SEVERE?
Since you control all the servlets AFAICT from your question would it not make more sense to define an abstract base servlet that defines all the error handling logic and then just have the rest of your servlets derive from this class?
So you have an abstract base servlet:
public abstract class MyServletBase extends HttpServlet {
#Override
public void doGet(HttpServletRequest req, HttpServletResponse resp) {
try {
doGetInternal(req, resp);
} catch (RuntimeException e) {
handleError(e, req, resp);
}
}
protected void handleError(RuntimeException e, HttpServletRequest req, HttpServletResponse resp) {
// Error handling logic goes here
}
protected void doGetInternal(HttpServletRequest req, HttpServletResponse resp);
}
And then your actual servlet:
public class MyServlet extends MyServletBase {
#Override
protected void doGetInternal(HttpServletRequest req, HttpServlet resp) {
// Actual servlet logic here
}
}
This is a rough sketch off the top of my head with no reference to the Javadoc so may not have the method signatures perfect but hopefully you get the idea.
It also has the advantage that if you ever need to add extra error handling logic to a derived servlet and you don't want to change the base servlet for whatever reason you can just override the handleError() method which is not something you can so easily do when using Tomcat's exception handler mechanism
I have started developing Java EE web applications mainly on Struts and Servlets. Most of the codes have a try catch block within Servlet or Struts Action class.
Is it a must to have try catch block for every servlet or action? The only advantages I saw with this kind of code template is stacktrace are log to application specified logging framework such as log4j.
If the runtime exception floats up, it will be printed on the server (Tomcat / Glassfish / Weblogic) logs instead.
public class HelloWorldAction extends Action{
public ActionForward execute(ActionMapping mapping,ActionForm form,
HttpServletRequest request,HttpServletResponse response)
throws Exception {
try {
// do all the processing here
} catch (Exception e) {
// log all exceptions
}
}
}
public class HelloWorldExample extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
try {
// do all the processing here
} catch (Exception e) {
// log all exceptions
}
}
}
Catching Exception is almost never what you really want to do. Hopefully it's obvious that it's not mandatory to always have a try/catch block–it depends on what the underlying code is doing, and how you want to handle any exceptions it may throw.
Catching Exception eliminates the ability to use Struts' declarative exception handling.
I would recommend against using a filter to handle exceptions in Struts 1 since it already has a mechanism built in. If there are exceptions at the framework level they'll be displayed anyway, and they generally indicate a development, not runtime, issue.
I echo Andrea's sentiments: unless you have a Very Good Reason, learning Struts 1 isn't useful. Consider instead Struts 2 or Spring MVC for "traditional" framework development, or Play, Grails, JRuby on Rails, etc. for a more modern approach.
If you are looking for one place to do exception logging, you can create ServletFilter:
public class ExceptionLoggerFilter implements Filter {
public void doFilter(ServletRequest req, ServletResponse res, FilterChain filterChain) {
try {
filterChain.doFilter(req, res);
}
catch(Exception e) { // Log exception }
}
}
You shouldn't really have to catch exceptions everywhere unless you want to handle that particular exception in a special way. Most of the time it's just noise getting in the way for the "real" code. The important thing is that you log the exception and enough context information that you can figure out what caused the error. To the user, you should probably just display a general error page.
You can specify global exception in struts-config.xml. It catches unhandled exceptions all over the application.
You need to implement your own ExceptionHandler class. Then write code what to want to do.
4.5 Exception Handler
http://www.jajakarta.org/struts/struts1.2/documentation/ja/target/userGuide/building_controller.html
Is there a standard way to catch uncaught exceptions that happen inside of a java servlet container like tomcat or Jetty? We run a lot of servlets that come from libraries so we cannot easily put our on try/catch code. It would also be nice to in as generic of a way as possible catch and log all uncaught exceptions in our web application (which runs in Jetty) to our bug tracker via the API provided.
Please not I need to log the exceptions only, whether a a redirect is issues to a custom error page will not help me. We do everything via GWT-RPC so the user would never see an error page.
I think a custom filter actually works best.
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
try {
chain.doFilter(request, response);
} catch (Throwable e) {
doCustomErrorLogging(e);
if (e instanceof IOException) {
throw (IOException) e;
} else if (e instanceof ServletException) {
throw (ServletException) e;
} else if (e instanceof RuntimeException) {
throw (RuntimeException) e;
} else {
//This should never be hit
throw new RuntimeException("Unexpected Exception", e);
}
}
}
In web.xml (the deployment descriptor) you can use the <error-page> element to specify error pages by exception type or HTTP response status code. For example:
<error-page>
<error-code>404</error-code>
<location>/error/404.html</location>
</error-page>
<error-page>
<exception-type>com.example.PebkacException</exception-type>
<location>/error/UserError.html</location>
</error-page>
For a NetBeans-centric description, mosey on over to Configuring Web Applications: Mapping Errors to Error Screens (The Java EE 6 Tutorial) (or see the Java EE 5 Tutorial's version).
Not 100% sure if this will work with a servlet container, or how far upstream this call would need to go, but you can call the static setDefaultUncaughtExceptionHandler method on Thread to set a handler that will handle all uncaught exceptions.