I've implemented a converter for Apache BeanUtils library for converting String to an enum constant:
class EnumConverter implements Converter {
@Override
public <T> T convert(Class<T> tClass, Object o) {
String enumValName = (String) o;
Enum[] enumConstants = (Enum[]) tClass.getEnumConstants();
for (Enum enumConstant : enumConstants) {
if (enumConstant.name().equals(enumValName)) {
return (T) enumConstant;
}
}
throw new ConversionException(String.format("Failed to convert %s value to %s class", enumValName, tClass.toString()));
}
}
I use it in the following way:
// Register my converter
ConvertUtils.register(new EnumConverter(), Enum.class);
Map<String, String> propMap = new HashMap<String, String>();
// fill property map
BeanUtils.populate(myBean, propMap);
Unfortunatelly a setter in myBean instance except ConcreteEnumClass enum, instead of java.lang.Enum, that is why I receive the following exception during BeanUtils.populate method call:
org.apache.commons.beanutils.ConversionException: Default conversion to ConcreteEnumClass failed.
at org.apache.commons.beanutils.converters.AbstractConverter.handleMissing(AbstractConverter.java:314)
at org.apache.commons.beanutils.converters.AbstractConverter.handleError(AbstractConverter.java:269)
at org.apache.commons.beanutils.converters.AbstractConverter.convert(AbstractConverter.java:177)
at org.apache.commons.beanutils.converters.ConverterFacade.convert(ConverterFacade.java:61)
at org.apache.commons.beanutils.ConvertUtilsBean.convert(ConvertUtilsBean.java:491)
at org.apache.commons.beanutils.BeanUtilsBean.setProperty(BeanUtilsBean.java:1000)
at org.apache.commons.beanutils.BeanUtilsBean.populate(BeanUtilsBean.java:821)
at org.apache.commons.beanutils.BeanUtils.populate(BeanUtils.java:431)
If I register EnumConverter in the following way:
ConvertUtils.register(new EnumConverter(), ConcreteEnumClass.class);
Everything woks perfectly.
Since I would like to use my EnumConverter in general case, I would prefer it be used to convert String to any enum class.
Is it possible? How should I do it?
As of the current BeanUtils v1.9.2 I don't believe there is any way to do this when using the static singleton BeanUtils
and ConvertUtils
classes.
You could create an instance of BeanUtilsBean
, passing a custom ConvertUtilsBean
instance that has special handling for Enum targets.
An example is shown here (not my example, credit to its author "jeremychone"): http://www.bitsandpix.com/entry/java-beanutils-enum-support-generic-enum-converter/
Jeremy's simple implementation is as follows:
BeanUtilsBean beanUtilsBean = new BeanUtilsBean(new ConvertUtilsBean() {
@Override
public Object convert(String value, Class clazz) {
if (clazz.isEnum()) {
return Enum.valueOf(clazz, value);
} else {
return super.convert(value, clazz);
}
}
});