Enterprise Java

Apache Commons BeanUtils Example

1. Introduction

Apache Common BeanUtils is one of the most common Java library. The latest version at the time of writing is 1.9.3 and published at September 26, 2016.

BeanUtils provides utility methods for populating JavaBeans properties. In this example, I will demonstrate the following methods:

  • static Object cloneBean(Object bean) – Clones a bean even if the bean class does not implement Cloneable.
  • static void copyProperties(Object dest, Object orig) – Copies property values from the original bean to the destination bean where the property names are the same.
  • static String getIndexedProperty(Object bean, String name) – Returns the String value of the specified indexed property of the specified bean.
  • static String getMappedProperty(Object bean, String name) – Returns the String value of the specified mapped property of the specified bean.
  • static String getNestedProperty(Object bean, String name) – Returns the String value of the nested property of the specified name for the specified bean.
  • static String getProperty(Object bean, String name) – Returns the String value of the specified property of the specified bean.
  • static String getSimpleProperty(Object bean, String name) – Returns the String value of the specified simple property of the specified bean.
  • static void setProperty(Object bean, String name, Object value) – Sets the specified property value, performing type conversions as required to conform to the type of the destination property.

2. Technologies used

The example code in this article was built and run using:

  • Java 1.11
  • Maven 3.3.9
  • Eclipse Oxygen
  • JUnit 4.12
  • Apache commons-beanutils 1.9.3

3. Maven Project

3.1 Dependency

Add JUnit and commons-beanutils to pom.xml.

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>jcg.zheng.demo</groupId>
	<artifactId>java-beanutils-demo</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<build>
		<sourceDirectory>src</sourceDirectory>
		<plugins>
			<plugin>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.8.0</version>
				<configuration>
					<release>11</release>
				</configuration>
			</plugin>
		</plugins>
	</build>
	<dependencies>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.12</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/commons-beanutils/commons-beanutils -->
		<dependency>
			<groupId>commons-beanutils</groupId>
			<artifactId>commons-beanutils</artifactId>
			<version>1.9.3</version>
		</dependency>

	</dependencies>
</project>

4. JavaBeans

In this step, I will create four Java classes:

  • Contact – It is a JavaBean which has two simple properties: firstName and lastName; a collection of topics; a map of addtionalProperties; two complex data: cellPhone and homePhone.
  • Person – It is a JavaBean which has similar members as Contact with two more data members: age and someData.
  • Phone – It is a JavaBean which has four simple properties: areaCode, countryCode, extension, and phoneNum.
  • NoDefaultConstructrorPOJO – It is a POJO with a non-default constructor. I will use it to demonstrate that calling BeanUtils.cloneBean for non-JavaBean will throw an exception.

4.1 Contact

In this step, I will create a Contact JavaBean which has simple, indexed, mapped, and nested properties.

Contact.java

package jcg.zheng.demo.data;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

public class Contact {
	private HashMap<String, String> addtionalProperties = new HashMap<>();
	private Phone cellPhone;
	private String firstName;
	private Phone homePhone;
	private String lastName;
	private List<String> topics = new ArrayList<>();

	public Contact() {
		super();
	}

	public HashMap<String, String> getAddtionalProperties() {
		return addtionalProperties;
	}

	public Phone getCellPhone() {
		return cellPhone;
	}

	public String getFirstName() {
		return firstName;
	}

	public Phone getHomePhone() {
		return homePhone;
	}

	public String getLastName() {
		return lastName;
	}

	public List<String> getTopics() {
		return topics;
	}

	public void setAddtionalProperties(HashMap<String, String> addtionalProperties) {
		this.addtionalProperties = addtionalProperties;
	}

	public void setCellPhone(Phone cellPhone) {
		this.cellPhone = cellPhone;
	}

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

	public void setHomePhone(Phone homePhone) {
		this.homePhone = homePhone;
	}

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

	public void setTopics(List<String> topics) {
		this.topics = topics;
	}

}

4.2 Person

In this step, I will create a Person JavaBean which has similar members as the Contact class with two more data members: age and someData.

