Alexandre Martins On Agile Software Development

30Sep/080

Spring MVC, almost there!

One of the things I really like about Spring 2.5 is the new set of annotations for defining controllers.
Now you don't have to extend any superclass to turn your class into a controller, just add the @Controller annotation on the top of the class definition and that's it, you got one (still have to define it as a bean in the XML file). Another cool feature in this set, is the combination of the @RequestMapping and @RequestParam annotations.

@Controller
public class ProductController {

	@Autowired
	private MemberRepository repository;

	@RequestMapping(value="/product", method=RequestMethod.GET)
	public String product(@RequestParam(value="id") String id, ModelMap model) {
		model.addAttribute("product", repository.getProduct(id));
		return "product/view";
	}
}

@RequestMapping gives you flexibility to map methods in the controller to whatever URIs and HTTP methods (default to RequestMethod.GET) you like. They are not dependent on another or on controller's name. This really turns things easier when mapping your methods to RESTful URIs. The only downside in this implementation is that it doesn't allow you to pull out parameters from an URI. If you want to grab some data from the URL, you are going to have to do it the old fashioned way, like:

mystore/product?id=123456

But on the other hand the @RequestParam annotation frees you from the dirty job of extracting parameters from a request. Thus, you don't even need to know about the HttpServletRequest and HttpServletResponse objects. To retrieve a parameter from a request, just add it as a method parameter and define it as a @RequestParam. The value attribute on the annotation should match the URL parameter name.

@RequestMapping("/products")
public String products(@RequestParam(value="letter", required=false) String letter, ModelMap model) {
	checkLetter(letter);
	model.addAttribute("products", repository.getProducts(letter));
	return "product/list";
}

You also have the option of defining a request parameter as required or not (default set to required), so as in the example above, the method would be able to handle requests coming from both mystore/products, to list all existent products, and mystore/products?letter=A, to list all existent products starting with the letter 'A'. Really neat!

The good news is that Spring 3.0 is coming out next November, and it will include the URI templating functionality. According to Springify blog, you will be able to define a URI like mystore/product/123456, and that will map to the controller method as follows:

@RequestMapping("/product/${id}")
public String product(@RequestParam("id") String id, ModelMap model) {
	model.addAttribute("product", repository.getProduct(id));
	return "product/view";
}

So let's wait for it!