Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring 3.0 MVC binding Enums Case Sensitive

If I have a RequestMapping in a Spring controller like so...

@RequestMapping(method = RequestMethod.GET, value = "{product}") public ModelAndView getPage(@PathVariable Product product) 

And Product is an enum. eg. Product.Home

When I request the page, mysite.com/home

I get

Unable to convert value "home" from type 'java.lang.String' to type 'domain.model.product.Product'; nested exception is java.lang.IllegalArgumentException: No enum const class domain.model.product.Product.home 

Is there a way to have the enum type converter to understand that lower case home is actually Home?

I'd like to keep the url case insensitive and my Java enums with standard capital letters.

Thanks

Solution

public class ProductEnumConverter extends PropertyEditorSupport {     @Override public void setAsText(final String text) throws IllegalArgumentException     {         setValue(Product.valueOf(WordUtils.capitalizeFully(text.trim())));     } } 

registering it

<bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">         <property name="customEditors">             <map>                 <entry key="domain.model.product.Product" value="domain.infrastructure.ProductEnumConverter"/>             </map>         </property>     </bean> 

Add to controllers that need special conversion

@InitBinder public void initBinder(WebDataBinder binder) {     binder.registerCustomEditor(Product.class, new ProductEnumConverter()); }  
like image 810
dom farr Avatar asked Jan 06 '11 16:01

dom farr


2 Answers

Broadly speaking, you want to create a new PropertyEditor that does the normalisation for you, and then you register that in your Controller like so:

@InitBinder  public void initBinder(WebDataBinder binder) {    binder.registerCustomEditor(Product.class,     new CaseInsensitivePropertyEditor());  } 
like image 166
GaryF Avatar answered Sep 20 '22 15:09

GaryF


I think you will have to implement a Custom PropertyEditor.

Something like this:

public class ProductEditor extends PropertyEditorSupport{      @Override     public void setAsText(final String text){         setValue(Product.valueOf(text.toUpperCase()));     }  } 

See GaryF's answer on how to bind it

Here's a more tolerant version in case you use lower case in your enum constants (which you probably shouldn't, but still):

@Override public void setAsText(final String text){     Product product = null;     for(final Product candidate : Product.values()){         if(candidate.name().equalsIgnoreCase(text)){             product = candidate;             break;         }     }     setValue(product); } 
like image 44
Sean Patrick Floyd Avatar answered Sep 21 '22 15:09

Sean Patrick Floyd