Person.java

package jcg.zheng.demo.data;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

public class Person {
	private HashMap<String, String> addtionalProperties = new HashMap<>();
	private int age;
	private Phone cellPhone;
	private String firstName;
	private Phone homePhone;
	private String lastName;
	private Boolean someData;

	private List<String> topics = new ArrayList<>();

	public Person() {
		super();
	}

	public HashMap<String, String> getAddtionalProperties() {
		return addtionalProperties;
	}

	public int getAge() {
		return age;
	}

	public Phone getCellPhone() {
		return cellPhone;
	}

	public String getDummy() {
		return "Dummy";
	}

	public String getFirstName() {
		return firstName;
	}

	public Phone getHomePhone() {
		return homePhone;
	}

	public String getLastName() {
		return lastName;
	}

	public Boolean getSomeData() {
		return someData;
	}

	public List<String> getTopics() {
		return topics;
	}

	public void setAddtionalProperties(HashMap<String, String> addtionalProperties) {
		this.addtionalProperties = addtionalProperties;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public void setCellPhone(Phone cellPhone) {
		this.cellPhone = cellPhone;
	}

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

	public void setHomePhone(Phone homePhone) {
		this.homePhone = homePhone;
	}

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

	public void setSomeData(Boolean dataNotINContact) {
		this.someData = dataNotINContact;
	}

	public void setTopics(List<String> topics) {
		this.topics = topics;
	}

	/**
	 * This is not following JavaBean Property pattern, so it will not be used by BeanUtils
	 * @return
	 */
	public boolean isSomeData() {
		return someData == null ? false : someData.booleanValue();
	}
}

4.3 Phone

In this step, I will create a Phone JavaBean which has simple properties.

Phone.java

package jcg.zheng.demo.data;

public class Phone {

	private String areaCode;
	private String countryCode;
	private String extension;
	private String phoneNum;

	public Phone() {
		super();
	}

	public String getAreaCode() {
		return areaCode;
	}

	public String getCountryCode() {
		return countryCode;
	}

	public String getExtension() {
		return extension;
	}

	public String getPhoneNum() {
		return phoneNum;
	}

	public void setAreaCode(String areaCode) {
		this.areaCode = areaCode;
	}

	public void setCountryCode(String countryCode) {
		this.countryCode = countryCode;
	}

	public void setExtension(String extension) {
		this.extension = extension;
	}

	public void setPhoneNum(String phoneNum) {
		this.phoneNum = phoneNum;
	}

}

4.4 NoDefaultConstructorPOJO

In this step, I will create a class which does not have a default constructor. It will be used to demonstrate the exception thrown by the BeanUtils.cloneBean method.

NoDefaultConstructorPOJO.java

package jcg.zheng.demo.data;

public class NoDefaultConstructorPOJO {

	private String name;

	public NoDefaultConstructorPOJO(String name) {
		super();
		this.name = name;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
}

5. JUnit Tests

I will create several JUnit tests to demonstrate how to use BeanUtils to copy a JavaBean, clone a JavaBean, get JavaBean’s property, and set JavaBean’s property.

5.1 TestBase

In this step, I will create a TestBase class to set up the constants and data used in all the test classes.

TestBase.java

package jcg.zheng.demo;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.beanutils.BeanUtils;
import org.junit.Before;
import org.junit.Test;

import jcg.zheng.demo.data.Contact;
import jcg.zheng.demo.data.Phone;

public class TestBase {

	protected static final String KEY_1 = "Color";
	protected static final String KEY_2 = "Food";
	protected static final String SHOULD_NOT_REACH = "should not reach here!";
	protected static final String TOPIC_1 = "Interface design";
	protected static final String TOPIC_2 = "BeanUtils";
	protected static final String TOPIC_3 = "Functional Interface";
	protected static final String VALUE_1 = "Purple";
	protected static final String VALUE_2 = "Rice";

	protected Contact mary;

	public TestBase() {
		super();
	}

