I was reading this article on Exception handling in Spring MVC and in
"what to use When " section of that blog, it mentions
For exceptions you write, consider adding #ResponseStatus to them.
For all other exceptions implement an #ExceptionHandler method on a #ControllerAdvice class or use an instance of
SimpleMappingExceptionResolver. You may well have
SimpleMappingExceptionResolver configured for your application
already, in which case it may be easier to add new exception classes
to it than implement a #ControllerAdvice.
Is there any good reason why we should not put all handling in #controlleradvice?
Thanks.
For example if you would write your own exception for NotFound - which is pretty self-explanatory, you don't have to add anything extra to this exception, writing a handler for it is overkill - you can just add a #ResponseStatus to it place some info like (value = HttpStatus.NOT_FOUND, reason = "Not found") which if fixed and be done with it.
Now for exceptions which require logging or require more control over the text - e.g. internationalization you will write it in the handler.
Think they were just trying to avoid the handler overkill for places where it can be handled with one line extra.
Related
I would like some advice on how to achieve the following. I'm not providing code, as my problem is theoretical, but upon request I can. So this is the situation:
I have multiple controllers, each can throw XYException
I have a #ControllerAdvice class, in which I have an #ExceptionHandler watching for XYExceptions. When it happens, it prints out "XY".
In one (and only one) controller, when XYException is thrown, I want to do some additional task (let's say, do something that only that controller can do), and then I want the exception to be "passed on" to the global handler mentioned above.
I know I can catch the exception, do the desired task in catch block, and then re-throw the exception so the global handler can catch it, but what if I have 23 methods in the controller potentially throwing XYExceptions, and I do not want to put try-catch blocks in all 23 methods.
What is the clean Spring way of achieving this?
You could use AOP to achieve that. You'd write a method that intercepts the method inside that controller and when they throw an exception, you're aop method would run and you can do your stuff and then the exception would go in your handler class.
To achieve that you should have a class and anotate it with #Aspect and #Component
then have a method anotated with #AfterThrowing and setting the pointcut which will intercept when the given method throws an exception.
Look into Aspect Oriented Programming and Aspectj for more info.
The easy way to handle this case in ControllerAdvice is checking the stacktrace where the exception originated.
#ExceptionHandler(Exception.class)
public String handleExc(HttpServletRequest req, HttpServletResponse res, Exception e) {
if ( /*Have all null and safe check */ e.getStackTrace()[0].contains("MyController")) {
// Do your exception handling
}
}
By default, Spring's Transactional annoation won't rollback on checked exceptions.
One can use Transactional's rollbackFor attribute to override this.
Is it possible to override this behaviour globally rather than on each annotation?
I have methods that throw IOException. A possibility could be wrapping those exceptions in RuntimeException, as they are unrecoverable for my code.
There are two approaches that I am aware of:
Create your own Meta-Annotation that handles your particular
transaction semantics
Write an aspect (either around or after-throwing) that wraps all checked exceptions in RuntimeExceptions
I am developing web application with spring + hibernate. As per my knowledge, it is best practice to put #transactional in service layer. Spring throws DataAccessException in case of any exception while updating data into database.
Below is my high level class structure.
#Transactional
class OrderService {
public void createOrder() {
try {
orderDAO.createOrder();
} catch (DataAccessException e) {
// convert into business exception and sends back to presentation logic.
}
}
}
What happens here is data access exception is thrown only after completion of method. so if any exception occurs, I am not able to convert it into business exception in catch block.
Work around is to flush the hibernate session in dao method but I do not like this approach. Is there any better approach to this?
I presume you are using Spring MVC, although you do not specify. If you are using Spring MVC, then there are a few different options.
You can create a Filter that looks for the DAE exception and recodes it to be a different status or exception that your front end would better understand. You can look at Spring Security's ExceptionTranslationFilter as an example of how this is already done for different exceptions
You can use a SimpleMappingExceptionResolver to map a specific exception to a particular view. This would allow your presentation layer to be agnostic and not need to know anything about the exception thrown.
You can use an #ExceptionHandler within a specific controller to handle the DAE exception in a general manner and appropriately prepare something for the presentation layer.
As an extension to #3, you can use a #ControllerAdvice to manage all DAE exceptions for any controllers in the webapp.
You can read about Exception Handling in Spring MVC for more details as well.
Generally speaking, I find that the best solution is to catch transaction exceptions at a much higher level and manipulate the information to present it to the front end in a way that is back-end agnostic. This allows you to set up your own error codes/etc. The only time I try/catch exceptions in my service itself is if I actually want to attempt a retry or modify the logic flow based on some specific exception and don't want the front end to know about it.
I have come across few Spring contoller's function, which are throwing IOException.
#RequestMapping(method = ***)
#ResponseBody
public List<Offering> getOfferingDetailsList(HttpServletResponse response, #PathVariable("productIds") String productIdString, HttpServletRequest request) throws IOException
I doubt about use of such exception throwing, when no one above is catching and handling it. Is it fine to set response status like "response.setStatus(HttpStatus.SC_NOT_FOUND)" in place of throwing such exception ? What is the standard way of handling exception in controller ?
it is always good to have common exception handling functionality , so that we can make our controller code free from exception handling , by externalize to common exception handling functionality, i have come across this interesting topic for this purpose
http://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc
and also use a global exception handler that will do that for all the exceptions of all the controller methods. That will centralize the exception handling, prevent massive code duplication, and avoid cluttering your controller methods.
Look at the #ControllerAdvice and #ExceptionHandler annotations.
A fairly standard way of handling exceptions in Spring Controllers is to use #ExceptionHandler.
Check out this post for more details
I am using Spring with Velocity. At times velocity produces an exception like
Error in interpolating string literal : org.apache.velocity.exception.MethodInvocationException: Invocation of method 'getMessage' in class org.springframework.web.servlet.support.RequestContext threw exception class org.springframework.context.NoSuchMessageException : No message found under code 'XX' for locale 'en_US'.
Question is - can I instruct spring to suppress NoSuchMessageException ? I am pretty new to Spring so do not know if I can create a exception handler which will not throw a exception if the message is not found? In my use case, it is a valid use case of not finding some of the messages in the messages.properties file.
[EDIT] - I found a way org.apache.velocity.app.event.MethodExceptionEventHandler to supply an even handler to velocity. I am however not sure how to register it with Spring.
It would be better, I think, to address the problem directly, rather than trying to suppress the exception, which could lead to avoid behaviour and uncompleted operations.
However, you didn't tell us how you'd want the system to respond in cases where the message is not defined for a given code. Do you want a blank String, or should the code itself be used as the default message?
I'm assuming that somewhere in your Spring context you have a defined a messageSource bean of some sort. These MessageSource beans usually have a property useCodeAsDefaultMessage. This defaults to false, but when set to true they will return the code itself as the message, in cases where no message is defined.
Alternatively, you can subclass the MessageSource class (whichever one you're using), and override the getDefaultMessage() method to handle cases where the code cannot be resolved.