Using an EJB Session Bean as a Model Facade

Status: In Early Access
Sean BrydonYutakaYoshida, Inderjeet Singh

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 persistence 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.

For a detailed description of the general Model Facade pattern, see Using a Model Facade in  a Java EE 5 application. There is also an alternative solution for web-only applications for Using a Web Component for a Model Facade in a Java EE 5 application.

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.

Strategy 1: Using a Session Bean Facade

One 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.

Lets take a look at the code and then cover some of the choices we made when implementing the facade in this example. This code example will use a servlet to demonstrate the concepts, but the same concepts can apply when using Java Server Faces technology and is briefly discussed below also. Lets consider a code example now, and first lets look at the interface of the facade as a Session Bean.

import java.util.List;

import com.sun.javaee.blueprints.sessionfacade.InvalidItemException;
import com.sun.javaee.blueprints.sessionfacade.model.Item;

public interface CatalogFacade {
    public void addItem(Item item)throws InvalidItemException;
    public Item getItem(int itemID);
    public List<Item> getAllItems();
}

Code Example 1: Interface for a Stateless Session Bean as a Facade to Entities and Model Tier

When using a Session Bean it is required to have an interface. In code example 1, notice that there is no importing of any EJB package specific classes. This interface is the client view of the facade. It is just like any other Java interface. This interface is what the Servlet in code example 3 will use to access the facade functionality. The interface contains all the information that the client servlet will need to access the model tier of this application.

@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 2: Session Bean as a Facade to Entities and Model Tier

As you can see, the code in example 2  is fairly simple. In this small example case, there is not a lot of business logic or a large set of entities in the domain model. However, similar concepts apply in a larger application so the example is illustrative.
Now lets look at some of the design considerations and choices made in this example to use session bean for the facade:

Next lets look at how a Web component, such as a Servlet or JSP page or JSF Managed Bean, can use the Session Bean facade.

public class CatalogServlet extends HttpServlet {

  @EJB private CatalogFacade cf;

  ...

  public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {

    ...       
    if ("additem.do".equals(selectedURL))  {
      //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 3: Web Component using the Session Bean Facade to Access Java Persistence Entities

In Code Example 3, the Servlet uses dependency injection to lookup and obtain the facade with @EJB private CatalogFacade cf;. Notice also that the facade is stored as a field so that it can be shared and used by other client requests. The Stateless Session Bean is a thread-safe object so is easy to store as a field in a web tier component such as a Servlet or JSF managed bean. Note that not all resources are thread-safe , for example the EntityManager object is not a thread-safe object so web components should avoid storing it as a field. See the discussion above on the issue of client caching of the session bean facade and thread-safety for more detail. Usage of the facade hides the detail of the access to the model tier and encapsulates the details of the technologies involved such as the JTA APIs and the Java Persistence APIs. In this simple example, the model tier is very small, but the concepts apply to larger examples as well.

Using the Session Bean Facade with Java Server Faces Technology
The code example 3 discussed using a Servlet as the web component that uses the Session bean facade to access the Java Persistence objects in the model tier. These same concepts can be used with JSF components. In fact, the code for a JSF managed bean would be almost identical to the Servlet example. The JSF managed bean would just inject the Session Bean Facade as a field like @EJB private CatalogFacade cf; and then just access the the session bean facade in its methods by calling its APIs. The code, design considerations, and issues for the Servlet example shown are very much the same as in the case of a JSF managed bean using a Stateless Session Bean as a model facade.

In general, each JSF page would access a JSF managed bean(backing bean) and the managed bean would then access the Session Bean facade using the session bean's interface. Note that the JSF managed bean would not need to access any of the Java Persistence APIs or JTA APIs and just needs to access the Session Bean facade, which helps avoid the issue of client caching of the session bean facade and thread-safety discussed previously. The Session Bean would then handle all the access to the persistence objects in the model tier. Also, the facade might return the Java Persistence objects as plain-old-Java-objects (POJOs) which can be used by the web tier, as discussed above. This is the expected programming model for Java EE 5 applications using JSF and EJB 3. The diagram below illustrates the programming model for JSF using a Session Bean as a facade.

image of JSF components using a Session Bean as a Facade

References

Here are some references to consider:

Java BluePrints | Sun Microsystems © 2007 Sun Microsystems Inc. All rights reserved. Use is subject to license terms.