	protected Contact buildContact(String firstName, String lastName) {
		Contact contact = new Contact();
		contact.setFirstName(firstName);
		contact.setLastName(lastName);

		contact.setTopics(Arrays.asList(TOPIC_1, TOPIC_2, TOPIC_3));
		HashMap<String, String> addtionalProperties = new HashMap<>();
		addtionalProperties.put(KEY_1, VALUE_1);
		addtionalProperties.put(KEY_2, VALUE_2);
		contact.setAddtionalProperties(addtionalProperties);
		contact.setCellPhone(buildPhone("8197000"));
		contact.setHomePhone(buildPhone("5272943"));

		return contact;
	}

	protected Phone buildPhone(String phoneNum) {
		Phone cellPhone = new Phone();
		cellPhone.setCountryCode("01");
		cellPhone.setAreaCode("314");
		cellPhone.setPhoneNum(phoneNum);

		return cellPhone;
	}

	@Before
	public void setup() {
		mary = buildContact("Mary", "Zheng");
	}
	
	@Test
	public void test_describe() {
		try {
			Map<String, String> maryContactMeta = BeanUtils.describe(mary);
			assertEquals("Mary", maryContactMeta.get("firstName"));
			assertEquals("Zheng", maryContactMeta.get("lastName"));
			assertEquals("{Color=Purple, Food=Rice}", maryContactMeta.get("addtionalProperties"));			 
		} catch (Exception e) {
			fail(SHOULD_NOT_REACH);
		}  
	}

}

Execute mvn test -Dtest=TestBase and capture the output.

TestBase Output

Running jcg.zheng.demo.TestBase
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.281 sec

Results :

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  9.263 s
[INFO] Finished at: 2019-07-19T20:42:52-05:00
[INFO] ------------------------------------------------------------------------

C:\MaryZheng\Workspaces\jdk12\java-beanutils-demo>

5.2 CloneBeanTest

In this step, I will create a CloneBeanTest class to show how to use cloneBean to clone a JavaBean. It will throw InstantiationException when cloning a POJO which does not have a default constructor.

CloneBeanTest.java

package jcg.zheng.demo;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import org.apache.commons.beanutils.BeanUtils;
import org.junit.Test;

import jcg.zheng.demo.data.Contact;
import jcg.zheng.demo.data.NoDefaultConstructorPOJO;
import jcg.zheng.demo.data.Person;

public class CloneBeanTest extends TestBase {

	@Test
	public void test_cloneBean() {
		try {
			Contact cloneMary = (Contact) BeanUtils.cloneBean(mary);

			assertEquals(mary.getFirstName(), cloneMary.getFirstName());
			assertEquals(mary.getLastName(), cloneMary.getLastName());
			assertNotNull(cloneMary.getCellPhone());
			assertEquals(mary.getCellPhone().getAreaCode(), cloneMary.getCellPhone().getAreaCode());
			assertEquals(mary.getCellPhone().getCountryCode(), cloneMary.getCellPhone().getCountryCode());
			assertEquals(mary.getCellPhone().getPhoneNum(), cloneMary.getCellPhone().getPhoneNum());
			assertNotNull(cloneMary.getHomePhone());
			assertEquals(mary.getHomePhone().getAreaCode(), cloneMary.getHomePhone().getAreaCode());
			assertEquals(mary.getHomePhone().getCountryCode(), cloneMary.getHomePhone().getCountryCode());
			assertEquals(mary.getHomePhone().getPhoneNum(), cloneMary.getHomePhone().getPhoneNum());

			assertNotNull(cloneMary.getTopics());
			assertEquals(mary.getTopics().size(), cloneMary.getTopics().size());
			assertTrue(cloneMary.getTopics().contains(TOPIC_1));
			assertTrue(cloneMary.getTopics().contains(TOPIC_2));
			assertTrue(cloneMary.getTopics().contains(TOPIC_3));

			assertNotNull(cloneMary.getAddtionalProperties());
			assertEquals(mary.getAddtionalProperties().size(), cloneMary.getAddtionalProperties().size());
			assertEquals(mary.getAddtionalProperties().get(KEY_1), cloneMary.getAddtionalProperties().get(KEY_1));
			assertEquals(mary.getAddtionalProperties().get(KEY_2), cloneMary.getAddtionalProperties().get(KEY_2));

		} catch (Exception e) {
			fail(SHOULD_NOT_REACH);
		}
	}

