Combining JavaServer Faces Technology, Spring, and the Java Persistence API

By Carol McDonald

An earlier Tech Tip, Using Java Persistence With JavaServer Faces Technology examined a sample application that uses the Java Persistence API with the JavaServer Faces framework. This tip examines a sample application that uses JavaServer Faces technology, the Java Persistence API, and the Spring 2.0 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 application in the tip is deployed on GlassFish, an open source reference implementation of Java EE 5. You can download GlassFish from the GlassFish Community Downloads page.

A Summary of the Technologies and Frameworks in the Sample Application

If you're not familiar with JavaServerFaces technology, the Java Persistence API, or Spring, here are brief descriptions:

  • JavaServer Faces Technology (often referred to as JSF) is a server-side user interface (UI) component framework for web applications. It simplifies the development of sophisticated interactive web UIs by providing configurable, reusable, extendable UI components, support for event handling, input converters and validators, a navigation model, a component rendering model, and a managed bean model for translating input events to server-side behavior.

  • The Java Persistence API provides a (plain old Java object) POJO-based persistence model for Java EE and Java SE applications. It handles the details of how relational data is mapped to Java objects, and it standardizes Object/Relational (O/R) mapping.

  • Spring is a lightweight, POJO-oriented, open source framework for developing Java enterprise applications. Spring does not reinvent application server functionality such as connection pooling, or provide an object-relational mapping layer. Instead it provides support for Inversion of Control (IoC), dependency injection, Aspect Oriented Programming (AOP), and an abstraction/services layer designed to make existing Java Enterprise application server technologies easier and more transparent to use.

The Sample Application

The sample application in this tip displays an online catalog of pets sold in a pet store.

A Listing Items page, list.jsp, displays pets in the catalog in a three-column table. Each row contains the name of a pet, its photo, and its price. A maximum of 10 rows are displayed on a page. The page also displays which items out of the total number of items in the catalog are displayed, such as "Item 31 ..40 out of 102". A user can click on links in the page to display the next 10 or previous 10 pets in the catalog, or display more details about a specific pet in the list.

This tip focuses on one feature of the sample application -- displaying the table of pets. You can learn how other features in the sample application are implemented by reading the blog entry Sample Application using JSF, Spring 2.0, and Java Persistence APIs.

Using JSF in the Application

If you examine the code in the list.jsp page, you'll notice that it uses JSF components. For example, the following dataTable component displays the table of pets:

   <h:dataTable value='#{item.items}' var='dataTableItem'
          border="1" cellpadding="2" cellspacing="0">

A dataTable component is useful when you want to show a set of results in a table. In a JSF application, the UIData component, the superclass of dataTable, supports binding to a collection of data objects. The UIData component does the work of iterating over each record in the data source. The HTML renderer for the dataTable component displays the data as an HTML table.

The value attribute in the dataTable tag points to a list of catalog items identified by the expression #{item.items}. The value is bound to the items property of a managed bean that has the managed bean name item.

The var attribute points to a single item in that list identified by dataTableItem. As the UIData component iterates through the list, each reference to dataTableItem points to the current item in the list.

JSF column components display the columns in the table. For example, the following column component displays the price column:

   <h:column>
       <f:facet name="header">
           <h:outputText value="Price"/>
       </f:facet>
       <h:outputText value="#{dataTableItem.price}"/>
   </h:column>

The column tag represent a column of data in a UIData component. As the UIData component iterates over the rows of data, it processes the UIColumn component associated with each column tag for each row in the table. The UIData component iterates through the list of items (item.items) and displays the dataTableItem.price. Each time UIData iterates through the list of items, it renders one cell in each column.

The dataTable and column tags use facet tags to represent parts of the table that are not repeated or updated. These include headers, footers, and captions.

Using Spring in the Application

One of the design goals of Spring is to easily integrate with other Java EE-based web frameworks and technologies. In fact, integrating Spring into JSF is simply a matter of configuring the Spring DelegatingVariableResolver in faces-config.xml, the file that lists the bean resources and navigation rules for a JSF application.

The Spring DelegatingVariableResolver enables a JSF application to register a custom replacement class for the standard JSF VariableResolver implementation. The standard JSF VariableResolver resolves variable references at evaluation time. The Spring DelegatingVariableResolver first delegates to the original resolver of the underlying JSF implementation, then to the Spring root WebApplicationContext. The WebApplicationContext is responsible for instantiating, configuring, and maintaining the lifecycle of a set of beans known as Spring beans. What this means is that you can configure Spring beans as managed properties of your JSF managed beans.

Here, for example, is a snippet of the faces-config.xml file for the sample application. In this example, the Spring bean named catalogService is configured as a managed property of the JSF managed bean class ItemController.

   <application>
       <variable-resolver>
         org.springframework.web.jsf.DelegatingVariableResolver
       </variable-resolver>
    </application>
    <managed-bean>
       <managed-bean-name>item</managed-bean-name>
         <managed-bean-class>
            sessionpagination.ItemController
         </managed-bean-class>
       <managed-bean-scope>session</managed-bean-scope>
        <managed-property>
             <property-name>catalogService</property-name>
             <value>#{catalogService}</value>
       </managed-property>
     </managed-bean>

Notice that the ItemController's <managed-bean-scope> is defined as session. A JSF managed bean with session scope is stored in the session. This means that the bean's properties stay alive for the life of the HTTP session.

The catalogService is defined as a Spring bean, CatalogDAO, in the Spring configuration resource file WEB-INF/applicationContext.xml. Here is a snippet of that file:

   <bean id="catalogService" class="service.CatalogDAO"/>
   
   <bean name="itemController" 
      class="sessionpagination.ItemController">
       <property name="catalogService">
           <ref bean="catalogService"/>
       </property>
   </bean>

The element <property name="catalogService"> refers to the setCatalogService method in ItemController. In response, the Spring root WebApplicationContext injects the catalogService Spring bean into the catalogService property of the JSF managed bean ItemController. Here is a snippet of the ItemController source file:

   public class ItemController {

      private CatalogService catalogService;
   
      public void setCatalogService(
       CatalogService catalogService) {
          this.catalogService = catalogService;            
      }
      
      public DataModel getItems() {
          if (model==null  || index != firstItem){
              model=getNextItems();
          }
          return this.model;
      }

      public DataModel getNextItems() {
          model = new ListDataModel(
            catalogService.getItems( firstItem,batchSize));
          index = firstItem;
          return this.model;
      }

The getItems() method wraps a List of item objects returned from the catalogService in a DataModel. UIData supports data binding to a collection of data objects represented by a DataModel instance. The data collection underlying a DataModel instance is modeled as a collection of row objects that can be accessed by a row index. The APIs provide mechanisms to position to a specified row index, and to retrieve an object that represents the data that corresponds to the current row index.

Using the Java Persistence API With Spring

The Spring bean CatalogDAO uses an EntityManager Query object in the Java Persistence API to return a list of items. If you look at the source code for CatalogDAO , you'll notice that it annotates an EntityManager field with a @PersistenceContext annotation. This injects an entity manager into the Spring Bean in the same way that an Entity Manager is injected into an Enterprise JavaBeans Technology (EJB) session bean.

   public class CatalogDAO implements CatalogService {
   
       @PersistenceContext(unitName="PetCatalogPu")
       private EntityManager em;

       public List<Item>  
         getItems(int firstItem,int batchSize) {      
           Query q = 
             em.createQuery("select object(o) from Item as o");
           q.setMaxResults(batchSize);
           q.setFirstResult(firstItem);
           List<Item> items= q.getResultList();
           return items;      
       }

The createQuery method creates an instance of a Query class for executing a Java Persistence query language statement. The setMaxResults() method in Query sets the maximum number of results to retrieve, and the setFirstResult method sets the position of the first result to retrieve.

Item is an Entity class -- a typical Java Persistence entity object -- which maps to an ITEM table that stores the item instances. If you examine the source code for Item, you'll see that it meets the two requirements for an entity:

  • The class is annotated with an @Entity annotation.
  • The primary key identifier is annotated with an @Id annotation.

   @Entity
   
   public class Item implements java.io.Serializable {  
   
   @Id
   
   private String itemid;
   
   private String name;    
   private String description;    
   
   @OneToOne(cascade={CascadeType.PERSIST})
   private Address address;
   @ManyToOne
   private Product product;
   ...

Because fields such as name and description are basic mappings from the object fields to columns of the same name in the database table, they don't have to be annotated. Notice that O/R relationships such one-to-one and many-to-one are specified in annotations for address and product.

The ItemController ManagedBean pages through the list of Items by maintaining the firstItem and batchSize attributes, and passes these as parameters to the CatalogService getItems(firstItem, batchSize) method, which gets the items for display in the table of pets.

Summary

This tip illustrated how Spring can be used with JSF and the Java Persistence API. Specifically, it showed how to use a JSF dataTable and DataModel to display a list of entities, where the entities are retrieved from a database using the Java Persistence API with Spring 2.0.

For more information on using Spring with JSF, see Chapter 15. Integrating with other web frameworks in the document "Spring - Java/J2EE Application Framework".

For more information about the sample application referenced in this tip, see the blog entry Sample Application using JSF, Spring 2.0, and Java Persistence APIs

Running the Sample Code

The sample code for this tip is available as a NetBeans project. You can build and run the sample code using the NetBeans IDE.

Setting Things Up

  1. Download and install NetBeans 5.5.1.
  2. Download and unzip Spring 2.1 (download the with dependencies version).
  3. Download and install GlassFish V1.
    Alternatively you can use Sun Java System Application Server PE 9, Sun's binary distribution of GlassFish.
  4. Add the GlassFish server to NetBeans:

    • Start NetBeans and switch to the Runtime window (Ctrl+5).
    • Right-click the Servers node and select Add Server.
    • Select Sun Java System Application Server.
    • Browse to the location where you installed GlassFish and select Finish.

Create the Spring Library in NetBeans

  1. Open the NetBeans Library Manager (in the Tools menu) and create a new library called Spring.
  2. Add the following jars to the class path:

       dist/spring.jar
       dist/weaving/spring-aspects.jar
       lib/jakarta-commons/commons-logging.jar
       lib/log4j/log4j-1.2.9.jar .

  3. Set the Sources to the Spring src directory.
  4. Set the Javadoc to the Spring docs\\api directory.

Open and Run the Sample code:

  1. Download the sample code and extract its contents. You should now see the newly extracted directory as <sample_install_dir>/SpringJPA, 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:\\SpringJPA.

  2. Start the NetBeans IDE. Click Open Project in the File menu and select the SpringJPA directory you just unzipped. The SpringJPA application is a NetBeans Enterprise Application Project, which is actually comprised of two projects: SpringJPA and SpringJPA-war. SpringJPA-war is a Java EE Module of the SpringJPA project. SpringJPA-war generates the war file and SpringJPA generates the ear file which contains the war.

    You will see a Reference Problems dialog when you open the project. That's because the Enterprise Application Project stores the absolute location to its J2EE Modules. To resolve the reference problems, you need to configure the location for the SpringJPA-war. However, first click Close in the dialog. The SpringJPA project will be in bold red meaning that it still has reference problems.

  3. Right click the SpringJPA project and select Resolve Reference Problems from the context menu. Use the Resolve Reference Problems dialog to map the SpringJPA-war module to its project, which you'll find is a subdirectory beneath the SpringJPA directory.

  4. Right click the SpringJPA project and select Open Required Projects. Now that the dependencies are correct, the SpringJPA-war project will always open with the SpringJPA project. However, there are additional references problems with the web module because it references the Spring jar files that are needed to build the project.

  5. Add the Spring library to the SpringJPA-war. In the Project window under SpringJPA-war:

    • Right click on Libraries and select Add Library.
    • Select the Spring Library in the list, then click Add Library.

  6. Edit the properties in the SpringJPA\\setup\\javadb.properties file, as appropriate.

  7. Start the Java DB database as follows:

    • Select Java DB Database in the Tools menu.
    • Select Start Java DB Server.

  8. Build the project as follows:

    • Right click the SpringJPA node in the Projects window.
    • Select Clean and Build Project.

  9. Run the project as follows:

    • Right click the SpringJPA node in the Projects window.
    • Select Run Project.

When you run the project, your browser should display the opening page of the JSF, Java Persistence API, and Spring 2.0 Sample Application (at http://localhost:8080/SpringJPA-war/).
Java Persistance Sample Application

About the Author

Carol McDonald is a Java Technology Evangelist at Sun Microsystems. As a software developer since 1986, Carol's experience has been in the technology areas of distributed network applications and protocols, including J2EE technology, XML, Internet/Intranet applications, LDAP, Distributed Network Management (CMIP,SNMP) and Email (X.400,X.500). Besides Java, Carol is also fluent in French and German.

Comments:

Nice blog.....Thanks for the info.....Really useful one.....

Posted by Rosy on September 25, 2007 at 08:42 PM PDT #

thanks i needed help on researching this topic

Posted by gemelle on October 27, 2007 at 04:30 AM PDT #

What sort of help are you looking for?

Posted by edort on October 29, 2007 at 01:27 AM PDT #

Hi Carol,

I need to have users log-in via a browser and be connected to their own DB. Currently have JSF and JPA working but can't seem to figure out how users, after log-in are connected with a completely seperate databases -- all with identical schemas but each with different content.

What I am I missing?

Posted by mike on November 01, 2007 at 08:39 AM PDT #

In order to have a different db per user you have to have a different username and password per user for the datasource. In the example app the dataSource is configured in the applicationContext.xml as follows:

<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.apache.derby.jdbc.ClientDriver" />
<property name="url" value="jdbc:derby://localhost:1527/pet-catalog" />
<property name="username" value="app" />
<property name="password" value="app" />
</bean>

Posted by carol on November 02, 2007 at 11:25 AM PDT #

I should have said you will need a different datasource per user if you want the data tables separate

Posted by carol mcdonald on November 03, 2007 at 09:08 AM PDT #

With the contributions of the expert group, the JavaServer Faces APIs are being designed so that they can be leveraged by tools that will make web application development even easier. Several respected tools vendors were members of the JSR-314 expert group, which developed the JavaServer Faces 2.0 specification.

Posted by l-carnitin on December 05, 2009 at 02:30 PM PST #

Post a Comment:
Comments are closed for this entry.
About

edort

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today