BO/DAO Patterns in Orchestra

Introduction

BO/DAO Pattern objects have been a common usage pattern for various business applications for a long time. Although it is probably the easiest to weave everything into a single page controller, it is not the best practice.

A separation of concerns is the most common use case in this area.

Short introduction to the BO/DAO pattern

If you already are familiar with this pattern you can skip this section in favor of the next section.

It is advisable to split an application into three layers. A view layer, which has all the visual information, a so called business ojbect or business facade layer, which most of the times is a service layer, which provides services and is generally decoupled from the view layer to the degree that it can live without it. And a data access layer the so called DAO layer, which provides basic data operation functionality on various data sources.

This pattern is used in many frameworks, BOs for instance in a classical sense are EJB entity beans also this business facades often can be found in applications on top of frameworks like Spring.

Orchestra and the BO DAO Layer

Orchestra provides basic mechanisms which still allow the implementation of BO dao objects. It makes it even better because a number of business objects and dao objects can be combined under the same conversation umbrella, making them stateful as well if needed.

Additionally to it an automated orm Entity manager control is provided. This means, that the entity manager for all referencing DAOs of the conversation (unless overridden) is generated at the beginning of the conversation, it then is shared over all data access objects which request it, and it finally is disposed at the end of the conversation.

This is the main advantage over other dialog frameworks (except Seam which provides a very similar control on EJB3 level), Orchestra provides you with a stateful entity manager which can live longer than a single request and shorter than an entire session.

The main advantage of having a long running entity manager is, that in most cases, the Object cannot be bound to Entity manager, Object already is bound to Entity manager Exceptions are gone.

You will work on the database objects directly all the time and never will lose them as long as the conversation endures.

Given the experiences in the past, using orms in combination with Web applications has been a huge pain, usally objects are lost and have to be reattached to Entity managers causing very often above mentioned conflicts, to avoid this, you had to deal with data passing the classical way, pass the request values, load the object again push the request values manually into the object and flush the entity manager!

All this is gone, you have your conversation, you have your entity manager, your have your objects. The objects are stateful in the way, that those are the same ones, always being referenced by the Entity manager. A single flush within a transaction brings the state of those objects back into sync with the database!

Application Objects

TODO fill image in here

The usual reference pattern Applications which utilize Business Facads is:

One view controller which is under conversation scope. It references several business objects probably one providing the outer rim of the operation which has to be performed.

The operation which is performed usually is under Transaction borders marked normally via the @Transactional annotation (we are in a java 5 scope here, so using this annotation is perfectly viable instead of an xml transaction)

The business object or the business method might reference several other business objects and those might reference several dao objects, which provide basic database operations.

What happens now is, that Orchestra assigns each DAO object with a @PersinstenceContext annotation referenced (and not having defined a non orchestra persistencecontext reference) the Entity manager which managed by Orchestra itself.

Such a DAO in the easiest case could look like following:

  public class BasicJPADAO{
 
    @PersistenceContext
    EntityManager em;
    public EntityManager getEm() {
        return em;
    }
 
    public void setEm(EntityManager em) {
        this.em = em;
    }
  }

So what happens here, once a bean with the class BasicJPADAO is created under conversation scope it will get the entity manager automatically assigned. The entity manager has the same lifecycle as the conversation, unless terminated manually before.

This does not only work for daos but basically any object under conversation scope having the @PersonstenceContext annotation on an EntityManager attribute. So if we have bean1 bean2 and bean3 and one controller bean referencing those three other beans, and bean1 2 and 3 have an EntityManager @PersistenceContext attribute all of those will get the same entity manager will work on the same db objects if their referencing view controller is under conversation.

If we have bean1 and 2 under one conversation, and bean 3 under another conversation, then bean1 and bean2 will share one Entity Manager and bean3 will get another one. Hence only bean1 and 2 work on the same entities, while bean3 has a different set of entities possibly working on the same datasets!

Code Examples

