commons-beans
Hacky solution, catching the NPE's. I have coded a clean solution, but I haven't tested it…
package com.rapidlime.pohlidame; import java.lang.reflect.InvocationTargetException; import java.util.Comparator; import org.apache.commons.beanutils.BeanComparator; import org.apache.commons.beanutils.NestedNullException; import org.apache.commons.beanutils.PropertyUtils; /** * * @author Ondrej Zizka */ public class NullSafeUglyBeanComparator extends BeanComparator { public NullSafeUglyBeanComparator( String property, Comparator comparator ) { super( property, comparator ); } private static Object getNullSafeProperty( Object o1, String property ) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException { Object val; try { val = PropertyUtils.getProperty( o1, property ); } catch( NestedNullException ex ){ val = null; } return val; } private static final boolean NULL_GOES_LAST = true; /** * Compare two JavaBeans by their shared property. * If {@link #getProperty} is null then the actual objects will be compared. * * @param o1 Object The first bean to get data from to compare against * @param o2 Object The second bean to get data from to compare * @return int negative or positive based on order */ @Override public int compare( Object o1, Object o2 ) { final String property = getProperty(); final Comparator comparator = getComparator(); if ( property == null ) { // compare the actual objects return comparator.compare( o1, o2 ); } try { //Object value1 = PropertyUtils.getProperty( o1, property ); //Object value2 = PropertyUtils.getProperty( o2, property ); Object value1 = getNullSafeProperty( o1, property ); Object value2 = getNullSafeProperty( o2, property ); if( null == value1 && null == value2 ) return 0; if( null == value1 ) return NULL_GOES_LAST ? +1 : -1; if( null == value2 ) return NULL_GOES_LAST ? +1 : -1; return comparator.compare( value1, value2 ); } catch ( IllegalAccessException iae ) { throw new RuntimeException( "IllegalAccessException: " + iae.toString() ); } catch ( InvocationTargetException ite ) { throw new RuntimeException( "InvocationTargetException: " + ite.toString() ); } catch ( NoSuchMethodException nsme ) { throw new RuntimeException( "NoSuchMethodException: " + nsme.toString() ); } } }// class NullSafeBeanComparator