Converting Spring MVC XML bean definitions into annotations

(Recovered from my old Blog).

As of Spring 2.5, annotations can be used on Spring MVC classes instead of defining each and every page in the *-servlet.xml definition file. However, most online guides still reference the old practice. Below is a simple guide to migrating to (in my opinion), the much cleaner annotation approach.

‘Normal’ Pages

Previously, ‘normal’ pages would:

  • Implement the Controller interface
  • Implement the handleRequest method
  • Have a simple *-servlet entry along the lines of:

Switching this to annotations is simple:

Firstly, add the context:component-scan element to your *-servlet.xml file, along with the Spring MVC annotation handlers:

For the above to work you will also need to add the context namespace URI to your main beans definition (third line down) and the schema to use (6th and 7th lines down):

Annotate your class with the @Controller annotation, and a @RequestMapping annotation which specifies which URL is mapped by this controller:

The method which handles the request (which – unlike the previous case where we implemented an interface – can have any name) should be annotated with @RequestMapping(method = RequestMethod.GET).

So the bean definition in *-servlet.xml is removed, and the class becomes:

Note that unlike the traditional xml based approach, the @RequestMapping annotation specifying which URL to map can be set at the method level (allowing multiple URLs to be mapped by a single Controller).

‘Form’ Pages

Form pages are a little more complicated. Previously, they would have:

  • Extending the superclass SimpleFormController
  • Overridden methods onSubmit and formBackingObject
  • Had a complicated bean definition containing all form options (e.g. which validator to use, which success page, etc)

To migrate these, first enable context:component-scan, along with the new Spring MVC annotation bean definitions as per the previous case.

Next, annotate the form class as per the ‘normal’ case. The method annotated with @RequestMapping(method = RequestMethod.GET) handles the initial ’setup’ of the form – basically what was previously handled in formBackingObject. This method also returns the view to use for the form. The command object will be initialised here, then stored in the model).

The method which is called when the ‘Submit’ button is pressed is annotated in a similar manner, except the RequestMethod is POST instead of GET. However, the differences then get larger:

There is no automated validation (assuming a validator is specified of course). See below how this is handled.
The validator will return a status. If there is an error we simply return the same view. If not, we set the SessionStatus to complete and return the name of the Success view to use.
To get at our command object we need to pull it out of the model – using the @ModelAttribute(“contactForm”) annotation.
As mentioned above, we need to call the validator directly. To do this, we need to @Autowire the validator into the class (as per normal Spring injection). Since we are no longer relying on Spring MVC calling the validator, we can improve the validate method on the validator to become typesafe, instead of passing in a generic object as before.

Complete class:

Leave a Reply

Your email address will not be published. Required fields are marked *

%d bloggers like this: