What is the best way to register a converter for all subclasses of a particular class when using Commons BeanUtils?

For example, if I wanted to register the Converter for all instances of java.util.Map, is there a way to do this:

new BeanUtilsBean().getConvertUtils().register(new MyConverter(), Map.class); 

where is the method MyConverter#convert() called for any instance of the Map (for example, HashMap)?

At the heart of this is that I use BeanUtils to populate various beans from the database. Some of their properties are enumerations that implement a specific interface, and a custom routine is required to set their values. I was hoping to register one converter class for all implementations of the interface in question, but could not find a way to do this, so he had to do it on the fly by checking the class of each property in beans and registering my converter class if they were instances of this interface:

 BeanUtilsBean b = new BeanUtilsBean(); Class< ? > propertyType = pu.getPropertyType(this, setterName); if (isImplementationOfMyInterface(propertyType)) { b.getConvertUtils().register(new MyConverter(), propertyType); } b.setProperty(this, setterName, value); 

It seems pretty nasty, and I'm sure there should be a better way to do this?

+4
source share
2 answers

You can override ConvertUtilsBean . The following code adds Enum support, but you can do the same for Map :

 BeanUtilsBean.setInstance(new BeanUtilsBean(new EnumAwareConvertUtilsBean())); 

Class Definitions:

 public class EnumAwareConvertUtilsBean extends ConvertUtilsBean2 { private static final EnumConverter ENUM_CONVERTER = new EnumConverter(); @Override public Converter lookup(Class pClazz) { final Converter converter = super.lookup(pClazz); if (converter == null && pClazz.isEnum()) { return ENUM_CONVERTER; } else { return converter; } } } public class EnumConverter extends AbstractConverter { private static final Logger LOGGER = LoggerFactory.getLogger(EnumConverter.class); @Override protected String convertToString(final Object pValue) throws Throwable { return ((Enum) pValue).name(); } @Override protected Object convertToType(final Class pType, final Object pValue) throws Throwable { // NOTE: Convert to String is handled elsewhere final Class<? extends Enum> type = pType; try { return Enum.valueOf(type, pValue.toString()); } catch (final IllegalArgumentException e) { LOGGER.warn("No enum value \"" + pValue + "\" for " + type.getName()); } return null; } @Override protected Class getDefaultType() { return null; } } 

I got a solution from reading a blog post and comments from http://www.bitsandpix.com/entry/java-beanutils-enum-support-generic-enum-converter/

+6
source

I tried the same (my use case was a common converter for all Enum types), but from what I could see in the ConvertUtils code, only direct mapping between the converter and the class was supported, and there was no way to register the base class or interface.

It basically uses a map, where the key is the class and value of the converter, and to get the correct converter based on the class, it just does Map # get.

+2
source

Source: https://habr.com/ru/post/1339181/


All Articles