views:

22

answers:

1

I have an application written in Spring 3.0 hooked up using Hibernate to a database. I have a controller to an update form. Whenever the form is submitted, I expect the object that is shown to be updated however a new object is created with a new ID value. I've looked over the "petclinic" sample and i can't see how it is different.

POJO

public class Person
{
    private int id;

    @NotNull
    private String name;

    //getter/setter for id
    //getter/setter for name

}

Controller

public class PersonUpdateController
{
    //injected
    private PersonService personService;

    @RequestMapping(value="/person/{personId}/form", method=RequestMethod.POST) 
    public String updateForm(ModelMap modelMap, @PathVariable personId)
    {
        Person person = personService.getById(personId);
        modelMap.addAttribute(person);
        return "person/update";     
    }

    @RequestMapping(value="/person/{personId}", method=RequestMethod.POST)
    public String update(ModelMap modelMap, @Valid Person person, BindingResult bindingResult)
    {
        if(bindingResult.hasErrors())
        {
            modelMap.addAttribute(person);
            return "person/update";
        }

        personService.save(person);

        return "redirect:person/" + person.getId() + "/success";
    }
}

JSP

<spring:url value="/person/${person.id}" var="action_url" />
<spring:form action="${action_url}" modelAttribute="person" method="POST">

<spring:input name="name" path="name" />

<input type="submit" value="Save" />

</spring:form>

PersonService Implementation

public class HibernatePersonService
    implements PersonService
{
    //injected
    private SessionFactory sessionFactory;

    //other methods

    public void save(Person person)
    {
        Session session = sessionFactory.getCurrentSession();
        session.saveOrUpdate(person);
    }
}
+3  A: 

Spring MVC doesn't do any magic with HTML forms. Since your form contains only one field, you get only one field populated in update method. So, you have two options:

  • Pass id as a hidden field in the form: <spring:hidden path = "id" />. Note that in this case you need to check possible consequences for security (what happens if malicious person changes the id).
  • Store Person in the session so that data from the form is used to update the stored object (note that it may cause interference if several instances of the form is opened in one session). That's how it's done in Petclinic:

-

@SessionAttributes("person")
public class PersonUpdateController {
    ...

    @RequestMapping(value="/person/{personId}", method=RequestMethod.POST) 
    public String update(ModelMap modelMap, @Valid Person person, 
        BindingResult bindingResult, SessionStatus status) 
    { 
        ...
        personService.save(person);
        status.setComplete(); // Removes person from the session after successful submit
        ...
    }

    @InitBinder
    public void setAllowedFields(WebDataBinder dataBinder) {
        dataBinder.setDisallowedFields("id"); // For security
    }
}
axtavt
That's exactly what I was missing! Thanks!
Jared Pearson