|
|
|
Contents: |
|
|
|
Related content: |
|
|
|
Subscriptions: |
|
|
| Maintain all the advantages of EJB technology without the
RMI penalty
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
One 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
RemoteException s. 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 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.
|
|
|