For exceptions thrown while handling a request, Spring has a number of different ways to register exception handlers. Is there a way to apply similar exception handling when the exception is thrown while rendering a view? At a minimum I'd like the ability to perform some logging.
The problem is that exceptions thrown during View rendering cannot do an awful lot. In particular, they typically can't render a HTML page containing an error report ... or even send a 5xx response ... because the response will typically have "committed" before the exception is thrown.
So the best you can do (probably) is:
create a wrapper for the View object that catches and logs the exception, or
do the logging in a servlet filter,
But the chances are that the web container can be configured to log uncaught exceptions anyway.
UPDATES
I just noticed spring's HandlerInterceptor class exposes an 'afterCompletion' method which will be invoked when exceptions are thrown. Any thoughts as to the benefits of using this vs. a filter?
Try it and see. :-) But given the following, I doubt that it will work.
Using a filter or interceptor does not work for exceptions thrown while rendering a jsp. It does print to err out:
Dec 16, 2012 12:18:03 PM org.apache.catalina.core.ApplicationDispatcher
invoke SEVERE: Servlet.service() for servlet jsp threw exception
javax.el.PropertyNotFoundException: Property 'fooo' not found on
type java.lang.String"
Unfortunately the exception is not propagated upwards to the filter. I'd like to add my own logging which sends out error notifications and logs additional information about the failed request. Keeping an eye on log files to spot errors isn't a good option.
The chances are that the log message is actually produced using the logging subsystem. If it is, you can use the logging configuration to add your own handler for JSP engine logging events and send out special notifications.
The fact that the exceptions are 1) being thrown during JSP view rendering, and 2) the JSP engine is not propagating them means that (IMO) it is unlikely there is a way for you to catch them.
The other option is to set up a scanner for the log files ... as part of your general system monitoring.
Related
I am working on a microservice which does some calculation based on certain configurations stored in its own data store. The calculations apis are stored via REST APIs. The application is a spring boot application.
Now there are mainly 3 layers in the application :
REST Controller
Service layer
DAO layer - it used spring data.
I am planning to handle the logging and exception handling using below points:
Log each request that the service receives and response or at least
the response if the status is not in 2xx series.
If there are any checked exception in either DAO layer or Service
layer then log them and throw a custom exception derived from
RuntimeException.
Have Several custom exception which should be thrown from Service
layer mainly if we come across scenarios like invalid values, null
values etc.
Have a try catch block in the REST Controller and log the
exception i.e. message along with stacktrace and return the
response accordingly.
So overall idea is to let the RuntimeExceptions propagate all the way to REST Controller where they should be logged and accordingly the response should be sent. Incase of checked exceptions log them in the same method and throw custom exceptions instead.
Please suggest what should be the correct or a good approach for logging exception in such applications.
Write controller advice which will catch all the exceptions & logs the required contents. You may catch exceptions here. I implemented same what you asked here.
*/
/**
* Uncaught exception handler
* #param e - Exception
*/
#ExceptionHandler(Exception.class)
#ResponseStatus(code=HttpStatus.INTERNAL_SERVER_ERROR)
#ResponseBody
public void handleError(Exception e,HttpServletRequest request, HttpServletResponse response){
logger.error("Exception occured : {}",e);
//logs request & response here
}
Also please check AbstractRequestLoggingFilter described here.
For all custom application specific exeptions create your own custom exception type & handle it with the help of #ExceptionHandler as specified in above code block.
Choose only one place to log the exceptions.
In your design, if an exception occurs in DAO, it will:
Get logged in DAO
Then trigger a runtime exception, which will be caught and logged in controller
Which should then return non-2xx response status via REST, which will trigger logging the response as per your first point
So you'll have either the same information in three places, or you will have the different bits of information regarding a single error scattered in two or three places across the log.
Choose a single place to log the errors, and make sure all relevant info is present at that place (i.e. set the underlying DAO exception as a cause of the runtime exception, and don't forget to log the runtime exception along with its cause).
I have a question about handling org.apache.shiro.cache.CacheException.
What is shiro's responsibility when a cache exception occurs? This RTE ripples through the whole stack, but I'm unclear where it is handled and in what manner.
Can a shiro enabled web application recover?
Is the cache manager reinitialised?
Do I have to restart the application when a cache exception occurs?
For example, a timeout exception or a failed to connect to node exception occurs on cache.get(key). What's the expected outcome apart from bubble to the stop and die?
Thanks
I have checked all usages of CacheException and the only thing shiro does is throw it. It never gets catched let alone handled.
So the only expected outcome is to "bubble to the stop and die".
What you can do about it is have a servlet filter in front of shiro that catches this exception, then get a hold of the CacheManager instance (how you do that depends on your setup) and call cacheManager.getCache().clear() so the cache is reset.
My code is throwing an exception (due to a bug). In the log, I see:
org.jboss.resteasy.spi.UnhandledException: java.lang.NullPointerException
at org.jboss.resteasy.core.SynchronousDispatcher.handleApplicationException(SynchronousDispatcher.java:323)
at org.jboss.resteasy.core.SynchronousDispatcher.handleException(SynchronousDispatcher.java:199)
at org.jboss.resteasy.core.SynchronousDispatcher.handleInvokerException(SynchronousDispatcher.java:175)
at org.jboss.resteasy.core.SynchronousDispatcher.getResponse(SynchronousDispatcher.java:529)
etc...
The stack of the actual exception is not logged. If I wrap my code in a try..catch and log the caught exception I can verify that my code is at fault. No other library in my system does this, even for deeply-wrapped exceptions, so it must be a problem in RESTEasy, perhaps in UnhandledException?
Is there a way to get around this behavior? I can't think of a good reason why it should be hiding the actual exception.
Jetty
Java
Spring 3.0.3
RESTEasy 2.0.1GA
Do you have an ExceptionMapper? See Chapter 27, Exception Handling, in the RESTEasy documentation.
I used RESTEasy to add REST to an existing system, and the existing system has a weird way of wrapping exceptions within exceptions, so my ExceptionMappers do a lot of unwrapping.
Throwable t = exception;
while (t.getCause() != null) {
t = t.getCause();
}
t.printStackTrace();
I don't use RESTeasy, but it appears to be a dispatch mechanism for RESTful web services.
Assuming this is the case, then it has different design goals from other libraries: they are invoked from your application, but RESTeasy is responsible for invoking your application. It therefore has to protect itself from poorly written code. A "last ditch" exception handler is a common way to do this; you'll see the same thing in Swing.
Whether or not it should log the uncaught exceptions is a different matter. Perhaps there's a configuration option to do this. Or perhaps you need to add a couple lines of code. It is open-source, after all, and I'm sure the maintainers would appreciate a well-written bug report with patch.
Yes, your exception is swallowed by RESTeasy, wrapped in UnhandledException and logged. But your exception lies too deep within to be included in the stacktracs.
To print out your exception to the console, you could append the following to 'WEB-INF/classes/logging.properties'
org.apache.catalina.core.ContainerBase.[Catalina].level = FINEST
org.apache.catalina.core.ContainerBase.[Catalina].handlers = java.util.logging.ConsoleHandler
in my application (using spring),
i try to call a method from view using spring exposingBean. and when i try to invoke a method from view, it throw error. i try to catch with HandlerExceptionResolver, but no luck, i think it cannot handled by HandlerExceptionResolver because exception wasn't thrown to controller.
so i try another way to redirect the request when exception thrown. and i think aspect has possibility to do it. is it possible to redirected request when exception thrown from aspect?
As you rightly say, HandlerExceptionResolver will not be invoked when an exception is thrown from inside the view. These resolvers are very specifically targetted at controller exceptions.
Your best options here are to use either a HandlerInterceptor and override the afterCompletion method, which will contain the exception thrown by the view. You may be able to send a redirect from here, dependning on whether or not the response has already been committed by the view.
I don't see how aspects would help you here, either. Not the tool for this job.
However, my advice to you is to stop using exposed bean in your JSP. I realise that it's temptingly convenient, but this is the sort of trouble you get from using it. I advise that your controller assemble all the data required by the view, stick it in the model, and send it to the view. That way, there's less danger of the view triggering an exception, since it already has everything it needs.
Also, if you need to send a redirect, as you do, then you really need to do this before the view starts executing. Otherwise, the view layer may start writing out the HTTP response headers before the exception is thrown. If this happens, then you won't then be able to send a redirect instead - the response is "committed".
I am working on an old web application which uses Struts 1.1. In order to do business validations (complex validations involving multiple form properties and invoking backend services), i wrote an ActionForm implementation which invokes a chain of validators on the ActionForm.validate method.
The chain of validators are implemented using commons chain. Everything is good, except that when an exception occurs in ActionForm.validate, it is not caught by the struts exception handler, instead the stacktrace is shown on the screen. The struts exception handler doesn't catch that
Is there anyway to avoid the stacktrace on the page and propagate the exception to struts exception handler?
Thanks
Maybe it's best that validators don't throw exceptions at all. Validations are ment to check user inputs against constraits like minChars, maxChars, password strength/verification, email syntactical correctness, isNumber and so on. If a validator fails, it should only return false - never throw an exception. See the examples at http://struts.apache.org/1.2.4/userGuide/dev_validator.html
If your validator invokes backend functions ... there is something wrong - I think. The validator should only add field errors.
If there are errors as the consequence of syntactical correct inputs (e.g. wrong user/password for a login) then your struts application (your actions) should handle this and return action errors to the user. This can be done by redirecting to error pages upon thrown exceptions (UserNotLoggedInException).