|
|
|||||||||||||||||||||||||||||||||||||||||||||||||||
Carol McDonald's Blog
«dojo 1.0 Presentation slides and Sample code |
Main
| Sample Application using JSF, Seam 2.0, and Java Persistence APIs on Glassfish V2 »
Sample Application using JSF, Spring 2.5, and Java Persistence APIsPosted by caroljmcdonald on January 07, 2008 at 02:36 PM | Comments (19)Sample Application using JSF, Spring 2.5, and Java Persistence APIs
with Netbeans 6 and Glassfish v2
| |||||||||||||||||||||||||||||||||||||||||||||||||||
| Code Sample from: List.jsp |
<h:dataTable value='#{itemController.items}' var='dataTableItem' |
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.value
is bound to the items
property
of the itemController
ManagedBean.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")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"
/> |
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> |
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. Item
properties Name, Photo, and price are
displayed with the column
component:| Code Sample from: List.jsp |
|
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.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.facet
to represent parts of the
table that are not repeated or updated. These include headers,
footers,
and captions. 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 |
|
catalogService
Spring Bean
into the catalogService
property
of the ItemController
JSF
ManagedBean : Code Sample from: ItemController.java |
@Controller("itemController") |
@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 |
|
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 |
|
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.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() { |
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.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 |
itemController.firstItem +1} ..#{itemController.lastItem}
of #{itemController.itemCount}"/> |
ItemController
ItemCount property
is defined as shown below:| Code Sample from: ItemController.java |
|
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 |
@Repositorypublic class CatalogDAO
implements CatalogService
{
@PersistenceContext(unitName="PetCatalogPu"). . . @Transactional(readOnly = true) public int getItemCount()
{ |
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 |
itemController.next}"
value="Next
#{itemController.batchSize}" |
commandLink action
attribute
references the ItemController
backing bean next()
method which calculates
the
next page's first row number and returns a logical outcome
String, which causes the List.jsp page
to display the next page's
list .
The ItemController
next
method is defined as shown below:Code Sample from: ItemController.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>item_list</from-outcome> |
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 :| Code Sample from: List.jsp |
itemController.prev}"
value="Previous
#{itemController.batchSize}"
|
ItemController
prev()
method is defined as shown
below: Code Sample from: ItemController.java |
public String prev()
{item_list"; |
ommandLink
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:| Code Sample from: List.jsp |
itemController.detailSetup}"
value="#{dataTableItem.name}"/> |
ItemController
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 :Code Sample from: ItemController.java
|
|
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.| Code Sample from: faces-config.xml |
|
outputText
component to display the ItemController
ManagedBean's item
properties:| Code Sample from: detail.jsp |
Controller.item.address.city}"
title="Address" />Controller.item.contactinfo.email}"
title="Address"/>
|
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.
Set up the Development Environment: (these directions are also here with screenshots)
<sample_install_dir>/SpringJPA/setup/sql/javadb/catalog.sql,
Open and Run the Sample code:
<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.SpringJPA directory you just unzipped. SpringJPA node in the Projects
window.SpringJPA node in the Projects
window.When you run the project, your browser should display the opening page of the JSF, Java Persistence API, and Spring 2.5 Sample Application (at http://localhost:8080/SpringJPA/).
Creating your own Netbeans Project with Spring 2.5 & Glassfish :
| Code Sample from: applicationContext.xml |
<?xml
version="1.0" encoding="UTF-8"?><bean id="catalogService"
class="service.CatalogDAO"/>
|
| Code Sample from: web.xml |
|
SpringBeanFacesELResolver to
the faces-config.xml :
| Code Sample from: faces-config.xml |
<application> |
For additional information see:
Could you please point out which Spring 2.5 features you used and where you used them?
Regards.
Posted by: dxxvi on January 08, 2008 at 06:36 AM
The main changes I made in this app between Spring 2.0 and Spring 2.5 was to use the @Autowired annotation to inject the CatalogService into the ItemController. Other changes were in the applicationContext.xml to update for changes from Spring 2.0 to Spring 2.5.
Posted by: caroljmcdonald on January 08, 2008 at 08:50 AM
Hi Carol,
Can you do a similar example using (JPOX)? Thanks
Posted by: paksegu on January 08, 2008 at 02:14 PM
The focus of this series of blogs was to show the same app build using first just Java EE , then Java EE with Spring , then Java EE with Seam (with Netbeans and Glassfish). I also did the same app using JRuby and Rails. I don't think I will have time to do this using JPOX. I want to also show groovy and grails in the future.
Posted by: caroljmcdonald on January 08, 2008 at 03:29 PM
Hi Carol and thanks for the article.
Just to mention two things about JSF and Spring 2.5 integration:
*1* Spring 2.5 (finally) provides a JSF 1.2 compliant EL Resolver (the old one is JSF 1.1 compliant I think, but certainly not with 1.2). In the faces-config.xml, one should use:
<application>
<el-resolver>
org.springframework.web.jsf.el.SpringBeanFacesELResolver
</el-resolver>
</application>
instead of the old:
<application>
<variable-resolver>
org.springframework.web.jsf.DelegatingVariableResolver
</variable-resolver>
</application>
*2* And now this is really fun ! you can get Spring to manage the JSF managed-beans instead of the JSF implementation, hence enabling a first class citizen acces to Spring functionalities within a JSF managed bean. You can even drop declaring these beans in faces-config.xml (and applicationContext.xml).
To do so, one have to:
As you did, annotate his controller with the @Controller annotation, optionally providing a name (String) under which the bean will be exposed to the JSF pages.
Optionally, add a @Scope annotation to specify the ... well, you should have guessed: @Scope("session"), @Scope("request"), etc.
But you have to add Spring's RequestContextListener to web.xml in order to get the Scope control working.
Add those two lines in applicationContext.xml (you did so for the first):
<context:annotation-config />
<context:component-scan base-package="foo.bar" />
where foo.bar is the package where you controllers classes lie.
That's it ! you can now use those beans in the JSF pages or anywhere else (within the Spring container naturally). You can also use the @Autowired annotation on these beans, etc.
Anyway, I've talked about this point in my blog (in french).
Regards,
djo.mos
Posted by: djomos on January 08, 2008 at 06:18 PM
Oui m'dame :-)
Je le sais, vous ĂȘtre membre dans nos forums (developpez.com).
Posted by: djomos on January 09, 2008 at 06:14 AM
Hi Again.
Just to mention that with the release of Spring 2.5.1 yesterday, Spring introduced two new Resolvers for JSF 1.2:
DelegatingFacesELResolver
WebApplicationContextFacesELResolver
Which acts as the old DelegatingVariableResolver for JSF 1.1.
It's a bit blurred to be honest, and I definitely have to go back to Spring Reference and sort this out.
Regards.
Posted by: djomos on January 10, 2008 at 01:44 AM
Still getting the java.lang.RuntimeException: java.lang.RuntimeException: javax.naming.NameNotFoundException
My theory is that the jdbc/PETCatalogDB is not being created. In your setup.xml file I see the following a 'create-resource-local" that looks like it would create this JNDI.
How do I create the JNDI jdbc/PETCatalogDB from the jdbc:derby://localhost:1527/pet-catalog connection?
Posted by: andreakendall on January 10, 2008 at 07:10 PM
I got it to work.
However I am not sure that the way I got this to work follows best practices.
What I ended up doing was
Creating a new JDBC pool, PETCatalogPool
Creating a new JDBC connection, jdbc/PETCatalogDB
adding spring-framework-2.5\lib\aspectj to the Spring library
Posted by: andreakendall on January 10, 2008 at 08:04 PM
So, how would some one do this in a real application where you would not want to have these pools and connections defined with your application?
Is there some other tool that you would use to define the Pool and the JDBC connection?
Posted by: andreakendall on January 10, 2008 at 08:06 PM
Correction I added aspectjweaver.jar to the Spring library not aspectj
Posted by: andreakendall on January 11, 2008 at 09:57 AM
I added instructions on how to define a connection pool and jdbc resource using the Glassfish Admin console.
Posted by: caroljmcdonald on January 15, 2008 at 04:37 PM
Hi Carol,,
After intergrating Spring, JSF1.2 (web 2.4 or, web 2.5), everything worked fine except that there was a simple problem.
If I use JSTL's tag for conditional checking, it does not seem to work at all. Have you faced this problem before? Could you just update this article slightly by adding a simple JSTL tag in your jsp page so that we have some idea about how to get JSTL tags work in sync with JSF1.2?
Thanks,
.... Chisty
Posted by: mchisty on March 31, 2008 at 12:06 AM
Hi,
Regarding my previous post, here is some code portion:
The following code demonstrates this:<f:view><h:form><h:dataTable value="#{userAction.usersList}" var="dataUser" border="1">
<h:column><f:facet name="header"><h:outputText value="Name" /></f:facet><h:commandLink action="#{userAction.viewUserDetail}" value="#{dataUser.name}" /></h:column>
<h:column><f:facet name="header"><h:outputText value="Is Enabled?" /></f:facet><h:outputText value="#{dataUser.active}" /></h:column>
<h:column><f:facet name="header"><h:outputText value="Status" /></f:facet>
<!-- PLEASE NOTE THE FOLLOWING JSTL CONDITION CHECKING --><c:choose><c:when test="${dataUser.active=='true'}">Process_Finished</c:when><c:otherwise>Show_something_else</c:otherwise></c:choose></h:column>
</h:dataTable></h:form></f:view>
The output shown is like this (which is WRONG):Name Email Address Is Enabled? Status
a a aaaa true Show_something_elseb b bbbb false Show_something_else
Whereas the correct output should be like this (the CORRECT form):
Name Email Address Is Enabled? Status
a a aaaa true Process_Finished
b b bbbb false Show_something_else
NOTE: Even if I do the condition checking like this:
test="${dataUser.active==true}" or, test="${dataUser.active}", it does not work
either. Interestingly it is showing the Boolean value correctly in the 4th column
'Is Enabled'. What might be wrong? Any suggestion?
Posted by: mchisty on March 31, 2008 at 12:34 AM
Hi Carol,
How the Spring DataAccessExceptions propagated are handled in your JSF controller/JSP pages?
Posted by: johnnyren on April 02, 2008 at 06:58 PM
if you nest non-JSF tags within JSF tags, you must wrap the non-JSF tags in f:verbatim; if you dynamically include JSP pages that contain JSF content, you must use f:subview and also wrap all included non-JSF content in f:verbatim.
Posted by: caroljmcdonald on April 02, 2008 at 07:48 PM
Hmmm, checked with <f:verbatim/> too (with the following code). But still not working.
Still shows the same output. This is surprising!! Is it possible for you to
provide an example?
<f:verbatim>
<c:choose>
<c:when test="${dataUser.active==true}">Process Finished</c:when>
<c:otherwise>Enable or Disable</c:otherwise>
</c:choose>
</f:verbatim>
Thanks,
... Chisty
Posted by: mchisty on April 03, 2008 at 03:36 AM
|
|