J2EE Without the Application Server

J2EE-based applications have become very successful in the enterprise market, despite the notorious complexity of both the J2EE platform (the application server) and its proposed programming model (Enterprise JavaBeans, or EJB). Thanks to modern notions like inversion-of-control (IoC) and aspect-oriented programming (AOP) represented in lightweight containers like the Spring framework, the programming model for J2EE can be made a lot simpler and more elegant. Nevertheless, even with these tools, the application server still remains an important source of complexity and cost. This article proposes a further simplification of J2EE, by showing a way to eliminate the overhead of the runtime platform: the application server. In particular, this article shows that many applications no longer need an application server to run. As a result, J2EE applications become:

Easier to program: No EJB plumbing code is required.

Simpler: There are no EJB classes or interfaces to inherit from.

Easier to test: Your application and its tests can be run from within your integrated development environment (IDE).

Less resource-consuming: You just need your objects, not the application server nor its objects.

Easier to install: There is no application-server-specific installation to perform, and no extra XML files to add.

Easier to maintain: The overall process is much simpler, so maintenance is also easier.

The unnecessary complexity of J2EE has been a show-stopper for many projects and teams. Today, this complexity can often be avoided by the approach outlined in this article. In addition, it is possible to preserve or even improve the typical services like transactions and security. J2EE programming has never been more fun!

Example: The Message-Driven Bank

To illustrate our point, we will develop and install a complete sample application: a message-driven banking system. We will do this without the need for EJBs or an application server, while preserving the same transactional guarantees and with (thanks to Spring) an improved programming model based on "plain old Java objects" (POJOs). In a later section, we will generalize from message-driven architectures to others, like web-based ones. Figure 1 shows the architecture of our demo application.

Figure 1. Architecture of the message-driven bank

In our scenario, we will process incoming bank orders from a Java Message Service (JMS) queue. The processing of an order involves updating the account database via Java Database Connectivity (JDBC). In order to avoid message loss or duplicates, we will use the Java Transaction API (JTA) and JTA/XA transactions to coordinate the updates: consuming a message and updating the database will happen in one atomic transaction. See the Resources section for more information on why we need JTA/XA.

Coding the Application

The application will consist of two simple Java classes: Bank (a data access object or DAO) and MessageDrivenBank. This is shown in Figure 2.

Figure 2. Classes for the message-driven bank

The Bank is a data access object that encapsulates the database access. The MessageDrivenBank is a message-driven façade and delegates to the DAO. Unlike with the classical J2EE approach, there are no EJB classes involved.