Java开发网 Java开发网
注册 | 登录 | 帮助 | 搜索 | 排行榜 | 发帖统计  

您没有登录

» Java开发网 » Java EE 综合讨论区  

按打印兼容模式打印这个话题 打印话题    把这个话题寄给朋友 寄给朋友    该主题的所有更新都将Email到你的邮箱 订阅主题
flat modethreaded modego to previous topicgo to next topicgo to back
作者 EJB best practices: Speed up your RMI transactions with value objects
palatum



CJSDN高级会员


发贴: 451
积分: 80
于 2002-11-19 18:38 user profilesend a private message to usersend email to palatumsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
EJB best practices: Speed up your RMI transactions with value objects

Maintain all the advantages of EJB technology without the RMI penalty
Level: Intermediate


Brett McLaughlin (brett@oreilly.com)
Author and Editor, O'Reilly & Associates
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:

Listing 1. The DVD remote interface
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.

Listing 2. The DVD value object
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:

Listing 3. The modified DVD remote interface
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:

Listing 4. The modified DVD remote interface
      // 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.




话题树型展开
人气 标题 作者 字数 发贴时间
4996 EJB best practices: Speed up your RMI transactions with value objects palatum 11162 2002-11-19 18:38

flat modethreaded modego to previous topicgo to next topicgo to back
  已读帖子
  新的帖子
  被删除的帖子
Jump to the top of page

   Powered by Jute Powerful Forum® Version Jute 1.5.6 Ent
Copyright © 2002-2021 Cjsdn Team. All Righits Reserved. 闽ICP备05005120号-1
客服电话 18559299278    客服信箱 714923@qq.com    客服QQ 714923