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.
Related
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.
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})
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
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
I don't quite understand what the #with annotation does.
in the Play framework site, it is written :
we can annotate the controllers using the #With annotation to tell
Play to invoke the corresponding interceptors
is it the same as inheritance ? will it invoke #before of the given class parameter ? what exactly does it do ?
The best way I can describe it, is that it kind of gives you multiple inheritance at your controller level for your interceptors. Interceptors being the #Before, #After annotations.
You could therefore
define a controller that dealt with your secure area #Before annotations
define a controller that dealt with injecting your static data for shared actions using #Before
you could then define a controller or controllers that contained all your actions, and use the #With annotation to make use of the two controllers described above. It means you can separate your code out cleanly, and not have to rely on inheritance to execute the #Before annotations.
Suppose you have 2 controllers:
A has #Before or other controller action injection annotations,
B get annotated with #With(A.class)
All those injection actions defined in A will be effective when calling B's action methods.
It's kind of inheritance. However with inheritance you can extend at most one class. But you can do #With({A.class, Z.class, ...})