ONJava.com -- The Independent Source for Enterprise Java
oreilly.comSafari Books Online.Conferences.

advertisement

AddThis Social Bookmark Button

EJB Inheritance, Part 1

by Emmanuel Proulx
09/04/2002

Java is an object-oriented language, which means it follows the principles of object-oriented programming, such as encapsulation, inheritance, and polymorphism. (Inheritance and polymorphism pretty much go together, so they are often simply referred to as inheritance, which is what I will do in these articles.) These are great principles and can be used to represent relationships between objects in very powerful ways.

Entity beans are objects that represent data coming from a persistent store, such as a database. The key word here is objects. Entity beans encapsulate the data and business logic. But what about the two other principles, inheritance and polymorphism?

The bad news is that entity beans do not easily enable the use of these principles. The good news is that if you follow certain restrictions and tricks, it can be done. This series of articles describes some techniques to put inheritance and polymorphism back into entity beans.

Why EJB Inheritance?

Most systems today use direct SQL access to flat relational databases. Since entity beans are often mapped to relational databases, why use inheritance? Let's not forget that SQL and relational database technology date back to the days of COBOL. Object-oriented programming was invented later, with some specific goals in mind:

Source Code

Download the source code for this article. This zip file contains a WebLogic Server domain, EJB source code, and a PointBase database. Install this under C:\inherit. The admin login is:

username: inherit 
password: password

  • Abstraction: Modelling real-life objects.
  • Reusability: Enabling subclasses to reuse the code in the base class.
  • Maintainability: Objects are easier to manage than procedures.

These goals do not apply to pure data, but rather to the behavior of objects. This means EJB inheritance is likely to be visible in the code, but not in the database. We can live with that, as long as the mapping between the data and the objects is done in a smart way. The advantages of EJB inheritance should be obvious when we see an example.

Recurrent Traveler Miles -- Requirements

Imagine a company named Recurrent Traveler Miles (RTM). This company has a customer retention plan similar to the airlines' "frequent flier miles" systems. Every time you spend a specified amount of money, you obtain a point or "reward mile." When you accumulate enough points, you earn some sort of prize, typically a free flight.

In this system, there are three kinds of customers: Regular, Gold, and Platinum. The differences between these three customers are the rules used for attributing and redeeming points. Those rules are listed here:

Table 1. Customer types and requirements

Customer

Purchase amount to get one point

Number of points to get a free trip

Regular

$20

Same region: 1500
Further away: 3500
Same continent: 10500
Out-of-continent: 25000

Gold

$18

Same region: 1300
Further away: 3100
Same continent: 10000
Out-of-continent: 22000

Platinum

Note: Platinum customers get to choose a charity. RTM will give 1% of all purchases to that charity.

$15

Same region: 1200
Further away: 2850
Same continent: 9500
Out-of-continent: 20000

These numbers are all arbitrary, so don't get mad if they don't make any sense. It's just an example.

With these requirements it's easy to do a single CMP entity bean, CustomerEJB, and put all of this business logic in a single place. Let's see what kind of code we obtain by doing this. Here's one method:

Example 1. Single entity bean method

public int redeemPoints(int zone) {
  int pts = 0;
  if(getType().equals("REGULAR")) {
    switch(zone) {
      case 1: pts=1500; break;
      case 2: pts=3500; break;
      case 3: pts=10500; break;
      case 4: pts=25000; break;
      default: return 0;
    }
  } else if (getType().equals("GOLD")) {
    switch(zone) {
      case 1: pts=1300; break;
      case 2: pts=3100; break;
      case 3: pts=10000; break;
      case 4: pts=22000; break;
      default: return 0;
    }
  } else if (getType().equals("PLATINUM")) {
    switch(zone) {
      case 1: pts=1200; break;
      case 2: pts=2850; break;
      case 3: pts=9500; break;
      case 4: pts=20000; break;
      default: return 0;
    }
  }
  if(getPoints() < pts) return 0;
  setPoints(getPoints()-pts);
  return pts;
}

How ugly. I could break apart this method into small pieces, it's true, but it wouldn't change the fact that this is bad design. The sure sign that object-orientation is missing here is that big if() else if() else if() block. There has to be a better way.

Pages: 1, 2, 3, 4, 5

Next Pagearrow