Riduidel
Riduidel

Reputation: 22300

Is there a way to know which properties are different between two beans?

I would like to persist changes made to my beans in a fashion similar to what Hibernate Envers does (but i can't use Envers, as i'm not connected to a JDBC back-end).

So, for that, i would like to know, between two instances of a given bean class, which properties have different values.

To be more clear, when given beans A and B, I would like to have a method ... say ... diff(A, B), that will output me a list (or map) linking properties to their old/new values.

Something like

<BeanClass> Collection<Field, Entry<Object, Object> diff(BeanClass a, BeanClass b)

Is there a library to do that in the Java world ?

Upvotes: 4

Views: 6854

Answers (5)

Boiler Bill
Boiler Bill

Reputation: 1960

You can use the EqualsBuilder class from Apache Commons:

String[] Arr = new String[excludedFields.size()]; //Add fields you want to exclude in here

boolean result = EqualsBuilder.reflectionEquals(object2, object1,Arr);

if(!result){
    System.out.println("----- Failure:" + StringUtils.difference(ReflectionToStringBuilder.toStringExclude(object1,excludedFields),ReflectionToStringBuilder.toStringExclude(object2,excludedFields)));
    return false;
}

Upvotes: 2

davidmontoyago
davidmontoyago

Reputation: 1833

You could go with Reflection + Apache Commons BeanUtils. The recursive part will be the tricky one, in case you want to do deep diff.

Upvotes: 0

Riduidel
Riduidel

Reputation: 22300

Well, the solution was to use java-object-diff, which provides a visitable tree of differences between objects. As a consequence, we ended up using that library with great success.

Upvotes: 5

Andrea Ligios
Andrea Ligios

Reputation: 50281

EDIT: of course there's a lot of work to do with reflections (as written by others), this is where you should start.

By the way, I've just found a project that should do what you are looking for, just checkout the trunk from the repository:

https://code.google.com/p/beandiff/source/checkout

Hope that helps


Try to look up at Apache BeanComparator;

This comparator compares two beans by the specified bean property. It is also possible to compare beans based on nested, indexed, combined, mapped bean properties. Please see the PropertyUtilsBean documentation for all property name possibilities.

compare(java.lang.Object o1, java.lang.Object o2)
          Compare two JavaBeans by their shared property.

Upvotes: 0

elias
elias

Reputation: 15510

Something like that:

public <T> Map<Field, Entry<Object, Object>> diff(T a, T b){
    //... initialize the map
    for (Method m : a.getClass().getMethods()){
        if(m.getName().startsWith("get")){
            Object obj1 = m.invoke(a, null);
            Object obj2 = m.invoke(b, null);
            if(!obj1.equals(obj2)){
                //converts getName to name, for example
                String fieldName = m.getName()...; 
                map.put(a.getClass().getField(fieldName), new Entry(obj1, obj2));
            }
        }
    }
}

Considering you follow the Java Beans convention.

Upvotes: 0

Related Questions