Using a Model Facade

Status: In Early Access
Sean BrydonSmitha Kangath

Problem Description

Java EE 5 applications can use Java Persistence APIs to create domain models. When designing code that will access your entities in the model tier, the calling client code, such as a Servlet, a JSP page or a JSF managed bean, will access the entity APIs.  With Java Persistence entities, the clients may get exposed to transactions APIs, EntityManager APIs and other features of the peristence APIs which are necessary to access the entities in the model. Also, the client code may need to interact with several entities, and each entity will have a different API and maybe different requirements for transactions and entity manager operations. As your application gets larger, the code can have a lot of APIs for clients of the model to use and this can get difficult to manage as the client code can become tightly coupled to the entity model. 

Solution

The Facade pattern defines a higher level class that encapsulates and centralizes the interactions between calling clients and the model entities and operations of the Java Persistence APIs. It provides a single interface for operations on a set of entities. A client using this facade does not have to be aware of all the details of the APIs of each entity and does not have to be aware of any persistence mechanisms being used when accessing the entity managers or other transaction managers. Introducing a facade between the calling clients and the entities in the model tier makes the code more loosely-coupled and hence easier to maintain.

As code example 1 shows, the code with a facade is cleaner. Without using a facade, the client of the entities needs to know details about the entity and you might have similiar code cut-and-pasted in other places whenever access to the entity was needed. The code after introducing a facade hides many of the details of the entities in the model tier.

Code Before Code After Introducing a Facade 
public class MyWebClient ... {
  
  ...


