IBM Skip to main content
Search for:   within 
      Search help  
     IBM home  |  Products & services  |  Support & downloads   |  My account

developerWorks > Java technology
developerWorks
EJB best practices: Speed up your RMI transactions with value objects
63KBe-mail it!
Contents:
A simple entity bean
Create a value object
Add two new methods
How the magic works
Resources
About the author
Rate this article
Related content:
EJB fundamentals tutorial
EJB best practices series
Subscriptions:
dW newsletters
dW Subscription
(CDs and downloads)
Maintain all the advantages of EJB technology without the RMI penalty

Level: Intermediate

Brett McLaughlin (mailto:brett@oreilly.com?cc=&subject=Speed up your RMI transactions with value objects)
Author and Editor, O'Reilly & Associates
1 September 2002

Column iconOne of the more popular uses of EJB components is in the realm of relational data management. Combined with RMI, EJB components let you access data from relational databases without ever having to delve into JDBC. But that abstraction comes at a price: RMI is slow, often to the extreme. The trick, then, is to find a way to maintain all the advantages of EJB technology without paying as stiff a penalty for using RMI. In this tip, you'll see how value objects (also known as object maps) can help you get around the worst RMI speed bumps. You'll start with a working example, and then learn what's going on behind the code.

A simple entity bean
Consider a simple database table, called DVDs. This table has several columns: id, title, releaseDate, producer (through a foreign key), and director (again through a foreign key). Since we're using EJB components, the table is represented by an entity bean, and each column has its own accessor and mutator methods. Listing 1 shows the remote interface for our DVD table:


import com.ibm.ejb;

import java.rmi.RemoteException;
import java.util.Date;
import javax.ejb.EJBObject;

public interface DVD extends EJBObject {

      public int getId() throws RemoteException;

      public String getTitle() throws RemoteException;
      public void setTitle(String title) throws RemoteException;

      public Date getReleaseDate() throws RemoteException;
      public void setReleaseDate(Date releaseDate) throws RemoteException;

      public Person getProducer() throws RemoteException;
      public void setProducer(Person producer) throws RemoteException;

      public Person getDirector() throws RemoteException;
      public void setDirector(Person director) throws RemoteException;
}

The problem here is in how the table data will be accessed, which is all at once. An online store or listing application could easily require most or all of the information contained in the above columns to run a single DVD sale or search. To access all that information, the application would invoke every accessor method for every column -- that's five method invocations, each one sucking up just a little more RMI traffic time. Add to this the complexities of possible error conditions, network traffic, and related issues, as well as the exponential quantity of data (most such tables have 15 or more rows) and our application could collapse in no time.

This is where value objects come in. Value objects are simple Java classes that can be used to represent many kinds of objects, including data in a relational database row. By using the value object directly, instead of repeatedly using the bean's remote interface, we can reduce our RMI traffic to a single method invocation.

Create a value object
The value object in Listing 2 looks almost identical to our remote interface, but it's actually a concrete class. Note that the value object is typically indicated by the bean's name followed by Info.


package com.ibm.ejb;

import java.io.Serializable;
import java.util.Date;

public class DVDInfo implements Serializable {

      private int id;
      private String title
      private Date releaseDate;
      private Producer producer;
      private Director director;

      public int getId() {
          return id;
      }

      void setId(int id) {
          this.id = id;
      }

      public String getTitle() {
          return title;
      }
      public void setTitle(String title) {
          this.title = title;
      }

      public Date getReleaseDate() {
          return releaseDate;
      }
      public void setReleaseDate(Date releaseDate) {
          this.releaseDate = releaseDate;
      }

      public Person getProducer() {
          return producer;
      }
      public void setProducer(Person producer) {
          this.producer = producer;
      }

      public Person getDirector() {
          return director;
      }
      public void setDirector(Person director) {
          this.director = director;
      }
}

You should observe two things about this class. First, it implements java.io.Serializable. Any object that can be returned by an entity bean (or any other EJB component) must fulfill this requirement. Second, none of the class's methods can throw RMI RemoteExceptions. This object will not require RMI traffic (that's the entire point of the exercise!), so the RemoteException will never occur. Otherwise, the value object is a carbon copy of the bean's remote interface.

Add two new methods
Creating a value object class is the first part of our RMI solution. The second part is the addition of two valuable methods to our remote interface, as shown in Listing 3:


