September 20, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

EJB Design Guidelines

  • August 28, 2003
  • By Saleem Siddiqui, Michael Landy, & Jeff Swisher
  • Send Email »
  • More Articles »

This material is from the book JBuilder Developer's Guide , written by Saleem Siddiqui, Michael Landy, and Jeff Swisher, published by Sams Publishing.

© Copyright Sams Publishing. All rights reserved.


Using entity beans is a practice that many users of application servers do not want to venture into. Part of this is due to the lack of understanding; the other part is due to the lack of capabilities in earlier versions of the EJB specification. As we look at entity beans, keep in mind two important considerations when designing the architecture:

Use the Local Interface

When accessing data remotely, the result of the data has to be moved from one location to another, thus, data has to be serialized. This process of serialization is expensive. In other words, the latency of serializing data, sending it over the wire, and rematerializing the data on the client can be time consuming. With the introduction of EJB 2.0 specification, the capability to call and communicate to an entity bean with a local interface was defined.

Inspiration

The inspiration of local interfaces is specifically to address the performance issues related to serializing data. With the use of session façades or the use of value objects, the need for network ubiquity and serializing data has become less important. Without the need for serialized data, an alternative was needed. This alternative is to pass data by reference rather than value. In other words, instead of copying/ serializing the data, a reference to the data is passed.

Inner Workings

The inner workings of this change in the design are rather simple. If the entity bean runs within the same process, you can access the entity bean using its local interface and pass all data by reference rather than value. There is a drawback to using this method of communication: You lose the concept of network ubiquity. In other words, the client needs to know the location of the bean you want to use, but you gain what was lost in higher performance throughput.

Use CMP Before BMP

When I first started to use J2EE servers, the idea of letting the container manage all the persistence for me seemed unsettling. So I found myself developing persistence code. The process was neither desirable nor ultimately a good, efficient process for developing large-scale applications. I was developing huge portions of code that did nothing other than save, read, and remove instances of data. They were virtually identical except for the details of the SQL statements and member attributes.

Inspiration

With the changes in the EJB specification from 1.1 to 2.0, container managed persistence became all the more important and powerful. Without these necessary changes to the specifications, many developers found that most uses of CMP were limited to simple persistence.

Inner Workings

Container managed persistence supports most of the persistence requirements that any enterprise application needs. Using the container for accomplishing these tasks is not only quicker to develop, but the performance is usually better. If those two reasons are not enough, container managed persistence is by far the most portable of the components within the J2EE architecture.

In Practice

The ChalkTalk application needs the capability to read and save data to the database structure. We have read and written data to the database using JDBC; now it is time to accomplish the same task using entity beans. The process of building the beans is rather simple; most of our work will be executed in the session facade.

Building the Persistence Layer

The creation of the persistence layer using JBuilder depends on the appropriate data structure being completed. In Chapter 15, "Database Connectivity," we created the necessary data store for our application. We will now create the entity beans to manage this persistence. The following steps are used to build the necessary entity beans:

  1. Import a schema from our data source in the EJB module containing our session beans. This is accomplished by right-clicking on the data source node when we are in the EJB Designer and selecting Import Schema from Datasource.

  2. Set the following database parameters:

    • Driver: com.borland.datastore.jdbc.DataStoreDriver

    • URL: jdbc:borland:dslocal:C:\JBDG\db\ChalkTalk.jds

    • Username: leave blank

    • Password: leave blank

  3. Right-click on each table and create a CMP 2.0 entity bean for each table. For example, right click on the table Room and create a CMP 2.0 bean.

  4. Define relationships.

Configuring an Entity Bean

Typically each entity bean that has been created requires more finder methods than just a findByPrimaryKey. Our Room entity bean is a perfect example.

  1. Right-click on our Room entity bean. Add a finder method.

  2. Configure the following properties for the finder method:

    • Name: findAll

    • Return type: java.util.Collection

    • Input parameters: leave empty

    • Home interfaces: Local Home

    • Query: SELECT OBJECT(o) FROM RoomSchema AS o

  3. Compile and save.

Creating an EJB Connection Factory

