Sun Java Solaris Communities My SDN Account Join SDN
 
Enterprise Java Technologies Tech Tips

Using Java Persistence With JavaServer Faces Technology, and Using a Model Facade

 
In This Issue
Welcome to the Enterprise Java Technologies Tech Tips for November 18, 2006. Here you'll get tips on using enterprise Java technologies and APIs, such as those in Java Platform, Enterprise Edition (Java EE).

These tips were developed using the Java EE 5 SDK. You can download the SDK from the Java EE Downloads page.

You can download the sample archive for the Using Java Persistence With JavaServer Faces Technology tip.

You can download the sample archive for the Using a Model Facade tip.

Any use of this code and/or information below is subject to the license terms.

See the Subscribe/Unsubscribe note at the end of this newsletter to subscribe to Tech Tips that focus on technologies and products in other Java platforms.

Using Java Persistence with JavaServer Faces Technology
By Roger Kitain  

JavaServer Faces technology, often abbreviated as JSF, is a framework that simplifies building user interfaces (UIs) for Java Platform, Enterprise Edition (Java EE) and Java 2 Platform, Enterprise Edition (J2EE) applications. The March 24, 2004 Tech Tip, "Introducing JavaServer Faces Technology" gave a brief overview of the technology. It also showed how to create a JSF application that includes GUI components that are modeled by the JSF framework. A later tip showed how to create custom components with JavaServer Faces technology.

This tip examines a sample application that uses the Java Persistence API with the JSF framework. A package that contains the code for the sample application accompanies the tip. The code examples in the tip are taken from the source code of the sample (which is included in the package).

The Java Persistence API and JSF

The Java Persistence API (or simply Java Persistence) simplifies the entity persistence model and adds additional capabilities that were not available in Enterprise JavaBeans (EJB) 2.1 technology. It handles all of the details of how relational data is mapped to Java objects, and it standardizes object-relational mapping. The Java Persistence API is included in the EJB 3.0 specification .

There are some JSF features that facilitate the use of Java Persistence in web applications. Value binding expressions bind UI components to model tier data, so that data can be pushed to the model when a form submit occurs. Method binding expressions bind UI components to action methods so that a method attached to a component can execute when that component is activated. For example, when a button is pressed it causes a form to be submitted. Managed beans are JSF application beans that can be instantiated on demand. They are the model tier in a JSF application, and instances of these beans can be stored in a request -- either in session or application scope.

The Java Persistence API also includes an EntityManager API that you can use to persist entities to a database. You can inject EntityManager instances into JSF managed beans to persist data. EntityManager instances are not thread safe, so you should not inject them into JSF managed beans that have a scope of session or application.

Here's an example of injecting EntityManager instances into a JSF managed bean (assume the bean in the example, BookBean, is an application-scoped JSF managed bean):

   public class BookBean {
       @PersistenceContext EntityManager em;
   ...
       public String placeOrder() {
   ...
          em.persist(order);
   ...  
       }
   }


However that's not a particularly good approach. Here is a better approach. It uses the EntityManagerFactory to create EntityManager instances. It also uses a request-scoped JSF managed bean -- this helps ensure thread safety.

public class BookBean {
       @PersistenceUnit EntityManagerFactory emf;
   ...
       public String placeOrder() {
   ...
           EntityManager em = emf.createEntityManager();
   ...
           em.persist(order);
   ...
       }
   }   


JSF Persistence Example

If you are familiar with JSF you might also be familiar with the JSF "guess number" application. The application asks the user to guess a number that the application picks within a range of numbers (1-to-10).

The following diagram shows the flow of the guess number application:

The application begins with the display of an HTML page that prompts for a number between a range. After entering a number, the user presses the "Guess" button to submit the information. If the user submits a number that is outside the range, or submits an invalid digit (a letter, for example), the application displays a validation error message from JSF.

If the user submits a valid number, the "response" page appears indicating whether the guess is correct or not.

The response page also displays an "Again" button. Pressing this button navigates back to the initial page to allow more guesses. A user can navigate back and forth between the pages until he makes a correct guess. If the user presses the "Again" button after making a correct guess it implicitly starts a new game.

Java Persistence is used to store in a database all the guess attempts, and it is used to display (or play back) guess attempts that have been stored in the database.

Let's take a look at some of the code for the guess number application.

Here is the script that creates the database table:

create table USERGUESS
       (ID INT NOT NULL,
        GUESS VARCHAR(10) NOT NULL,
        OUTCOME VARCHAR(10) NOT NULL,
        PRIMARY KEY(ID));  


Here is an entity class, UserGuess, that corresponds to the database table:

   ...
   import javax.persistence.Entity;
   import javax.persistence.GeneratedValue;
   import javax.persistence.GenerationType;
   import javax.persistence.Id;
 
   @Entity
   public class UserGuess implements java.io.Serializable {
 
       @Id
       @GeneratedValue(strategy=GenerationType.AUTO)
       private int id;
 
       private String guess;
       public String getGuess() {
           return guess;
       }
       public void setGuess(String guess) {
           this.guess = guess;
       }
 
       private String outcome;
       public String getOutcome() {
           return outcome;
       }
       public void setOutcome(String outcome) {
           this.outcome = outcome;
       }
   }


The UserGuess entity consists of three properties, id, guess, and outcome, that correspond to the database columns. The id is the primary key that is automatically generated when a row of data is added to the database.

A JSF managed bean, UserNumberBean.java, contains the processing logic for the application. This bean has other methods such as validate, but let's focus on the code that uses Java Persistence.

This application uses a container-managed EntityManager, so it must be controlled using the Java Transaction API (JTA). First, let's inject the instances:

   ...
   public class UserNumberBean {
   ...
       // This injects the default entity manager factory
       @PersistenceUnit
       private EntityManagerFactory emf;
       
       // This injects a user transaction object.
       @Resource
       private UserTransaction utx;
   ...


You can use the injected EntityManagerFactory instance anywhere to create and use an EntityManager. You can also use the injected UserTransaction instance to control the transactions:

   ...
   public class UserNumberBean {
   ...
       /∗∗
        ∗ This method persists each attempted guess (number).
        ∗/
       private String sameGame() {
           String message = null;
           EntityManager em = null;
           try {
               em = emf.createEntityManager();
               utx.begin();
               em.persist(userGuess);
               utx.commit();
           } catch (Exception ee) {
               try {
                  utx.rollback();
               } catch (Exception re) {}
               if (logger.isLoggable(Level.SEVERE)) {
                   logger.log(Level.SEVERE, "Database Error:", 
                           ee.getCause());
               }
               message += "Database Error: "+ee.getCause();
           } finally {
               if (em != null) {
                   em.close();
               }
           }
           return message;
      }
   ...
       /∗∗
        ∗ This method clears the database table in preparation 
        ∗ of a new game.
        ∗/
       private String newGame() {
           String message = null;
           EntityManager em = null;
           String statement = "delete from UserGuess";
           try {
               em = emf.createEntityManager();
               utx.begin();
               em.createQuery(statement).executeUpdate();
               utx.commit();
           } catch (Exception ee) {
               try {
                   utx.rollback();
               } catch (Exception re) { }
               if (logger.isLoggable(Level.SEVERE)) {
                   logger.log(Level.SEVERE, "Database Error:", 
                           ee.getCause());
               }
               message = "Database Error: "+ee.getCause();
           } finally {
               if (em != null) {
                   em.close();
               }
           }
           return message;
       }
   ...


Posting From The Client

The initial page has a text field for entering a number and a button labeled "Guess" for submitting the guess. Here is a snippet of the greeting.jsp page:

   ...
      <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
      <%@ taglib uri="http://java.sun.com/jsf/core" 
        prefix="f" %>
   ...   
      <h:inputText id="userNo" label="User Number" 
         value="#{UserNumberBean.userNumber}"
         validator="#{UserNumberBean.validate}"/>
      <h:commandButton id="guess" action="success" 
        value="Guess" />

      <h:dataTable
         border="1"
         rendered="#{UserNumberBean.hasGuesses}"
         value="#{UserNumberBean.guessList}"
         var="guessItem">
         <h:column>
            <f:facet name="header">
               <h:outputText value="Guess" />
            </f:facet>
            <h:outputText value="#{guessItem.guess}"/>
         </h:column>
         <h:column>
            <f:facet name="header">
               <h:outputText value="Outcome" />
            </f:facet>
                <h:outputText value="#{guessItem.outcome}"/>
         </h:column>
      </h:dataTable>
   ...


The <h:dataTable> component displays the attempted guesses that have been stored in the database for the current game. When the page renders initially, or at the start of each new game, the <h:dataTable> component does not render. This is controlled by the boolean property hasGuesses on the bean UserNumberBean as identified by the expression "#{UserNumberBean.hasGuesses}". A value of true indicates that guesses have been attempted.

   ...
   public class UserNumberBean {
   ...
       // Indicates that we have some attempted guesses.
       private boolean hasGuesses = false;
   ...
       /∗∗
        ∗ -- Accessor methods for the hasGuesses 
        ∗ property (used to control rendering of the 
        ∗ DataTable of attempted guesses).
        ∗/
        
       public void setHasGuesses(boolean hasGuesses) {
           this.hasGuesses = hasGuesses;
       }
       
       public boolean getHasGuesses() {
           return hasGuesses;
       }
   ...


The expression "#{UserNumberBean.guessList}" refers to the Java Collection of UserGuess entity beans. When this expression is evaluated during rendering, the UserNumberBean.getGuessList method uses Java Persistence to load the collection from the database:

   ...
   public class UserNumberBean {
   ...
       // The attempted guesses.
       private Collection <UserGuess> guessList;
   ...
       /∗∗
        ∗ This method loads the Collection from the
        ∗ database. The Collection is used by the
        ∗ DataTable to display attempted guesses.
        ∗/
       public Collection <UserGuess> getGuessList() {
           EntityManager em = emf.createEntityManager();
           guessList = em.createQuery()
                   "select g from UserGuess g").getResultList();
           return guessList;
       }
   ...


The <h:dataTable> component renders the results.

Running the Sample Code

A sample package accompanies this tip that demonstrates the techniques covered in the tip. You can deploy the sample package on any web container that supports the Servlet 2.5 API, JavaServer Pages (JSP) Technology 2.1, and JavaServer Faces Technology 1.2. These instructions also assume that you are using the Java EE 5 SDK.

To install and run the sample:

  1. If you haven't already done so, download the Java EE 5 SDK from the Java EE Downloads Page.


  2. Set the following environment variables:
    • JAVAEE_HOME. This should point to where you installed the Java EE 5 SDK.
    • JAVA_HOME. This should point to the location of JDK 5.0 on your system. JDK is included in the Java EE 5 SDK bundle that you downloaded. (In Windows, it's in the jdk subdirectory.)

    Add $JAVA_HOME/bin and $JAVAEE_HOME/bin to your PATH environment variable.

  3. Download the sample package for the tip and extract its contents. You should now see the newly extracted directory as <sample_install_dir>/guessNumber, where <sample_install_dir> is the directory where you installed the sample package. For example, if you extracted the contents to C:\ on a Windows machine, then your newly created directory should be at C:\guessNumber. The guessNumber directory contains the web archive, web-app.war, for the application, and the subdirectories src and web for viewing source. It also contains a script, db.sql, for creating the database table.

  4. Start the derby database by entering the following command:
    $JAVAEE_HOME/bin/asadmin start-database
  5. Start the Application Server by entering the following command:
    $JAVAEE_HOME/bin/asadmin start-domain domain1
  6. Create the database table for the application:
    1. Set your CLASSPATH to include:
      $JAVAEE_HOME/javadb/lib/derbyclient.jar $JAVAEE_HOME/javadb/lib/derbytools.jar $JAVAEE_HOME/javadb/lib/derby.jar
    2. Go to <sample_install_dir>/guessNumber/ directory.
    3. Get into ij:
      java org.apache.derby.tools.ij
    4. At the "ij" prompt enter the following commands:
      ij>DRIVER 'org.apache.derby.jdbc.ClientDriver';

      ij>CONNECT 'jdbc:derby://localhost:1527/sun-appserv-samples';
      If the database does not exist yet you need to enter the following command:
      CONNECT 'jdbc:derby://localhost:1527/sun-appserv-samples;create=true';
    5. At the "ij" prompt, execute:
      ij> run 'db.sql';
  7. Deploy the sample by copying:
    <sample_install_dir>/guessNumber/wep-app.war to $JAVAEE_HOME/domains/domain1/autodeploy
  8. Open your browser to the URL: http://localhost:8080/web-app/

About the Author

Roger Kitain is the JavaServer Faces technology co-specification lead. He has been extensively involved with server-side web technologies and products since 1997. Roger started working on JavaServer Faces technology in 2001 as a member of the reference implementation team. He has experience with Servlet and JSP technologies. Most recently, Roger has been involved with different rendering technologies for JavaServer Faces technology.

Using a Model Facade
By Sean Brydon and Yutaka Yoshida  

A number of recent Tech Tips, including the other tip in this issue, "Using Java Persistence With JavaServer Faces Technology," have covered various aspects of the Java Persistence API. What's significant is that you can use the Java Persistence API to manage persistence in the domain model of your Java EE 5 applications and take advantage of additional capabilities that were not available in the J2EE platform.

However there are a number of things to consider when you use Java Persistence. For example, a Java Persistence client such as a servlet, JSP page, or a JSF managed bean, might need to access various types of APIs to access entities in the model. (In this tip, the term "client" refers to web components such as JSF managed beans, servlets, or JSP pages that call methods on Java Persistence entity objects.) These APIs include Java Transaction (JTA) APIs, EntityManager APIs, as well as the Java Persistence API. Also, the client code might need to interact with several entities, where each entity has a different API and perhaps different requirements for transactions and entity manager operations. The need to access these different types of APIs, as well as the multiplicity of transactions and entity manager operations can lead to a lot of complexity in the client code.

As your application grows, you might need to repeat the same code for access to multiple entities. This might involve copying similar data access logic into each servlet or managed bean that needs to access the entities. Not only is this repetitive code difficult to manage, but it tightly couples the code to the entity model.

A Model Facade is a good way to simplify the code in a Java Persistence client.

What is a Model Facade?

A Model Facade (or simply a "Facade") is a design pattern. The Facade pattern defines a higher-level class that encapsulates and centralizes the interactions between Java Persistence clients and the entities and operations of the Java Persistence API. The pattern provides a single interface for operations on a set of entities. Using the Facade pattern can make the code in your Java Persistence clients cleaner. A web component that uses a Facade to access the model tier does not have to be aware of all the details of the APIs for each entity. Neither does the web component need to be aware of the persistence mechanisms being used when accessing the entity managers or transaction managers. Also, if you add a Facade between the calling clients and the entities in the model tier, it makes your code more loosely-coupled and easier to maintain.

A Facade isn't limited to use with Java Persistence. It's also useful with other persistence technologies such as JDBC.

Designing and Coding a Facade

To illustrate how much cleaner it is to code with a Facade, let's look at a "before" and "after" example. The "before" example shows the code for a servlet that accesses entities in a model tier. The "after" example shows the servlet code if a Facade is used.

Here is the "before" code:

   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();
       }
     }
   ...
   
Here is the "after" code:

   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);
     }


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 you don't want to use an EJB container. It's also a useful strategy if you want to keep the Facade in the web container. If your application uses a web-only architecture and its web components access the entities, then using a Facade can help clean up your code. Note that the focus in this tip is on implementing a Facade for web-only applications that are not using an EJB tier, that is, Java EE applications that do not use the EJB container or services.

An Example Facade for a Web-Only Application

Let's take a look at the code for a Facade. You can find the source code for the Facade as well as the code for the other examples in this tip in the sample application package that accompanies the tip.

   public class CatalogFacade implements ServletContextListener {
    @PersistenceUnit(unitName="CatalogPu") 
    private EntityManagerFactory emf;
    @Resource UserTransaction utx;

    public CatalogFacade(){}

    public void contextDestroyed(ServletContextEvent sce) {
      if (emf != null && 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(exe);
         try {
             utx.rollback();
         } catch (Exception e){
             e.initCause(exe);
             throw new RuntimeException(e);
         }
         throw new RuntimeException(exe);
       } finally {
           if (em != null) {
               em.close();
           }
       }
    }
    
    public Item getItem(int itemID){
        EntityManager em = emf.createEntityManager();
        Item item =  em.find(Item.class,itemID);
        em.close();
        return item;
    }
    

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


There are a couple design choices to notice in the CatalogFacade example:

  • The Facade implements the ServletContextListener interface. This allows it to use annotations that are useful when accessing Java Persistence entities and related services in the Java EE platform. If you want the Facade to use annotations and dependency injection, the Facade must be a web component. Plain-old Java objects (POJOs) cannot use Java EE 5 dependency injection.

  • The Facade does not expose calling clients to persistence-related exceptions. The example Facade catches the exceptions from the Java Persistence and Java Transaction APIs and throws a runtime exception instead.

  • The Facade handles all the transactional code and the entity manager interactions.

  • The Facade does not add an extra interface (beyond that of the Facade itself). An extra interface can make the code more loosely-coupled from the entities and model tier, but it requires an extra class. However you can consider adding an extra interface in more complex cases.

  • The Facade returns Java Persistence objects to be used as POJOs by the client code. It does not return a data transfer object or a value object that is a copy of the Java Persistence entities. Java Persistence entities are managed by the entity manager and can be used as model objects. Entities can be used as POJOs. The Facade returns the Java Persistence entities in detached mode. If you want to further loosely-couple the code from the entities and model tier, consider adding objects that are client-specific. Return those instead of the entity objects.

  • The Facade is thread-safe and only stores objects that can be safely cached. It does not cache any stateful objects. The facade only holds the EntityManagerFactory and the UserTransaction objects, both of which are thread-safe and can be held and cached for subsequent requests. This allows this Facade to be cached and shared. Note that web components should not hold EntityManager objects because doing so is not thread safe.

Notice too that in the addItem method, JTA APIs for transaction demarcation are needed to access the entities. Also, 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 repeating the code in your application whenever you need to access an entity.

Using the Facade

Now let's look at how a web component such as a servlet uses the example Facade.

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

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


The servlet uses the init method to obtain the Facade. It then stores the Facade as a field in the servlet so that it can be used and shared by other client requests.

private CatalogFacade cf;


By using the Facade, the servlet is shielded from the details of the entities and from any persistence operations required to access the entities.

Running the Sample Code

A sample package accompanies this tip that includes a Model Facade. To install and run the sample:

  1. If you haven't already done so, download the Java EE 5 SDK from the Java EE Downloads Page. Also be sure to have an installed version of the Java Platform Standard Edition (Java SE) 5 SDK.

  2. Download the sample package for the tip and extract its contents. You should now see the newly extracted directory as <sample_install_dir>/ttnov2006facade, where <sample_install_dir> is the directory where you installed the sample package. For example, if you extracted the contents to C:\ on a Windows machine, then your newly created directory should be at C:\ttnov2006facade. The TechTip-Facade directory below the ttnov2006facade directory contains the source files and other support files for the sample.

  3. Edit the build.properties file in the TechTip-Facade directory and set properties appropriately for your environment. For example, set javaee.home to point to your Java EE 5 installation directory.

  4. Start the derby database by entering the following command:
    $JAVAEE_HOME/bin/asadmin start-database
  5. Start the Application Server by entering the following command:
    $JAVAEE_HOME/bin/asadmin start-domain domain1
  6. Change to the TechTip-Facade directory and enter the command:
    ant setup
    This sets up the database resources.


  7. Enter the command:
    ant run
    This builds, deploys, and launches the sample application. The application is the Java Persistence sample application taken from the Java BluePrints Solutions Catalog .

Click on the links in the displayed page to retrieve or add items in a catalog. If you examine the source for the application, you'll see that it uses a Model Facade as the interface for operations on the persistent entities in the catalog.

Summary

If you are building a Java EE 5 web application that uses the Java Persistence API, consider refactoring your code by introducing a Model Facade.

For additional information about Facades and the Java Persistence API see:

About the Authors

Sean Brydon is an engineer with Sun Microsystems where he is the technical lead for the Java BluePrints program. He has been involved with the Java BluePrints since its inception. He is an author of the Addison-Wesley Java-series books, "Designing Enterprise Applications with the Java 2 Platform, Enterprise Edition," and "Designing Web Services with the J2EE 1.4 Platform." He is a regular speaker on enterprise application design.

Yutaka Yoshida was a Servlet 2.4 specification lead, and is currently working in the Java BluePrints project. He has been involved in designing and developing the Java Adventure Builder reference application, the Java BluePrints Solutions Catalog, and the Java Pet Store 2.0 reference application.

 
Developer Assistance

Need programming advice on Java EE? Try Developer Expert Assistance.

Java EE SDK Contest

Download the Java EE SDK. Then enter the Java EE SDK Contest and get a chance to win an iPod Nano. The contest ends November 30.

Rate and Review
Tell us what you think of the content of this page.
Excellent   Good   Fair   Poor  
Comments:
If you would like a reply to your comment, please submit your email address:
Note: We may not respond to all submitted comments.