Skip to content

The difference between pojos and java beans

Java Beans and Pojos are often used and misunderstood terms. Some think that a pojo is a java bean and vice versa. In fact it is not. There are differences that matter.

The pojo

If you want to know what a term really means you have to find the source context in which the term has been created. So for the term pojo it was originally created by Martin Fowler, Rebecca Parsons and Josh MacKenzie at a time when J2EE had it’s hype. At that time J2EE developer were more busy with technology instead of concentrating on the business value. The problem arised because J2EE requires a lot of techology code in your domain objects and this moved the focus to techology. So Martin Folwer, Rebecca Parsons and Josh MacKenzie prepared a talk at a conference in September 2000. They wanted to tell the audience about this problem and that it would be easier if developers use “just a java object” for the business code, which means that it has only dependencies to plain java (JRE). At least a “plain old java object” makes the “heart of software” (the domain logic) independent to technology changes and easier to test, because you are not tied to a specific implementation technology like J2EE.

They decided to talk about this at the conference, but they knew that knowone would listen or take them serious if they say “lets just use java objects”. The problem is that talking to software developers has more common with the fashion week as you might expect. Therefore they searched for a fancy name and as we all know they choosed:

Plain Old Java Object

I guess that the fancy name was the only reason why developers started to implement POJOs.

POJO or not POJO

Unfortunately a lot of developers think that a POJO must only have simple getter and setters for it’s internal fields. But if you do that you must place the logic that operates on that fields in another class which leads to an anemic model.

The following class is a real POJO, because it doesn’t contain a technical aspect nor is derived from one. A POJO can have simple getters and setters, but it can also contain logic approriate for that class.

public class Person {

    private String firstname;
    private String lastname;
    private LocalDate birthday;

    public Person(String firstname, String lastname, LocalDate birthday) {
        this.firstname = firstname;
        this.lastname = lastname;
        this.birthday = birthday;
    }

    public String getFirstname() {
        return firstname;
    }

    public String getLastname() {
        return lastname;
    }

    public boolean isOfFullAge(Area area) {
        LocalDate currentDateInArea = area.getCurrentDate();
        int fullAgeYears = area.getFullAgeYears();
        int age = ChronoUnit.YEARS.between(birthday, currentDateInArea);
        return age >= fullAgeYears;
    }
}

I recommend to also read my blog Anemic vs. Rich Domain Models.

The java bean

The term java bean is defined in the Java Bean Specification. A java bean might be technology independent. Therefore it can be a pojo.

Initially a java bean was invented to provide a software component model for Java:

The goal of the JavaBeans APIs is to define a software component model for Java, so that third
party ISVs can create and ship Java components that can be composed together into applications
by end users.

Java Bean Specification – Chapter 1 –  Introduction

Java provides easy access to java bean properties through the Introspector, BeanInfo and PropertyDescriptor apis. E.g.

Object javaBean = new JTextField();

BeanInfo beanInfo = Introspector.getBeanInfo(javaBean.getClass());
PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();

for (int i = 0; i < propertyDescriptors.length; i++) {
    PropertyDescriptor propertyDescriptor = propertyDescriptors[i];
    String propertyName = propertyDescriptor.getName();

    Method propertyGetter = propertyDescriptor.getReadMethod();
    if(propertyGetter != null){
        // Getter available
        Object propertyValue = propertyGetter.invoke(javaBean);
        System.out.println("Property " + propertyName + " value = " + propertyValue);
    }
}

Because of the easy property access apis a lot of frameworks today want components to be java beans.

But in order to fulfill the Java Bean Specification requirements,  a Java Bean must

  1. have a public default constructor
  2. be serializable
  3. must define public accessors for it’s properties (getter and setter methods)

Especially point 1 “must have a public default constructor” makes the implementation of a java bean complex, because it means that a java bean is in a legal state even if it has no references to other objects.  In a lot of cases an object must have references to other objects. So if you implement a java bean that needs references to other objects, you must define how this bean handles the “unconnected” state – the state when the bean is created by the default constructor, but no other objects it needs has been set.

You can specify that the bean might react like the Null object pattern in it’s initial state or the bean just throws exceptions to indicate that it is not completely initialized. Both strategies increases the complexity of state handling, because every method must first check if the object’s pre-conditions (all mandatory references are set – object is initialized) are fulfilled. You might think now that you can workaround this problem by defining a factory that ensures that all references are set before returning the object, but keep in mind that the default constructor must be public. Therefore you can not really workaround, because every client has the possibility to create an instance using the default constructor. You can not prevent the creation with default java language features and you only have the option to document it in javadoc.

Think about how complex a DAO might get if you try to write it as a java bean

public class CustomerDaoImpl implements CustomerDao {

