Looking for a way to assign #ControllerAdvice to specific url path pattern or controllers - spring

I was looking for a way to make #ControllerAdvice to be called for only specific url path pattern or a group of controllers. So, I found I can create custom ExceptionHandlerExceptionResolver and assign it to custom controllers by setMappedHandlerClasses(). The problem is, there is also a default ExceptionHandlerExceptionResolver and it also picks up my #ControllerAdvice. So I end up with two ExceptionHandlerExceptionResolver's, both of them having handler defined in #ControllerAdvice-annotated class. So, while my custom ExceptionHandlerExceptionResolver isn't called on all beans, default one does. Probably the solution would be to remove #ControllerAdvice and manually assign custom ResponseEntityExceptionHandler inside custom ExceptionHandlerExceptionResolver. I tried last way, but it appeared that I have to override a lot of methods from ExceptionHandlerExceptionResolver and in the end code looks very unclean. So, is there a way to make it in a different way, or maybe implement ExceptionHandlerExceptionResolver with custom handler cleaner?

As Ralph mentioned - as from Spring 4 (which by now had a stable release) ControlerAdvice's can be limited to Controler's with the specified annotations. Take a look at:
http://blog.codeleak.pl/2013/11/controlleradvice-improvements-in-spring.html
(second half of this article) for more details.

Put the Exception handling method in the Controller class and annotated the method with #ExceptionHandler. So this handler will be used only by this controller. -- And of course remove the #ControllerAdvice stuff.

Since Spring 4.0 you can use
#ControllerAdvice(assignableTypes = {OneOfControllersToApply.class})

Related

InitBinder for Spring Rest controller for #Valid

The way to use a Validator interface for Spring #RestController based is to create a validator custom class, implement Validator interface. In the controller class call InitBinder to register the validator class. Then when the REST req comes, the validator for that class is called. This still has a problem for me. Say I have a PersonValidator class that does one type of validation for POST and another type for PUT. Since both these handlers exist in the same REST controller class, how can I run different validations?
Say in the same rest controller class, i want to use PostPersonValidator for POST and PutPersonValidator for PUT. I do not know how to do it.
Just follow this article: http://howtodoinjava.com/2015/02/12/spring-mvc-custom-validator-example/
You basically have to create two separate validators - just as you said (one for POST, one for PUT). Then just call them inside your proper POST/PUT handling methods. Should be pretty straightforward if you follow the linked example.

Accessing Spring Controller Name from View

With Spring, how can i retrieve the following Controller attributes in the view?
Controller name
Controller's #RequestMapping URI
Action method name
Action method's #RequestMapping URI
One approach which i have tried is by creating a subclass of HandlerInterceptorAdapter and overriding postHandle. I register my subclass as an mvc:interceptor for a list of given paths - which is clunky to maintain but was the only way to avoid my interceptor being called for ResourceHandler requests (which i don't want). In my postHandle i can easily add the 2 name attributes, but not the URIs...
Parsing from the HttpRequest object requires constraints on all Controller RequestMappings. I.e. i must always map /Controller/Action or equiv scheme. Quite limiting.
Creating an ApplicationContext and querying that with the requestURI is too long-winded.
I am thinking about dropping the HandlerInterceptorAdapter and instead defining a BaseController for all my controllers to extend.
I wanted to ask before i do this, is there a better approach?
You haven't stated why you need to do this (it sometimes helps to include your motivation, as others can suggest alternative approaches).
But I'm guessing that the Spring 3.1 features loosely termed "end point documentation" may do what you are asking... See RequestMappingHandlerMapping in the Spring documentation which doesn't provide a lot of detail, so this example project is the best place to see it in action:
Spring MVC 3.1 Demo App
example controller
example JSP page

Override spring #ExceptionHandler methods

If I have a Spring Controller with two SEPARATE methods, one annotated by:
#ExceptionHandler(Exception.class)
and another annotated by:
#ExceptionHandler(SubException.class)
And my controller throws SubException.class, does it get handled by both methods, or just #ExceptionHandler(SubException.class)?
One handler will be invoked on a best fit basis.
The exact implementation is in AnnotationMethodHandlerExceptionResolver.findBestExceptionHandlerMethod(Object,Exception)
You can create your own annotation class which act as exception. And after that you need to provide your class annotation instead of Exception-handler.
Please let me know, if you have any query.
Handlers typically implement Spring’s Ordered interface so you can define the order that the handlers run in.
see Exception Handling in Spring MVC

SpringAOP-generated Dynamic subclass is missing annotation

I'm trying to use Spring AOP to inject behavoir into an object. The target object has a single method which is the join point for this new behavior. That method also has a custom annotation that I want to be able to read from other unrelated code. Because my class doesn't implement an interface, Spring is using CGLIB to dynamically subclass the target object. The generated subclass doesn't seem to have the annotation added to the original class.
I tried adding the #Inherited annotation to the custom annotation without luck. It turns out #Inherited only applies to classes. This suggests that Spring would have to explicitly apply my annotation to the overridden method in the subclass.
EDIT: I found a workaround and some more information on the problem. It looks like the CGLib people are aware of the issue. Annotations are treated like implementation in Java (rather than like part of the method signature). Overriding methods must re-declare annotations. CGLib doesn't do this (intentionally by the sound of things).
My workaround was to change my reflection logic. Where I was searching for the annotated method on the class passed to me, I now look at the class and it's super classes. I end up locating the method using the superclass (in the case of a proxy), but when I call the method, regular polymorphisim applies. This makes for some ugly reflection code (even more ugly than normal). It also seems like I shouldn't have to compensate for a SpringAOP implementation detail in my code.
It seems like Spring should provide a cleaner way to handle this. If anyone has other suggestions, they would be appreciated.
Are you sure you have the RetentionPolicy on your annotation set to RUNTIME ?

Calling #Controller methods once per request

Is there a nice way to have Spring's #Controller classes to call a specific method once per request?
Right now I'm using a method annotated with #InitBinder for this purpose, but this is suboptimal as #InitBinder methods get called several times per request. I just want to do some initialization / update stuff to use in my controllers.
What I'm looking for is something like Rails' before_filter, but as far as I can tell there's no functionality like that in Spring.
Sounds like you need a request-scoped controller bean. Spring will create a new instance of the controller for each request, and will initialize the bean each time using the standard mechanisms like #PostConstruct.

Resources