October 30, 2007

Spring 2.5 web mvc gripe

Spring 2.5 is almost upon us, so I thought I’d grab the RC and have a look at what’s new.

My eye was drawn immediately to the enhancements to the MVC layer; specifically, support for convention-over-configuration and annotation-based configuration. Both of these techniques should help to reduce the yards of XML needed to configure spring web applications (although to be fair, things have been getting better since 2.0 re-worked the config file formats).

Anyway, I started building a little demo, using the sample apps as a template. And came up against an interesting problem almost immediately. Here’s an excerpt from the docs, showing a MultiActionController using annotated configuration:

@Controller
public class ClinicController {

    @RequestMapping("/vets.do")
    public ModelMap vetsHandler() {
        return new ModelMap(this.clinic.getVets());
    }

    @RequestMapping("/owner.do")
    public ModelMap ownerHandler(@RequestParam("ownerId") int ownerId) {
        return new ModelMap(this.clinic.loadOwner(ownerId));
    }

Spot the obvious mistake? There is no need for the @RequestMapping annotation to have to repeat the name of the mapping, if every method follows the same convention. Just take ‘handler” off the end of the method name and use that for the URL. Don’t make me type it twice!
What’s more annoying is that this works in the old-style MultiActionController – but if you go down that route your controller methods have to take HttpServletRequest/Response parameters and you can’t use the lovely new @RequestParam binding annotations. Gah!

If you’re content to have a separate controller per URL, with separate functions for GET/POST (SimpleFormController style), then the convention + annotation based approach works pretty well – so it’s a shame that they couldn’t finish the job and sort out MultiActionController as well; then we could have rails-style create/read/update/delete controllers. Oh well…


- 5 comments by 2 or more people Not publicly viewable

  1. Nick Howes

    That is a bit unnecessary… I wonder if there’s a resolver that could be implemented to determine a default mapping like this.

    I do really like the look of the @RequestParam stuff… less ServletRequestUtils.getStringParemeter(blah, blahblah) about the place is a good thing, and would make unit tests a hell of a lot nicer to read and write.

    30 Oct 2007, 11:22

  2. Chris May

    I’m pretty sure it could be improved, either with a smarter resolver, or even with an annotation-aware MultiActionController; the current version just looks for all methods with a signature like “Map doSomething(request, response,command)” – that could be made to look for all methods annotated with (something like) either ”@DefaultRequestMapping” or ”@RequestMapping(url) and process them accordingly.

    I’m kind of puzzled, though, why this didn’t occur to the Interface21 guys when they wrote the code above. Or maybe it did, and there’s some subtle reason why it can’t be done.

    30 Oct 2007, 11:30

  3. Juergen Hoeller

    Hi Chris,

    We have actually considered something like this already but didn’t include in RC1 since we wanted to keep the scope limited to the basics. The main reason for specifying paths at the handler method level is that this does not require any path (or path pattern) mapped at the controller type level, in contrast to MultiActionController. The mappings expressed at the handler method level are perfectly sufficient.

    That said – I agree that such MultiActionController-style defaulting makes sense as well. Hence I’ve implemented MethodNameResolver support in Spring 2.5’s AnnotationMethodHandlerAdapter, using an InternalPathMethodNameResolver by default for resolving handler methods with ‘empty’ @RequestMapping annotation. Note that you do need a ”/*.do” (or the like) mapping at the controller type level (or a corresponding externally specified mapping), just like for MultiActionController. The handler methods will then be mapped based on their method name, within that ‘primary’ mapping that comes from the type level. The actual method name resolution can be customized through AnnotationMethodHandlerAdapter’s “methodNameResolver” property, for example using an InternalPathMethodNameResolver with custom ‘suffix’ (analogous to MultiActionController).

    This will be released in Spring 2.5 RC2 on Monday. Thanks for raising this!

    Cheers, Juergen

    10 Nov 2007, 23:42

  4. Chris May

    Awesome! Thanks Juergen; looking forward to trying it out…

    12 Nov 2007, 12:14

  5. nidhin

    nice post

    29 Dec 2007, 09:08


Add a comment

You are not allowed to comment on this entry as it has restricted commenting permissions.

Most recent entries

Loading…

Search this blog

on twitter...


    Tags

    Not signed in
    Sign in

    Powered by BlogBuilder
    © MMXXI