I am trying to find a best practice approach for a Spring MVC simple CRUD controller. There are a lot of examples of CRUD controllers both on the web and on this forum, but most of them suffer from one of two problems:
or
Does anyone have an example of crud controller that does not have these two problems?
Thank you,
Henry
@Controller
@RequestMapping(value="/role")
public class RoleController {
private static final Logger log = Logger.getLogger(RoleController.class);
@Autowired
private RoleValidator validator = null;
@Autowired
private RoleService service = null;
public void setService(RoleService service) {
this.service = service;
}
public void setValidator(RoleValidator validator) {
this.validator = validator;
}
@RequestMapping(method=RequestMethod.GET)
public String showForm(ModelMap model){
List<Role> domainObjectList = service.getRoles();
model.addAttribute("domainObjectList", domainObjectList);
return "role";
}
@RequestMapping(value="/add", method=RequestMethod.GET)
public String preAdd(ModelMap model){
Role domainObject = new Role();
model.addAttribute("domainObject", domainObject);
addConstrainedFields(model);
return "roleEdit";
}
@RequestMapping(value="/add", method=RequestMethod.POST)
public ModelAndView add(@ModelAttribute(value="domainObject") Role domainObject, BindingResult result) {
validator.validate(domainObject, result);
ModelAndView mv = new ModelAndView("role");
if(result.hasErrors()){
mv = new ModelAndView("roleEdit");
mv.addObject("domainObject", domainObject);
return mv;
}
service.insertRole( domainObject );
mv.addObject("domainObjectList", service.getRoles());
mv.addObject("messageKey","label.form.item.added");
//PROBLEM: the URL will remain "/add", but the content will be one of showing all roles + message that role was added.
return mv;
}
@RequestMapping(value="/update/{id}")
public String preUpdate(@PathVariable Integer id, ModelMap model) {
Role domainObject = service.getRole( id );
model.addAttribute("domainObject", domainObject);
return "roleEdit";
}
@RequestMapping(value="/update", method=RequestMethod.POST)
public String update(@ModelAttribute(value="domainObject") Role domainObject, ModelMap model, BindingResult result){
validator.validate(domainObject, result);
ModelAndView mv = new ModelAndView("role");
if(result.hasErrors()){
model.addAttribute("domainObject", domainObject);
return "roleEdit";
}
service.insertRole(domainObject);
model.addAttribute("messageKey","label.form.item.added");
model.addAttribute("domainObjectList", service.getRoles());
//PROBLEM: the message that the object was updated will be lost, but the URL will be /role and we will show all roles.
return "redirect:/role";
}
@RequestMapping(value="/delete/{id}")
public String delete(@PathVariable Integer id, ModelMap model) {
Role domainObject = service.getRole( id );
if (domainObject == null) {
model.addAttribute("messageKey","label.form.item.notfound");
return showForm(model);
}
service.deleteRole(domainObject);
model.addAttribute("messageKey","label.form.item.deleted");
return showForm(model);
}
@RequestMapping(value="/delete", method=RequestMethod.POST)
public ModelAndView delete(@ModelAttribute(value="domainObject") Role domainObject, BindingResult result){
validator.validate(domainObject, result);
ModelAndView mv = new ModelAndView("role");
if(!result.hasErrors()){
service.deleteRole(domainObject);
mv.addObject("messageKey","label.form.item.deleted");
domainObject = new Role();
mv.addObject("domainObject", domainObject);
}
mv.addObject("domainObjectList", service.getRoles());
return mv;
}
}
You should use RESTful URL design, and use gEt to rEad, posT to creaTe, pUt to Update, and Delete to Delete. Use the HiddenHttpMethodFilter for user agents that don't PUT or DELETE.
Use the Post-Redirect-Get pattern to avoid re-POSTs.
Use Flash Attributes to show Success/Failure messages on subsequent pages.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With