On the road to simplicity

JBoss 4.0 simplifies middleware development

In September 2004, the JBoss Application Server (AS) 4.0 became J2EE 1.4 certified. For JBoss's core developers and early adopters, the coolest thing about JBoss AS 4.0 is not the J2EE certification, but the new technologies that currently reach beyond the scope of J2EE and aim to greatly simplify Java middleware development. The idea is to replace existing Enterprise JavaBeans (EJB) with simpler and more manageable plain old Java objects (POJOs). Simplified applications lead to higher developer productivity, better application performance, and less bugs. Simplicity (a.k.a. lightweight development) is the "next big thing" in the server-side Java community, and JBoss AS 4.0 is the first major J2EE server to take solid steps in that direction.

In this article, I use three example applications to show you the simplicity of the POJO middleware frameworks in JBoss AS 4.0 and how they relate to the current and future J2EE specifications. If you are a JBoss user or a general J2EE developer, this article teaches you portable skills that you can use in both today's JBoss AS 4.0 server and the future JBoss 5.0 or J2EE 1.5 servers.

Let's start with the problems inherent in the current EJB 2.1 middleware frameworks to show the need for a simpler POJO-based framework.

Open source and J2EE certification
The official J2EE certification for JBoss is a milestone for both the Java and open source communities. Not too long ago, it was believed that without charity from Sun, no open source J2EE project would pass certification due to the high cost and extensive quality assurance efforts required. JBoss achieved J2EE certification by itself and hence proved the validity of the open source development model in delivering enterprise-ready Java solutions.

What's wrong with EJB 2.1?

Since its inception, J2EE has achieved great success in the marketplace for developing scalable and distributed server-side applications. However, EJB, a core component for middleware in the J2EE stack, has gained the reputation of being too complex and difficult to use, especially for small to midsize business applications. The overhead of EJB infrastructure code and deployment descriptors drains both server resources and, more importantly, developer productivity. Developers often end up writing and maintaining more infrastructure code than business logic code.

To illustrate the above point and provide a comparison for alternative simpler solutions enabled by JBoss AS 4.0, let's look at an EJB 2.1-based example application. The Mortgage Calculator Web application calculates the monthly mortgage payment for a loan and stores the results in a relational database. After each calculation, the application searches the database for past results that have lower monthly payments. Those results are displayed at the bottom of the page. Figure 1 shows how the application works. When you first access the application, you are prompted to enter a username and password. Use the username and password combo "user1"/"pass1" to log in. If you want to see the error message for unauthorized users, try the "user3/pass3" combo.

Figure 1. The Mortgage Calculator Web application in action. Click on thumbnail to view full-sized image.

The application's source code is available from the ejb2 folder in the sample source code bundle. Just execute the command build.bat (for Windows) or build.sh (for Linux, Unix, or Mac OS X) in the ejb2 directory to build the application. Copy the resultant ejb2/build/jar/MortgageCalculatorEJB2.ear file to your JBoss server's server/default/deploy/ directory to deploy it. The URL to the application is http://localhost:8080/MortgageCalculatorEJB2/servlet/Calculator.

Why use EJB?
Why use EJB for such a simple application? Well, the EJB container offers some valuable services that could immediately add enterprise features to our little application without requiring us to write code. For instance, the EJB container checks the user credentials and monitors database transactions for all EJB method invocations according to the configuration files. It also manages the database table and database connections without requiring us to write any SQL or JDBC (Java Database Connectivity) code.

Under the hood, the application has a servlet that takes in user input and generates the HTML page. The servlet delegates the payment calculation and database-related work to an EJB module.

This application has two EJB components. The Calculator bean is a stateless session bean. It contains transactional methods to calculate the payment, save results to the database, and search the database. Those methods are exposed to the servlet. The Calculator bean uses the History entity bean to access the database. In the EJB configuration files, we define how the History entity bean's data fields are mapped to database columns and how to search the database for a list of History objects. Since the History bean is an EJB component, it cannot be used outside the EJB container. So we create a HistoryList value object to hold the result of any search operation, which is passed back to the servlet.

Figure 2 illustrates the EJB module's structure. It shows all the required EJB component interfaces and key elements of the deployment descriptors.

Figure 2. Key components in the EJB module. Click on thumbnail to view full-sized image.

As you can see, the structure shown in Figure 2 is complex, with multiple tightly coupled Java interfaces, classes, and XML artifacts. Wouldn't it be nice if a framework allowed developers to focus on what they do best—writing Java code—instead of distracting them with a flurry of component interfaces and XML artifacts? Well, the good news is that the POJO middleware framework in JBoss AS 4.0 enables developers to take advantage of EJB container services without all the EJB 2.1 baggage.

Innovate for simplicity

Learning from the perils of EJB, we can see that a successful alternative framework should have the following key characteristics:

  • The framework should not impose an arbitrary component model to developers, as such models break the object-oriented design structure. In other words, the framework should support POJOs that developers can extend and reuse inside and outside the application container.
  • The framework should eliminate the need to manually write verbose and often excessive EJB deployment descriptors. A POJO should be able to simply declare what container services it needs.
  • The framework should support local access to the POJOs by reference. Java object serialization is slow and should be avoided when possible, especially for most small to midsized applications.