	@Test
	public void test_cloneBean_error_NoDefaultConstructorPOJO() {
		NoDefaultConstructorPOJO object = new NoDefaultConstructorPOJO("Test");
		try {
			BeanUtils.cloneBean(object);
		} catch (Exception e) {
			assertEquals(InstantiationException.class, e.getClass());
		}
	}

	@Test
	public void test_cloneBean_wont_clone_getter_not_follow_naming() {
		Person person = new Person();
		person.setSomeData(Boolean.TRUE);
		assertTrue(person.isSomeData());
		try {
			BeanUtils.copyProperties(person, mary);
			person.setSomeData(Boolean.TRUE);
			assertTrue(person.isSomeData());

			Person clonedPon = (Person) BeanUtils.cloneBean(person);
			assertFalse(clonedPon.isSomeData());
			
		} catch (Exception e) {
			fail(SHOULD_NOT_REACH);
		}
	}
}

Execute mvn test -Dtest=CloneBeanTest and capture the output.

CloneBeanTest Output

Running jcg.zheng.demo.CloneBeanTest
Tests run: 4, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.314 sec

Results :

Tests run: 4, Failures: 0, Errors: 0, Skipped: 0

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  10.307 s
[INFO] Finished at: 2019-07-19T20:36:05-05:00
[INFO] ------------------------------------------------------------------------

C:\MaryZheng\Workspaces\jdk12\java-beanutils-demo>

5.3 CopyPropertiesTest

In this step, I will create a CopyPropertiesTest class to show how to use copyProperties to copy properties from one JavaBean to another. It will work when copying properties from a POJO which does not have a default constructor.

CopyPropertiesTest.java

package jcg.zheng.demo;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.lang.reflect.InvocationTargetException;

import org.apache.commons.beanutils.BeanUtils;
import org.junit.Test;

import jcg.zheng.demo.data.NoDefaultConstructorPOJO;
import jcg.zheng.demo.data.Person;

public class CopyPropertiesTest extends TestBase {

	@Test
	public void test_copyProperties() {
		Person person = new Person();
		try {
			BeanUtils.copyProperties(person, mary);
			assertEquals(mary.getFirstName(), person.getFirstName());
			assertEquals(mary.getLastName(), person.getLastName());
			assertNotNull(person.getCellPhone());
			assertEquals(mary.getCellPhone().getAreaCode(), person.getCellPhone().getAreaCode());
			assertEquals(mary.getCellPhone().getCountryCode(), person.getCellPhone().getCountryCode());
			assertEquals(mary.getCellPhone().getPhoneNum(), person.getCellPhone().getPhoneNum());
			assertNotNull(person.getHomePhone());
			assertEquals(mary.getHomePhone().getAreaCode(), person.getHomePhone().getAreaCode());
			assertEquals(mary.getHomePhone().getCountryCode(), person.getHomePhone().getCountryCode());
			assertEquals(mary.getHomePhone().getPhoneNum(), person.getHomePhone().getPhoneNum());

			assertNotNull(person.getTopics());
			assertEquals(mary.getTopics().size(), person.getTopics().size());
			assertTrue(person.getTopics().contains(TOPIC_1));
			assertTrue(person.getTopics().contains(TOPIC_2));
			assertTrue(person.getTopics().contains(TOPIC_3));

			assertNotNull(person.getAddtionalProperties());
			assertEquals(mary.getAddtionalProperties().size(), person.getAddtionalProperties().size());
			assertEquals(mary.getAddtionalProperties().get(KEY_1), person.getAddtionalProperties().get(KEY_1));
			assertEquals(mary.getAddtionalProperties().get(KEY_2), person.getAddtionalProperties().get(KEY_2));

			assertNull(person.getSomeData());

		} catch (IllegalAccessException | InvocationTargetException e) {
			fail(SHOULD_NOT_REACH);
		}
	}

