View Full Version : annotation based controller
hussain_engr
Feb 1st, 2008, 03:11 PM
In annotation based controller isn't there a single method like
protected Map referenceData(HttpServletRequest request)
which used to be in SimpleFormController to load all the refernce data.
or the only option is to use @ModelAttribute for each reference data you wan't to load?
joshk
Feb 7th, 2008, 05:52 AM
Hi hussain,
Although the new 2.5 annotation based controllers do not provide a convenient referenceData method, there are are still ways to add a large amount of reference information in a clean and simple fashion.
In some cases the reference information you are adding to the model will be the same for the majority of your controllers, eg. css paths etc. What you can do is create an abstract class which contains the common annotated ModelAttribute methods and have controllers extend the class, thus encapsulating the model attribute information into one central location.
public abstract class AbstractMainController {
@ModelAttribute("cssLocation")
public String cssLocationInformation(){
return "http://some.other.css.location/main.css";
}
}
But the problem with @ModelAttribute is that it is run before the @RequestMapping defined method, even if the reference data isn't required and the final view result is just going to be a redirect. Thus the other way around it, and not the cleanest way, is to create a method which adds all the required reference data into a ModelMap which is passed in as a parameter.
public void getBasicReferenceData(ModelMap modelMap){
modelMap.addAttribute("someInfo","boo");
}
But to be honest, I think the previous work-around is a bit cleaner as all you are going to end up doing is having this method being called in every request mapping annotated method.
Cheers
Josh
Bjoern
Feb 7th, 2008, 08:15 AM
Hi,
I'd say the most similar approach to teh referenceData method should be having a whole controller for the form-request.
@Controller
@RequestMapping("</whateveryouneed>")
public class ....
Inside this one you can define
@RequestMapping(method=RequestMethod.GET)
public String prepareForm(ModelMap model){...
// do what reference Data in the SimpleFormCoiltroller does
// basically put everything you need in the ModelMap and
// return the name of the view containing your form
...
return "<nameOfYourView>";
and
@RequestMapping(method=RequestMethod.POST)
public String onSubmit(...
//do what handleRequest of the SimpleFormController does
joshk
Feb 7th, 2008, 02:36 PM
Hi Bjoern,
I agree that creating one annotated controller which deals with a singular get and post request is similar to the simple form controller, but it is hardly utilizing the power and flexibility the new annotated controllers, and if the reference data is added in the get request like your example showed, then its not like the reference data method at all because now you have a simple form controller with no separate reference data info method.
I am not saying my solutions are better, but I think yours are a step back. Spring docs, core training, and a large proportion of the articles and blogs out there all agree that encapsulating related model concerns inside of one controller, eg. crud or help and about us etc. is best practice.
Your suggested way would mean that instead of reducing the number of controllers you would just be increasing them.
Josh
hussain_engr
Feb 9th, 2008, 06:29 AM
Thankyou guyz for you help
Bjoern, I have already tried your suggestion and it has issues ... like in case of validation if any error occurs combo box is not refilled but it is refilled in case of @ModelAttribute
following is the solution that I have come up with which also matches joshk's suggestion
@ModelAttribute("referenceDate")
public ModelMap referenceData() {
Customer customer = SecurityUtils.getUser();
Map<String,Object> map = this.taskService.loadNewTask(customer.getSsoId());
return new ModelMap().addAllAttributes(map);
}
Thanks for you help guys
joshk
Feb 9th, 2008, 07:10 PM
Hi hussain_engr,
The implementation you have decided to go with is a bit weird, to be honest.
When you declare a @ModelAttribute which returns a ModelMap, you are not returning a ModelMap of reference data to be used as the central request model data, but instead a ModelMap which is added to the central ModelMap.
I could understand if you grouped together similar reference data information within a single ModelAttribute method using a Map or class or something similar, but using a ModelMap seems a bit over kill to me, even though it is just a LinkedHashMap extension.
Can I recommend one last option which is not only clean and simple, but is very similar to the reference data method in the SimpleFormController :
@ModelAttribute
public void refDataTest(ModelMap modelMap){
modelMap.addAttribute("cssInfo", "http://www.css.com/test.css");
}
Spring MVC is smart enough to add the model map to the method and let you add as much ref data to the model map as you like.
This allows you to access the ref data via code similar to :
${cssInfo}
And, if you combine this with my first recommendation by putting this in a central abstract class which your other controllers extend from, you have a powerful way to add reference data in a singular central model attribute method.
I hope this helps
Josh
hussain_engr
Feb 9th, 2008, 11:09 PM
Thanks for you Help .... I'll consider you option.
Powered by vBulletin® Version 4.2.1 Copyright © 2013 vBulletin Solutions, Inc. All rights reserved.