Proxy Visitor Pattern

Version 3

    Note: The explanation in the first paragraph is not entirely correct, better read the one in the "Performance" chapter of the reference documentation first.

    Anyone using Hibernate for any length of time has no doubt run into the dreaded "proxy problem" when using polymorphic collections. In Hibernate, lazy loading of persistent relationships and collections is facilitated by proxies. For example, let's say you have a LooneyBin object that has a collection of Nutter objects that is lazily loaded. If you call looneyBin.getNutters(), Hibernate will only load the ID and version number of the Nutter objects, thus saving all the work of loading individual objects until later. You think you have all the related Nutter objects, but what you really have is a collection of proxies. The thinking is that if you have a collection of a few hundred items, chances are good that you'll only work with a few of them, so why go through the effort of instantiating all the objects. This can be a huge performance gain in certain situations.

     

    Hibernate Proxies and Polymorphism

    Proxies are created dynamically by subclassing your object at runtime. The subclass has all the methods of the parent, and when any of the methods are accessed, the proxy loads up the real object from the DB and calls the method for you. Very nice in simple cases with no object hierarchy. Typecasting and instanceof work perfectly on the proxy in this case since it is a direct subclass. But there's a big problem lurking that can cause no end of grief: Polymorphism. Let's say you have the following object hierarchy:

    public class Politician {
      ...
    }
    public class Democrat extends Politician {
      public Intern getFavoriteIntern() { ... }
    }
    public class Republican extends Politician {
      public Lobbyist getGolfBuddy() { ... }
    }
    

     

    Now, let's say you've got a collection of lazy Politicians. Oh, I mean a lazy collection of Politicians. Let's also say that you want to extract all the Interns from the Democrats. Assuming you had an instance of a Congress object that has a related collection of politicians, you'd be tempted to do something like:

    public List<Intern> getInterns(Congress congress) {
      Collection<Politition> lazyPoliticians = congress.loadPoliticians();
      ArrayList<Intern> interns = new ArrayList<Intern>();
    
      for (Politician politician : lazyPoliticians) {
        if (politician instanceof Democrat) {
          interns.add(((Democrat)politician).getFavoriteIntern());
        }
      }
    }
    

     

    But guess what?  Not only is this bad form (instanceof is the hallmark of bad design), this won't work if the collection is populated with lazy Hibernate proxies. The reason is that when Hibernate creates the proxies at runtime it creates proxies that descend from Politician, not from each of the individual subclasses.  That means that typecasts and instanceof operations will not work. Some would argue (myself included) that this sucks and breaks a fundamental aspect of the Java language. Whether you agree with this or not, you do have to agree that code constructs like:

    for (Politician politician : lazyPoliticians) {
      if (politician instanceof Democrat) {
        interns.add(((Democrat)politician).getFavoriteIntern());
      } else if (politician instanceof Republican) {
        lobbyists.add(((Republican)politician).getGolfBuddy());
      } else if (politician instanceof Libertarian) {
        wwf.giveBack(politician);
      }
    }
    

     

    are not only ugly and unmaintainable, but are fragile and easy to screw up when the hierarchy changes. Plus, more to the point, they don't work with Hibernate lazy proxies. You can just plan on ClasCastException(s).  But don't worry, there's an elegant OO way to solve it.  The visitor pattern.

     

    The Visitor Pattern

    The Visitor pattern is a "Gang of Four" design pattern that allows you to manipulate a collection of polymorphic objects without all the messy typecasts and instanceof operations. It can also be used to "visit" a single object as well, allowing you to adapt the object in various ways. Here's how it works in code:

    public interface PoliticianVisitor {
      public void visit(Democrat dem);
      public void visit(Republican rep);
      public void visit(Libertarian lib);
    }
    public class Politician {
      public void accept(PoliticianVisitor visitor) {
        // do nothing
      }
    }
    public class Democrat {
      public void accept(PoliticianVisitor visitor) {
        visitor.visit(this);
      }
    }
    

     

    Notice that we didn't have to make Republican override the accept() method? If the subclass doesn't need it, you can just ignore it. Now, I don't like having to override all the methods of an iterface every time I want to use it, so I like to have an adapter:

    public class PoliticianVisitorAdapter implements PoliticianVisitor {
      public void visit (Democrat dem) { // do nothing }
      public void visit (Republican rep) { // do nothing }
      public void visit (Libertarian lib) { // do nothing }
    }
    

     

    And, here's our same code to iterate the list of politicians and extract all the interns from the Democrat objects in the collection:

    public List getInterns(Congress congress) {
      Collection lazyPoliticians = congress.loadPoliticians();
      final ArrayList<Intern> interns = new ArrayList<Intern>();
    
      PoliticalVisitor extractIntern = new PoliticalVisitorAdapter() {
        public void visit(Democrat democrat) {
          interns.add(democrat.getFavoriteIntern());
        }
      }
    
      for (Politician politician : lazyPoliticians) {
        politician.accept(extractIntern);
      }
    }
    

     

    Notice the use of an annonymous inner class? You don't have to do it that way, but you can. Get jiggy with it and you'll find all sorts of creative ways to use this pattern. For example, you could create a visitor that manipulates both Republicans and Democrats at the same time, all without a single instanceof. Better yet, it will penetrate the Hibernate proxy and actually execute within the real object.

     

    Visiting a Single Proxied Object

    Sometimes it's helpful to be able to work with a single object and "introspect" it in some way. For example if you're creating a Tapestry page that dynamically changes form fields depending on the type of object. Not that it's good form, but you can create a visitor like:

    public class PoliticianViewHelper extends PoliticianVisitorAdapter {
      private Democrat democrat;
      public PageVisitor(Politiican politician) {
        politician.accept(this);
      }
      public void visit(Democrat democrat) {
    
        this.democrat = democrat;
      }
      public boolean isDemocrat() {
        return this.democrat != null;
      }
      public Democrat getDemocrat() {
        return this.democrat;
      }
    }
    
    // and on the page...
    ...
    public PoliticianViewHelper getPoliticianHelper() {
      return new PoliticianViewHelper(getPolitician());
    }
    
    // and in your Tapestry page...
    <!-- Only show interns for democrats -->
    <span jwcid="@Conditional" condition="ognl:politicianHelper.democrat">
      <span jwcid="@Insert" value="ognl:politicianHelper.favoriteIntern.name"/>
    </span>;
    
    // or, in JSP EL //
    <!-- Only show interns for democrats -->
    <c:if test="${politicianHelper.democrat}">
      ${politicianHelper.favoriteIntern.name}
    </c:if>
    

     

    The view (Tapestry or JSP page) is able, in a Hibernate proxy-safe way, to introspect the objects without the nasty instanceof and typecast code. You can also see how the code could be extended to allow the page to dynamically respond to different types of politicians - you'd just add PoliticianViewHelper.isRepublican() and .getGolfBuddy() methods.

    As you can see the Visitor pattern is an effective OOP club to knock some sense into Hibernate proxies.

    Kurtis Williams

    http://www.jroller.com/page/cardsharp