This factory supplies caching to both local and remote interfaces. Although this connection factory differentiates between local and remote interfaces, you have the capability to make this interface ubiquitous. The following steps build your EJB connection factory:

  1. Create a new class within your project, calling it EJBConnectionFactory.

  2. Move the newly created class to the package com.sams.chalktalk.beans.

  3. Add the following code to implement the connection to both local and remote beans in addition to placing them into a cache when the connection has been established:

  4. package com.sams.chalktalk.beans;
    
    import javax.naming.*;
    import java.util.*;
    import javax.ejb.*;
    
    class EJBHomeFactory {
    
     private static EJBHomeFactory instance = null;
     private Context initialContext;
     private Map ejbHomes;
    
     private EJBHomeFactory() throws NamingException {
      initialContext = new InitialContext();
      ejbHomes = Collections.synchronizedMap(new HashMap());
     }
    
     public static EJBHomeFactory getInstance() throws NamingException {
      if(instance == null) {
       instance = new EJBHomeFactory();
      }
      return instance;
     }
    
     public EJBLocalHome lookupByLocalEJBReference(String ejbReferenceComponent)
      throws NamingException {
    
      java.lang.Object home = ejbHomes.get(ejbReferenceComponent);
      if(home == null) {
       home = initialContext.lookup("java:comp/env/ejb/" + 
                      ejbReferenceComponent);
       ejbHomes.put(ejbReferenceComponent, home);
      }
      return (EJBLocalHome) home;
     }
    
     public EJBHome lookupByRemoteEJBReference(String ejbReferenceComponent, 
       Class homeClass)
      throws NamingException {
    
      java.lang.Object home = ejbHomes.get(ejbReferenceComponent);
      if(home == null) {
       java.lang.Object obj =
        initialContext.lookup("java:comp/env/ejb/" + ejbReferenceComponent);
       home = javax.rmi.PortableRemoteObject.narrow(obj, homeClass);
       ejbHomes.put(ejbReferenceComponent, home);
      }
      return (EJBHome) home;
     }
    }
  5. Compile and save your project.

Creating a Manager Bean

A manager bean surfaces the business logic and ultimately interfaces to the persistence utilizing the entity beans. These manager beans will then be attached to the session facade to consolidate the middle-tier access. The following steps are required to create one of the manager beans:

  1. Create a new class, naming the class RoomManager and placing the new class in the package com.sams.chalktalk.beans.

  2. The following code surfaces the required business logic. The requirements of the manager class are used to implement all the appropriate business logic, such as checking to make sure that a room has a capacity.

  3. package com.sams.chalktalk.beans;
    
    import javax.naming.*;
    import javax.ejb.*;
    import java.util.*;
    
    class RoomManager {
     //Add a home factory for caching the home interfaces
     private EJBHomeFactory homeFactory;
     private static RoomManager instance = null;
     
     //Use the RoomValueFactory to create
     private RoomValueFactory roomValueFactory;
    
     private RoomManager() throws NamingException {
      homeFactory = EJBHomeFactory.getInstance();
     }
    
     public static RoomManager getInstance() throws NamingException {
      if(instance == null) {
       instance = new RoomManager();
      }
      return instance;
     }
    
     public String createRoom(RoomValue roomValue)
       throws FinderException, NamingException {
    
      try {
       RoomHome roomHome =
         (RoomHome) homeFactory.lookupByLocalEJBReference("Room");
       Room room = roomHome.create(roomValue.getLocation(),roomValue. getCapacity()
    ,roomValue.getName(),roomValue.getKey());
       return room.getName();
      }
      catch(Exception e) {
       throw new EJBException(e);
      }
     }
    
     public void updateRoom(RoomValue roomValue)
       throws FinderException, NamingException {
    
      try {
       Room room = roomValueFactory.findRoom(roomValue.getKey());
       room.setCapacity(roomValue.getCapacity());
      }
      catch(Exception e) {
       throw new EJBException(e);
      }
     }
    
     public void removeRoom(Short key)
       throws FinderException, NamingException {
    
      try {
       Room room = roomValueFactory.findRoom(key);
       room.remove();
      }
      catch(Exception e) {
       throw new EJBException(e);
      }
     }
    
     public void removeAllRooms()
       throws FinderException, NamingException {
    
      try {
       Collection rooms = roomValueFactory.findAllRooms();
       Iterator iterator = rooms.iterator();
       Room room = null;
       while(iterator.hasNext()) {
        room = (Room) iterator.next();
        room.remove();
       }
      }
      catch(Exception e) {
       throw new EJBException(e);
      }
     }
    }