import com.ibm.ejb;

import java.rmi.RemoteException;
import java.util.Date;
import javax.ejb.EJBObject;

public interface DVD extends EJBObject {

      public DVDInfo getInfo() throws RemoteException;
      public void setInfo(DVDInfo info) throws RemoteException;

      public int getId() throws RemoteException;

      public String getTitle() throws RemoteException;
      public void setTitle(String title) throws RemoteException;

      public Date getReleaseDate() throws RemoteException;
      public void setReleaseDate(Date releaseDate) throws RemoteException;

      public Person getProducer() throws RemoteException;
      public void setProducer(Person producer) throws RemoteException;

      public Person getDirector() throws RemoteException;
      public void setDirector(Person director) throws RemoteException;
}

Next, and finally, we implement these two new methods getInfo() and setInfo()) in our bean's implementation class, as shown in Listing 4:


      // Rest of class excluded for brevity
      public DVDInfo getInfo() throws RemoteException {
          DVDInfo info = new DVDInfo();

          // Load value object with current variable values
          info.setId(this.id);
          info.setTitle(this.title);
          info.setReleaseDate(this.releaseDate);
          info.setProducer(getProducer());
          info.setDirector(getDirector());

          return info;
      }

      public void setInfo(DVDInfo info) throws RemoteException {
          setTitle(info.getTitle());
          setReleaseDate(info.getReleaseDate());
          setProducer(info.getProducer());
          setDirector(info.getDirector());
      }

How the magic works
Our application needs to be able to access all the data in the DVD bean, from the DVDs table. Rather than calling all five accessor methods, however, we set up the application to only call one: getInfo(). This cuts our RMI traffic down considerably.

Behind the scenes in the bean's implementation class all of the same accessor methods are being called. But, because they're happening in the EJB container, they're local calls. All of the data is still going to the bean client, however, so it can still be used. If any modifications are required we can just send them back to the bean with the setInfo() method, rather than using four or five more RMI-expensive calls.

The only drawback to this approach is the slight risk of getting stale data. You run this risk if you keep the value object around in memory for a while. The value object contains a snapshot of the data in the database, but it won't dynamically reflect changes to that data. The best way to avoid stale data is to use the value object immediately; if you need to use it again later, you should pay the one-time RMI cost and call getInfo() again, to ensure the most current data is available.

Using value objects in your EJB applications can yield tremendous performance advantages, especially in beans with multiple accessor methods. In a similar vein to this one, my next tip will focus on decreasing the performance overhead of using JNDI with EJB components. Until then, I'll see you online.

Resources

  • Check out the other tips in Brett McLaughlin's EJB best practices series.

  • Sun Microsystems's EJB technology home page is a good resource for all things related to EJB technology.

  • The Server Side offers lots of articles and information pertaining to J2EE.

  • The tutorial EJB fundamentals (developerWorks, March 2001) provides a comprehensive introduction to Enterprise JavaBeans technology with particular attention to the role of EJB components in distributed-computing scenarios, the architecture, the extension APIs, and the fundamentals of working with EJB technologies.

  • Visit the developerWorksJava tutorials page for a listing of other free Java technology-related tutorials.

  • You'll find hundreds of articles about every aspect of Java programming in the developerWorks Java technology zone.

About the author
Photo of Brett McLaughlin Brett McLaughlin is one of the leading authorities today on enterprise programming. He has designed, architected, and implemented enterprise solutions at Nextel Communications and Allegiance Telecom, Inc., and helped develop the Lutris Enhydra open source J2EE application server. He has written books on XML, Java, data binding, and enterprise applications, and is the author of over 50 articles on enterprise programming. Additionally, Brett is a committing member of every open source J2EE application server available today: JBoss, Enhydra, and OpenEJB. He is also the co-founder of the JDOM API for Java and XML, the Apache Turbine project, and is involved in numerous other open source projects. He currently writes and edits for O'Reilly & Associates, the world's leading technical publisher. Contact Brett at brett@oreilly.com.


63KBe-mail it!

What do you think of this document?
Killer! (5) Good stuff (4) So-so; not bad (3) Needs work (2) Lame! (1)

Comments?



developerWorks > Java technology
developerWorks
  About IBM  |  Privacy  |  Terms of use  |  Contact