  private DataSource dataSource;

  public Customer findById(String id){
      checkInitialized();

      Customer customer = null;
     /*
       * getConnection, build sql, execute and map data
       */
     return customer;
  }

  private void checkInitialized(){
     if (this.dataSource == null) {
          throw new IllegalStateException("Dao has not been initialized. DataSource is missing.");
     }
  }

  public void setDataSource(DataSource dataSource){
     if(dataSource == null){
        throw new IllegalArgumentException("Parameter dataSource must not be null");
     }
     if(this.dataSource == null){
         this.dataSource = dataSource;
     } else {
         throw new IllegalStateException("Dao already initialized.");
     }
  }

}

The dao will get much easier if it is not a java bean, because you can ensure that an instance only exists if all mandatory references are available.

public class CustomerDaoImpl implements CustomerDao {

  private DataSource dataSource;

  public CustomerDaoImpl(DataSource dataSource){
      if(dataSource == null){
        /*
          * Only if a dataSource is provided
          * a CustomerDaoImpl can be created.
          * So all methods can assume that a
          * dataSoure is available.
          */
        throw new IllegalArgumentException("Parameter dataSource must not be null");
     }
     this.dataSource = dataSource;
  }

  public Customer findById(String id) {    
      Customer customer = null;
     /*
       * getConnection, build sql, execute and map data
       */
     return customer;
  }
}

As you can see the second example is much easier to understand and straight forward to implement. A lot of components should not be java beans so think twice when you make the decision to implement something as a java bean. Keep in mind that the second example is still a pojo.

Spring and java beans

As described above a java bean must have a public default constructor and the examples show that components like DAOs are much easier to implement if they are not a java bean. A lot of developers argue that you can design a component like a DAO as a java bean, because the spring framework ensures that the required dependencies are set before the object will be used.

First of all the framework only ensures what you tell it. So if you you tell it to check that all references are set, why don’t you do this in your code? Why do developers want to define this constraints somewhere else? If you let spring ensure this constraint and not your code it also means that your component can be used incorrect in a non-spring environment.

The second problem is that the spring framework only checks that the dependencies are set. But how can you execute some logic after a dependency is set? One place could be the setter of a property. This is a good place to implement validation logic if validation logic does not depend on more properties. Otherwise the order of setter calls might be important or the complexity of the setters increases. So a lot of developers tend to use the InitializingBean interface of spring. That is ok, but keep in mind that you are not implementation technology independent anymore. Take a look at the following example of an InitializingBean and especially at the import statements.

import javax.sql.DataSource;

import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;

public class CustomerDaoImpl implements CustomerDao, InitializingBean {

private DataSource dataSource;

public Customer findById(String id) {
  Customer customer = null;
 /*
   * getConnection, build sql, execute and map data
   */
 return customer;
}

public void setDataSource(DataSource dataSource) {
 this.dataSource = dataSource;

}

public void afterPropertiesSet() throws Exception {
 /*
   * Bad implementation of a initialization check, because implementing
   * InitializingBean makes this class spring dependent.
   */
  Assert.notNull(dataSource, "DataSource is missing.");
}

}

This kind of implementing an initialization check makes the CustomerDaoImpl depend on the spring framework, because you have to implement the InitializingBean interface. If you are writing a component that is an extensions for spring the usage of the InitializingBean interface is ok. But omit the usage in your application code. A better solution is to use the init-method attribute in the spring configuration.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean class="CustomerDaoImpl" init-method="init">
      <property name="dataSource" ref="someDataSource" />
    </bean>
</beans>

But one question still remains open even if you use the init-method approach. When you write an initialization check method like the init() method above, why don’t you just put that code into the constructor? A constructor is made for initializing an object, isn’t it? And if you put that initialization logic in the constructor you can prevent objects that are not in a legal state. This would make the client code easier, because a client can rely on the fact that the object is in a legal state if it has a reference to it (if it exists). Keep also in mind that the spring framework supports constructor injection. See Why use constructor over setter injection in CDI?

As I showed above, improving the code step by step will automatically lead to a design where an object is always in a valid state.

4 thoughts on “The difference between pojos and java beans”

  1. Very good and worth reading blog! for java beginners. I new to java and want to clear each and every concept in java, i was looking for the difference between pojos and java beans and i have found it here in your blog that is so helpful for me. It will be also helpful if you can share java beans and spring beans. Thanks a lot .

  2. First of all, I would like to thank you for sharing such a useful information.
    Do keep sharing on like future posts in future career.
    Thank you so much…..

Leave a Reply to pranit patil Cancel reply

Your email address will not be published. Required fields are marked *

 

GDPR Cookie Consent with Real Cookie Banner