Core Java

Java POJO and Java Bean Example

1. Introduction

POJO stands for a Plain Old Java Object. It’s a term coined by Martin Fowler, Rebecca Parsons, and Josh MacKenzie while preparing for a conference in September 2000. POJO is an ordinary Java object which doesn’t tie to any framework or external reference. It has no naming rule for its methods nor data members.

Java Bean is a Java object which meets Java Bean Conventions:

  • Properties must set as private and expose via getters/setter.
  • The getter and setter must name as getX (isX for boolean) and setX convention.
  • Must have a public default no-argument constructor
  • Must implement java.io.serializable interface

In this example, I will demonstrate the following items in a Maven project.

  • Define a POJO class
  • Define a Java Bean class
  • Create a POJO object via Reflection
  • Create a Java Bean object via Reflection

2. Technologies Used

java pojo
java pojo

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

  • Java 11
  • Maven 3.3.9
  • Eclipse Oxygen
  • Junit 4.12
  • Apache Commons BeanUtils 1.9.3

3. Maven Project

3.1 Dependencies

I will include Junit and commons-beanutils in the 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-pojo-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>

3.2 POJO

I will create a POJODemo class which represents a POJO and includes:

  • six fields naming from field1 to field6 with various access modifiers
  • toString to return a String value of the object
  • constructor to build an object with the field1 value

POJODemo.java

package jcg.zheng.demo.data;

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

public class POJODemo {

	private int field1;

	public Long field2;

	Integer field3;

	protected String field4;

	public List<String> field5 = new ArrayList<>();

	public boolean field6;

	public POJODemo(final int field1) {
		super();
		this.field1 = field1;
	}

	@Override
	public String toString() {
		return "POJODemo [field1=" + field1 + ", field2=" + field2 + ", field3=" + field3 + ", field4=" + field4
				+ ", field5=" + field5 + ", field6=" + field6 + "]";
	}

	public Integer getField3() {
		return field3;
	}

	public void setField3(Integer field3) {
		this.field3 = field3;
	}

}

3.3 Java Bean

I will create a JavaBeanDemo class which has the same six fields as the POJODemo class but satisfies the Java Bean conventions:

  • has a public default constructor
  • all properties have a private access modifier
  • all properties have getX (isX) and setX
  • implements Serializable interface

JavaBeanDemo.java

package jcg.zheng.demo.data;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

public class JavaBeanDemo implements Serializable {
	private static final long serialVersionUID = 1L;

	private int field1;

	private Long field2;

	private Integer field3;

	private String field4;

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

	private boolean field6;

	public JavaBeanDemo() {
		super();
	}

	public int getField1() {
		return field1;
	}

	public Long getField2() {
		return field2;
	}

	public Integer getField3() {
		return field3;
	}

	public String getField4() {
		return field4;
	}

	public List<String> getField5() {
		return field5;
	}

	public boolean isField6() {
		return field6;
	}

	public void setField1(int field1) {
		this.field1 = field1;
	}

	public void setField2(Long field2) {
		this.field2 = field2;
	}

	public void setField3(Integer field3) {
		this.field3 = field3;
	}

	public void setField4(String field4) {
		this.field4 = field4;
	}

	public void setField5(List<String> field5) {
		this.field5 = field5;
	}

	public void setField6(boolean field6) {
		this.field6 = field6;
	}

	@Override
	public String toString() {
		return "JavaBeanDemo [field1=" + field1 + ", field2=" + field2 + ", field3=" + field3 + ", field4=" + field4
				+ ", field5=" + field5 + ", field6=" + field6 + "]";
	}

}

You can also check our Java Bean example for further knowledge.

3.4 PlayingCard

I will create a PlayingCard class which is a POJO with:

  • two String data members – faceValue and suit
  • constructor to build an object with both faceValue and suit
  • toString method to return a String value of the object

PlayingCard.java

package jcg.zheng.demo.data;

public class PlayingCard {

	private String faceValue;
	private String suit;

	public PlayingCard(String suit, String faceValue) {
		super();
		this.suit = suit;
		this.faceValue = faceValue;
	}

	@Override
	public String toString() {
		return "Card [suit=" + suit + ", faceValue=" + faceValue + "]";
	}

}

3.5 PlayingCard Bean

I will create a PlayingCardBean class which is a Java Bean and has the same data members as PlayingCard.

PlayingCardBean.java

package jcg.zheng.demo.data;

import java.io.Serializable;

public class PlayingCardBean implements Serializable {

	private static final long serialVersionUID = 1L;

	private String faceValue;
	private String suit;
	public PlayingCardBean() {
		super();
	}