	@Test
	public void test_copyProperties_NoDefaultConstructorPOJO() {
		NoDefaultConstructorPOJO pojo = new NoDefaultConstructorPOJO("Test");
		try {
			BeanUtils.copyProperties(pojo, mary);
			assertEquals("Test", pojo.getName());
		} catch (IllegalAccessException | InvocationTargetException e) {
			fail(SHOULD_NOT_REACH);
		}
	}

}

Execute mvn test -Dtest=CopyPropertiesTest and capture the output.

CopyPropertiesTest Output

Running jcg.zheng.demo.CopyPropertiesTest
Tests run: 3, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.349 sec

Results :

Tests run: 3, Failures: 0, Errors: 0, Skipped: 0

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  9.050 s
[INFO] Finished at: 2019-07-19T20:39:41-05:00
[INFO] ------------------------------------------------------------------------

C:\MaryZheng\Workspaces\jdk12\java-beanutils-demo>

5.4 SimplePropertyTest

In this step, I will create a SimplePropertyTest class to show how to get and set the indexed properties. I will demonstrate three ways to get and set a simple property:

  • get and set the simple property via the getter and setter
  • get and set the simple property via getProperty and setProperty
  • get and set the simple property via getSimpleProperty and setSimpleProperty

Note: It will throw NoSuchMethodException when calling setSimpleProperty at a non-exist property, but it will not throw exception when calling setPropery at a non-existing property.

SimplePropertyTest.java

package jcg.zheng.demo;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.PropertyUtils;
import org.junit.Test;

public class SimplePropertyTest extends TestBase {

	@Test
	public void getProperty_for_definedProperty() {
		try {
			String fname = BeanUtils.getProperty(mary, "firstName");
			assertEquals("Mary", fname);
		} catch (Exception e) {
			fail(SHOULD_NOT_REACH);
		}
	}

	@Test
	public void getSimpleProperty_retrun_value_for_definedProperty() {
		try {
			String firstName = BeanUtils.getSimpleProperty(mary, "firstName");
			assertEquals("Mary", firstName);
		} catch (Exception e) {
			fail(SHOULD_NOT_REACH);
		}
	}

	@Test
	public void getter_return_value_for_definedProperty() {
		try {
			assertEquals("Mary", mary.getFirstName());
		} catch (Exception e) {
			fail(SHOULD_NOT_REACH);
		}
	}
	
	@Test
	public void setProperty_for_definedProperty() {
		try {
			BeanUtils.setProperty(mary, "firstName", "UpdateMary");
			assertEquals("UpdateMary", mary.getFirstName());
		} catch (Exception e) {
			fail(SHOULD_NOT_REACH);
		}
	}

	@Test
	public void setProperty_for_not_definedProperty() {
		try {
			BeanUtils.setProperty(mary, "noGetter", Integer.valueOf(1));
		} catch (Exception e) {
			fail(SHOULD_NOT_REACH);
		}
	}

	@Test
	public void setSimpleProperty_for_definedProperty() {
		try {
			PropertyUtils.setSimpleProperty(mary, "firstName", "UpdateMary");
			assertEquals("UpdateMary", mary.getFirstName());
		} catch (Exception e) {
			fail(SHOULD_NOT_REACH);
		}
	}

	@Test
	public void setSimpleProperty_for_NamingNotMatchProperty() {		
		try {
			PropertyUtils.setSimpleProperty(mary, "someData", true);
		} catch (Exception e) {
			assertEquals(NoSuchMethodException.class, e.getClass());
		}		
	}

	@Test
	public void setSimpleProperty_for_not_definedProperty() {
		try {
			PropertyUtils.setSimpleProperty(mary, "isSomeData", Integer.valueOf(1));
		} catch (Exception e) {
			assertEquals(NoSuchMethodException.class, e.getClass());
		}
	}
}

Execute mvn test -Dtest=SimplePropertyTest and capture the output.

SimplePropertyTest Output

Running jcg.zheng.demo.SimplePropertyTest
Tests run: 9, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.313 sec

Results :

Tests run: 9, Failures: 0, Errors: 0, Skipped: 0

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  8.985 s
[INFO] Finished at: 2019-07-19T20:41:17-05:00
[INFO] ------------------------------------------------------------------------

C:\MaryZheng\Workspaces\jdk12\java-beanutils-demo>

5.5 IndexedPropertyTest

In this step, I will create an IndexedPropertyTest class to show how to get and set the indexed properties via getProperty, setProperty, getIndexedProperty, and setIndexedProperty. It will work when setting properties from a POJO which does not have a default constructor.

Note: The indexed property follows the array index naming convention.

IndexedPropertyTest.java

package jcg.zheng.demo;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.PropertyUtils;
import org.junit.Test;

import jcg.zheng.demo.data.NoDefaultConstructorPOJO;

public class IndexedPropertyTest extends TestBase {

	@Test
	public void getIndexedProperty() {
		try {
			String topic = BeanUtils.getIndexedProperty(mary, "topics[0]");
			assertEquals(TOPIC_1, topic);

			topic = BeanUtils.getIndexedProperty(mary, "topics[2]");
			assertEquals(TOPIC_3, topic);

		} catch (Exception e) {
			fail(SHOULD_NOT_REACH);
		}
	}

	@Test
	public void getIndexedProperty_error() {
		try {
			BeanUtils.getIndexedProperty(mary, "topics[3]");
		} catch (Exception e) {
			assertEquals(ArrayIndexOutOfBoundsException.class, e.getClass());
		}
	}

	@Test
	public void getIndexedProperty_index() {
		try {
			String topic = BeanUtils.getIndexedProperty(mary, "topics", 1);
			assertEquals(TOPIC_2, topic);

		} catch (Exception e) {
			fail(SHOULD_NOT_REACH);
		}
	}

	@Test
	public void getIndexedProperty_index_error() {
		try {
			BeanUtils.getIndexedProperty(mary, "topics", 3);
		} catch (Exception e) {
			assertEquals(ArrayIndexOutOfBoundsException.class, e.getClass());
		}
	}

	@Test
	public void getProperty() {
		try {
			String value = BeanUtils.getProperty(mary, "topics[1]");
			assertEquals("BeanUtils", value);
		} catch (Exception e) {
			fail(SHOULD_NOT_REACH);
		}
	}

	@Test
	public void getter() {
		try {
			assertEquals(3, mary.getTopics().size());
		} catch (Exception e) {
			fail(SHOULD_NOT_REACH);
		}
	}

	@Test
	public void setIndexedProperty() {
		try {
			PropertyUtils.setIndexedProperty(mary, "topics[1]", "Java 8");
			assertEquals("Java 8", mary.getTopics().get(1));
		} catch (Exception e) {
			fail(SHOULD_NOT_REACH);
		}
	}

	@Test
	public void setIndexedProperty_index() {
		try {
			PropertyUtils.setIndexedProperty(mary, "topics", 1, "Java 8");
			assertEquals("Java 8", mary.getTopics().get(1));
		} catch (Exception e) {
			fail(SHOULD_NOT_REACH);
		}
	}
	
	@Test
	public void setProperty() {
		try {
			BeanUtils.setProperty(mary, "topics[1]", "Java 12");
			assertEquals("Java 12", mary.getTopics().get(1));
		} catch (Exception e) {
			fail(SHOULD_NOT_REACH);
		}
	}

