Spring 3.0 MVC Binding Enumerates Case

If I have RequestMapping in a Spring controller, for example ...

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

And the product is an listing. eg. Product.Home

When I request a 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 for an enum type converter to understand that a lowercase house is actually Home?

I would like url not to be case sensitive and my Java enumerations with standard capital letters.

thank

Decision

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

register 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 require special conversion

 @InitBinder public void initBinder(WebDataBinder binder) { binder.registerCustomEditor(Product.class, new ProductEnumConverter()); } 
+44
java spring spring-mvc
Jan 06 2018-11-11T00:
source share
4 answers

In general, you want to create a new PropertyEditor that does the normalization for you, and then you register this in your controller as follows:

 @InitBinder public void initBinder(WebDataBinder binder) { binder.registerCustomEditor(Product.class, new CaseInsensitivePropertyEditor()); } 
+21
Jan 06 '11 at 16:33
source share

I think you have to implement a custom PropertyEditor .

Something like that:

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

See GaryF 's answer on how to tie it

Here's a more tolerant version if you use lowercase letters 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); } 
+16
Jan 06 '11 at 16:35
source share

It is also possible to create a universal converter that will work with all Enums as follows:

 public class CaseInsensitiveConverter<T extends Enum<T>> extends PropertyEditorSupport { private final Class<T> typeParameterClass; public CaseInsensitiveConverter(Class<T> typeParameterClass) { super(); this.typeParameterClass = typeParameterClass; } @Override public void setAsText(final String text) throws IllegalArgumentException { String upper = text.toUpperCase(); // or something more robust T value = T.valueOf(typeParameterClass, upper); setValue(value); } } 

Using:

 @InitBinder public void initBinder(WebDataBinder binder) { binder.registerCustomEditor(MyEnum.class, new CaseInsensitiveConverter<>(MyEnum.class)); } 

Or globally, as the scaffman explains

+11
Jun 03 '15 at 2:54
source share

To add @GaryF to the answer and refer to it, you can declare global custom property editors by typing them into your custom AnnotationMethodHandlerAdapter . Spring MVC usually registers one of them by default, but you can specify it specially configured if you choose, for example.

 <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"> <property name="webBindingInitializer"> <bean class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer"> <property name="propertyEditorRegistrars"> <list> <bean class="com.xyz.MyPropertyEditorRegistrar"/> </list> </property> </bean> </property> </bean> 

MyPropertyEditorRegistrar is an instance of PropertyEditorRegistrar that MyPropertyEditorRegistrar turns registering custom PropertyEditor objects using Spring.

Just declaring this should be enough.

+7
Jan 06 2018-11-17T00:
source share



All Articles