Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Binding spring:checkboxes to enumset on submit causes error

Just a heads up, I am using Java and Spring for a web app.

I have an object (objectBean) that contains an EnumSet (enumSet) of type EnumInnerObject as an attribute. I am passing this object as a bean from my controller to my .jsp view. I use the following .jsp code to bind the checkboxes:

<form:form commandName="objectBean" name="whatever" action="./save.htm" method="post">
    <form:checkboxes items="${allOptions}" path="enumSet" />
</form:form>

Here is my controller initbinder:

@InitBinder
protected void initBinder(WebDataBinder binder) throws Exception{
    binder.registerCustomEditor(EnumSet.class, "enumSet", new CustomCollectionEditor(Collection.class){
        protected Object convertElement(Object element){
            if(element instanceof String){
                EnumInnerObject enumInnerObject= EnumInnerObject.valueOf((String)element);
                return enumInnerObject;
            }
             return null;
         }
     });

In the controller, I pass allOptions (separate from my bean), and this contains all EnumInnerObject options, so all the checkboxes are displayed. "enumSet" is the EnumSet attribute with the appropriate values contained (if the value is contained in EnumSet, then it automatically checks the correct box in "allOptions"). All of this works and the .jsp correctly shows the correct checked boxes. However, the problem is when I submit the page to save. I get the following error:

java.lang.IllegalArgumentException: Cannot convert value of type [java.lang.String[]] to required type [java.util.EnumSet] for property 'enumSet': PropertyEditor [com.example.controller.MyController$1] returned inappropriate value]

I have a feeling I have to modify the InitBinder to get the form submit to work. Any ideas??

Thanks!

like image 502
Jared Avatar asked Sep 06 '11 19:09

Jared


1 Answers

Frankly speaking, I can hardly imagine how this idea is gonna work: EnumSet collection is designed to store the values of enums, but at the moment it is constructed is needs to know the number of elements in that enum (= size of universe it its terms).

CustomCollectionEditor is passed a collection class as it's constructor argument, so it need to create this collection and it will fail for above reason. More over CustomCollectionEditor supports only the limited amount of target collections (ArrayList, TreeSet, LinkedHashSet, see CustomCollectionEditor#createCollection()).

In order not to overcomplicate things I suggest you to use common collections, rather than EnumSet. Otherwise you need to write your own property editor. The implementation won't be difficult, something like:

binder.registerCustomEditor(EnumSet.class, "enumSet",
    new PropertyEditorSupport() {
        @Override
        public void setValue(Object value) {
            EnumSet<EnumInnerObject> set = EnumSet.noneOf(EnumInnerObject.class);

            for (String val: (String[]) value) {
                set.add(EnumInnerObject.valueOf(val));
            }

            super.setValue(set);
        }
    });
like image 51
dma_k Avatar answered Sep 21 '22 04:09

dma_k