Welcome!

Java Authors: Aditya Banerjee, Al Mannarino, Christopher Keene, Anatoly Krivitsky, Pat Romanski

Related Topics: Java, Websphere

Java: Article

Cover Story: What Is POJO Programming?

Introducing POJO application development

Each Spring bean definition includes a name, an implementation class, and one or more dependencies, which are supplied by either constructor or setter injection. When the presentation tier asks the bean factory to create a MoneyTransferService, first it will instantiate an AccountDAOHibernateImpl, which is the Hibernate implementation of the AccountDAO interface. The bean factory will then instantiate the MoneyTransferServiceImpl passing the AccountDAOHibernateImpl to its constructor.

Spring provides an extremely flexible dependency injection mechanism. It can inject aribitrary POJOs in POJOs. Spring can even, for example, do a JNDI lookup to get an object and inject it into a POJO.

EJB 3 Dependency Injection
In comparison, EJB 3 dependency injection is limited to injecting values from JNDI into either session beans or message-driven beans. You can configure field or setter injection using either XML or annotations. Listing 2 shows how you could inject an AccountDAO into a MoneyTransferServiceImpl using an annotation.

In this example, the @EJB annotation specifies that when the EJB 3 container instantiates a MoneyTransferServiceImpl it must initialize the accountDAO field with a reference to an AccountDAO. Behind the scenes, the EJB 3 container does a JNDI lookup of the AccountDAO, which is also implemented as a session bean. If the MoneyTransferServiceImpl called the EJB 3 persistence APIs directly then you'd simply inject the EJB 3 EntityManager directly.

Dependency injection is one of the cornerstones of POJO development. Another one is the ability to persist POJOs with an object/relational mapping (ORM) framework.

Persisting POJOs
POJOs often have to be persisted in a relational database. For example, the Money Transfer application must store Account objects in the ACCOUNT table. It could, of course, access the database using JDBC or iBATIS. Sometimes this is the right approach. But unless you have a really simple object model, it can be a lot of work to develop and maintain the Data Access Objects (DAOs) and the SQL needed to transfer objects to and from the database. It's usually a lot easier to use an ORM framework.

An Overview of ORM
When using an ORM framework you declaratively specify how your object model maps to the database schema. You specify how classes map to tables; fields map to columns, and relationships map to either foreign keys or join tables. The ORM framework then generates the SQL statements to create, find, update, and delete persistent objects. It also keeps track of which objects have changed and automatically writes them back to the database. As a result, you have to write a lot less code. Moreover, it's usually a lot easier to switch databases because the ORM framework is generating the SQL for you.

EJB 2 CMP provides a primitive form of ORM. However, it requires your classes to implement or extend EJB interfaces. In comparison, modern ORM frameworks such as Hibernate, JDO, and EJB 3 provide what's termed transparent persistence. Apart from perhaps having to add a field to store the primary key, the code for the objects shows no sign that they are persistent. The only classes that are dependent on the ORM framework are classes such as DAOs that create, find, and delete persistent objects. Let's look at an example.

Declarative Mapping
When using an ORM framework you define the mapping using either XML or Java 5 annotations. Table 1 shows how you map the Account class to the ACCOUNT table using EJB 3 annotations and a Hibernate 3 XML mapping document.

In each example, the Account class is mapped to the ACCOUNT table; the id field that stores the primary key is mapped to the ACCOUNT_ID column; and the balance field is mapped to the BALANCE column.

AccountDAOHibernateImpl
Once you've defined the mapping you can use the ORM framework's API for creating, finding, and deleting persistent objects. The APIs provided by each of the ORM frameworks are pretty similar. Here's an example of a DAO that uses a Spring HibernateTemplate, which is an ease-of-use wrapper around the Hibernate APIs:

public class AccountDAOHibernateImpl
   implements AccountDAO {
     private HibernateTemplate hibernateTemplate;
     public AccountDAOHibernateImpl(HibernateTemplatetemplate) {
     hibernateTemplate = template;
   }
     public Account findAccount(String accountId) {
     return (Account) hibernateTemplate.get(new Integer(accountId));
   }
...
}

The HibernateTemplate is passed to the AccountDAOHibernateImpl using constructor injection. The findAccount() method loads an account by calling HibernateTemplate.get(). When get() is called, Hibernate generates and executes a SELECT to load the corresponding row from the ACCOUNT table. If the Account object is then modified by the application, Hibernate will execute an UPDATE statement to save the changes in the database. An EJB 3 DAO would work the same way. It would call the EJB 3 EntityManager to create, find, and delete persistent objects.

But There Are Also Some Drawbacks and Limitations
When used appropriately ORM is an extremely powerful tool that can significantly increase development productivity while providing excellent performance. But like every tool, it has its limitations. For example, an ORM framework might not be a good choice in the following situations:

  • Your application accesses a denormalized legacy schema
  • Your DBA insists on inspecting your SQL statements
  • Your DBA requires all database accesses to go through stored procedures.
  • Your application must perform bulk updates or inserts.
Don't be afraid to use SQL when you have to.

Making POJOs Transactional
Transactions are an essential part of the Enterprise Java application. Without them we risk corrupting data. Consider, for example, the MoneyTransferService shown earlier in Listing 2. It's vital that when the transfer() method executes in a transaction that you ensure that updates are made atomically. Otherwise, if the application crashes after debiting one account but before crediting the other account the money could disappear into the ether.