	public PlayingCardBean(String suit, String faceValue) {
		super();
		this.suit = suit;
		this.faceValue = faceValue;
	}

	public String getFaceValue() {
		return faceValue;
	}

	public String getSuit() {
		return suit;
	}

	public void setFaceValue(String faceValue) {
		this.faceValue = faceValue;
	}

	public void setSuit(String suit) {
		this.suit = suit;
	}

	@Override
	public String toString() {
		return "Card [suit=" + suit + ", faceValue=" + faceValue + "]";
	}

}

3.6 ReflectionService

In this step, I will create a ReflectionService class which has three methods:

  • createInstanceViaDefaultConstructor – creates an object via a given class’s default constructor.
  • createInstanceviaConstructorWithInt – creates an object via a given class’s constructor which takes one int argument.
  • displayAllFields – displays all fields for a given class and set one of the fields – field2 with 4.

ReflectionService.java

package jcg.zheng.demo;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;

public class ReflectionService {

	public Object createInstanceviaDefaultConstructor(String objClassName) {
		Object object = null;
		try {
			object = Class.forName(objClassName).getDeclaredConstructor().newInstance();
		} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | IllegalArgumentException
				| InvocationTargetException | NoSuchMethodException | SecurityException e) {
		}

		return object;
	}

	public Object createInstanceViaConstructorWithInt(String objClassName, int intF) {
		Object object = null;
		try {
			object = Class.forName(objClassName).getDeclaredConstructor(int.class).newInstance(intF);
		} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | IllegalArgumentException
				| InvocationTargetException | NoSuchMethodException | SecurityException e) {
		}

		return object;
	}

	public void displayAllFields(Object obj) throws IllegalArgumentException, IllegalAccessException {
		Field[] allFields = obj.getClass().getDeclaredFields();
		System.out.print("\nClass " + obj.getClass().getName() + " has declared fields: ");

		for (Field f : allFields) {
			System.out.printf("\n\t %s %s ", Modifier.toString(f.getModifiers()), f.getName());
			if( "field2".equalsIgnoreCase(f.getName())) {
				f.setAccessible(true);
				f.set(obj, 4l);
			}
		}
	}

}

4. JUnit Test

4.1 POJO Test

I will create POJODemoTest which includes four tests:

  • create_via_reflection_with_default_constructorPOJODemo has no default constructor, so it cannot create an instance with the no-argument constructor
  • create_via_reflection_with_int_constructor – POJODemo has a constructor that takes an int argument, so it can be used to create an instance via reflection.
  • displayAllFields – displays all the fields via reflection and set its field2 value to 4.
  • test_BeanUtils_copyProperties – Apache BeanUtils.copyProperties only works for the properties which meet getter and setter format.

POJODemoTest.java

package jcg.zheng.demo.data;

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 java.lang.reflect.InvocationTargetException;

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

import jcg.zheng.demo.ReflectionService;

public class POJODemoTest {

	private static final String POJO_DEMO = "jcg.zheng.demo.data.POJODemo";

	private POJODemo testClass = new POJODemo(3);

	private Object objectFromReflection;

	private ReflectionService reflectionDao = new ReflectionService();

	@Test
	public void create_via_reflection_with_default_constructor() {
		objectFromReflection = reflectionDao.createInstanceviaDefaultConstructor(POJO_DEMO);
		assertNull(objectFromReflection);
	}

	@Test
	public void create_via_reflection_with_int_constructor() {
		objectFromReflection = reflectionDao.createInstanceViaConstructorWithInt(POJO_DEMO, 4);
		assertNotNull(objectFromReflection);
	}

	@Test
	public void displayAllFields() throws IllegalArgumentException, IllegalAccessException {
		reflectionDao.displayAllFields(testClass);
		assertEquals(4, testClass.field2.intValue());
	}

	@Test
	public void test_BeanUtils_copyProperties() throws IllegalAccessException, InvocationTargetException {
		testClass.field2 = 100l;
		testClass.field3 = 123;
		testClass.field4 = "Mary";
		testClass.field6 = true;

		POJODemo dest = new POJODemo(4);
		BeanUtils.copyProperties(dest, testClass);
		System.out.println(dest);
		// Did not copy any properties at all
		assertTrue(dest.toString().contains("field1=4"));
		assertTrue(dest.toString().contains("field2=null"));
		assertTrue(dest.toString().contains("field3=123"));
		assertTrue(dest.toString().contains("field4=null"));
		assertTrue(dest.toString().contains("field5=[]"));
		assertTrue(dest.toString().contains("field6=false"));
		assertEquals(dest.getField3().intValue(), testClass.getField3().intValue());

	}
}

