Spring - how to handle exception - spring

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.

Related

Mixing #ResponseStatus on our own Exceptions and handling other Exceptions in #ControllerAdvice

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.

How to use different error codes for validation messages?

I have a Spring Boot REST server which should return specific error codes when invalid input is provided. I don't need any i18n here, just plain English error codes like 'missing' is sufficient.
Using Spring Boot with Hibernate Validator, after validation I get a back Spring Errors object.
For each error I can get the code and defaultMessage. For a #NotBlank constraint this would return NotBlank and may not be null resp.
Basically I want to translate this error to just missing as I'm not interested in i18n translation. Also other constraints I want to more REST friendly error codes.
I though to use use a simple messages.properties or ValidationMessages.properties inside src/main/resources but this wouldn't work unfortunately. Note I tried both adding a general NotBlank=missing and specific NotBlank.entity.field=missing properties.
I'm not sure why it's not working... maybe because resolving i18n messages (in jsp world) does not go directly via Spring Errors but through the MessageCodesResolver implementation (just guessing).
Probably I could get the error code from the Spring Error and do a lookup from the message code resolver.
But I wonder why error.getDefaultMessage does not return the appropriate value form the ValidationMessages.properties.
Any suggestion is welcome.
The default message is the message as stated by the programmer. In the case of those JSR-303 annotations probably the ones as Hibernate thought of them. The default message including the code is passed to the MessageSource.getMessage method, which contains a parameter defaultMessage
When you look at the Errors object or actually the ObjectError method you will see that it implements the MessageSourceResolvable interface. This means you can just pass the error, as is, to the MessageSource, including the Locale if you want.
#RequestMapping
public Object foo(#Valid #RequestBody MyObject obj, Errors errors, Locale locale) {
for (ObjectError err : errors.getAllErrors()) {
String msg = messageSource.getMessage(err, locale);
// Do something with msg
}
}
Something like the above should resolve the message. The advantage of using the ObjectError itself is that next to the code you also have the parameters (for #Range or #Min) which you can then use in your message with placeholders.

ControllerAdvice ExceptionHandler not called from PropertyEditorSupport

I'm using Spring 3.2.1 and have a PropertyEditorSupport to force a parameter I'd like autoconverted to an enum to uppercase so it converts wrong-cased parameters. An IllegalArgumentException can be thrown if the parameter String can't be converted to the enum. My problem is that the status code is returned as 500 when it ought to be 400. I created a ResponseEntityExceptionHandler annotated with #ControllerAdvice and with a method annotated #ExceptionHandler (IllegalArgumentException.class), intending to set the status code there, but the method is never called when the exception is thrown. Why not? Is it the same problem as discussed here, MaxUploadSizeExceededException doesn't invoke the exception handling method in Spring ? i.e.
"...the exception is thrown before the request has reached the
dispatcher servlet. Therefore your exceptionhandler isn't called
because at the point the exception is thrown the target controller has
yet to be determined."
If so how can I return the proper status code?
Short version:
Put #ExceptionHandler(Exception) annotated method in #Controller class.
Longer version:
I noticed that the #ExceptionHandler(XxxException.class) annotated method in #ControllerAdvice class will only be called if XxxException happens "after" entering the method with matching #RequestMapping.
Conditions like MaxUploadSizeExceededException and MethodArgumentNotValidException will cause SpringMVC to NOT enter the #RequestMapping method, so advice is not applied.
My solution was to sadly place #ExceptionHandler(XxxException.class) annotated method in the actual controller class. Not nice but works.
Hope this helps. If someone knows of a better solution (when using #ControllerAdvice), do share.

Spring #ExceptionHandler handling multiple kinds of exceptions

I can't figure out how to handle more than one kind of exception by #ExceptionHandler.
I need to programmatically deal with these exceptions, for this I'd need a shared reference. Is this done via this reference "Exception ex" ? I don't think so, cause the exception is not caught like this, how would I do it then ?
I can't put all the exception references as arguments to the handler method, it wouldn't make sense, it can't be programmatically dealt with. I need a shared reference so that I could use "instanceof" on it or just send it somewhere else as a general "Exception"
#ExceptionHandler({DescriptionCstOrderException.class, SpecializationCstOrderException.class, NoUploadFileException.class,
DeadLineCstOrderException.class, DocumentCstOrderException.class, CommentCstOrderException.class})
public String handleFormException(Exception ex, ActionRequest actionRequest) {
logger.error(ex.getMessage());
SessionErrors.add(actionRequest, ex.getClass().getName());
return "mainOrderForm";
}
Additional question: what if I wanted to handle org.springframework.web.multipart.MaxUploadSizeExceededException, that is not thrown from any method of the handler? Because #ExceptionHandler catches only exceptions that are thrown from one of the handler methods.
The exceptionHandler method could be placed into some extended parent controller but if one uses only defaultAnnotationHandlerMapping... ?
Appreciate any help, I'm going crazy, this is very frustrating....
The #ExceptionHandler value can be set to an array of Exception types.
The implementation of using exception array as mentioned in Spring documentation will be like:
#ExceptionHandler({
NotFoundException.class,
MissingServletRequestParameterException.class
})
The #ExceptionHandler value can be set to an array of Exception types. If an exception is thrown matches one of the types in the list, then the method annotated with the matching #ExceptionHandler will be invoked. If the annotation value is not set then the exception types listed as method arguments are used. See the documentation for details.
Your question is rather confusing but your exception handler method will only handle one exception at a time. It will not catch multiple exceptions and then pass both of them into your handleFormException() method. If you need to handle these exception types differently then you should create an exception handler method for each one, specify an argument of that specific Exception type to your method, and then do the appropriate handling. For example:
#ExceptionHandler(DescriptionCstOrderException.class)
public String handleDescriptionCstOrderException(DescriptionCstOrderException exception, ActionRequest actionRequest) {...}
#ExceptionHandler(SpecializationCstOrderException.class)
public String handleSpecializationCstOrderException(SpecializationCstOrderException exception, ActionRequest actionRequest) {...}
// and so on...
Please refer to the Spring documentation for further information:
http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/mvc.html#mvc-ann-exceptionhandler

Spring destroy-method & half injected objects

In spring I often find myself utilizing the init-method & destroy-method attributes on beans. I'm curious about the contract of these methods. The init-method attribute seems to be called post construction and after all properties have been set. My question is if destroy-method has the same contract. If a setter throws for whatever reason, and the object doesn't have all its properties set, spring won't call the init-method, but I can't find any documentation about spring calling the destroy-method in this situation.
If it does obviously checks for null have to be in place, I'm curious what others do in this situation.
I did a simple test and I found out that in case of a setter throwing an exception both the init and the destroy methods won't be called.
I believe that this is the logical thing to do. A setter shouldn't be allowed to fail - if it does, there is nothing the framework can do to help you. The only reaction to this kind of error is to correct the setter. So I think that your question is irrelevant. Half injected objects shouldn't be allowed.
If you know that a setter could throw an Exception, you should catch it and set a reference to null or do whatever else is appropriate.
The Spring code of interest here is AbstractAutowireCapableBeanFactory.doCreateBean() (I'm looking at the Spring 3 M4 source, but it should be essentially the same for Spring 2.5). The the last thing this method does is register the bean for disposal, and it only does that if the rest of the method (including instantiation and initialization) succeeds. So if any part of the bean initialization fails, the destroy-method callback won't be invoked.

Resources