	@Test
	public void setProperty_NoDefaultConstructorPOJO() {
		NoDefaultConstructorPOJO object = new NoDefaultConstructorPOJO("Test");
		try {
			BeanUtils.setProperty(object, "name", "Java");
			assertEquals("Java", object.getName());
		} catch (Exception e) {
			fail(SHOULD_NOT_REACH);
		}
	}
}

Execute mvn test -Dtest=IndexedPropertyTest and capture the output.

IndexedPropertyTest Output

Running jcg.zheng.demo.IndexedPropertyTest
Tests run: 11, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.323 sec

Results :

Tests run: 11, Failures: 0, Errors: 0, Skipped: 0

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  9.683 s
[INFO] Finished at: 2019-07-19T21:28:24-05:00
[INFO] ------------------------------------------------------------------------

C:\MaryZheng\Workspaces\jdk12\java-beanutils-demo>

5.6 MappedPropertyTest

In this step, I will create a MappedPropertyTest class to show how to get and set the mapped properties via getProperty, setProperty, getMappedProperty, and setMappedProperty. It will throw IllegalArgumentException when the property doesn’t exist.

Note: The mapped property encloses the key value inside “()”.

MappedPropertyTest.java

package jcg.zheng.demo;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.fail;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.PropertyUtils;
import org.junit.Test;

public class MappedPropertyTest extends TestBase {

	@Test
	public void getMappedProperty() {
		try {

			String colorValue = BeanUtils.getMappedProperty(mary, "addtionalProperties(Color)");
			assertEquals(VALUE_1, colorValue);

		} catch (Exception e) {
			fail(SHOULD_NOT_REACH);
		}
	}

	@Test
	public void getMappedProperty_error_notexist_property() {
		try {
			BeanUtils.getMappedProperty(mary, "NA");
		} catch (Exception e) {
			assertEquals(IllegalArgumentException.class, e.getClass());
		}
	}

	@Test
	public void getMappedProperty_key() {
		try {
			String keyValue = BeanUtils.getMappedProperty(mary, "addtionalProperties", KEY_1);
			assertEquals(VALUE_1, keyValue);

			keyValue = BeanUtils.getMappedProperty(mary, "addtionalProperties", KEY_2);
			assertEquals(VALUE_2, keyValue);

		} catch (Exception e) {
			fail(SHOULD_NOT_REACH);
		}
	}

	@Test
	public void getMappedProperty_return_null_for_not_exist_key() {
		try {
			String naValue = BeanUtils.getMappedProperty(mary, "addtionalProperties", "NA");
			assertNull(naValue);
		} catch (Exception e) {
			fail(SHOULD_NOT_REACH);
		}
	}

	@Test
	public void getProperty() {
		try {
			String value = BeanUtils.getProperty(mary, "addtionalProperties(Color)");

			assertEquals("Purple", value);
		} catch (Exception e) {
			fail(SHOULD_NOT_REACH);
		}
	}

	@Test
	public void getter() {
		try {
			assertEquals(2, mary.getAddtionalProperties().size());
		} catch (Exception e) {
			fail(SHOULD_NOT_REACH);
		}
	}


	@Test
	public void setMappedProperty() {
		try {
			PropertyUtils.setMappedProperty(mary, "addtionalProperties(Color)", "Blue");
			assertEquals("Blue", mary.getAddtionalProperties().get(KEY_1));
		} catch (Exception e) {
			fail(SHOULD_NOT_REACH);
		}
	}
	
	@Test
	public void setMappedProperty_key() {
		try {
			PropertyUtils.setMappedProperty(mary, "addtionalProperties", KEY_1, "Blue");
			assertEquals("Blue", mary.getAddtionalProperties().get(KEY_1));
		} catch (Exception e) {
			fail(SHOULD_NOT_REACH);
		}
	}
	
