Results 1 to 6 of 6

Thread: Binding checkboxes to Enums and possible bug in Booking demo

  1. #1
    Join Date
    Dec 2008
    Posts
    4

    Default Binding checkboxes to Enums and possible bug in Booking demo

    Im trying to bind a list of 5 optional checkboxes (so 0 to 5 values will be form submitted). I want these to bind into a model field of type List<MyEnumeration>, similar to what the Amenities do on the Booking application.

    I have encountered a few problems while working on this, but firstly I dont think the Booking example works quite right.

    Booking.java
    Code:
        public void setAmenities(final List<Amenity> amenities) {
    	this.amenities = amenities;
        }
    bookingForm.jsp
    Code:
    <li><form:checkbox path="amenities" value="OCEAN_VIEW" label="Ocean View" /></li>
    <li><form:checkbox path="amenities" value="LATE_CHECKOUT" label="Late Checkout" /></li>
    <li><form:checkbox path="amenities" value="MINIBAR" label="Minibar" /></li>
    Rendered bookingForm.jsp
    Code:
    <ul>
    	<li>
                <input id="amenities1" name="amenities" type="checkbox" value="OCEAN_VIEW"/>
                <label for="amenities1">Ocean View</label>
                <input type="hidden" name="_amenities" value="on"/>
           </li>
    	<li>
               <input id="amenities2" name="amenities" type="checkbox" value="LATE_CHECKOUT"/>
               <label for="amenities2">Late Checkout</label>
               <input type="hidden" name="_amenities" value="on"/>
           </li>
    	<li>
                <input id="amenities3" name="amenities" type="checkbox" value="MINIBAR"/>
                <label for="amenities3">Minibar</label>
                <input type="hidden" name="_amenities" value="on"/>
    </li>
    </ul>
    If you run a debugger on it, it looks like it takes the "amenities" parameter from the request as a String (if one is selected) or Array of Strings (if more than one are selected) and converts them to a List<String>. It then puts the List into setAmenities(List<Amenity>). The JVM doesnt complain because its all done in the EL with reflection and its apparently not clever enough to figure out that the type of List is wrong. (Im told this is due to Java Generics using type Erasure) If you do something like the following in the setter, you get a ClassCastException (String to Amenity) that results in an ExpressionEvaluationException in the EL:

    Booking.java
    Code:
        public void setAmenities(final List<Amenity> amenities) {
        	this.amenities = amenities;
            for(Amenity a : this.amenities){ //ClassCastException thrown
                System.out.println("Amenity: "+ a);
            }
        }
    I dont think theres any place in the sample app where the Amenities are extracted from a saved Booking, but if they were, I think ClassCastExceptions would ensue.

    So, part 2, Id like to sidestep this by doing custom conversion. The problem I have there is that when one box is selected it wants to convert String to List, but when 2 or more are selected, it wants to convert Array of String to List. However I can only associate one custom converter Id with the bound field:

    webflow code
    Code:
    <binder>
    	<binding property="amenities" required="false" converter="myAmenitiesConverter"/>
    </binder>
    Converter Code:
    Code:
        public Class getSourceClass() {
            return String[].class;
            //or return String.class; ???
        }
    
        public Class getTargetClass() {
            return List.class;
        }
    I tried using indexed properties to force the source type to be an array all the time, but webflow didnt seem to work with that:

    Code:
    <li><form:checkbox path="amenities[0]" value="X" label="X" /></li>
    <li><form:checkbox path="amenities[1]" value="Y" label="Y" /></li>
    Any help on what to do about mapping checkboxes into Lists of Enums is greatly appreciated but hopefully someone will at least check out the Booking example and confirm or disconfirm that its got a problem.

  2. #2
    Join Date
    Aug 2004
    Location
    Melbourne, FL
    Posts
    2,794

    Default

    This is a known limitation with today's EL-based binding systems.

    The Spring BeanWrapper can do this type of conversion when binding to parameterized lists; however it's only enableable in Spring MVC view environments. To turn it on, configure the "useSpringBeanBinding" flag on a custom MvcViewFactoryCreator instance.

    Spring EL will generally solve this problem in the Spring Framework 3.0 timeframe.

    Keith
    Keith Donald
    Core Spring Development Team

  3. #3
    Join Date
    Dec 2008
    Posts
    4

    Default

    Thanks for the quick reply, sorry to hear that. I guess since im using someone elses model object my best bet will just be to make a wrapper class for it that takes List<String>

    I tried turning on Spring BeanMapping but it looks like that just makes things fail faster by detecting the mismatch at set-time instead of get-time.

  4. #4
    Join Date
    Dec 2004
    Location
    New York
    Posts
    30

    Default Solution?

    Had anyone figured this out? Is there a provisional fix? We are having the same problem and any suggestions greatly appreciated.

    Thanks,

    Dave
    Last edited by dreed; Jan 12th, 2009 at 01:03 PM.

  5. #5
    Join Date
    Sep 2005
    Location
    Chicago, IL
    Posts
    143

    Default I have a similiar problem

    I'm running into the same problem

    I'm trying to bind checkboxes to a List<Integer> and what I get is a List full of string values and not Integers so when I look over the List using generics, I get a class cast exception.

    I'm still trying to figure out a way to write a custom converter to get this to work.
    Grant Gochnauer
    Vodori Inc.
    Personal Blog

  6. #6
    Join Date
    Sep 2005
    Location
    Chicago, IL
    Posts
    143

    Default

    Quote Originally Posted by GrantGochnauer View Post
    I'm running into the same problem

    I'm trying to bind checkboxes to a List<Integer> and what I get is a List full of string values and not Integers so when I look over the List using generics, I get a class cast exception.

    I'm still trying to figure out a way to write a custom converter to get this to work.
    Looks like I'm going to have to run a post-bind method that goes through every list that contains Integer objects and manually loop through and convert each value. Then I manually create a new Integer object and re-add it back to a list.

    Very terrible hack. I wish there was a better way.
    Grant Gochnauer
    Vodori Inc.
    Personal Blog

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •