Reputation: 22300
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
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
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
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
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
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