Skip to main content

Pagination of Data Sets in a Sample Application using JSF, Catalog Facade Stateless Session, and Java Persistence APIs

Posted by caroljmcdonald on May 31, 2007 at 3:46 PM PDT

This Sample Store Catalog app demonstrates the usage of JSF,
the new Java Persistence APIs, and a Stateless Session EJB to implement pagination in a Java EE 5 application




download sample code



target="bpcatalog">Sean
Brydon


target="bpcatalog">
Carol McDonald



Pagination using Java Persistence APIs 

The Java Persistence href="http://java.sun.com/javaee/5/docs/api/javax/persistence/Query.html">Query
APIs are used to create and execute queries that can return a
list of results.  The query APIs also have some methods that
you can use to specify the chuck of a list you desire, in particular:

  •  href="http://java.sun.com/javaee/5/docs/api/javax/persistence/Query.html"
    title="interface in javax.persistence">Query setMaxResults(int maxResult)

    Set the maximum number of results to retrieve.
  •  href="http://java.sun.com/javaee/5/docs/api/javax/persistence/Query.html"
    title="interface in javax.persistence">Query setFirstResult(int startPosition)

    Set the position of the first result to retrieve.



Lets consider an example, assume you have an Item.java object
that is a Java Persistence object entity and each item object
represents a row in the database. Lets assume the database is populated
with 100 items that have a productID="dog", and a client web
application wants to retrieve 10 items at a time. Lets look at some
code to use in this type of example.




cellpadding="2" cellspacing="0">
Code Sample: Method
showing usage of the setFirstResult and setMaxResults method
 public
List<Item> getItemsVLH(String pID, int start, int
chunkSize){

       
EntityManager em =
emf.createEntityManager();      

       
Query query =

         
em.createQuery("SELECT i FROM Item i WHERE i.productID = :pID");

        query = query.set
Parameter("pID",pID);

        query = query.
setFirstResult(start);

        query =
query.
setMaxResults(chunkSize);

       
List<Item>  items = query.getResultList();

       
em.close();

       
return items;

    }

     

     



The key line in code example 1 is 


List<Item>  items =
query.setParameter("pID",pID).setFirstResult(start).setMaxResults(chunkSize).getResultList();

 


which sets the query up and gets the results. Note the query.setFirstResult starts
counting at zero.  In this example, the client, maybe a JSP page
or Servlet, would need to keep track of the index position of the list
it is showing to the users. For example if it is showing the dogs from
index position 10 through 19 on its page and the user clicked the
"next" button then the JSP would have to submit the index position that
it desired 20 and the chunk size 10 to get the dogs at index positions
20 through 29. As you can see these APIs are easy to use and very
useful.



In code example 2 below, we show the
Item.java object. Notice this is just a
typical Java Persistence entity object, and we just show it here for
completeness of the example.



Now lets consider some design choices when using these APIs:

  • The
    Java Persistence APIs use lazy loading by default so you do not get a
    deep copy of the objects that are retrieved. For example, in the list
    of items, each Item contains all the data in the fields but does not
    contain the data in the relationships, such as the tags which are
    declared as 
    private Collection<Tag>
    tags=new Vector<Tag>();
     (see
    code example 2
    ).
    This is because of the performance implications of fetching a list of
    objects and all of the network of objects in their relationships. You
    can change the fetching to eager or if you want you can fetch the data
    in a relationship by calling the get method on that field on the
    managed object.

cellpadding="2" cellspacing="0">
Code Sample from: Item.java


@Entity

public class Item implements java.io.Serializable {

     

    private String itemID;

    private String productID;

    private String productID;

    private String name;

    private String description;

    private BigDecimal price;

    private Address address;

    private Collection<Tag>
tags=new Vector<Tag>();

    

    public Item() { }

   

    @Id

    public String getItemID() {

       
return itemID;

    }

    public String getProductID() {

       
return productID;

    }

