I\'m working with Spring MVC and I\'d like it to bind a a persistent object from the database, but I cannot figure out how I can set my code to make a call to the DB before
While it is possible that your domain model is so simple that you can bind UI objects directly to data model objects, it is more likely that this is not so, in which case I would highly recommend you design a class specifically for form binding, then translate between it and domain objects in your controller.
So I ended up resolving this by annotating a method with a @ModelAttribute of the same name in the class. Spring builds the model first before executing the request mapping:
@ModelAttribute("item")
BenefitType getBenefitType(@RequestParam("id") String id) {
// return benefit type
}
I'm a little confused. I think you're actually talking about an update workflow?
You need two @RequestMappings, one for GET and one for POST:
@RequestMapping(value="/update/{id}", method=RequestMethod.GET)
public String getSave(ModelMap model, @PathVariable Long id)
{
model.putAttribute("item", benefitDao.findById(id));
return "view";
}
then on the POST actually update the field.
In you example above, your @ModelAttribute should already be populated with a method like the above method, and the properties be bound using something like JSTL or Spring tabglibs in conjunction with the form backing object.
You may also want to look at InitBinder depending on your use case.
There are several options:
In the simpliest case when your object has only simple properties you can bind all its properties to the form fields (hidden
if necessary), and get a fully bound object after submit. Complex properties also can be bound to the form fields using PropertyEditor
s.
You may also use session to store your object between GET
and POST
requests. Spring 3 faciliates this approach with @SessionAttributes
annotation (from the Petclinic sample):
@Controller
@RequestMapping("/owners/*/pets/{petId}/edit")
@SessionAttributes("pet") // Specify attributes to be stored in the session
public class EditPetForm {
...
@InitBinder
public void setAllowedFields(WebDataBinder dataBinder) {
// Disallow binding of sensitive fields - user can't override
// values from the session
dataBinder.setDisallowedFields("id");
}
@RequestMapping(method = RequestMethod.GET)
public String setupForm(@PathVariable("petId") int petId, Model model) {
Pet pet = this.clinic.loadPet(petId);
model.addAttribute("pet", pet); // Put attribute into session
return "pets/form";
}
@RequestMapping(method = { RequestMethod.PUT, RequestMethod.POST })
public String processSubmit(@ModelAttribute("pet") Pet pet,
BindingResult result, SessionStatus status) {
new PetValidator().validate(pet, result);
if (result.hasErrors()) {
return "pets/form";
} else {
this.clinic.storePet(pet);
// Clean the session attribute after successful submit
status.setComplete();
return "redirect:/owners/" + pet.getOwner().getId();
}
}
}
However this approach may cause problems if several instances of the form are open simultaneously in the same session.
So, the most reliable approach for the complex cases is to create a separate object for storing form fields and merge changes from that object into persistent object manually.