Junit output

Running jcg.zheng.demo.data.POJODemoTest
POJODemo [field1=4, field2=null, field3=123, field4=null, field5=[], field6=false]

Class jcg.zheng.demo.data.POJODemo has declared fields:
         private field1
         public field2
          field3
         protected field4
         public field5
         public field6 Tests run: 4, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.02 sec

Results :

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

4.2 Java Bean Test

I will create JavaBeanTest to test the following:

  • create_via_reflection_with_default_constructorJavaBeanDemo has a default constructor, so it can create an instance with the no-argument constructor
  • displayAllFields – displays all the fields via reflection and set its field2 value to 4.
  • test_BeanUtils_copyProperties – Apache BeanUtils.copyProperties works for the Java Bean properties

JavaBeanDemoTest.java

package jcg.zheng.demo.data;

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

import java.lang.reflect.InvocationTargetException;

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

import jcg.zheng.demo.ReflectionService;

public class JavaBeanDemoTest {
	private static final String BEAN_DEMO = "jcg.zheng.demo.data.JavaBeanDemo";
	private JavaBeanDemo testClass = new JavaBeanDemo();
	private Object objectFromReflection;

	private ReflectionService reflectionDao = new ReflectionService();

	@Test
	public void create_via_reflection_default_constructor() {
		objectFromReflection = reflectionDao.createInstanceviaDefaultConstructor(BEAN_DEMO);
		assertNotNull(objectFromReflection);
	}

	@Test
	public void getDeclaredFields() throws IllegalArgumentException, IllegalAccessException {
		reflectionDao.displayAllFields(testClass);
		assertEquals(4, testClass.getField2().intValue());
	}

	@Test
	public void test_copyProperties() throws IllegalAccessException, InvocationTargetException {
		testClass.setField2(100l);
		testClass.setField3(123);
		testClass.setField4("Mary");
		testClass.setField6(true);
		testClass.setField1(3);
		JavaBeanDemo dest = new JavaBeanDemo();
		BeanUtils.copyProperties(dest, testClass);
		System.out.println(dest);
		assertEquals(3, dest.getField1());
		assertEquals(100, dest.getField2().intValue());
		assertEquals(123, dest.getField3().intValue());
		assertEquals("Mary", dest.getField4());
		assertTrue(dest.isField6());

	}
}

Junit Output

Running jcg.zheng.demo.data.JavaBeanDemoTest

Class jcg.zheng.demo.data.JavaBeanDemo has declared fields:
         private static final serialVersionUID
         private field1
         private field2
         private field3
         private field4
         private field5
         private field6 JavaBeanDemo [field1=3, field2=100, field3=123, field4=Mary, field5=[], field6=true]
Tests run: 3, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.257 sec

4.3 Bean Disadvantage Test

I will create a BeanDisadvantageTest class which demonstrates that the object’s state is updated by the bean’s setter when it should be the same during its life cycle. For a PlayingCard object, its face value and suit should not be changed. But setters enable other processes to update them, which sometimes causes confusion or problem. This is one of drawback about the Java Bean.

BeanDisadvantageTest.java

package jcg.zheng.demo.data;

import static org.junit.Assert.*;

import org.junit.Test;

public class BeanDisadvantageTest {

	@Test
	public void javabean_state_changes_by_setter() {
		PlayingCard aceSpadePojo = new PlayingCard("Spade", "A");
		assertEquals("Card [suit=Spade, faceValue=A]", aceSpadePojo.toString());

		PlayingCardBean aceSpadeBean = new PlayingCardBean("Spade", "A");
		aceSpadeBean.setSuit("Club");
		aceSpadeBean.setFaceValue("1");

		// OOPS. the variable aceSpadeBean now changed to Club 1
		assertEquals("Card [suit=Club, faceValue=1]", aceSpadeBean.toString());
	}

}

Junit Output

Running jcg.zheng.demo.data.BeanDisadvantageTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.165 sec

5. Summary

As you saw in this example, Java Bean is a subset of POJO. They both can be created via Java reflection. Here are the major differences between them:

POJOJava Bean
DescriptionA normal Java object which meets Java programming language specificationA subset of POJO which meets Java Beans specification
Used ByAny application.
e.g. Spring framework uses it widely. All Spring Beans are POJO
A builder tool which creates an instance via a toolbox.
Apache commons BeanUtils
DisadvantageNADefault constructor and public setter can change the object state when it should be immutable.

6. Download the Source Code

Download
You can download the full source code of this example here: Java POJO and Java Bean 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