Browse DevX
Sign up for e-mail newsletters from DevX


Getting Started with EJB 3.0 and Enterprise Bean Components : Page 2

The time is ripe to give the EJB 3.0 spec, which was engineered to offer big gains in productivity, a test drive. Learn how to start using JBoss and Maven to develop EJB 3.0 enterprise bean components.




Building the Right Environment to Support AI, Machine Learning and Deep Learning

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<Genre> 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<Genre> 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.

@Stateless public 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 @Remote public 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:

@Remote public 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.

Thanks for your registration, follow us on our social networks to keep up-to-date