Example1 a simple view contoller, business object/facade and DAO

  public class BasicJPADAO{
 
    @PersistenceContext
    EntityManager em;
    public EntityManager getEm() {
        return em;
    }
 
    public void setEm(EntityManager em) {
        this.em = em;
    }
    public MyEntity loadEntity() {
      ....  
    }

    public void doSomethingWithEntity(MyEntity entity) {
       em....
       ....
    }
    public void doSomethingElseWithEntity(MyEntity entity) {
       em....
      ....
    }


  }

  public class BasicBO {
      BasicJPADAO basicdaobean;



      public MyEntity loadSomething() {
      }
 
      @Transactional
      public MyEntity doSomething(MyEntity entity) {
          basicdaobean.doSomethingWithEntity(entity);
          basicdaobean.doSomethingWithEntity(entity);
      }


      //setters and getters
      public BasicJPADAO getBasicdaobean() {
         return basicdaobean;
      }
      public void setBasicdaobean(BasicJPADAO  basicdaobean) {
         this.basicdaobean = basicdaobean;
      }
  }

  public class BasicViewController {
      BasicBO basicbo;

      MyEntity workEntity;


      public void doAction() {
          basicbo.doSomething(workEntity);
          return "success";
      }
      

      public void valueBound(ConversationBindingEvent arg0) {
        workEntity = basicbo.loadEntity(); //we first init it with an empty query
      }

     //setters and getters
     public  BasicBO set....  
  }

Thats basically it in the simplest case... Lets go through this code step by step:

public class BasicJPADAO{
 
    @PersistenceContext
    EntityManager em;
    public EntityManager getEm() {
        return em;
    }
 
    public void setEm(EntityManager em) {
        this.em = em;
    }
    public MyEntity loadEntity() {
      ....  
    }

    public void doSomethingWithEntity(MyEntity entity) {
       em....
       ....
    }
    public void doSomethingElseWithEntity(MyEntity entity) {
       em....
      ....
    }


  }

We have seen this before, a basic dao, which gets its PersistenceContext from Orchestra, it implements three operations a load operation, and two operations doing something else (probably some writes) Nothing really to see here, except one thing, there is no dedicated Transaction control on this level. We have the transaction control on the business facade level. This is a very common usecase to push the Transactions onto the rim between the view layer and the business layer.

  public class BasicBO {
      BasicJPADAO basicdaobean;



      public MyEntity loadSomething() {
      }
 
      @Transactional
      public MyEntity doSomething(MyEntity entity) {
          basicdaobean.doSomethingWithEntity(entity);
          basicdaobean.doSomethingWithEntity(entity);
      }


      //setters and getters
      public BasicJPADAO getBasicdaobean() {
         return basicdaobean;
      }
      public void setBasicdaobean(BasicJPADAO  basicdaobean) {
         this.basicdaobean = basicdaobean;
      }
  }

This is a simple business facade it references our dao and implements two operations one load and a do something which does the other two dao operations combined, the interesting part is this one.

      @Transactional
      public MyEntity doSomething(MyEntity entity) {
          basicdaobean.doSomethingWithEntity(entity);
          basicdaobean.doSomethingWithEntity(entity);
      }

Annotation magic in action... It puts all operations in this method under Transactions.

Now to the most interesting part, the view controller bean:

   public class BasicViewController {
      BasicBO basicbo;

      MyEntity workEntity;


      public void doAction() {
          basicbo.doSomething(workEntity);
          return "success";
      }

      public void doWearedonewithit() {
         Conversation.getCurrentInstance().invalidate();
         return "done";  
      }      

      public void valueBound(ConversationBindingEvent arg0) {
        workEntity = basicbo.loadEntity(); //we first init it with an empty query
      }



     //setters and getters
     public  BasicBO set....  
  }

there are several interesting parts mainly following:

  public void valueBound(ConversationBindingEvent arg0) {
        workEntity = basicbo.loadEntity(); //we first init it with an empty query
  }

This method is called after the conversation is initiated, and the EntityManagers have been assigned, what happens here is that our entity is loaded for further processing later on.

Now we do something .... Page Refresh..... Page Refresh... Page Refresh.... our action is triggered:

   public void doAction() {
          basicbo.doSomething(workEntity);
          return "success";
   }

Yes, there still is the same entity (although the internal values might have changed), the chance that we get an object cannot be assigned error is zero. We simply do something with the object.

Note for the sake of readability we omitted the error handling in case of an operation fail with a subsequent automated rollback entirely

Now we are done with it, seriously, yes we do not want to work on this form or these forms any more. How can we close everything so that all resources will be released, and the memory is freed?

Easy, forget about it

The conversation will time out after a while (the default value is 30 minutes), but in most cased you clearly know a definitive end point when you know you are really done with it, here we have our doWearedonewithit action

  public void doWearedonewithit() {
         Conversation.getCurrentInstance().invalidate();
         return "done";  
  }      

It is pretty clear what happens here. We are done with it, the conversation is invalidated, everything is closed and freed or pushed into recycling.

BO/DAO_Patterns_in_Orchestra (last edited 2009-09-20 23:00:57 by localhost)