Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

find out the differences between two java beans for version tracking

Tags:

say i have a java bean/an entity with 100 fields (inherited or not it is not relevant in this case). After update operations - in a transaction, i want to determine which fields are modified to track updates like a CVS. What is the easiest way to do this? Any Framework suggestion? Should i make two instances of this object and iterate over all fields and match the values of fields ? How would the best equals method seem in such situations ? The following equals() seems very awkward :

return (field1.equals(o.field1)) &&  (field2.equals(o.field2)) &&   (field3.equals(o.field3)) &&   ... (field100.equals(o.field100)); 
like image 737
Erhan Bagdemir Avatar asked May 23 '11 15:05

Erhan Bagdemir


People also ask

What is difference JavaBeans?

The main difference between EJB and Java Beans is that the EJB is a server-side software component that encapsulates the business logic of an application while JavaBeans are classes that encapsulates multiple objects into a single object that helps to create reusable software components for Java.

What are the differences between JavaBeans and Java class?

The only difference between both the classes is Java make java beans objects serialized so that the state of a bean class could be preserved in case required.So due to this a Java Bean class must either implements Serializable or Externalizable interface.

What is the difference between JavaBeans and EJB?

A JavaBean is a Java class that encapsulates multiple objects and conforms to certain conventions. JavaBeans are used mainly for client-side development. An enterprise bean (EJB) is a Java class imbued with specific server-side capabilities. Enterprise beans are used in large-scale business applications and systems.

What is the use of JavaBeans?

JavaBeans is a portable, platform-independent model written in Java Programming Language. Its components are referred to as beans. In simple terms, JavaBeans are classes which encapsulate several objects into a single object. It helps in accessing these object from multiple places.


2 Answers

You could use Apache Commons Beanutils. Here's a simple example:

package at.percom.temp.zztests;  import java.lang.reflect.InvocationTargetException; import org.apache.commons.beanutils.BeanMap; import org.apache.commons.beanutils.PropertyUtilsBean; import java.util.Arrays; import java.util.HashSet; import java.util.Objects; import java.util.Set;  public class Main {      public static void main(String[] args) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {         Main main = new Main();         main.start();     }      public void start() throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {         SampleBean oldSample = new SampleBean("John", "Doe", 1971);         SampleBean newSample = new SampleBean("John X.", "Doe", 1971);          SampleBean diffSample = (SampleBean) compareObjects(oldSample, newSample, new HashSet<>(Arrays.asList("lastName")), 10L);     }  public Object compareObjects(Object oldObject, Object newObject, Set<String> propertyNamesToAvoid, Long deep) {     return compareObjects(oldObject, newObject, propertyNamesToAvoid, deep, null); }  private Object compareObjects(Object oldObject, Object newObject, Set<String> propertyNamesToAvoid, Long deep,         String parentPropertyPath) {     propertyNamesToAvoid = propertyNamesToAvoid != null ? propertyNamesToAvoid : new HashSet<>();     parentPropertyPath = parentPropertyPath != null ? parentPropertyPath : "";      Object diffObject = null;     try {         diffObject = oldObject.getClass().newInstance();     } catch (Exception e) {         return diffObject;     }      BeanMap map = new BeanMap(oldObject);      PropertyUtilsBean propUtils = new PropertyUtilsBean();      for (Object propNameObject : map.keySet()) {         String propertyName = (String) propNameObject;         String propertyPath = parentPropertyPath + propertyName;          if (!propUtils.isWriteable(diffObject, propertyName) || !propUtils.isReadable(newObject, propertyName)                 || propertyNamesToAvoid.contains(propertyPath)) {             continue;         }          Object property1 = null;         try {             property1 = propUtils.getProperty(oldObject, propertyName);         } catch (Exception e) {         }         Object property2 = null;         try {             property2 = propUtils.getProperty(newObject, propertyName);         } catch (Exception e) {         }         try {             if (property1 != null && property2 != null && property1.getClass().getName().startsWith("com.racing.company")                     && (deep == null || deep > 0)) {                 Object diffProperty = compareObjects(property1, property2, propertyNamesToAvoid,                         deep != null ? deep - 1 : null, propertyPath + ".");                 propUtils.setProperty(diffObject, propertyName, diffProperty);             } else {                 if (!Objects.deepEquals(property1, property2)) {                     propUtils.setProperty(diffObject, propertyName, property2);                     System.out.println("> " + propertyPath + " is different (oldValue=\"" + property1 + "\", newValue=\""                             + property2 + "\")");                 } else {                     System.out.println("  " + propertyPath + " is equal");                 }             }         } catch (Exception e) {         }     }      return diffObject; }      public class SampleBean {          public String firstName;         public String lastName;         public int yearOfBirth;          public SampleBean(String firstName, String lastName, int yearOfBirth) {             this.firstName = firstName;             this.lastName = lastName;             this.yearOfBirth = yearOfBirth;         }          public String getFirstName() {             return firstName;         }          public String getLastName() {             return lastName;         }          public int getYearOfBirth() {             return yearOfBirth;         }     } } 
like image 184
t3chris Avatar answered Nov 12 '22 21:11

t3chris


Hey look at Javers it's exactly what you need - objects auditing and diff framework . With Javers you can persist changes done on your domain objects with a single javers.commit() call after every update. When you persist some changes you can easily read them by javers.getChangeHistory, e.g.

public static void main(String... args) {     //get Javers instance     Javers javers = JaversBuilder.javers().build();      //create java bean     User user = new User(1, "John");      //commit current state     javers.commit("author", user);      //update operation     user.setUserName("David");      //commit change     javers.commit("author", user);      //read 100 last changes     List<Change> changes = javers.getChangeHistory(instanceId(1, User.class), 100);      //print change log     System.out.printf(javers.processChangeList(changes, new SimpleTextChangeLog())); } 

and the output is:

commit 2.0, author:author, 2015-01-07 23:00:10   changed object: org.javers.demo.User/1     value changed on 'userName' property: 'John' -> 'David' commit 1.0, author:author, 2015-01-07 23:00:10     new object: 'org.javers.demo.User/1 
like image 44
Paweł Szymczyk Avatar answered Nov 12 '22 20:11

Paweł Szymczyk