  public void doGet(HttpServletRequest request,
            HttpServletResponse response)
{
...
//processing a web request to
//add a new Item to the database
if (selectedURL.equals("additem.do")) {
  String desc = request.getParameter("item_desc");
  String name = request.getParameter("item_name");
  ...
  Item item = new Item();
  item.setName(name);
  item.setDescription(desc);

 
//now access entities in model tier
  EntityManager em =
          emf.createEntityManager();
    try{
      utx.begin();
      em.joinTransaction();
      em.persist(item);
      utx.commit();
    } catch(Exception exe){
            System.out.println("Error persisting item: "+exe);
        try {
            utx.rollback();
        } catch (Exception e) {}
    } finally {
        em.close();
    }
  }
...

public class MyWebClient { ...

...

  public void doGet(HttpServletRequest request,
            HttpServletResponse response)
{
...
//processing a web request to
//add a new Item to the database
if (selectedURL.equals("additem.do")) {
  String desc = request.getParameter("item_desc");
  String name = request.getParameter("item_name");
  ...
  Item item = new Item();
  item.setName(name);
  item.setDescription(desc);
  //now access entities in model tier
  MyModelFacade myfacade = new 
MyModelFacade(); 
  myfacade.addItem(item);
  }
Code Example 1: Refactoring the Client Calling Code by Introducing a Facade to Access the Entities in the Model Tier

When designing a facade, here are some design choices to consider: Lets consider some of the choices we made in the facades we used. In our example applications we show both a web and a session bean facade. These examples will be discussed in more details below.

 Strategy 1: Using a Web Component Facade 

One strategy to implement a facade is to use a Web component as the facade class. This strategy is useful if you want to have a web-only architecture and dont want to use an EJB container or if you just want to keep the facade in the web container.  If your application is using a web-only architecture and has the web components accessing the entities then using a facade can help clean up the code.

This will discuss implementation details of build web facade

public class CatalogFacade implements ServletContextListener {

 @PersistenceUnit(unitName="CatalogPu") private EntityManagerFactory emf;
 @Resource UserTransaction utx;

 public CatalogFacade(){}

 public void contextDestroyed(ServletContextEvent sce) {
   if (emf.isOpen()) {
     emf.close();
   }
 }

 public void contextInitialized(ServletContextEvent sce) {
   ServletContext context = sce.getServletContext();
   context.setAttribute("CatalogFacade", this);
 }

 public void addItem(Item item) throws InvalidItemException {
   EntityManager em = emf.createEntityManager();
   if(item.getName().length() == 0)
     throw new InvalidItemException("The item" + " name cannot be empty. Please specify a name for the item. ");

   try {
     utx.begin();
     em.joinTransaction();
     em.persist(item);
     utx.commit();
   } catch(Exception exe){
     System.err.println("Error persisting item: "+exe);
     try {
       utx.rollback();
     } catch (Exception e) {
       throw new RuntimeException("Error persisting item: "+ e.getMessage(), e);
     }
     throw new RuntimeException("Error persisting item: "+ exe.getMessage(), exe);
   } finally {
     em.close();
   }
 }

 public Item getItem(int itemID){
   EntityManager em = emf.createEntityManager();
   Item item = em.find(Item.class,itemID);
   em.close();
   return item;
 }

 public List getAllItems(){
   EntityManager em = emf.createEntityManager();
   List items = em.createQuery("SELECT OBJECT(i) FROM Item i").getResultList();
   em.close();
   return items;
 }

}

Code Example 2: Web Component as a Facade to Entity Bean and Model

In code example 2, one thing to note is that we chose to have the facade implement the ServletContextListener interface. This allows it to use annotations which are useful when accessing Java Persistence entities and related services of the Java EE platform. Now lets look at how a web component such as a servlet would look this facade up, and then use it. For example, in the addItem method, the JTA APIs for transaction demarcation are needed to access the entities. Also, the EntityManager APIs are needed to store the new Item in the database. Having this code in one place in a facade class is better than cutting-and-pasting similar code all around your application whenever entity access is required.

public class CatalogServlet extends HttpServlet {
  private ServletContext context;
  private CatalogFacade cf; 

  public void init(ServletConfig config)throws ServletException {              
context = config.getServletContext();
cf = (CatalogFacade)context.getAttribute("CatalogFacade");
initPathMapping();
  }

  public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {     
  ...       
try {           
if (selectedURL.equals("additem.do")) {          
    //get values from request and set in a
//new Item to then add to database              
String desc = request.getParameter("item_desc");              
String name = request.getParameter("item_name");              
...               
Item item = new Item();               
item.setName(name);            
item.setDescription(desc);              
  ...
cf.addItem(item);  //now call facade             
  ...           
}
}
Code Example 3: Web Component Using a Model Facade to Access Java Persistence Entities

In code example 3, one thing to note is that the facade is obtained by the init method of the Servlet and then stored as a field in the Servlet so that it can be used and shared by other client requests. When processing a request, the Servlet can then uses the facade and is shielded from the details of the entities and any persistence work required to access the entities.

Strategy 2: Using a Session Bean Facade

An alternative strategy for implementing a facade is to use a SessionBean as the facade. In this design you will need to use the EJB container as it offers support for SessionBeans. One advantage of this strategy is that session beans can take advantage of container services such as container-managed transactions. So your code does not need to include any extra code to manage the transactions using JTA APIs. 

@Stateless
public class CatalogFacadeBean implements CatalogFacade {  

  @PersistenceContext(unitName="CatalogPu")
  private EntityManager em;

  public void addItem(Item item) throws InvalidItemException {
    if(item.getName().length() == 0)
      throw new InvalidItemException("The item" +
        " name cannot be empty. Please specify a name for the item. ");
    em.persist(item);
  }

  public Item getItem(int itemID) {
    Item item =  em.find(Item.class,itemID);
    return item;
  }

  public List<Item> getAllItems() {
    List<Item> items = em.createQuery("SELECT OBJECT(i) FROM Item i").getResultList();
    return items;
  }
}

Code Example 4: Session Bean as a Facade to Entities and Model Tier

In code example 4, notice there is no code to demarcate the transactions. In this case, we decided to leverage the container-managed transaction services of the EJB container. The desired transaction behavior can be specified by annotations (we used the defaults here) or optionally can be specified in a deployment descriptor. Additionally in this example, we decided to use the container-managed entity manager so the code did not need to include any calls to the EntityManager APIs, and instead the EJB container does the work. If you choose to use application-managed entity managers and transaction, then your code would still need to include code to manage those services programmatically.

public class CatalogServlet extends HttpServlet {
  private Map nameSpace;
  private ServletContext context;
  @EJB(name="CatalogFacadeBean") private CatalogFacade cf;  

  public void init(ServletConfig config) throws ServletException {
    context = config.getServletContext();       
    initPathMapping();
  }  

  public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    ...       
    try {
    if (selectedURL.equals("additem.do")) {
      //get values from request and place them into new Item
      String desc = request.getParameter("item_desc");
      String name = request.getParameter("item_name");
      ...
      Item item = new Item();
      item.setName(name);
      item.setDescription(desc);
      ...
      //use facade to add new Item to database
      cf.addItem(item);
      ...         
    }
    ...
  }

Code Example 5: Web Component using the Session Bean Facade to Access Java Persistence Entities

In Code Example 5, the Servlet uses dependency injection to lookup and obtain the facade with @EJB(name="CatalogFacadeBean"). Notice also that the facade is stored as a field so that it can be shared and used by other client requests. Usage of the facade hides the detail of the access to the model tier.

References

Here are some references to consider:

© Sun Microsystems 2006. All of the material in The Java BluePrints Solutions Catalog is copyright-protected and may not be published in other works without express written permission from Sun Microsystems.