One of the nice features of EJB2 session beans is its support for container-managed transactions, which are a form of declarative transaction management. They simplify the application and make it more reliable by eliminating error-prone transaction management code. In a POJO application, the two main ways to implement declarative transaction management are to use either the Spring framework or EJB 3. Both frameworks use either Java 5 annotations or XML to specify the transactional attributes of a POJO.

Spring Transaction Management
The Spring bean factory does more than simply instantiate objects. It can also wrap the objects that it creates with interceptors (a k a proxies). These interceptors are how Spring provides a simple, yet effective Aspect-Oriented programming (AOP) implementation. AOP is the foundation of Spring transaction management. To make a POJO transactional you configure the bean factory to wrap it with TransactionInterceptor, which executes method calls within a transaction.

Spring provides a couple of ways to configure the bean factory to apply the TransactionInterceptor. One option is to use the @Transactional annotation on the interface, implementation class, or individual methods. For example:

@Transactional interface MoneyTransferService {...}

The @Transactional specifies that when the Spring bean factory instantiates the MoneyTransferServiceImpl that implements the interface, it must apply TransactionInterceptor.

Another option is to write XML bean definitions that explicitly apply the TransactionInterceptor to the POJO. Here's an example bean definition that uses the Spring BeanNameAutoProxyCreator to apply a TransactionInterceptor to the MoneyTransferService.

<bean id="transactionProxyCreator"
class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"
   <property name="beanNames">
    <list>
   <idref bean="moneyTransferService" />
    </list>
</property>
<property name="interceptorNames">
    <list>
     <idref bean="transactionInterceptor" />
    </list>
</property>
</bean>

The XML is more verbose than the annotation but has the advantage of leaving the source code unchanged. It also works with older JDKs that don't support annotations.

Spring doesn't implement transactions itself but is, instead, a wrapper around other transaction management APIs. Unlike EJB 3, it gives you the flexibility of using either JTA (as provided by an application server) or the transaction management APIs provided by ORM frameworks such as Hibernate and JDO.

More Stories By Christopher Richardson

Chris Richardson is the author of the recently published POJOs in Action. He's a developer, architect, and mentor with over 20 years of experience. Chris runs a consulting company that jumpstarts new development projects and helps teams that are frustrated with Enterprise Java to become more productive and successful. He lives in Oakland, CA with his wife and three children.

Comments (8) View Comments

Share your thoughts on this story.

Add your comment
You must be signed in to add a comment. Sign-in | Register

In accordance with our Comment Policy, we encourage comments that are on topic, relevant and to-the-point. We will remove comments that include profanity, personal attacks, racial slurs, threats of violence, or other inappropriate material that violates our Terms and Conditions, and will block users who make repeated violations. We ask all readers to expect diversity of opinion and to treat one another with dignity and respect.


Most Recent Comments
Preet 06/24/08 01:42:08 PM EDT

interesting read... answers the what, but, and what ifs..
Thanks! I am newbie in this domain and this is exactly what I was looking for.

Mathan 02/26/08 10:39:21 AM EST

The main advantage of the POJOs are felt in distributed applications. Assume that your application is consuming services from 10 different applications. If one of them is down, then your application is effectively down. Instead, if you have the POJOs for all those apps bundled in your app, then your application can stand alone without any dependency

rogerv 03/28/06 05:20:31 PM EST

What Is POJO Programming?

Oh - that's where you write 30% of a Java application in a declarative, XML-based domain specific language.

For all practical purposes (and by very definition) the domain specific language will be unique to a given POJO container and hence will render the Java application essentially unportable.

Patrick Ellul 03/14/06 10:25:04 PM EST

I found this article very helpful with introducing me to the concepts behind POJO's and ORM's and frameworks such as Spring and Hibernate.

Justin Peck 03/13/06 12:28:09 AM EST

I liked this article so much, I wrote a Web application after having read it. Spring really does make programming Java-base Web apps fun again. Thanks for the article!

[You can see the app now at http://javajuster.com]

Alain Ah Ming 02/26/06 05:21:30 AM EST

Is this simply replacing the underlying entity EJB with the value object?
If a J2EE app were designed in a way that we had distinct segregation as follows:
Session EJB --> BusinessLogic Helper class --ValueObj--> DAO interface --ValueObj--> DAO impl class --ValueObj--> Entity EJB

would that would make it as good as what POJO prog is trying to achieve?

From our test class, we can easily invoke our business logic helper class (which is a pure POJO) by injecting a test DAO impl class.
That effectively leaves out any dependency to the underlying framework (EJB or spring).

harris reynolds 02/23/06 05:39:06 PM EST

Trackback Added: JDJ RIP; I receive several trade rags about technolgy. Most of them get stacked up in a pile by my desk that I eventually go through after they start cluttering the office. When going through the latest round of magazines recently I...

SYS-CON Italy News Desk 02/21/06 01:40:28 PM EST

The novel A Deepness in the Sky by Vernor Vinge is set in the distant future. The character Pham Nuwen is responsible for maintaining software whose components are thousands of years old. Today, however, it's difficult to imagine maintaining an Enterprise Java application for more than a few years. More often than not, the application is tightly coupled to infrastructure frameworks that evolve rapidly in ways that don't preserve backwards compatibility. Consequently, upgrading to a new and improved framework can be challenging and risky.