devxlogo

Getting Started with EJB 3.0 and Enterprise Bean Components

Getting Started with EJB 3.0 and Enterprise Bean Components

lthough the EJB 3.0 specification has yet to be released, it is already generating much interest in the software development community by both proponents and opponents alike. All recognize the need to find more productive methods for developing software; the debate centers on whether, and to what extent, EJB 3.0 will play a role in this new landscape.

Debate notwithstanding, the release of the EJB 3.0 public draft and preliminary support in JBoss mean that now is a great time to explore this influential technology. In fact, reports of the use of EJB 3.0 in production systems are already emerging.

This article is the first in a three-part series exploring EJB 3.0 as defined in the public draft. Each article will introduce you to particular concepts from the specification and will walk you through the implementation of these techniques using JBoss. This first article will introduce EJB 3.0 and the basics of Enterprise Bean Components.

What You Need

Introducing EJB 3.0
Enterprise applications are a class of software applications that perform business functions and typically involve large quantities of data concurrently accessed by many users. These applications rarely perform in isolation. Instead, each usually forms just one piece in the puzzle of a company’s IT landscape and must interact with people and other systems. In short, developing enterprise applications is tough work. Issues such as performance, scalability, concurrency, and security must be addressed in almost all enterprise applications in order that they will successfully fulfill their role in the enterprise.

In answer to these challenges, the EJB specification was introduced in March of 1998 to make it easier to write distributed object-oriented business systems. The specification and the application servers implementing it have succeeded in this goal for the most part. But over the years the shortcomings of EJB, along with the advent of simpler alternatives, have caused many to question whether EJB offers the best solution for the productive development of enterprise applications.

Frequently cited shortcomings of EJB include the following:

  • Components wanting to take advantage of provided enterprise services are coupled to the EJB API.
  • It is an all-or-nothing proposition. Even if you want just one service of EJB, you have to accept all that comes with EJB.
  • EJB components require a container and prove difficult to test.
  • Each EJB requires several artifacts (interfaces, classes, and descriptors).
  • Traditional EJB architectures are less object-oriented and introduce “fake objects” that have only state and no behavior.

Popular alternatives to EJB include the following:

  • Aspect Oriented Programming
  • Lightweight containers such as Spring, Pico Container, and Hivemind
  • Object relational mapping (ORM) tools like Hibernate, JDO, and iBatis
  • .NET Serviced Components

The public draft of the EJB 3.0 specification aims to ease development and to make it simpler to leverage enterprise services. These improvements are to some extent influenced by the success of the alternatives listed above. Some aspects of the above tools that have left their mark on EJB 3.0 include:

  • A POJO (Plain Old Java Object) programming model
  • A lightweight ORM persistence framework
  • Dependency injection
  • Metadata annotations

Other notable aspects of the EJB 3.0 specification include:

  • Configuration by exception
  • Elimination of component interfaces
  • Elimination of home interfaces
  • Reduction of the use of checked exceptions

This article assumes that you are already familiar with EJB 2.x and will focus on the changes introduced in the public draft of the 3.0 specification. The rest of this discussion will explore these improvements as you walk through the process of building an EJB 3.0 application using Maven and the JBoss application server.

Example Application?An Online Music Store
The techniques discussed in this article are illustrated by the example application, an online music store. This store allows users to browse and purchase music, videos, and audio books. Figure 1 shows a screenshot of the interface; you can download the source code from the link at the bottom of any page or in the left column.

This example application demonstrates all three types of enterprise bean components in action: namely, stateless session beans, stateful session beans, and message-driven beans. Notice that in the EJB 3.0 specification entity beans are no longer considered enterprise bean components in the same way that session and message-driven beans are. Instead, they are considered persistent entities (this will be covered in my next article on EJB 3.0 persistence). The class diagram in Figure 2 is a high-level illustration of how the music store application is implemented with EJB.

Figure 1. Music Store: The music store allows products to be browsed, added to a shopping cart, and eventually purchased.

The example application included with this article has been designed and tested with JBoss Application Server 4.0.3 and JBoss AOP 1.3.4, and uses Maven 2.0 to build the application. The attached code provides instructions for setting up JBoss, building the source with Maven, and deploying the application.

Stateless Session Beans
Along with the other enterprise bean components in the EJB 3.0 specification, stateless session beans are POJOs that implement a business interface. Take our music store example: The music store is queried for various types of audio and video as users browse. A simple interface for a music store implementing this functionality could look as follows:

