views:

24

answers:

1

I am using spring security and have an admin jsp page for editing user details. I want to be able to grant or revoke authorities on this page. The following checkboxes tag works to display a given user's existing authorities:

<form:checkboxes path="authorities" items="${roles}" delimiter="<br />" />

where authorites is an attribute of the User entity and ${roles} is a model attribute that is a list of all possible authorities.

This works for GETs: if I query up a user in this page, all the authorities are listed and the ones the user has are checked.

The problem is, if I make a change to the user's authorities (either adding a new authority or deleting an existing one) and attempt to save, I get the following error:

HibernateSystemException: IllegalArgumentException occurred calling getter of com.ebisent.domain.Authority.id

I can see in the debugger that Hibernate is wrapping my Set<GrantedAuthority> authorities in an org.hibernate.collection.PersistentSet. Hibernate doesn't add the new authority to my authorities set. Instead it adds a new Set containing the string value of the authority. The result is that my authorities HashSet (which should contain only GrantedAuthority elements) now contains LinkedHashSets that contain string representations of the authorities I am adding.

Here are the getter and setter for User.authorities:

public Set<GrantedAuthority> getAuthorities() {
    return authorities;
}
public void setAuthorities(Set<GrantedAuthority> authorities) {
    this.authorities = authorities;
}

What am I doing wrong?

A: 

It's an inherent limitation of HTML forms - since field values in HTML form are represented as strings, you need to instruct Spring how to reconstruct GrantedAuthority from the string representation. It can be done as follows:

@InitBinder
public void initBinder(WebDataBinder binder) {
    binder.registerCustomEditor(GrantedAuthority.class, new PropertyEditorSupport() {
        @Override
        public void setAsText(String text) throws IllegalArgumentException {
            GrantedAuthority value = ...;
            setValue(value);
        }
    });
}
axtavt
Thanks for the hint, axtavt. I added the initBinder and created an AuthorityEditor. I still seem to be missing something, but it looks like your suggestion has put me on the right path.
robert