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()); }
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()); }
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); }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With