Mary
Mary

Reputation: 1595

spring Form binding using path not attribute not working

I have a form ,when I am using spring form tags with the path attribute,I get the following error java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'selectedPerson' available as request attribute

However when I use the regular HTML input with the name attribute I don't see any issues.

What am I doing wrong.

Here is the controller code

@RequestMapping(value="/savePersonChanges.htm",method=RequestMethod.POST)
 public ModelAndView savePersonChanges(HttpSession session,@Valid @ModelAttribute(value="selectedPerson")PersonBean editedPersonBean,BindingResult bindingResult){
 ModelAndView mav=new ModelAndView();
 mav.setViewName(LANDING_PAGE;
 mav.addObject(TAB_SELECTOR,"EditPerson");
    if(session!=null){
        Rpt_date=(java.util.Date)session.getAttribute("editDate");
    }
    if(bindingResult.hasErrors()){
        mav.addObject("errorDescription",errorDescription );

    }
    else{
            /* Call service that updates database with table changes */
        try{
        PersonService.updatePerson(Rpt_date, editedPersonBean
        }
        catch(Exception e){
            log.logError("Exception while updating Person", e.toString());

    }

    }
 return mav;

}

The form is as follows:

 <form:form modelAttribute="selectedPerson" id="editPersonForm">
 <table id="selectPerson">
 <tbody>
    <tr>
 <td>
 <select id="personId"  name="personId" onchange="getPersonDetails(this)">
 <c:choose> 
   <c:when test="${empty selectedPerson}">
     <option value="0" selected ="selected">Select A Person</option>
     <c:forEach var="personIdItem" items="${editPersonProperties.personproperties}">
     <option value="${personIdItem.personId}"><spring:escapeBody>${personIdItem.personName}</spring:escapeBody></option>    
  </c:forEach>
   </c:when>
   <c:otherwise>
      <c:forEach var="personIdItem"    items="${editPersonProperties.personproperties}">
           <c:if test="${personIdItem.personId eq selectedPerson.personId}">
            <option value="${personIdItem.personId}"  selected ="selected">${personIdItem.personName}</option>  
            </c:if>
            <c:if test="${personIdItem.personId ne selectedPerson}">
            <option value="${personIdItem.personId}"><spring:escapeBody>${personIdItem.personName}</spring:escapeBody></option> 
           </c:if>
       </c:forEach>
   </c:otherwise>
  </c:choose>

   </select>
</td>
</tr>
</tbody>
    </table>

<!-- Person Details -->
<table id="editPersonTable">
  <tr>
     <td>First Name</td>
     <td> <form:input type ="text" path="fname" value="${selectedPerson.fname}"></form:input></td>
     <td>Last Name</td>
     <td> <form:input type ="text" path="lname" value="${selectedPerson.lname}"/></td>
   </tr>
 </table>

 <div class="editcancelstyle">
 <input id="savebtn"  type="button" onclick="savePerson()" value="Save" />
 <input id="cancelbtn"  type="button" onclick="cancelPersonEdits ()"value="Cancel" />
 </div>
</form:form>

I understand that the path attribute will bind the field to the form. However, I keep getting the bind error. If I replace using plain HTML, the controller sees the edited values for the fname and lname for the SelectedPerson bean.

Upvotes: 0

Views: 2729

Answers (1)

Fevly Pallar
Fevly Pallar

Reputation: 3099

Here is your problem, when you do :

<form:... modelAttribute="selectedPerson" ...>, the selectedPerson is the key of model object mapped from the holder of both Model & View class ( ex : ModelAndView), suppose you bind a model in your controller with new ModelAndView ("yourForm", "selectedPerson", new Person()),

 @RequestMapping(value = "/form")
    public ModelAndView userInput() {
        ModelAndView mv = new ModelAndView("personForm", "selectedPerson", new Person()); 
            return mv;
    }

now the Person is mapped with selectedPerson so when this form returned as the response from controller, your form has already been bound to the Person model, so that you use path to refer to this Person's attributes (ex. path="name" , means it refers to Person's name attribute)

In your form, on modelAttribute="selectedPerson", the selectedPerson is not binded to any models, since "selectedPerson" is never assigned to any object because you didn't do any binding first before processing ( submitting ) the form.

this is why you got

> java.lang.IllegalStateException: Neither BindingResult nor plain
> target object for bean name 'selectedPerson' available as request
> attribute.

Note that to get this binding works, add also the following on the top of your form

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>

you can then populate the fields of the form (assuming you put action="result.html"):

 @RequestMapping(value = "/result")
public ModelAndView processUser(  @ModelAttribute("selectedPerson") Person person, BindingResult result) {
    if (result.hasErrors()) {
        return new ModelAndView("errorPage","message","Something goes wrong");
    }

   /*System.out.println(person.getName());*/

    ModelAndView modelAndView = new ModelAndView();
    modelAndView.setViewName("personResult");
    modelAndView.addObject("person", person);
    return modelAndView;
}

Upvotes: 1

Related Questions