Spring WebMVC's tag library: form:checkboxes works as expected while an iteration over form:checkbox does not

StackOverflow https://stackoverflow.com/questions/22724747

  •  23-06-2023
  •  | 
  •  

Domanda

Introduction

When creating a form for an @Entity with a related list, I ran into a strange behaviour. <form:checkboxes/>and an iteration over a list generating several <form:checkbox/> behave differently where they should not, at last not from my point of view.

The code

I have removed everything which seemed unnecessary to me, but feel free to ask if any code is missing.

Models

I have a more ore less simple (or anemic as some might say) models of roles and rights.

The entity for Role:

@Entity
public class Role implements Serializable{

/* Setters and Getters and some annotations omitted for readability
 * Some annotations too. Unittests for the relations have no error so far.
 */

  @Id
  @GeneratedValue(strategy=GenerationType.AUTO)
  private Long id;

  @Version
  private Date lastModified;

  @ManyToMany(cascade={CascadeType.PERSIST,CascadeType.MERGE},fetch=FetchType.EAGER)
  private List<Right> rights = new ArrayList<Right>();
}

And for Right:

@Entity
public class Right implements GrantedAuthority,Serializable{

  @Id
  @GeneratedValue(strategy=GenerationType.AUTO)
  private Long id;

  @Version
  @Temporal(TemporalType.TIMESTAMP)
  private Date lastModified;

  @ManyToMany(mappedBy="rights")
  private List<Role> roles;

}

The form

Now obviously I want to add rights to my roles. This is a dynamic process in my app, so there is a form for it. Please see the comments in code for further details.

<form:form commandName="role">
    <p>
        <form:label path="name">Role Name</form:label><br/>
        <form:input path="name" cssClass="form-control"/>
    </p>
    <p>
        <form:label path="description">Description of role</form:label><br/>
        <form:textarea path="description" rows="3" class="form-control"></form:textarea>
    </p>
    <p>
        <%-- Now for whatever reason this (form:checkboxes) works as expected: --%>
        <%-- * Transfers correct values to the controller --%>
        <%-- * Is correctly checked and unchecked when the controller returns the page --%> 
        <form:checkboxes items="${allRights}" path="rights" itemLabel="name" itemValue="id" delimiter=" - "/>

        <%-- This does not work: --%>
        <%-- * The values are sent to the controller --%>
        <%-- * My CustomCollectionsEditor resolves the to the according rights --%>
        <%-- * Once the method returns, the values simply dissapear --%>
        <%--    <c:forEach items="${allRights}" var="right"> --%>
        <%--        <form:checkbox path="rights"  value="${right.id}" />${right.name} --%>
        <%--    </c:forEach> --%>
    </p>
    <p><button type="submit">Create new role</button></p>

</form:form>

The controller

My @Controller does nothing more than to create the form and send it back at the moment:

/* Makes allRights available in every page */
/* rightService.getRights() WAS an eternally cached method (memory only) 
 * but I deactivated caching when I ran into these problems
 */ 
@ModelAttribute("allRights")
public List<Right> populateRights() {
  _logger.debug("allRights:{}",rightService.getRights());
  return rightService.getRights();
}

@RequestMapping(value = "/add", method = RequestMethod.GET)
public ModelAndView addRoleView(ModelMap model) {
  model.addAttribute("role", new Role());
  return new ModelAndView("admin/roles/add", model);
}

@RequestMapping(value = "/add", method = RequestMethod.POST)
public ModelAndView addRole(@ModelAttribute("role") Role role,
            BindingResult result , ModelMap model) {

  /* Logs the selected rights and does so for both methods */
  _logger.debug("Role's Rights:{}",role.getRights());

  return new ModelAndView("admin/roles/add",model);
}
/* @InitBinder omitted for readability, as it is obviously working since both
 * ways actually send the data to the Controller method.
 */

Questions

  1. Is the behavior of the form what could be expected in conjunction with my code?
  2. If yes: Why and what am I missing here?
  3. If no: Do you see a work around other than processing the form entirely by hand?

Thanks...

...for taking the time to read this question and for your answer!

È stato utile?

Soluzione

Actually, it was my fault (as to be expected).

To be able to use related fields in this way, one either needs to implement an according @InitBinder or a Formatter.

See the according thread in Thymeleaf's user forum for details.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top