public interface IMusicStore{    public List listGenres();    public Genre findGenreById(int id);    public Artist findArtistById(int id);    public Product findProductById(int id);        public void checkOut(IShoppingCart cart);}

And here is a simple implementation of this:

public class MusicStore implements IMusicStore{    public List listGenres()    {        return MusicStoreDAO.getInstance().listGenres();    }    public Genre findGenreById(int id)    {        return MusicStoreDAO.getInstance().findGenreById(id);    }    public Artist findArtistById(int id)    {        return MusicStoreDAO.getInstance().findArtistById(id);    }    public Product findProductById(int id)    {        return MusicStoreDAO.getInstance().findProductById(id);    }    public void checkOut(IShoppingCart cart)    {        ...    }}
Figure 2. Music Store Design: In this design web, requests are handled by a Struts action that uses two EJBs (one stateless and the other stateful) to fulfill the request. At checkout the customer’s cart is passed via JMS to an order processor implemented as a MDB for fulfillment.

In EJB 2.x, if you wanted to take advantage of enterprise services such as declarative transaction management or object distribution, then you would have to modify the music store to implement the javax.ejb.SessionBean interface as well as the methods defined in this interface and create local and remote bean and home interfaces.

In EJB 3.0 a class that is intended as a stateless session bean must meet two basic requirements:

  1. Implement at least one business interface.
  2. Be annotated with the @javax.ejb.Stateless annotation.

A business interface is simply a plain Java interface. The java.io.Serializable and java.io.Externalizable interfaces are automatically ignored in this determination, as are all interfaces in the javax.ejb package. If only one interface is specified then it is assumed to be a local interface. This is only one example of the specification’s configuration by exception paradigm. If the bean has more than one business interface then each will have to be explicitly defined as either local or remote by annotating either the bean class or the interfaces themselves.

So, to make the MusicStore class a stateless session bean only one change is required. You must annotate it with the @Stateless annotation.

@Statelesspublic class MusicStore implements IMusicStore{    ...}

The next major change associated with EJB 3.0 is actually a change in the J2EE 1.5 specification: dependency injection. The J2EE 1.5 specification requires that J2EE application clients, enterprise beans, and web components have access to a JNDI naming environment. The naming environment can be accessed either through explicit JNDI lookup calls or through annotations which specify that the container injects the dependency automatically. What this means is that you can now declare a dependency on an EJB or other container-managed resources through a simple annotation such as:

import com.devx.musicstore.IMusicStore;public abstract class AbstractStoreAction extends Action{    @EJB    protected IMusicStore store;    ...}

That’s it! The container will inject an implementation of the IMusicStore interface into the action and the action can use the store object as if were a simple POJO.

