|
|
|||||||||||||||||||||||||||||||||
Carol McDonald's Blog
«Sample Application using JSF, Spring 2.0, and Java Persistence APIs |
Main
| Sample Application using JAX-WS, JSF, EJB 3.0, and Java »
Sample Application using JSF, Seam, and Java Persistence APIs on GlassfishPosted by caroljmcdonald on July 06, 2007 at 01:29 PM | Comments (10)This Sample Store Catalog app demonstrates the usage of JavaServer Faces, a Catalog Stateful Session Bean, the Java Persistence APIs, and Seam to implement pagination of data sets. I took this example Pagination of Data Sets in a Sample Application using JSF, Catalog Facade Stateless Session, and Java Persistence APIs and refactored it to use Seam on Glassfish by following the steps in Brian Leonards blog Seam Refresh and the clickable list example in the Seam Tutorial. Download the Seam Sample Application Code Explanation of the usage of JSF, Seam, and Java Persistence APIs in a sample Store Catalog ApplicationThe image below shows the Catalog Listing page, which allows a user to page through a list of items in a store.![]() DataTable JSF componentThe List.jsp page uses a JSFdataTable
component to display a list of
catalog itemsThe 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: (Note: Red colors
are for Java EE
tags, annotations code, Blue for Seam specific
and Green
for my code
or variables)
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
attribute
of the CatalogBean
class:
The @DataModel
Seam annotation exposes an attribute of type java.util.List to a JSF
page as an instance of javax.faces.model.DataModel.
The
<h:dataTable> 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. In this case, the DataModel is made available
in a session
context variable named items.When the List.jsp page is diplayed it will try to resolve the items context variable. Since this context variable is not initialized, Seam will call the factory method getItems(), which performs a JPA query (see getNextItems() code below)
and results in a DataModel being outjected. The @Name Seam
annotation specifies catalog as
the application unique component name which Seam will use to resolve
references to the catalog
context variable. Seam will instantiate the
component
and bind a new instance to the context variable the first time JSF
encounters the variable name catalog.
The instance will be bound to the
context specified by the @Scope
Seam annotation. The CatalogBean
is a org.jboss.seam.ScopeType.SESSION
scoped component.The @Stateful EJB 3.0
annotation marks this as a Stateful EJB. A Stateful EJB is used because
the current chunk of items, and
the user's position in the count of items in the db table, is
maintained for the user's session.The @Interceptors EJB
3.0 annotation registers the SeamInterceptor.class as
an EJB interceptor for this session bean component.The Seam framework uses EJB interceptors to perform bijection, context demarcation, validation, etc, (the interceptor could be defined in the ejb-jar.xml instead).
Column JSF component
On the List.jsp page the Item Name, Photo, and Price properties
are displayed with the
column component: | |||||||||||||||||||||||||||||||||
Code Sample from: List.jsp |
|
dataTableItem points to the current item in the
list.CatalogBean
Session EJB uses the Java Persistence API Query object
to return a list of items.
With the @PersistenceContext annotation
the CatalogBean 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).
Code Sample from: CatalogBean.java |
@DataModel @PersistenceContext(unitName="PetCatalogPu") |
Item
entity class which maps to the ITEM table that stores the
item instances. This is a
typical Java Persistence entity object. There are two requirements for
an entity:Address
and Product
are also annotated. For more information on
defining JPA entities see Pro
EJB 3: Java Persistence API book.Code Sample from: Item.java |
@Id
@ManyToOne public String getName() { public BigDecimal getPrice() { |
@Name
seam annotation specifies the (application unique) component name item,
which is used in
the Detail.jsp to display the selected item's
attributes. The @Scope
Seam annotation binds the item
instance to the org.jboss.seam.ScopeType.EVENT
context.CatalogBean
pages through the list of items
by
maintaining the firstItem
and batchSize
attributes and passing these as
parameters to the query.setFirstResult(int startPosition), query.setMaxResults(int maxResult)
methods.
The CatalogBean's scope is defined as org.jboss.seam.ScopeType.SESSION,
which corresponds to the JSF managed bean session scope.CatalogBean
itemCount
property is used to get and display
the number of Catologue items in the data base:Code Sample from: List.jsp |
|
CatalogBean
getItemCount()
method uses the JPA javax.persistence.Query
interface to get the count of
all items in the database item table:Code Sample from: CatalogBean.java |
private int itemCount = 0; public int getItemCount()
{itemCount =
((Long)q.getSingleResult()).intValue(); itemCount; |
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. Code Sample from: List.jsp |
|
commandLink action attribute
references the CatalogBean 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 CatalogBean
next()
method is defined as shown below:Code Sample from: CatalogBean.java |
public String next() { |
NavigationHandler
matches the logical outcome, item_list
against the navigation rules
in the application configuration resource
file faces-config.xml to
determine which page to access next. In this case, the
JavaServer Faces implementation loads the List.jsp
page after this method returns.| Code Sample from: faces-config.xml |
<navigation-rule> |
commandLink
is used to provide a link to click on to
display the previous page of items. This commandLink
action attribute
references the CatalogBean's
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 :Code Sample from: List.jsp |
|
CatalogBean
prev() method
is defined as shown
below: Code Sample from: CatalogBean.java |
public String prev()
{ |
commandLink
action attribute
references the CatalogBean select()
method:Code Sample from: List.jsp |
|
@DataModelSelection with the @DataModel
annotation, when the user clicks on the link, Seam will propagate the
selected row from the DataModel into the
annotated attribute:Code Sample from: CatalogBean.java
|
|
@DataModelSelection
Seam annotation tells Seam to inject the DataModel
List
element corresponding to the clicked link into the item attribute.
The @Out
Seam annotation transfers the value of this attribute to the item
event context
variable, making it available to a
JSP page after the action
catalog.select
method execution. So when a row of the
dataTable is selected, the
selected row
is injected to the item
attribute of the CatalogBean Stateful bean, and then
outjected to the event context
variable named item
which is used in the Detail.jsp page to display
the item details. CatalogBean
select() returns a string, "item_detail", which
causes the Detail.jsp page to display
the item details. The JavaServer Faces NavigationHandler
matches the logical outcome, item_detail
against the navigation rules in the application configuration resource
file faces-config.xml to determine which page to
access next. In this case, the
JavaServer Faces implementation loads the Detail.jsp
page after this method returns.| Code Sample from: faces-config.xml |
|
outputText
component to display the item
properties:Code Sample from: Detail.jsp |
item.description}"
title="Description"/> |
<lifecycle>
<phase-listener>
org.jboss.seam.jsf.SeamPhaseListener
</phase-listener>
</lifecycle>
<context-param>
<param-name>
org.jboss.seam.core.init.jndiPattern
</param-name>
<param-value>
java:comp/env/your ear name/#{ejbName}/local
</param-value>
</context-param>
<listener>
<listener-class>
org.jboss.seam.servlet.SeamListener
</listener-class>
</listener>
<ejb-local-ref>
<ejb-ref-name>your ear name/CatalogBean/local</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<local-home/>
<local>your package name.Catalog</local>
<ejb-link>CatalogBean</ejb-link>
</ejb-local-ref>
@Interceptors({org.jboss.seam.ejb.SeamInterceptor.class})Nice write-up. I have just begun using Seam a couple of months back on JBoss AS. You've written a good summary for deployment to Glassfish.
Posted by: javajuneau001 on July 09, 2007 at 09:56 AM
Hi carol,
I'm just wondering whether you have managed to get jbpm to work with seam. Currently I am stuck with it as glassfish can not read the jbpm process definitions where ever I place it. Perhaps this is due to my knowledge shortage of glassfish.
Regards
Posted by: thejavafreak on July 11, 2007 at 12:00 AM
Hi, no, I haven't tried jbpm yet. Did you try adding this librairy to your project: jboss-seam\lib\jbpm-3.1.4.jar ?
Posted by: caroljmcdonald on July 11, 2007 at 05:04 AM
Nice work !
Thanks for taking the time to write this kind of tutorial.
This is a good example to see how the clickable list works in SEAM.
However, it seems to me there's quite a difficult point with seam when you have to handle with some "recursive" data models.
PetStore Example : you can display a category List (dogs, cats, parrots, or even devloppers :-) ) with the technique you present, then you may want to display a list of items belonging to that category (as you've just done) when clicking on a category.
How do you think one can handle that case ? Which is the design we can use. One bean per List (datamodel) with eager persistence fetch ?
Have you ever tried to do that
Regards
Posted by: dazzx on July 23, 2007 at 02:52 AM
Thanks! No I haven't yet coded a clickable category list which when clicked would display the corresponding category items. I think I would add a DataModel for the category list and when a category was selected I would then fetch the corresponding item list chunk as a DataModel .
Posted by: caroljmcdonald on July 23, 2007 at 07:28 AM
Very nice article indeed.
I really liked the use of different colors (associated with different technologies)
Keep up doing the good work!
Posted by: lucduponcheel on August 08, 2007 at 03:02 AM
Nicely written Carol, very useful information. I do have a question though. What if you wanted to use a service infrastructure instead of EJB(s) here how would that impact what you've done here?
Posted by: jtryon on August 08, 2007 at 06:45 AM
Seam takes advantage of EJB 3 Session beans. If you want to see an example without EJB 3, I also wrote this same application using Spring, see my previous blog example. Also in Netbeans 5.5 if you right click on the project node , select new file/ persistence , generate JSF pages from entity classes , netbeans will generate jsf pages and a controller backing bean which performs the JPA query services without using EJBs. You can see an example of this in this hands on lab:
http://www.javapassion.com/j2ee/#Java_EE_5__EJB_3.0
Posted by: caroljmcdonald on August 10, 2007 at 09:02 AM
Thanks for the great article Carol. Just one question in regards to this statement:
For any EJB's referenced from the web add a Seam interceptor to the EJB, for example:
@Interceptors({org.jboss.seam.ejb.SeamInterceptor.class})
What is the fully qualified name of the "Interceptors" annotation? There are two that I find in Eclipse:
javax.interceptors.Interceptors
org.jboss.seam.annotations.Interceptors
Thanks!
Posted by: khatchad on August 16, 2007 at 01:02 PM
use
import javax.interceptors.Interceptors;
See also: EJB 3.0 Interceptors
Marc
Posted by: mdzaebel on March 24, 2008 at 04:14 AM
|
|