    public String getProductID() {

       
return productID;

    }

    public String getName() {

       
return name;

    }   

    public String getDescription() {

       
return description;

    }

    public BigDecimal getPrice() {

       return
price;

    } 

    @OneToOne(cascade={CascadeType.PERSIST})

    public Address getAddress() {

       
return address;

    }

     
   
@ManyToMany(mappedBy = "items")

    public Collection<Tag>
getTags() {

       
return tags;

    }


    

    public void setItemID(String itemID) {

       
this.itemID = itemID;

   
}    

    public void setProductID(String
productID) {

       
this.productID = productID;

    }

    public void setName(String name) {

       
this.name = name;

    }

    public void setDescription(String
description) {

       
this.description = description;

    }

    public void setPrice(BigDecimal price) {

       
this.price = price;

    }

    public void setAddress(Address address) {

       
this.address = address;

    }

    public void
setTags(Collection<Tag> tags) {

       
this.tags=tags;

    }

    ... could add other business methods too

}   

     

     




Explanation of the usage of JSF, Catalog Facade Stateless
Session EJB , and Java Persistence APIs in a sample Store Catalog Application





The image below shows the Catalog Listing page, which allows a user to page through a list of items
in a store.



listpage.jpg




The List.jsp page uses a JSF dataTable component to display a list of
catalog items



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



In the List.jsp web page the dataTable is defined as shown below:


cellpadding="2" cellspacing="0">
Code Sample from:  List.jsp



<h:dataTable value='#{item.items}' var='dataTableItem' border="1"

      cellpadding="2" cellspacing="0">

     

     



The value attribute of a dataTable tag references the data to be included
in the table. The var attribute specifies a
name that is used by the components within the dataTable
tag as an alias to the data referenced in the value
attribute of dataTable.  In the dataTable tag from the List.jsp
page, the value attribute points to a list
of catalog items. The var attribute points
to a single item in that list. As the UIData
component iterates through the list, each reference to dataTableItem points to the current item in the
list.



The dataTable's value
is bound to the items property
of the item controller class, ItemController, which is defined in the
faces-config.xml file:


cellpadding="2" cellspacing="0">
Code Sample from: faces-context.xml


 <managed-bean>

    <managed-bean-name>item</managed-bean-name>

      <managed-bean-class>

        
com.sun.javaee.blueprints.sessionpagination.ItemController

      </managed-bean-class>

   
<managed-bean-scope>session</managed-bean-scope>

 </managed-bean>

     

     





This ItemController ManagedBean items
property is defined as shown below:


cellpadding="2" cellspacing="0">
Code Sample from: ItemController.java


      
@EJB private CatalogFacade
catalogfacade;

     

     
   public DataModel getItems()
{

       model = new
ListDataModel(catalogFacade.getItems( firstItem,batchSize));

       return
model;       

   }

     

     



The getItems() method wraps a List of items, returned from the
CatalogFacade Stateless Session EJB,  in a DataModel.

UIData, the superclass of dataTable, supports data binding to a
collection of data objects represented by a DataModel instance, which
is the current value of this component itself.  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.   



The Name, Photo, and Price item properties are displayed with the
column component:


cellpadding="2" cellspacing="0">
Code Sample from: List.jsp



  <h:column>

      <f:facet name="header">

          <h:outputText
value="Price"/>

      </f:facet>

      <h:outputText
value="#{dataTableItem.price}"/>

 
</h:column>

     

     



The column tags represent columns of data in a UIData component. While
the UIData component is iterating 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 names, photos, and prices. Each
time UIData iterates through the list of items, it renders one cell in
each column.



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





The ItemController ManagedBean uses dependency injection to lookup and
obtain a reference to the CatalogFacade Stateless Session EJB :


cellpadding="2" cellspacing="0">
Code Sample from: ItemController.java


@EJB private CatalogFacade catalogfacade;

     

     



