EJB Inheritance, Part 1

EJB Inheritance, Part 1

5. Finders & ejbSelects

Working out inheritance in finders and ejbSelect methods is not so simple. Finders are written by the container, using EJB-QL provided in the deployment descriptor. There's no hook for us to exploit.



In reality, a finder exists to find objects of a single type. This is highlighted in our example by the fact that each finder bares the name of its returned object; for example, findAllGoldCustomers(). Finders cannot find objects from the base type and all of its sub-types; they were not made for that. Queries are not polymorphic.

A solution is to use what I call locate methods -- essentially "smart finders," which know how to handle the base class' and subclasses' finders in order to collect the results properly. Locate methods have to know about subclasses, special finders that may be used depending on the table mapping, etc. Some other things about locate methods:

  • They are home methods.
  • They start with the prefix "locate".
  • The corresponding bean implementation method name would have the prefix ejbHomeLocate.
  • One would call a finder method to do non-polymorphic finds and a locate method to do polymorphic finds.

Locate methods are not natural in the world of inheritance and polymorphism, but they are necessary. I am working on ways to make the task of authoring locate methods easier. I plan to report my findings in future articles.

Let's see some examples of finders and locate methods.

First, the home interfaces:

Example 8. BaseCustomerHome

//...

public interface BaseCustomerHome extends EJBLocalHome {

//...

  public BaseCustomer findByPrimaryKey(String customerID)

    throws FinderException;



  public Collection findAllBaseCustomers()

    throws FinderException;



  public BaseCustomer locate(String customerID)

    throws FinderException;



  public Collection locateAll()

    throws FinderException;

}

Example 9. PlatinumCustomerHome

//...

public interface PlatinumCustomerHome extends EJBLocalHome {



//...

  public PlatinumCustomer findByPrimaryKey(String customerID)

    throws FinderException;



  public Collection findAllPlatinumCustomers()

    throws FinderException;

}

Note that the finders are implemented by the container based on these query definitions:

Example 10. Query definitions for BaseCustomer

<query>

  <query-method>

    <method-name>findAllBaseCustomers</method-name>

    <method-params>

    </method-params>

  </query-method>

  <ejb-ql>

    <![CDATA[SELECT OBJECT(c) FROM BaseCustomerEJB AS c</XMLCDATA>

  </ejb-ql>

</query>

Example 11. Query definitions for PlatinumCustomer

<query>

  <query-method>

    <method-name>findAllPlatinumCustomers</method-name>

    <method-params>

    </method-params>

  </query-method>

  <ejb-ql>

    <![CDATA[SELECT OBJECT(c) FROM PlatinumCustomerEJB AS c</XMLCDATA>

  </ejb-ql>

</query>

The GoldCustomer bean has a similar implementation.

Now the tricky part: how to implement the locate methods in the base class:

Example 12. Implementing the locate method for a single customer

  public BaseCustomer ejbHomeLocate(String customerID) throws

FinderException {

    //At this point, all base EJB classes must know their EJB subclasses...

    Context jndiCtx;

    BaseCustomerHome bHome;

    GoldCustomerHome gHome;

    PlatinumCustomerHome pHome;

    try {

      jndiCtx = new InitialContext();

      bHome = (BaseCustomerHome)ctx.getEJBLocalHome();

      gHome = (GoldCustomerHome)jndiCtx.lookup("GoldCustomerEJB");

      pHome = (PlatinumCustomerHome)jndiCtx.lookup("PlatinumCustomerEJB");

    } catch (NamingException e) {

      throw new FinderException("Cannot obtain JNDI initial context.");

    }

    BaseCustomer b=null;

    try {

      b = bHome.findByPrimaryKey(customerID);

      return b;

    } catch (FinderException e) {

    }

    try {

      b = gHome.findByPrimaryKey(customerID);

      return b;

    } catch (FinderException e) {

    }

    try {

      b = pHome.findByPrimaryKey(customerID);

      return b;

    } catch (FinderException e) {

    }

    throw new FinderException("Cannot find any bean with that key.");

  }

Example 13. Implementing the locate method for all customers

  public Collection ejbHomeLocateAll() throws FinderException

{

    Context jndiCtx;

    BaseCustomerHome bHome;

    GoldCustomerHome gHome;

    PlatinumCustomerHome pHome;

    try {

      jndiCtx = new InitialContext();

      bHome = (BaseCustomerHome)ctx.getEJBLocalHome();

      gHome = (GoldCustomerHome)jndiCtx.lookup("GoldCustomerEJB");

      pHome = (PlatinumCustomerHome)jndiCtx.lookup("PlatinumCustomerEJB");

    } catch (NamingException e) {

      throw new FinderException("Cannot obtain JNDI initial context.");

    }

    //At this point, all base EJB classes must know their EJB subclasses...

    ArrayList l = new ArrayList();

    l.addAll(bHome.findAllBaseCustomers());

    l.addAll(gHome.findAllGoldCustomers());

    l.addAll(pHome.findAllPlatinumCustomers());

    return l;

  }

The logic here is as follows:

  • For a locate method returning a single object, find the object in the current bean using its finder. If no object was found, try in each subclass until it is found.
  • For a locate method returning multiple objects, create a list to accumulate the results. Find the objects in the current bean and add them to the list. Find the objects in each subclass and add them to the list.

Note that, depending on your table mapping, the code for finders can be quite different. My next article will be dedicated to the various techniques for table mapping.

I know this code is ugly, but it is the only way I have found so far to emulate inheritance in finder methods. If you find a better solution, let me know.

But what about ejbSelect methods? The same principle exists with ejbSelect methods; they must be wrapped with other methods in the bean implementation. I decided to give them the prefix ejbLocate and call them ejbLocate methods. Note that they are not exposed through the home interfaces, just like regular ejbSelect methods.

Prev  [1] [2] [3] [4] [5] Next

Close    To Top
  • Prev Article-Java:
  • Next Article-Java:
  • Now: Tutorial for Web and Software Design > Java > JavaBeans > Java Content
    Photoshop Tutorial
     

    Special Effect

      3D Effect
      Photoshop Articles
    Programming Tutorial
     

    C/C++ Tutorial

      Visual Basic
      C# Tutorial
    Database Tutorial
     

    MySQL Tutorial

      MS SQL Tutorial
      Oracle Tutorial
    Geek Tutorial
     

    Blogging Tutorial

      RSS Tutorial
      Podcasting Tutorial
    Graphic Design Tutorial
      Coreldraw Tutorial
      Illustrator Tutorial
      3D Tutorials
    Webmaster Articles
     

    Domain Service

      Web Hosting
      Site Promotion
    Java Tutorial/ Articles
     

    Java Servlets

      JavaEE Tutorial
     

    JavaBeans Tutorial

    XML Tutorial/ Articles
     

    XML Style

      AJAX Tutorial
      XML Mobile
    Flash Tutorial/ Articles
     

    Flash Video

      Action Script
      Flash Articles
    OS Tutorial/ Articles
      Linux Tutorial
      Symbian Tutorial
      MacOS Tutorial
    Personal Tech
      Hardware Tutorial
      Software Tutorial
      Online Auction