Rather than waiting for the Java Community Process (JCP) to invent and standardize a POJO-based lightweight middleware framework, the Java open source community has experimented with numerous different approaches over the past several years. Examples of such open source projects include XDoclet, Hibernate, Spring, and various aspect-oriented programming (AOP) projects. The new POJO-based middleware framework in JBoss AS 4.0 leverages those past research and development efforts.

Two JBoss-sponsored open source projects play key roles in the POJO middleware framework:

  • The JBoss AOP project supports service delivery to POJOs via Java annotations
  • The Hibernate project is the de facto standard framework for object-relational mapping and POJO persistence

Both projects integrate and leverage the proven and J2EE-certified container services in JBoss AS to support enterprise-class applications. Now let's refactor the Mortgage Calculator EJB components to POJOs and see how this powerful new development model works.

The power of enterprise POJO

The POJO Mortgage Calculator application is also included in the source code bundle. As I will soon explain, the application source code and build scripts differ slightly for J2SE 1.4 and J2SE 5.0 environments. I prepared both versions in the pojo-jdk14 and pojo-jdk50 directories, respectively. The building and deployment instructions are the same as the ejb2 example application. Once deployed, the URL to the POJO sample application is http://localhost:8080/MortgageCalculatorPOJO/servlet/Calculator.

As I discussed, our goal is to use POJO to replace the session and entity beans. Meanwhile, the framework should be able to preserve a key benefit of EJB servers—declaratively apply container services to applications. This way, when we need to change the services later, we need only modify the declaration and not refactor large amounts of Java code. But how can a POJO tell the JBoss container what services it needs without using deployment descriptors? Well, that is where AOP and Java annotation come into play.

Annotation to the rescue

Annotation was introduced as part of the official Java language syntax in J2SE 5.0. JBoss AS 4.0 defines a set of annotation tags as APIs for POJOs to access J2EE container services. You can annotate any POJO or POJO method with those tags and declare how the container services should be applied to them. Under the hood, JBoss AS uses the JBoss AOP framework to dynamically alter the behavior of the annotated objects and methods. You can find more information about JBoss AOP and how it works with annotations from the JBoss AOP user's guide and reference documentation (see Resources).

The following listing shows the skeleton of the Calculator POJO class, which replaces the Calculator session bean:

 

@SecurityDomain ("other") public class Calculator {

@Unchecked public Calculator () { }

@Permissions ({"AuthorizedUser"}) @Tx (TxType.REQUIRED) public double getPayment (int principal, double rate, int term) throws Exception { // Calculate and save to database. // Code omitted for clarity. }

@Permissions ({"AuthorizedUser"}) @Tx (TxType.REQUIRED) public List getHistory (double payment) throws Exception {

// Search the database. // Code omitted for clarity. } }

The @SecurityDomain annotation declares that the POJO's security domain is other, which tells JBoss to find the password and user role lists in the classpath's users.properties and roles.properties files. The @Permissions annotation specifies that only the user with username AuthorizedUser is permitted to access the getPayment() and getHistory() methods. JBoss AS performs the permission check at runtime. The @Tx annotation starts the JBoss transaction manager for the getPayment() and getHistory() methods to ensure any change they make to the database is committed only when the complete method successfully executes and returns.

But what about J2EE 1.4 users? Can they still take advantage of the simple annotated POJOs as EJB alternatives? The answer is a resounding "Yes!" You can embed annotations as Javadoc-style comments in J2EE 1.4 source code. The JBoss AOP framework provides an annotation compiler that post-processes those Java comments and adds annotations into the bytecode. This compiler's functionality resembles that of XDoclet. The following listing shows the J2EE 1.4 version of the Calculator POJO class in the pojo-jdk14 directory:

 

/**

* @@org.jboss.aspects.security.SecurityDomain ("other") */ public class Calculator {

/** * @@org.jboss.aspects.security.Unchecked */ public Calculator () { }

/** * @@org.jboss.aspects.security.Permissions ({"AuthorizedUser"}) * @@org.jboss.aspects.tx.Tx (org.jboss.aspects.tx.TxType.REQUIRED) */ public double getPayment (int principal, double rate, int term) throws Exception { // Calculate and save to database. // Code omitted for clarity. }

/** * @@org.jboss.aspects.security.Permissions ({"AuthorizedUser"}) * @@org.jboss.aspects.tx.Tx (org.jboss.aspects.tx.TxType.REQUIRED) */ public List getHistory (double payment) throws Exception {

// Search the database. // Code omitted for clarity. } }

To use the JBoss AOP annotation compiler, you just need to add one more task in the Ant build script. The following listing shows the relevant parts of the pojo-jdk14/build.xml script:

 

<target name="prepare"> ... ...

<taskdef name="annotationc" classname="org.jboss.aop.ant.AnnotationC" classpathref="build.classpath" /> </target> ... ... <target name="annotate" depends="compile"> <annotationc compilerclasspathref="build.classpath" classpath="${build.dir}/classes" bytecode="true"> <src path="${src.dir}"/> </annotationc> </target>

With Java annotations, we replace the session bean and its related components with a simple POJO. But what about the entity bean?

Lightweight POJO persistence

The primary function of the container-managed persistence (CMP) entity bean is to model the application data and persist it transparently to the backend database. In the JBoss AS 4.0 lightweight middleware framework, Hibernate completes the data modeling and persistence.

The History class is a simple POJO that models data in a calculation transaction. It only contains the data fields and JavaBean-style accessor methods:

1 2 Page 1
Page 1 of 2