The CatalogFacade Session EJB uses the Java Persistence API
EntityManager Query object to return a list of items.
The Catalog Facade uses dependency injection to lookup and obtain a
Container Managed EntityManager.
Since the EntityManager can be  container managed for EJB Session
Beans, the application does not
have to manage its lifecycle (i.e. call the
EntityManagerFactory.create() and EntityManager.close() methods).



cellpadding="2" cellspacing="0">
Code Sample from: CatalogFacadeBean.java
 

   @Stateless

   public class CatalogFacadeBean implements CatalogFacade {

   @PersistenceContext(unitName="PetCatalogPu")

   private EntityManager entityManager;

 

  
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)

   public List<Item>  getItems(int
firstItem,int batchSize) {      

       Query q =
entityManager.createQuery("select object(o) from Item as o");

       q.setMaxResults(batchSize);

       q.setFirstResult(firstItem);

       List<Item> items=
q.getResultList();

       return
items;      

   }

   

     



Since this query is used for Read-Only browsing, the transaction
attribute in this example is specified as NOT_SUPPORTED. Queries using
transaction-scoped entity managers outside of a transaction are
typically more efficient than queries inside a transaction when the
result type is an entity.  The JPA Query interface provides
support for pagination via the setFirstResult() and setMaxResults()
methods.



The ItemController ManagedBean pages through the list of items by
maintaining the firstItem and batchSize attributes and passing these as
parameters to the catalogFacade.getItems(firstItem, batchSize) method.
The ItemController's scope is defined as session, a JSF Managedbean
with session scope will be stored in the session meaning that the
bean's properties will stay alive for the life of the Http Session.





The ItemController itemCount property is  used to get and display
the number of Catologue items in the  data base:


cellpadding="2" cellspacing="0">
Code Sample from: List.jsp


<h:outputText value="Item #{item.firstItem + 1}..#{item.lastItem} of

    
#{item.itemCount}"/>

     

     



This ItemController property is defined as shown below:


cellpadding="2" cellspacing="0">
Code Sample from: ItemController.java


    public int getItemCount()
{      

        int count =
catalogFacade.getItemsCount();

        return
count;     

    }

     



The ItemController getItemCount() method calls the CatalogFacade to get
the count of the list of items. The Catalog Facade Session EJB
getItemCount() method uses the JPA Query interface to get the count of
all items in the database item table:


cellpadding="2" cellspacing="0">
Code Sample from: CatalogFacadeBean.java


    public int getItemCount() {

        Query q =
entityManager.createQuery("select count(o) from Item as
o");     

        int count =
((Long)q.getSingleResult()).intValue();     

        return count;

    }   

    

     



A JSF commandLink is  used to provide a link to click on to
display the next page of items. The commandLink
tag represents an HTML hyperlink and is rendered as an HTML <a> element. The commandLink
tag is used to submit an action event to the application. 


cellpadding="2" cellspacing="0">
Code Sample from: List.jsp


 <h:commandLink action="#{item.next}" value="Next
#{item.batchSize}"

   
rendered="#{item.lastItem + item.batchSize <=
item.itemCount}"/>   

     



This commandLink action attribute
references an ItemController backing bean next() method that calculates
the
next page's first row number  and returns a logical outcome
String, which causes the List page to display the next page's
list .
This ItemController next method is defined as shown below:


cellpadding="2" cellspacing="0">
Code Sample from: ItemController.java


   public String next() {

       if (firstItem + batchSize
< getItemCount()) {

          
firstItem += batchSize;

       }

       return "item_list";

   }

     



The JavaServer Faces NavigationHandler
matches the logical outcome,  item_list
against the navigation rules in the application configuration resource
file to determine which page to access next. In this case, the
JavaServer Faces implementation loads the List.jsp
page after this method returns.


cellpadding="2" cellspacing="0">
Code Sample from: faces-config.xml


  <navigation-rule>

      <navigation-case>

         
<from-outcome>item_list</from-outcome>

         
<to-view-id>/item/List.jsp</to-view-id>

      </navigation-case>

  </navigation-rule>

     

     



A JSF commandLink is  used to provide a link to click on to
display the previous page of items. This

commandLink
action
attribute 
references the  ItemController  prev() method that calculates the
previous page's first row number  and returns a logical outcome
String, which causes the List page to display the previous page of
items :


cellpadding="2" cellspacing="0">
Code Sample from: List.jsp


 <h:commandLink action="#{item.prev}" value="Previous
#{item.batchSize}"        

       
rendered="#{item.firstItem >=item.batchSize}"/>

     

     



 This ItemController previous() method  is defined as shown
below: 

 

cellpadding="2" cellspacing="0">
Code Sample from: ItemController.java


    public String prev()
{

        firstItem -= batchSize;

        if (firstItem < 0) {

           
firstItem = 0;

        }

        return "item_list";

    }     

     



A JSF commandLink is  used to provide a link to click on to
display a page with the item details. This

commandLink
action
attribute 
references The ItemController detailSetup() method:


cellpadding="2" cellspacing="0">
Code Sample from: List.jsp


   <h:column>

       <f:facet name="header">

          <h:outputText
value="Name"/>

       </f:facet>

       <h:commandLink action="#{item.detailSetup}"
value="#{dataTableItem.name}"/>   

   </h:column>

     



The item.detailSetup () method  gets the Item data from the
current row of the dataModel, and returns a string which causes the
Detail.jsp page to display
the item details :


cellpadding="2" cellspacing="0">
Code Sample from: ItemController.java


    public String detailSetup() {

        item = (Item)
model.getRowData();

        return "item_detail";

    }

     



The JavaServer Faces NavigationHandler
matches the logical outcome,  item_detail
against the navigation rules in the application configuration resource
file to determine which page to access next. In this case, the
JavaServer Faces implementation loads the Detail.jsp
page after this method returns.


cellpadding="2" cellspacing="0">
Code Sample from: faces-config.xml
 

    <navigation-rule>

        <navigation-case>

           
<from-outcome>item_detail</from-outcome>

           
<to-view-id>/item/Detail.jsp</to-view-id>

        </navigation-case>

    </navigation-rule>
   


   



The Detail.jsp uses the outputText component to display the
ItemController ManagedBean's item properties:


cellpadding="2" cellspacing="0">
Code Sample from: detail.jsp
 

   
<h:outputText value="#{item.item.name}" title="Name" />

   
<h:outputText value="#{item.item.description}"
title="Description"/>

   
<h:graphicImage url="#{item.item.imageurl}" title="Imageurl" />

   
<h:outputText value="#{item.item.price}" title="Price" />

   
<h:outputText value="#{item.item.address.city}" title="Address" />

   
<h:outputText value="#{item.item.contactinfo.email}"
title="Address"/>
 




   
detailpage.jpg






Conclusion

This concludes the sample application which demonstrates how to work
with the JSF dataTable and  DataModel  to page through a list
of  Item Entities which are retrieved using  the
CatalogFacade Stateless Session  EJB methods which use  the
Java
Persistence API.


References

Here are some references to consider:



Related Topics >>

Comments

Hi Carol, is it possible to get the code some how? The ...

Hi Carol,

is it possible to get the code some how? The link is broken!
Thanks

Pagination of Data Sets in a

I try download sample code, but I am redirect to pages "ERROR. Your account does not have the "Project Document - View" permission needed for you to access the page you requested in the techdayscode project "
How I can get permission for download?

I have the same problem. Where can I get the code?

hzapata wrote:

I try download sample code, but I am redirect to pages "ERROR. Your account does not have the "Project Document - View" permission needed for you to access the page you requested in the techdayscode project "

How I can get permission for download?

I&nbsp;think the project that had the source code has been ...

I think the project that had the source code has been deleted. I will try to find it