Attaching the Session Facade

Our session facade wraps multiple manager beans together into one session bean. In other words, we will access all functionality for our ChalkTalk system utilizing this one session bean. The following steps are required to attach the facade to our manager bean:

  1. Define a private member for each type of bean manager you want to use. For example, the following code defines one for our RoomManager:

  2.  private RoomManager roomManager;
  3. Create an instance of our manager bean within ejbCreate(). The following demonstrates the implementation using our RoomManager:

  4.  public void ejbCreate() throws CreateException {
      try {
       roomManager = RoomManager.getInstance();
      }
      catch (NamingException ex) {
       //pass exception to the container
       throw new EJBException(ex);
      }
  5. Attach the manager bean call to be called from the corresponding session bean method. If the client calls the createRoom method of the session bean, it then needs to pass the information to the manager class. The following code demonstrates such an implementation:

  6.  public void createRoom(RoomValue room) {
      try {
       roomManager.createRoom(room);
      }
      catch (Exception ex) {
        throw new EJBException(ex);
      }
     }
  7. Compile and save your project.

Testing the Implementation

It is time to test the client we created. The easiest way to test the session facade is to build a client dedicated to testing the interface. The following steps build a test client to exercise this facade:

  1. Select File, New from the JBuilder menu.

  2. Within the Object Gallery, under the Enterprise tab, select the EJB Test Client.

  3. Specify the following parameters to build our test client:

    • EJB name: ChalkTalkFacade

    • Package: com.sams.chalktalk.client

    • Class name: ChalkTalkFacadeTestClient

    • Generate Method for Testing Remote Interface Calls with Arguments: Checked

    • Generate Logging Messages: Checked

    • Generate Main Functions: Checked

    • Generate Header Comments: Checked

  4. Add the following code to the main method to test your session bean interface:

  5.   //create a Remote interface
      client.create();
    
      //Add a room
      client.addRoom(new RoomData(5,"Small Room",5,"2nd Floor"));
    
      //Add with invalid capacity
      client.addRoom(new RoomData(3,"Error Room",0,"3rd Floor"));
  6. Save, compile, and run your test application.

Summary

Using entity beans is a question for design, experience, need, and implemented technology. Entity beans are designed to handle all the persistence requirements for most enterprise applications. Entity beans, like session beans, are designed to be distributed objects with the following characteristics:

  • Entity beans provide persistence.

  • Entity beans are transactional.

  • Entity beans are multiuser.

  • Entity beans are long-lived.

  • Entity beans survive the life of the container.

The introduction of more advanced container managed persistence and the other important features added to the EJB specification has made building and ultimately managing an application much more efficient.

Reflections

  • Should I use container managed or bean managed persistence?

  • Should I design for use with local or remote interfaces?

  • Should entity beans be used to encapsulate nontraditional data access?


About the Authors

Saleem Siddiqui is a technical architect and trainer with Dunn Solutions Group. He is also a Sun Certified Developer and a Borland Certified JBuilder Instructor. At Dunn, he provides consulting services and business application development.

Michael Landy is Director of Business Applications for Dunn Solutions Group directing the strategic solutions for clients.

Jeff Swisher is a technical manager for the Dunn Solutions Group business applications. He works as a programmer, trainer, architect, and instructional designer. He is a Sun Certified Java Developer and a Borland Certified Instructor in JBuilder.

Source of this material

This material is from Chapter 23: Developing Entity Beans from the book JBuilder Developer's Guide (ISBN: 0-672-32427-X) written by Saleem Siddiqui, Michael Landy, and Jeff Swisher, published by Sams Publishing.

To access the full Table of Contents for the book.


Other Chapters from Sams Publishing:

Web Services and Flows (WSFL)
Overview of JXTA
Introduction to EJBs
Processing Speech with Java
The Java Database Control in BEA Weblogic
Databases and Tomcat
Working with JAX-RPC
Understanding Servlets







Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel