Apache Commons BeanUtilsBean - exclude attributes from description ()

I am using the BeanutilsBean.describe() method to capture data for the audit log. It works great - that’s not a question!

However, there are certain attributes that need not be verified. They are written as strings in a list. For example, if you have the DomainObject.myValue attribute, the list will contain "myValue" , so the result of a call made to DomainObject.getMyValue() will not be included in the audit trail.

Currently, the code gets all the attributes from BeanutilsBean.describe() , and then iterates through them to undo the unwanted ones.

What I want to do is configure an instance of BeanUtilsBean with such a list of attribute names to exclude it so that it never calls these methods. Therefore, in my example, DomainObject.getMyValue () is never called at all.

I cannot figure out if this is possible when viewing the API or code.

+4
source share
2 answers

No, filtering as you do is the easiest way. The source of this method does not provide any custom filters. There are only two options that I can see when using BeanUtilsBean :

  • Call describe() and then filter the results (what are you doing now). You can wrap this with a static method using a signature, e.g. public static Map<String, String> describeBean(Object bean, String... excludedProperties)
  • Reset your own utility method (signature similar to the one above) that copies the describe() implementation, but does the filtering during the initial iteration. This would be more productive since it would not require an additional pass through the Map .
+1
source

This is the code I used to solve this problem.

This is a small adjusted copy of BeanUtilsBean.describe() that does not call the extracted attribute attributes; this is the “Roll your own” option from ach answer (the first option was used in real code for several years, but it never sat right with me!).

 import java.beans.PropertyDescriptor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; import java.util.Set; import org.apache.commons.beanutils.BeanUtilsBean; import org.apache.commons.beanutils.DynaBean; import org.apache.commons.beanutils.DynaProperty; import org.apache.commons.beanutils.MethodUtils; public class BeanUtilsBeanExtensions { private static final BeanUtilsBean BEAN_UTILS_BEAN = BeanUtilsBean .getInstance(); public BeanUtilsBeanExtensions() { } /** * Extends BeanUtilsBean.describe() so that it can be given a list of * attributes to exclude. This avoids calling methods which might derive * data which don't happen to be populated when the describe() call is made * (and therefore could throw exceptions) as well as being more efficient * than describing everything then discarding attributes which aren't * required. * * @param bean * See BeanUtilsBean.describe() * @param excludedAttributeNames * the attribute names which should not be described. * @return See BeanUtilsBean.describe() */ public Map<String, String> describe(Object bean, Set<String> excludedAttributeNames) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException { // This method is mostly just a copy/paste from BeanUtilsBean.describe() // The only changes are: // - Removal of reference to the (private) logger // - Addition of Reference to a BeanUtilsBean instance // - Addition of calls to excludedAttributeNames.contains(name) // - Use of generics on the Collections // - Calling of a copy of PropertyUtilsBean.getReadMethod() if (bean == null) { return (new java.util.HashMap<String, String>()); } Map<String, String> description = new HashMap<String, String>(); if (bean instanceof DynaBean) { DynaProperty[] descriptors = ((DynaBean) bean).getDynaClass() .getDynaProperties(); for (int i = 0; i < descriptors.length; i++) { String name = descriptors[i].getName(); if (!excludedAttributeNames.contains(name)) { description.put(name, BEAN_UTILS_BEAN.getProperty(bean, name)); } } } else { PropertyDescriptor[] descriptors = BEAN_UTILS_BEAN .getPropertyUtils().getPropertyDescriptors(bean); Class<? extends Object> clazz = bean.getClass(); for (int i = 0; i < descriptors.length; i++) { String name = descriptors[i].getName(); if (!excludedAttributeNames.contains(name) && getReadMethod(clazz, descriptors[i]) != null) { description.put(name, BEAN_UTILS_BEAN.getProperty(bean, name)); } } } return description; } /* * Copy of PropertyUtilsBean.getReadMethod() since that is package-private. */ private Method getReadMethod(Class<? extends Object> clazz, PropertyDescriptor descriptor) { return MethodUtils.getAccessibleMethod(clazz, descriptor.getReadMethod()); } } 
+4
source

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


All Articles