Copy JavaBean attributes using Reflection

Reflection provides a very good way to read the Java Class attributes via PropertyDescriptor class. At times, we come across scenarios where we need to move attributes from Class A to Class B, but most of time freshers keep writing the code like B.set(A.get()). In such scenarios, using Reflection should be a good practice. Apache came out with library commons-beanutils which solved the overhead of re-writing the reflection code again and again by individuals.

The below example helps one on how to use BeanUtils class to copyProperties from one object to another without the overhead of re-writing the reflection code. I know you may be interested in understanding how behind the scenes BeanUtils class is doing the job, for details on same, refer to javadoc for BeanUtils.

1. Define the Origin and Destination classes.


// Origin Class

package com.dirtyyourhands.reflection.orig;

public class StudentOriginBean {
  String firstName;
  String lastName;

  int rollNumber;

  public StudentOriginBean() {
  }

  public StudentOriginBean(String firstName, String lastName, int rollNumber) {
    this.firstName = firstName;
    this.lastName = lastName;
    this.rollNumber = rollNumber;
  }

  public String getFirstName() {
    return firstName;
  }

  public void setFirstName(String firstName) {
    this.firstName = firstName;
  }

  public String getLastName() {
    return lastName;
  }

  public void setLastName(String lastName) {
    this.lastName = lastName;
  }

  public int getRollNumber() {
    return rollNumber;
  }

  public void setRollNumber(int rollNumber) {
    this.rollNumber = rollNumber;
  }
}

// Destination Class

package com.dirtyyourhands.reflection.dest;

public class StudentDestinationBean {
  String firstName;
  String lastName;

  int rollNumber;

  public StudentDestinationBean() {
  }

  public StudentDestinationBean(String firstName, String lastName, int rollNumber) {
    this.firstName = firstName;
    this.lastName = lastName;
    this.rollNumber = rollNumber;
  }

  public String getFirstName() {
    return firstName;
  }

  public void setFirstName(String firstName) {
    this.firstName = firstName;
  }

  public String getLastName() {
    return lastName;
  }

  public void setLastName(String lastName) {
    this.lastName = lastName;
  }

  public int getRollNumber() {
    return rollNumber;
  }

  public void setRollNumber(int rollNumber) {
    this.rollNumber = rollNumber;
  }

}

2. The below code will do the job for us. Make sure you have common-beanutils.jar and commons-logging.jar in your classpath


package com.dirtyyourhands.reflection;

import org.apache.commons.beanutils.BeanUtils;

import com.dirtyyourhands.reflection.dest.StudentDestinationBean;
import com.dirtyyourhands.reflection.orig.StudentOriginBean;

public class CopyUsingBeanUtilsClass {
  public static void main(String[] args) throws Exception {
    StudentOriginBean studentOriginBean = new StudentOriginBean("Tom", "Dotty", 2090);
    StudentDestinationBean studentDestinationBean = new StudentDestinationBean("Rom", "Dotty", 1090);

    System.out.println("==== BEFORE COPY ====");
    System.out.println("First Name  : " + studentDestinationBean.getFirstName());
    System.out.println("Last Name   : " + studentDestinationBean.getLastName());
    System.out.println("Roll Number : " + studentDestinationBean.getRollNumber());

    try {
      BeanUtils.copyProperties(studentDestinationBean, studentOriginBean);
    } catch (Exception ex) {
      ex.printStackTrace();
    }

    System.out.println("==== AFTER COPY ====");
    System.out.println("First Name  : " + studentDestinationBean.getFirstName());
    System.out.println("Last Name   : " + studentDestinationBean.getLastName());
    System.out.println("Roll Number : " + studentDestinationBean.getRollNumber());

  }
}

Output from the above code looks like below:


==== BEFORE COPY ====
First Name  : Rom
Last Name   : Dotty
Roll Number : 1090

==== AFTER COPY ====
First Name  : Tom
Last Name   : Dotty
Roll Number : 2090

In case you are interested in writing your own Reflection code, the below snippet can be used and refined further


package com.dirtyyourhands.reflection;

import java.beans.PropertyDescriptor;

import org.apache.commons.beanutils.PropertyUtilsBean;

import com.dirtyyourhands.reflection.dest.StudentDestinationBean;
import com.dirtyyourhands.reflection.orig.StudentOriginBean;

public class CopyUsingReflection {
  public static void main(String[] args) throws Exception {
    StudentOriginBean studentOriginBean = new StudentOriginBean("Tom", "Dotty", 2090);
    StudentDestinationBean studentDestinationBean = new StudentDestinationBean("Rom", "Dotty", 1090);

    PropertyUtilsBean propertyBeanUtils = new PropertyUtilsBean();
    PropertyDescriptor[] descriptors = propertyBeanUtils.getPropertyDescriptors(studentOriginBean);
    for (int i = 0; i < descriptors.length; i++) {
      String name = descriptors[i].getName();
      System.out.println("name: " + name);
      if ("class".equals(name)) {
        continue;
      }
      if (propertyBeanUtils.isReadable(studentOriginBean, name) 
                        && propertyBeanUtils.isWriteable(studentDestinationBean, name)) {
        try {
          Object value = propertyBeanUtils.getSimpleProperty(studentOriginBean, name);
          // copyProperty(studentDestinationBean, name, value);
        } catch (NoSuchMethodException e) {
          // handle exception
        }
      }
    }
  }
}