	@Test
	public void setProperty() {
		try {
			BeanUtils.setProperty(mary, "addtionalProperties(Color)", "Green");

			assertEquals("Green", mary.getAddtionalProperties().get(KEY_1));
		} catch (Exception e) {
			fail(SHOULD_NOT_REACH);
		}
	}
}

Execute mvn test -Dtest=MappedPropertyTest and capture the output.

MappedPropertyTest Output

Running jcg.zheng.demo.MappedPropertyTest
Tests run: 10, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.331 sec

Results :

Tests run: 10, Failures: 0, Errors: 0, Skipped: 0

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  9.816 s
[INFO] Finished at: 2019-07-19T21:31:34-05:00
[INFO] ------------------------------------------------------------------------

C:\MaryZheng\Workspaces\jdk12\java-beanutils-demo>

5.7 NestedPropertyTest

In this step, I will create a NestedPropertyTest class to show how to get and set the nested properties via getProperty, setProperty, getNestedProperty, and setNestedProperty.

Note: The nested property uses dot(.) for each nested object.

NestedPropertyTest.java

package jcg.zheng.demo;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.PropertyUtils;
import org.junit.Test;

public class NestedPropertyTest extends TestBase {


	@Test
	public void getNestedProperty() {
		try {
			String areaCode = BeanUtils.getNestedProperty(mary, "cellPhone.areaCode");

			assertEquals("314", areaCode);
		} catch (Exception e) {
			fail(SHOULD_NOT_REACH);
		}
	}

	@Test
	public void getProperty() {
		try {
			String areaCode = BeanUtils.getProperty(mary, "cellPhone.areaCode");
			assertEquals("314", areaCode);
		} catch (Exception e) {
			fail(SHOULD_NOT_REACH);
		}
	}

	@Test
	public void getter() {
		try {
			assertEquals("314", mary.getCellPhone().getAreaCode());
		} catch (Exception e) {
			fail(SHOULD_NOT_REACH);
		}
	}

	@Test
	public void setNestedProperty() {
		try {
			PropertyUtils.setNestedProperty(mary, "cellPhone.areaCode", "404");

			assertEquals("404", mary.getCellPhone().getAreaCode());
		} catch (Exception e) {
			fail(SHOULD_NOT_REACH);
		}
	}
	
	@Test
	public void setProperty() {
		try {
			BeanUtils.setProperty(mary, "cellPhone.areaCode", "636");
			assertEquals("636", mary.getCellPhone().getAreaCode());
		} catch (Exception e) {
			fail(SHOULD_NOT_REACH);
		}
	}
}

Execute mvn test -Dtest=NestedPropertyTest and capture the output.

NestedPropertyTest Output

Running jcg.zheng.demo.NestedPropertyTest
Tests run: 6, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.318 sec

Results :

Tests run: 6, Failures: 0, Errors: 0, Skipped: 0

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  9.756 s
[INFO] Finished at: 2019-07-19T21:33:16-05:00
[INFO] ------------------------------------------------------------------------

C:\MaryZheng\Workspaces\jdk12\java-beanutils-demo>

6. Apache Commons BeanUtils – Summary

In this example, I demonstrated how to use the following common methods in BeanUtils to copy, clone, get, and set properties of a JavaBean:

  • static Object cloneBean(Object bean)
  • static void copyProperties(Object dest, Object orig)
  • static String getProperty(Object bean, String name)
  • static void setProperty(Object bean, String name, Object value)
  • static String getSimpleProperty(Object bean, String name)
  • static void setSimpleProperty(Object bean, String name, Object value)
  • static String getIndexedProperty(Object bean, String name)
  • static void setIndexedProperty(Object bean, String name, Object value)
  • static void setIndexedProperty(Object bean, String name, int index, Object value)
  • static String getMappedProperty(Object bean, String name)
  • static void setMappedProperty(Object bean, String name, Object value)
  • static void setMappedProperty(Object bean, String name,String key, Object value)
  • static String getNestedProperty(Object bean, String name)
  • static void setNestedProperty(Object bean, String name, Object value)

7. Download the Source Code

This example consists of a Maven project which demonstrates the usage of the BeanUtils class.

Download
You can download the full source code of this example here: Apache Commons BeanUtils Example

Mary Zheng

Mary has graduated from Mechanical Engineering department at ShangHai JiaoTong University. She also holds a Master degree in Computer Science from Webster University. During her studies she has been involved with a large number of projects ranging from programming and software engineering. She works as a senior Software Engineer in the telecommunications sector where she acts as a leader and works with others to design, implement, and monitor the software solution.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button