 |
Community: Java Enterprise Archives
speaking at Community One
Posted by caroljmcdonald on April 19, 2008 at 11:16 AM | Permalink
| Comments (5)
Speaking at CommunityOne 2008
Kito Mann and I are
speaking at CommunityOne
2008 on: "Examining
a Sample Application Built in Three Ways: Java™ Platform, Enterprise
Edition (Java EE Platform), Spring 2.5, and Seam 2.0 Deployed on the
GlassFish™ Project". CommunityOne is the day before JavaOne (May
05), its free, and you can learn about a wide range of open source
projects.
Our talk is May 05 12:25 - 13:20 Moscone South -
Esplanade 305. Here is the abstract:
This session looks at the implementation of the same web application
developed with three open source frameworks and highlights what was
done differently with each one. First it explains the implementation of
the sample application with JavaServer™ Faces and Enterprise JavaBeans™
3.0 (EJB™ 3.0) technology and the Java™ Persistence API (JPA). Next it
looks at how this application was developed with JavaServer Faces
technology, the JPA, and Spring 2.5. Finally, it looks at this
application developed with JavaServer Faces and EJB 3.0 technology, the
JPA, and Seam 2.0. The presentation highlights differences in the
frameworks, such as the Seam context model for stateful components. All
three versions were deployed on GlassFish™ project V2, and the source
code is available in my blog.
|
|
|
Sample Application using JSF, Seam 2.0, and Java Persistence APIs on Glassfish V2
Posted by caroljmcdonald on January 27, 2008 at 07:58 PM | Permalink
| Comments (11)
Sample Application using JSF, Seam 2.0,
and Java Persistence APIs on Glassfish V2
I updated this example Sample
Store Catalog app using JavaServer
Faces, EJB, the Java Persistence APIs, and
Seam 1.2 on Glassfish v1 to use Seam 2.0 on Glassfish V2. The
Seam jar files needed to run on Glassfish have changed in Seam 2.0,
(thanks to Cay
Horstmann for pointing out which Seam 2.0 jars are needed)
nothing else in the example needs changing. I also successfully
tested Brian
Leonard's Seam
Refresh example with the Seam 2.0 jars, listed below, on Glassfish
V2.
Download
the Seam Sample Application Code
Configuration of the Application
for Seam 2.0, JSF, JPA, running on Glassfish V2
First I recommend reading Brian Leonard's
blog Seam
Refresh . I will summarize and update
those steps here:
To Open and Test Run the seampagination Project:
- Use the Resolve Reference Problems dialog to map the ejb and web
modules to their
project, which are subdirectories beneath the seampagination
directory.
- After the references are resolved, right-click the seampagination
project and select Open Required Projects.
- Right-click
the seampagination-EJBModule and select Resolve
Reference
Problems:
- browse to the Seam lib directory and select jboss-seam.jar
and
select Open. This should resove the reference to the following jars:
jboss-seam.jar, hibernate.jar, hibernate-validator.jar,
hibernate-annotations.jar, hibernate-commons-annotations.jar,
javassist.jar, dom4j.jar, commons-logging.jar
- Right-click the seampagination-WebModule and select Resolve
Reference
Problems:
- Browse to the seampagination-ejb directory which is a
sub-directory below the seampagination directory and select Open
Project
Folder.
- Browse to the jboss-seam-ui.jar found in Seam lib
directory and select Open Project
Folder. This should resove the reference to the following jars:
jboss-seam-ui.jar and jboss-el.jar.
If you want to create your own Java EE
application using Seam 2.0 on Glassfish V2 with Netbeans from scratch
(read the steps in Brian Leonard's
blog Seam
Refresh but use the SEAM 2.0 jars listed here here):
- Use
Netbeans to create a new Enterprise Application
- Right-click the Libraries node of the EJBModule project , choose
Add Jar and add these jars:
- Seam \lib\jboss-seam.jar
- Seam \lib\hibernate.jar
- Seam \lib\hibernate-validator.jar
- Seam \lib\hibernate-annotations.jar
- Seam \lib\hibernate-commons-annotations.jar
- Seam \lib\javassist.jar
- Seam \lib\dom4j.jar
- Seam \lib\commons-logging.jar
- Right-click the Libraries node of the WebModule project ,
choose Add Jar and add these jars:
- your ejbModule
- Seam \lib\jboss-seam-ui.jar
- Seam \lib\jboss-el.jar
- create an empty seam.properties file in the
seampagination-EJBModule src\conf Folder.
- add the following phase listener to your faces-config.xml
file under webpages web-inf:
<lifecycle> <phase-listener> org.jboss.seam.jsf.SeamPhaseListener </phase-listener> </lifecycle>
- add the following context parameter
to your web.xml file
<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>
- add the following listener class to your
web.xml file
<listener> <listener-class> org.jboss.seam.servlet.SeamListener </listener-class> </listener>
- For any session EJB's referenced from the web, add EJB
references to your web.xml, for example:
<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>
- For any EJB's referenced from the web add a Seam
interceptor to
the EJB, for example :
@Interceptors({org.jboss.seam.ejb.SeamInterceptor.class})
References:
Sample Application using JSF, Spring 2.5, and Java Persistence APIs
Posted by caroljmcdonald on January 07, 2008 at 02:36 PM | Permalink
| Comments (19)
Sample Application using JSF, Spring 2.5, and Java Persistence APIs
with Netbeans 6 and Glassfish v2
I took this example Sample
Application using JSF, Spring 2.0, and Java Persistence APIs
and updated it to use the Spring 2.5 framework (which comes with
Netbeans 6) on Glassfish v2.
You can dowload the sample
code and a related presentation JavaServer
Faces, Java Persistence API, Java EE, Spring, Seam.
Explanation of the usage of JSF, Spring 2.5 , 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.
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:
(Note: Red
colors
are for Java EE
tags, annotations code, Blue for Spring
specific
and Green
for my code
or variables)
Code Sample from: List.jsp
|
<h:dataTable value='#{itemController.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 itemController
ManagedBean.
This ItemController ManagedBean items
property is defined as shown below:
Code Sample from: ItemController.java |
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
@Controller("itemController")
@Scope("session")
public class ItemController
{
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;
}
|
@Controller is a Spring 2.5
"stereotype" annotation, @Repository, @Service
and @Controller are role designations for a common
three-tier architecture (data access objects, services, and web
controllers). By
clearly indicating application roles, these stereotypes facilitate the
use of Spring AOP and post-processors for providing additional behavior
to the annotated objects based on those roles. The @Scope("session")
annotation binds a web-tier Spring-managed object to the specified
scope. The Spring 2.5 component scanning
functionality removes the need to define Web tier "controllers"
in the faces-config.xml. The following configuration is used to
trigger the
auto-detection of all web controllers:
| Code Sample from: applicationContext.xml |
<context:component-scan
base-package="sessionpagination"
/>
|
To integrate Spring with JSF configure the Spring
JSF 1.2 ELResolver that delegates to the Spring root WebApplicationContext,
resolving name references to Spring-defined beans. Configure this resolver in
your faces-config.xml file as follows:
| Code Sample from: faces-context.xml |
<application>
<el-resolver>
org.springframework.web.jsf.el.SpringBeanFacesELResolver
</el-resolver>
</application>
|
The ItemController
getItems()
method wraps a List of item objects, returned from the catalogService,
in a DataModel.
UIData,
the superclass of 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.
The Item
properties Name, Photo, and price are
displayed with the column
component:
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 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
to represent parts of the
table that are not repeated or updated. These include headers,
footers,
and captions.
The catalogService,
and its implementation CatalogDAO,
is defined as a Spring
bean in the Spring configuration resource file /WEB-INF/applicationContext.xml :
| Code Sample from: applicationContext.xml
|
<bean id="catalogService" class="service.CatalogDAO"/>
</beans>
|
The Spring root
WebApplicationContext will inject the catalogService
Spring Bean
into the catalogService
property
of the ItemController
JSF
ManagedBean :
Code Sample from: ItemController.java |
@Controller("itemController")
@Scope("session")
public class ItemController
{
private CatalogService catalogService ;
@Autowired
public void setCatalogService(CatalogService
catalogService) {
this.catalogService =
catalogService;
}
|
@Autowired is a
Spring 2.5
annotation that makes it possible to inject
dependencies that match by type. This behavior is enabled for
fields,
constructors, and methods. To enable this, add this to the
applicationContext.xml:
| Code Sample from: applicationContext.xml
|
<context:annotation-config/>
|
For more information on using JSF with Spring, see Spring
- Java/J2EE Application Framework Integrating with JavaServer Faces
.
Using the Java Persistence API (JPA) with Spring 2.5
The Spring bean CatalogDAO
uses the Java
Persistence API
EntityManager
Query object to return a list of items.
The CatalogDAO annotates the field private EntityManager em;
with @PersistenceContext
, which causes an entity manager to be
injected. (note that using the
@PersistenceContext annotation is the same
way an
Entity Manager is injected for a EJB
3.0 Session Bean.)
| Code Sample from: CatalogDAO.java |
@Repository
@Transactional
public class CatalogDAO
implements CatalogService
{
@PersistenceContext(unitName="PetCatalogPu")
private EntityManager
em;
@Transactional(readOnly =
true)
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 Java Persistence Query
APIs are used to create and execute queries that can return a
list of results. The JPA Query interface provides
support for pagination via the setFirstResult() and setMaxResults()
methods: q.setMaxResults(int maxResult)
sets the maximum number of results to retrieve. q.setFirstResult(int startPosition)
sets the position of the first result to retrieve.
In the code below, we show the 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:
- annotating the class with an @Entity
annotation.
- annotating the primary key identifier with @Id
Because the fields name, 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. The O/R relationships with 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 |
@Entity
public class Item
implements java.io.Serializable {
@Id
private String itemID;
private String name;
private String description;
private String imageurl;
private String imagethumburl;
private BigDecimal price;
@OneToOne(cascade={CascadeType.PERSIST})
private Address
address;
@ManyToOne
private Product
product;
public Item() { }
public String getItemID() {
return itemID;
}
public void setItemID(String itemID) {
this.itemID = itemID;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String
description) {
this.description = description;
}
public BigDecimal getPrice() {
return
price;
}
public void setPrice(BigDecimal price) {
this.price = price;
}
public void setAddress(Address address) {
this.address = address;
}
public Product getProduct() {
return product;
}
public void setProduct(Product product) {
this.product = product;
}
...
}
|
The ItemController
ManagedBean pages through the list of Items
by
maintaining the firstItem and batchSize attributes and passing these as
parameters to the CatalogService getItems(firstItem,
batchSize) method.
The ItemController's
<managed-bean-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 Catolog items
in the data base on the List.jsp page:
| Code Sample from: List.jsp |
<h:outputText
value="Item
#{itemController.firstItem +1} ..#{itemController.lastItem}
of #{itemController.itemCount}"/>
|
This ItemController
ItemCount property
is defined as shown below:
| Code Sample from: ItemController.java |
public int getItemCount()
{
int count = catalogService.getItemsCount();
return
count;
}
|
The ItemController
getItemCount()
method calls the CatalogService
interface to get
the count of the list of items. The CatalogDAO
Spring bean getItemCount()
method uses the JPA Query interface to get the count of
all items in the database item table:
Code Sample from: CatalogDAO.java |
@Repository
@Transactional
public class CatalogDAO
implements CatalogService
{
@PersistenceContext(unitName="PetCatalogPu")
private EntityManager
em;
. . .
@Transactional(readOnly = true)
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.
| Code Sample from: List.jsp |
<h:commandLink
action="#{itemController.next}"
value="Next
#{itemController.batchSize}"
rendered="#{itemController.lastItem + itemController.batchSize <=
itemController.itemCount}"/>
|
Continue Reading...
Sample Application using JSF, Seam, and Java Persistence APIs on Glassfish
Posted by caroljmcdonald on July 06, 2007 at 01:29 PM | Permalink
| 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 Application
The image below shows the Catalog Listing page, which allows a user to
page through a list of items
in a store.
DataTable JSF component
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: (Note: Red colors
are for Java EE
tags, annotations code, Blue for Seam specific
and Green
for my code
or variables)
Code Sample from: List.jsp |
<h:dataTable value='#{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
attribute
of the CatalogBean
class:
Code Sample from: CatalogBean.java |
@Stateful
@Scope(SESSION)
@Name("catalog")
@Interceptors({org.jboss.seam.ejb.SeamInterceptor.class})
public class CatalogBean
implements Serializable, Catalog {
@DataModel
private List<Item> items=null;
@Factory("items")
public void getItems() {
if ((items==null) ||
(index != firstItem) ){
getNextItems();
}
}
|
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 |
<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 the dataTable component.
While
the dataTable component is iterating over the rows of data, it
processes
the column component associated with each column tag for each row in
the table. As the dataTable
component iterates through the list, each reference to dataTableItem points to the current item in the
list.
The dataTable component iterates through the list of items and
displays the names, photos, and prices. Each
time the dataTable 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.
Java Persistence Query API
The 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
private List<Item> items=null;
@PersistenceContext(unitName="PetCatalogPu")
private EntityManager em;
private int batchSize =
10;
private int index = 0;
private int firstItem = 0;
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public void getNextItems()
{
Query q = em.createQuery("select
object(o) from Item as o");
q.setMaxResults(batchSize);
q.setFirstResult(firstItem);
items= q.getResultList();
index = firstItem;
}
|
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 Java Persistence Query
APIs are used to create and execute queries that can return a
list of results. The JPA Query interface provides
support for pagination via the setFirstResult() and setMaxResults()
methods: query.setMaxResults(int maxResult)
sets the maximum number of results to retrieve. query.setFirstResult(int startPosition)
sets the position of the first result to retrieve.
In the code below, we show the 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:
- annotating the class with an @Entity
annotation.
- annotating the primary key identifier with @Id
Because the fields name, 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. The O/R relationships with 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 |
@Entity
@Name("item")
@Scope(ScopeType.EVENT)
public class Item
implements java.io.Serializable {
@Id
private String itemID;
private String name;
private String description;
private String imageurl;
private String imagethumburl;
private BigDecimal price;
@OneToOne(cascade={CascadeType.PERSIST})
private Address address;
@ManyToOne
private Product product;
public Item() { }
public String getItemID() {
return itemID;
}
public void setItemID(String itemID) {
this.itemID = itemID;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String
description) {
this.description = description;
}
public BigDecimal getPrice() {
return
price;
}
public void setPrice(BigDecimal price) {
this.price = price;
}
public void setAddress(Address address) {
this.address = address;
}
public Product getProduct() {
return product;
}
public void setProduct(Product product) {
this.product = product;
}
...
}
|
The @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.
The 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.
The CatalogBean
itemCount
property is used to get and display
the number of Catologue items in the data base:
Code Sample from: List.jsp |
<h:outputText value="Item #{catalog.firstItem
+
1}..#{catalog.lastItem}
of
#{catalog.itemCount}"/>
|
The 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()
{
Query q = entityManager.createQuery("select
count(o) from Item as
o");
itemCount =
((Long)q.getSingleResult()).intValue();
return itemCount;
}
|
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.
Code Sample from: List.jsp |
<h:commandLink
action="#{catalog.next}"
value="Next
#{catalog.batchSize}"
rendered="#{catalog.lastItem + catalog.batchSize <=
catalog.itemCount}"/>
|
This 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() {
if (firstItem + batchSize
< getItemCount()) {
firstItem += batchSize;
getNextItems();
}
return "item_list";
}
|
The JavaServer Faces 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>
<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 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 |
<h:commandLink
action="#{catalog.prev}"
value="Previous
#{catalog.batchSize}"
rendered="#{catalog.firstItem >=catalog.batchSize}"/>
|
This CatalogBean
prev() method
is defined as shown
below:
Code Sample from: CatalogBean.java |
public String prev()
{
firstItem -= batchSize;
if (firstItem < 0) {
firstItem = 0;
}
getNextItems();
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 CatalogBean select()
method:
Code Sample from: List.jsp |
<h:column>
<f:facet name="header">
<h:outputText
value="Name"/>
</f:facet>
<h:commandLink
action="#{catalog.select}"
value="#{dataTableItem.name}"/>
</h:column>
|
With Seam if you use the @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
@Out(required=false)
private Item item;
public String select() {
return "item_detail";
}
|
The @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.
The 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
|
<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 item
properties:
Code Sample from: Detail.jsp |
<h:outputText
value="#{item.name}"
title="Name" />
<h:outputText value="#{item.description}"
title="Description"/>
<h:graphicImage url="#{item.imageurl}"
title="Imageurl" />
<h:outputText value="#{item.price}"
title="Price" />
<h:outputText value="#{item.address.city}"
title="Address" />
<h:outputText value="#{item.contactinfo.email}"
title="Address"/>
|
Conclusion
This concludes the sample application which demonstrates how to use Seam
with the JSF dataTable and DataModel to page through a
list
of Item Entities which are retrieved
using the
CatalogBean Stateful Session EJB methods
which use the
Java
Persistence APIs.
Configuration of the Application
for Seam, JSF, JPA, running on Glassfish
First I recommend reading and following the steps in Brian Leonard's
blog Seam
Refresh . I will summarize
those steps here:
- Download
and extract JBoss 4.2.0 GA
- Download
and install GlassFish V1, following the instructions on the download
page. Alternatively you can use Sun Java System Application Server PE
9, Sun's GlassFish distribution.
- Download
and extract Seam 1.2.1 GA
- Download
and install NetBeans 5.5.1
- Download
the Seam Sample Application Code
- install Glassfish and Netbeans 5.5.1. Then add the
glassfish application server to Netbeans.
To Open and Test Run the seampagination Project:
- Use the Resolve Reference Problems dialog to map the ejb and web
modules to their
project, which are subdirectories beneath the seampagination
directory.
- After the references are resolved, right-click the seampagination
project and select Open Required Projects.
- In Netbeans create a JBossSeam Library as documented in Seam
Refresh.
- Right-click the seampagination-EJBModule to resolve the
reference problems:
- browse to the server\default\deploy\jboss-web.deployer\jsf-libs
directory of your JBoss server installation, select jsf-api.jar and
select Open.
- browse to the Seam lib directory and select hibernate-all.jar
and thirdparty-all.jar, and
select Open.
- Right-click the Libraries node of the seampagination-EJBModule
project , choose Add Library and add the JBossSeam library you created.
- Right-click the seampagination-WebModule and select Resolve
Reference
Problems:
- Browse to the seampagination-ejb directory which is a
sub-directory below the seampagination directory and select Open
Project
Folder.
- Browse to the jboss-seam-ui.jar found in the root of
where you extracted the Seam framework and select Open Project
Folder.
If you want to create your own Java EE
application using Seam on Glassfish with Netbeans from scratch
(read the steps in Brian Leonard's
blog Seam
Refresh summarized here):
- In Netbeans create a JBossSeam Library as documented in Seam
Refresh.
- Use Netbeans to create a new Enterprise Application
- Right-click the Libraries node of the EJBModule project , choose
Add Library and add the JBossSeam library you created.
- Right-click the Libraries node of the EJBModule project , choose
Add Jar and add these jars:
- jboss
\server\default\deploy\jboss-web.deployer\jsf-libs\jsf-api.jar
- jboss
\server\default\deploy\jboss-web.deployer\jsf-libs\jsf-impl.jar
- Seam \lib\hibernate-all.jar
- Seam \lib\thirdparty-all.jar
- Right-click the Libraries node of the WebModule project ,
choose Add Jar and add these jars:
- your ejbModule
- Seam jboss-seam-ui.jar
- create an empty seam.properties file in the
seampagination-EJBModule src\conf Folder.
- add the following phase listener to your faces-config.xml
file under webpages web-inf:
<lifecycle> <phase-listener> org.jboss.seam.jsf.SeamPhaseListener </phase-listener> </lifecycle>
- add the following context parameter
to your web.xml file
<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>
- add the following listener class to your
web.xml file
<listener> <listener-class> org.jboss.seam.servlet.SeamListener </listener-class> </listener>
- For any session EJB's referenced from the web, add EJB
references to your web.xml, for example:
<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>
- For any EJB's referenced from the web add a Seam
interceptor to
the EJB, for example :
@Interceptors({org.jboss.seam.ejb.SeamInterceptor.class})
References:
Carol McDonald
Sample Application using JSF, Spring 2.0, and Java Persistence APIs
Posted by caroljmcdonald on June 19, 2007 at 12:53 PM | Permalink
| Comments (30)
Pagination of Data Sets in a Sample Application using JSF, Spring
2.0, and Java Persistence APIs on Glassfish
This Sample Store Catalog app demonstrates the usage of JavaServer
Faces, the new Java Persistence APIs, and Spring 2.0 to implement
pagination. I took this example Pagination
of Data Sets in a Sample Application using JSF, Catalog Facade
Stateless Session, and Java Persistence APIs and modified it
slightly to use a Spring Bean instead of a EJB 3.0 Stateless Session
Bean. If you compare the two, you will see that the code is
almost the same, the main difference is the extra xml configuration for
Spring, and for me it wasn't easy to get the .xml
configuration right. It took looking at several articles, blogs,
examples, and some trial and error to get it working. (see the
references at the end).
download the SpringJPA sample application code
Note: I updated the Spring JSF integration part of this
application to use the
org.springframework.web.jsf.DelegatingVariableResolver instead
of a JSF Managed Bean ServiceLocator in order to get a
reference to the CatalogService Spring
Bean from the Spring
application context.
Explanation of the usage of JSF, Spring 2.0 , 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.
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:
(Note: Red
colors
are for Java EE
tags, annotations code, Blue for Spring
specific
and Green
for my code
or variables)
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:
| Code Sample from: faces-context.xml |
<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>
|
This ItemController ManagedBean items
property is defined as shown below:
Code Sample from: ItemController.java |
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,
the superclass of 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.
The Item
properties Name, Photo, and price are
displayed with the column
component:
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 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
to represent parts of the
table that are not repeated or updated. These include headers,
footers,
and captions.
|