Author’s Note: In the 4.0.3 version of JBoss resource injection is not implemented for web components, although this support is coming (http://jira.jboss.com/jira/browse/EJBTHREE-212). The example code contains an aspect written with JBoss AOP that performs the dependency injection.

What is actually going on behind the scenes is that this annotation specifies that an EJB reference of type IMusicStore be injected into the store field. The target of the dependency is not specified and must be supplied by the deployer just as with traditional resource references. If the name of the dependency is unspecified (as in the above example) then it will be assumed to be the fully-qualified name of the class. In the above example this would be java:comp/env/com.devx.musicstore.IMusicStore.

Author’s Note: There is some ambiguity in the EJB 3.0 and J2EE 1.5 specifications regarding whether to use the unqualified or fully-qualified name of the class when defaulting the name of the EJB reference. The EJB 3.0 public draft specifies the unqualified name of bean class while the J2EE 1.5 draft shows a fully-qualified name as an example. The JBoss implementation uses the fully-qualified name.

Alternatively, you can further refine the declaration of this dependency as illustrated below:

public abstract class AbstractStoreAction extends Action{    @EJB(            name = "ejb/musicStore",             beanName = "store1",             businessInterface = com.devx.musicstore.IMusicStore.class    )    protected IMusicStore store;    ...}

In this case the EJB reference will be accessible via JNDI at java:comp/env/ejb/musicStore.

Remote Interfaces
To make a session bean accessible remotely you need only annotate it with the @Remote annotation as follows:

@Stateless@Remotepublic class MusicStore implements IMusicStore{    ...}

In the above example the MusicStore bean only implements one business interface; it is assumed to be remote since the class is annotated as remote. If instead the MusicStore implemented two business interfaces, then you would be required to specify which interfaces are local and which are remote. You can specify this in one of two ways: on the class or on the interfaces themselves. Changing the MusicStore class to use a remote interface would look like this:

@Stateless@Local( { IMusicStore.class } )@Remote( { IMusicStoreRemote.class } )public class MusicStore implements IMusicStore, IMusicStoreRemote{    ...}

Compare the above method to that of specifying on an interface:

@Remotepublic interface IMusicStoreRemote{    ...}

Notice that the remote interface does not throw RemoteExceptions. If an exception is encountered at a protocol level then an EJBException wrapping the RemoteException will be thrown by the container. As a RuntimeException, the EJBException does not need to be declared in the method signature of the remote interface or in its implementing bean class.

Stateful Session Beans
Stateful session beans have very similar requirements to stateless session beans. Like stateless beans, they must have at least one business interface. Appropriately, however, they are annotated with the @Stateful annotation instead. So in the music store example the user’s shopping cart has been modeled as a stateful session bean since it represents a stateful conversation between a user and the server:

@Statefulpublic class ShoppingCart implements IShoppingCart{    ...}

As in EJB 2.x, invocations on the same reference to a stateful session bean are handled by the same EJB instance, making it important to store this reference in a location that can be repeatedly read by the client. In the case of the music store, this reference is stored in the user’s HttpSession.

Message Driven Beans
Message Driven Beans (MDBs) also implement a business interface and are annotated to indicate their bean type. In this case, though, the business interface does not come from the domain but is an appropriate listener interface for the type of messaging system being used. In the case of JMS this is javax.jms.MessageListener. The music store’s order processor provides an example:

@MessageDrivenpublic class OrderProcessor implements MessageListener{    public void onMessage(Message message)    {        ObjectMessage objectMessage = (ObjectMessage) message;        try        {            Order order = (Order) objectMessage.getObject();            System.out.println("Products Ordered:");            for (Product p : order.getProducts())            {                System.out.println(p.getTitle());            }        }        catch (JMSException e)        {            e.printStackTrace();        }    }}

Just as with EJB 2.x, you may supply additional information to the deployer about how the MDB is to be configured. This information can now be provided through the activationConfig element of the @MessageDriven annotation. For example, to define that the OrderProcessor activates only for JMS messages arriving on the orders queue you could annotate the class as follows:

@MessageDriven(activateConfig = {        @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),        @ActivationConfigProperty(propertyName = "destination", propertyValue = "queue/orders")})public class OrderProcessor implements MessageListener{    ...}

But as with previous versions of EJB, the deployer still carries the responsibility to associate an MDB with a destination or endpoint.

Packaging and Deployment
Packaging in EJB 3.0 bears many similarities to packing in previous versions of EJB. Just as with previous versions, the enterprise bean classes must be packaged in a .JAR file. The biggest difference is that with the EJB 3.0 release the deployment descriptor becomes optional. If one is supplied, however, then it must exist in its usual place (META-INF/ejb-jar.xml).

The example program illustrates building an EJB3.0 EJB-JAR and bundles this JAR along with the web application (WAR) in an Enterprise Archive (EAR). This build uses Maven 2.0; see the attached source bundle for more information.

Author’s Note: In JBoss EJB 3.0 jars have the extension .ejb3?a JBoss convention and not a requirement of the specification.

To deploy the sample application, simply copy the resultant .EAR file to the deploy directory of a JBoss 4.0.3 server configured with the JBoss AOP 1.3.4 deployer. The attached source bundle also contains installation instructions.

Welcoming a Simplified Model
The public draft of EJB 3.0 reveals a drastically simplified model for writing enterprise components. This new paradigm serves to simplify development and introduces very little new functionality beyond what was previously available. Still, the simplifications offered by EJB 3.0 should significantly enhance a team’s productively. It will be interesting to see how this new lighter-weight implementation will fare against other lightweight frameworks such as Spring and Hibernate.

Stay tuned for my next article exploring entity persistence in EJB 3.0.

devxblackblue

About Our Editorial Process

At DevX, we’re dedicated to tech entrepreneurship. Our team closely follows industry shifts, new products, AI breakthroughs, technology trends, and funding announcements. Articles undergo thorough editing to ensure accuracy and clarity, reflecting DevX’s style and supporting entrepreneurs in the tech sphere.

See our full editorial policy.

About Our Journalist