I must say I am enjoying using the new Spring MVC - it's a massive improvement over the original framework which I found pretty clunky, especially with regard to form handling.
Setup
Configuring the application is a doddle. All you need to do is register the annotation HandlerAdapter (which does the main request processing work) and HandlerMapping (which maps URLs to your controllers). You can do this using Spring config like:<bean class="org.springframework.web.servlet.mvc.
annotation.DefaultAnnotationHandlerMapping"> <bean class="org.springframework.web.servlet.mvc.
annotation.AnnotationMethodHandlerAdapter">and then you're ready to go. Controllers definitions can found automatically via class path scanning, or added explicitly into the Spring config files, which I prefer to do.
One really nice thing about the controllers is the simple way to map URLs to methods as well as to provide arguments to the methods, both using annotations. An example is show below:
@RequestMapping("/warehouse/postProductsSubmit.htm") public String postProductsSubmit( Map model, @ModelAttribute("command") PostProductsForm command, BindingResult result) { //do stuff //redirect when finished return "redirect:postProductsForm.htm"; }
So what's missing?
There were still a few bits I felt needed to be added to make the Spring MVC annotation truly usable for my application. Here's what they are.Missing annotations for obvious argument types
The Spring MVC annotations recognise a whole bunch of argument types. Many of these will be automatically recognised from the Servlet API including HttpServletRequest, HttpServletResponse, ServletRequest, ServletResponse, HttpSession, Principal, Locale, InputStream, Reader, OutputStream and Writer. Others will be recognised from Spring MVC annotations, such as @ModelAttribute and @RequestParam (which binds a request parameter).What would be nice would be some built in annotation types which you could extract other types of information from the Servlet API environment in an non-intrusive way. Here I am thinking of the following:
- @SessionAttribute: extract and bind a named session attribute.
- @RequestAttribute: do the same for a named request attribute.
- @RequestHeader: extract a request header.
- Plus various others
Flash Scope
Flash scope, popularised initially by Rails, is a mechanism for transferring state from one request to the next without having to pass it via URLs. It is implemented through a session scoped attribute which is removed as soon as the value is consumed in the subsequent request. It works particuarly well with redirecting after a post.Flash scope is especially convenient for certain use cases because it combines the convenience of session-based attributes without the long running overhead of having state hanging around in a session over a long period.
Spring MVC annotations currently don't support flash scope, so added an extension to AnnotationMethodHandlerAdapter which support flash scope. Basically you can use it as follows. In your controller method, simply set a model attribute with the prefix "flash:". The attribute will be available in the next request using the @RequestAttribute annotation. An example below demonstrates this.
@RequestMapping("/submit.htm") public String submit( Map model) { //do stuff //redirect when finished model.put("flash:mydata", mydataObject); return "redirect:show.htm"; } @RequestMapping("/show.htm") public void(@RequestAttribute("mydata") MyDataClass mydata) { //if you redirected using flash, mydata
//will contain the mydataObject instance //from the last call }
No subclass hooks for manipulating model
When I first started with the annotation-based controller I found it a little frustrating that there were no subclass hooks in the provided AnnotationMethodHandlerAdapter for manipulating the model. The only way you can do this is in the mapped request method as well as in special @ModelAttribute methods, which are also present in your controllers. An example is below:@ModelAttribute("command") public PostProductsForm getPostProductsForm() { return new PostProductsForm(); }
I'm not sure if this is still a problem because I have found quite acceptable workarounds which solve the problems I was trying to solve, without having to resort to such a technique. Nevertheless, is does strike me as a sensible thing to be able to do, provided it is is done in a well-defined and controlled way.
5 comments:
I feel its easier and better to use annotations instead of extending the SimpleFormController class. Very nice tutorial indeed.
regards,
Eswar.
Vaannila
I've noticed the parameters I add using model.addAttribute("flash:var",var) , append 'var' to the querystring. Is there any way to avoid this, or does it happen before the Annotation handler gets hold of it.
Thanks for the example.
When we add using model.addAttribute("flash:successMessage","Information is successfully updated") , append "Information is successfully updated" to the query string.
Is there any way to avoid this?
awesome!
Thank you!
Post a Comment