ThisSampleStoreCatalogappdemonstratestheusageofJavaServerFaces,thenewJavaPersistenceAPIs,andSpring2.0toimplementpagination.Itookthisexample
PaginationofDataSetsinaSampleApplicationusingJSF,CatalogFacadeStatelessSession,andJavaPersistenceAPIsandmodifieditslightlytouseaSpringBeaninsteadofaEJB3.0StatelessSessionBean.Ifyoucomparethetwo,youwillseethatthecodeisalmostthesame,themaindifferenceistheextraxmlconfigurationforSpring,andformeitwasn'teasytogetthe.xmlconfigurationright.Ittooklookingatseveralarticles,blogs,examples,andsometrialanderrortogetitworking.(seethereferencesattheend).downloadtheSpringJPAsampleapplicationcodeNote:IupdatedtheSpringJSFintegrationpartofthisapplicationtousetheorg.springframework.web.jsf.DelegatingVariableResolverinsteadofaJSFManagedBeanServiceLocatorinordertogetareferencetotheCatalogServiceSpringBeanfromtheSpringapplicationcontext.ExplanationoftheusageofJSF,Spring2.0,andJavaPersistenceAPIsinasampleStoreCatalogApplication
TheimagebelowshowstheCatalogListingpage,whichallowsausertopagethroughalistofitemsinastore.TheList.jsppageusesaJSFdataTable
componenttodisplayalistofcatalogitemsThedataTablecomponentisusefulwhenyouwanttoshowasetofresultsinatable.InaJavaServerFacesapplication,theUIData
component(thesuperclassofdataTable)supportsbindingtoacollectionofdataobjects.Itdoestheworkofiteratingovereachrecordinthedatasource.TheHTMLdataTable
rendererdisplaysthedataasanHTMLtable.IntheList.jspwebpagethedataTableisdefinedasshownbelow:(Note:RedcolorsareforJavaEEtags,annotationscode,BlueforSpringspecificandGreenformycodeorvariables)CodeSamplefrom:List.jsp |
<h:dataTablevalue='#{item.items}'var='dataTableItem'border="1"cellpadding="2"cellspacing="0"> |
Thevalue
attributeofadataTable
tagreferencesthedatatobeincludedinthetable.Thevar
attributespecifiesanamethatisusedbythecomponentswithinthedataTable
tagasanaliastothedatareferencedinthevalue
attributeofdataTable
.InthedataTable
tagfromtheList.jsp
page,thevalue
attributepointstoalistofcatalogitems.Thevar
attributepointstoasingleiteminthatlist.AstheUIData
componentiteratesthroughthelist,eachreferencetodataTableItem
pointstothecurrentiteminthelist.ThedataTable'svalue
isboundtotheitems
propertyoftheitem
controllerclass,ItemController
,whichisdefinedinthefaces-config.xmlfile:CodeSamplefrom: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> |
ThisItemController
ManagedBeanitems
propertyisdefinedasshownbelow:CodeSamplefrom:ItemController .java |
publicDataModelgetItems(){if(model==null||index!=firstItem){model=getNextItems();}returnthis.model;}publicDataModelgetNextItems(){model=newListDataModel(catalogService.getItems(firstItem,batchSize));index=firstItem;returnthis.model;} |
ThegetItems()methodwrapsaListofitemobjects,returnedfromthecatalogService,inaDataModel.UIData
,thesuperclassofdataTable
,supportsdatabindingtoacollectionofdataobjectsrepresentedbyaDataModelinstance.ThedatacollectionunderlyingaDataModelinstanceismodeledasacollectionofrowobjectsthatcanbeaccessedbyarowindex.TheAPIsprovidemechanismstopositiontoaspecifiedrowindex,andtoretrieveanobjectthatrepresentsthedatathatcorrespondstothecurrentrowindex.TheItem
propertiesName,Photo,andprice
aredisplayedwiththecolumn
component:CodeSamplefrom:List.jsp |
<h:column><f:facetname="header"><h:outputTextvalue="Price"/></f:facet><h:outputTextvalue="#{dataTableItem.price}"/></h:column> |
Thecolumn
tagsrepresentcolumnsofdatainaUIData
component.WhiletheUIDatacomponentisiteratingovertherowsofdata,itprocessestheUIColumncomponentassociatedwitheachcolumntagforeachrowinthetable.TheUIData
componentiteratesthroughthelistofitems(item.items
)anddisplaysthedataTableItem.price
.EachtimeUIDataiteratesthroughthelistofitems,itrendersonecellineachcolumn
.ThedataTableandcolumntagsusefacet
torepresentpartsofthetablethatarenotrepeatedorupdated.Theseincludeheader
s,footers,andcaptions.TherecommendedwaytointegrateSpringwithJSFistoconfiguretheSpringDelegatingVariableResolver
inthefaces-context.xml.The<application>
<variable-resolver>
elementsinafaces-config.xmlfileallowsaFaces-basedapplicationtoregisteracustomreplacementclassfortheimplementationofthestandardFacesVariableResolverimplementation.TheSpringDelegatingVariableResolver
firstdelegatestotheoriginalresolveroftheunderlyingJSFimplementation,thentotheSpringrootWebApplicationContext.ThisallowsyoutoconfigureSpringBeansasmanagedpropertiesofyourJSFManagedBeans.Forexample,belowthecatalogService
SpringBeanisconfiguredasamanagedpropertyoftheItemController
JSFManagedBean:CodeSamplefrom:faces-context.xml |
<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> |
ThecatalogService
,anditsimplementationCatalogDAO
,
isdefinedasaSpringbeanintheSpringconfigurationresourcefile/WEB-INF/applicationContext.xml:CodeSamplefrom:applicationContext.xml |
<beanid="catalogService"class="service.CatalogDAO"/><beanname="itemController"class="sessionpagination.ItemController"><propertyname="catalogService"><refbean="catalogService"/></property></bean></beans> |
<propertyname="catalogService">
referstotheItemController
setCatalogService
method.TheSpringrootWebApplicationContextwillinjectthecatalogService
SpringBeanintothecatalogService
propertyoftheItemController
JSFManagedBean:
CodeSamplefrom:ItemController .java |
publicclassItemController{privateCatalogServicecatalogService;publicvoidsetCatalogService(CatalogServicecatalogService){this.catalogService=catalogService;} |
FormoreinformationonusingJSFwithSpring,seeSpring-Java/J2EEApplicationFrameworkIntegratingwithJavaServerFaces.UsingtheJavaPersistenceAPI(JPA)withSpring2.0
TheSpringbeanCatalogDAO
usestheJavaPersistenceAPIEntityManagerQueryobjecttoreturnalistofitems.TheCatalogDAO
annotatesthefieldprivateEntityManagerem;
with@PersistenceContext
,whichcausesanentitymanagertobeinjected.(
notethatusingthe@PersistenceContext
annotationisthesamewayanEntityManagerisinjectedforaEJB3.0SessionBean.)CodeSamplefrom:CatalogDAO.java |
@Repository@TransactionalpublicclassCatalogDAOimplementsCatalogService{@PersistenceContext(unitName="PetCatalogPu")privateEntityManagerem;publicList<Item>getItems(intfirstItem,intbatchSize){Queryq=em.createQuery("selectobject(o)fromItemaso");q.setMaxResults(batchSize);q.setFirstResult(firstItem);List<Item>items=q.getResultList();returnitems;} |
TheJavaPersistenceQueryAPIsareusedtocreateandexecutequeriesthatcanreturnalistofresults.TheJPAQueryinterfaceprovidessupportforpaginationviathesetFirstResult()andsetMaxResults()methods:q.setMaxResults
(intmaxResult)setsthemaximumnumberofresultstoretrieve.q.setFirstResult
(intstartPosition)setsthepositionofthefirstresulttoretrieve.
Inthecodebelow,weshowtheItem
entityclasswhichmapstotheITEMtablethatstorestheiteminstances.ThisisatypicalJavaPersistenceentityobject.Therearetworequirementsforanentity:annotatingtheclasswithan@Entityannotation.annotatingtheprimarykeyidentifierwith@IdBecausethefieldsname,description....arebasicmappingsfromtheobjectfieldstocolumnsofthesamenameinthedatabasetable,theydon'thavetobeannotated.TheO/RrelationshipswithAddress
andProduct
arealsoannotated.FormoreinformationondefiningJPAentitiesseeProEJB3:JavaPersistenceAPIbook.CodeSamplefrom:Item.java |
@EntitypublicclassItemimplementsjava.io.Serializable{ @Id privateStringitemID; privateStringname;privateStringdescription;privateStringimageurl;privateStringimagethumburl;privateBigDecimalprice;@OneToOne(cascade={CascadeType.PERSIST})privateAddressaddress; @ManyToOneprivateProductproduct; publicItem(){}publicStringgetItemID(){returnitemID;} publicvoidsetItemID(StringitemID){this.itemID=itemID;} publicStringgetName(){returnname;} publicvoidsetName(Stringname){this.name=name;} publicStringgetDescription(){returndescription;} publicvoidsetDescription(Stringdescription){this.description=description;} publicBigDecimalgetPrice(){returnprice;} publicvoidsetPrice(BigDecimalprice){this.price=price;}publicvoidsetAddress(Addressaddress){this.address=address;}publicProductgetProduct(){returnproduct;}publicvoidsetProduct(Productproduct){this.product=product;}...} |
TheItemController
ManagedBeanpagesthroughthelistofItem
sbymaintainingthefirstItemandbatchSizeattributesandpassingtheseasparameterstotheCatalogService
getItems
(firstItem,batchSize)method.TheItemController
's<managed-bean-scope>
isdefinedassession
,aJSFManagedbeanwithsessionscopewillbestoredinthesessionmeaningthatthebean'spropertieswillstayaliveforthelifeoftheHttpSession.TheItemController
ItemCount
propertyisusedtogetanddisplaythenumberofCatologitem
sinthedatabaseontheList.jsppage:CodeSamplefrom:List.jsp |
<h:outputTextvalue="Item#{item.firstItem+1}..#{item.lastItem}of#{item.itemCount}"/> |
ThisItemController
ItemCount
propertyisdefinedasshownbelow:CodeSamplefrom:ItemController.java |
publicintgetItemCount(){intcount=catalogService.getItemsCount();returncount;} |
TheItemController
getItemCount
()methodcallstheCatalogService
interfacetogetthecountofthelistofitems.TheCatalogDAO
SpringbeangetItemCount
()methodusestheJPAQueryinterfacetogetthecountofallitemsinthedatabaseitemtable:CodeSamplefrom:CatalogDAO .java |
publicclassCatalogDAOimplementsCatalogService{... publicint getItemCount (){Queryq=entityManager.createQuery("selectcount(o)fromItemaso");intcount=((Long)q.getSingleResult()).intValue();returncount;} |
AJSFcommandLink
isusedtoprovidealinktoclickontodisplaythenextpageofitems.ThecommandLink
tagrepresentsanHTMLhyperlinkandisrenderedasanHTML<a>
element.ThecommandLink
tagisusedtosubmitanactioneventtotheapplication.CodeSamplefrom:List.jsp |
<h:commandLinkaction="#{item.next}"value="Next#{item.batchSize}"rendered="#{item.lastItem+item.batchSize<=item.itemCount}"/> |
ThiscommandLinkaction
attributereferencestheItemController
backingbeannext
()methodwhichcalculatesthenextpage'sfirstrownumberandreturnsalogicaloutcomeString,whichcausestheList.jsppagetodisplaythenextpage'slist.TheItemController
next
methodisdefinedasshownbelow:CodeSamplefrom:ItemController .java |
publicStringnext(){if(firstItem+batchSize<getItemCount()){firstItem+=batchSize;}return"item_list";} |
TheJavaServerFacesNavigationHandler
matchesthelogicaloutcome,item_list
againstthenavigationrulesintheapplicationconfigurationresourcefilefaces-config.xmltodeterminewhichpagetoaccessnext.Inthiscase,theJavaServerFacesimplementationloadstheList.jsp
pageafterthismethodreturns.CodeSamplefrom: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> |
AJSFcommandLink
isusedtoprovidealinktoclickontodisplaythepreviouspageofitems.ThiscommandLinkaction
attributereferencestheItemController
prev
()methodthatcalculatesthepreviouspage'sfirstrownumberandreturnsalogicaloutcomeString,whichcausestheListpagetodisplaythepreviouspageofitems:CodeSamplefrom:List.jsp |
<h:commandLinkaction="#{item.prev}"value="Previous#{item.batchSize}"rendered="#{item.firstItem>=item.batchSize}"/> |
ThisItemController
prev
()methodisdefinedasshownbelow:CodeSamplefrom:ItemController .java |
publicStringprev(){firstItem-=batchSize;if(firstItem<0){firstItem=0;}return" item_list ";} |
AJSFommandLink
isusedtoprovidealinktoclickontodisplayapagewiththeitem
details.ThiscommandLinkaction
attributereferencesTheItemController
detailSetup
()method:CodeSamplefrom:List.jsp |
<h:column><f:facetname="header"><h:outputTextvalue="Name"/></f:facet><h:commandLinkaction="#{item.detailSetup}"value="#{dataTableItem.name}"/></h:column> |
TheItemController
detailSetup
()methodgetstheitem
datafromthecurrentrowofthedataModel,andreturnsastringwhichcausestheDetail.jsppagetodisplaytheitemdetails:CodeSamplefrom:ItemController .java |
publicStringdetailSetup(){item=(Item)model.getRowData();return"item_detail";} |
TheJavaServerFacesNavigationHandler
matchesthelogicaloutcome,item_detail
againstthenavigationrulesintheapplicationconfigurationresourcefiletodeterminewhichpagetoaccessnext.Inthiscase,theJavaServerFacesimplementationloadstheDetail.jsp
pageafterthismethodreturns.CodeSamplefrom: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> |
TheDetail.jspusestheoutputText
componenttodisplaytheItemController
ManagedBean'sitem
properties:CodeSamplefrom:detail.jsp |
<h:outputTextvalue="#{item.item.name}"title="Name"/><h:outputTextvalue="#{item.item.description}"title="Description"/><h:graphicImageurl="#{item.item.imageurl}"title="Imageurl"/><h:outputTextvalue="#{item.item.price}"title="Price"/><h:outputTextvalue="#{item.item.address.city}"title="Address"/><h:outputTextvalue="#{item.item.contactinfo.email}"title="Address"/> |
ConclusionThisconcludesthesampleapplicationwhichdemonstrateshowtoworkwiththeJSFdataTableandDataModeltopagethroughalistofItemEntitieswhichareretrievedusingtheCatalogmethodswhichusetheJavaPersistenceAPIswithSpring2.0.Settingupthedatabasetablesforthesampleapplication:editthepropertiesintheSpringJPA/setup/javadb.propertiesfile,thenruntheantscriptinthedirectorySpringJPA/setup,orjustrunthesqlinthedirectorySpringJPA/setup/sql/javadbwithwhatevertoolyouhave.ConfigurationoftheApplicationforSpring2.0,JSF,JPA,runningonGlassfish
TosetupglassfishandthenetbeansprojectforSpring,ImodifiedthestepsfromSpringandHibernateinGlassFish:SettingThingsUp:downloadandextractSpring(Idownloaded2.1).DownloadandinstallNetBeans5.5.1DownloadandinstallGlassFishV1,followingtheinstructionsonthedownloadpage.AlternativelyyoucanuseSunJavaSystemApplicationServerPE9,Sun'sGlassFishdistribution.AddtheGlassfishservertoNetbeans:StartNetBeansandswitchtotheRuntimewindow(Ctrl+5).Right-clicktheServersnodeandselectAddServer.selectSunJavaSystemApplicationServer(Sun'sbinarydistributionofGlassFish).BrowsetothelocationwhereyouinstalledGlassFishandselectFinish.CreatetheSpringLibraryinNetbeans:OpentheNetbeansLibraryManager(Toolsmenu)andcreateanewlibrarycalledSpring.AddthefollowingjarstotheClasspath:dist/spring.jar,dist/weaving/spring-aspects.jar,lib/jakarta-commons/commons-logging.jar,lib/log4j/log4j-1.2.9.jar.SettheSourcestotheSpringsrcdirectory.SettheJavadoctotheSpringdocs/apidirectory.Thislibraryisnowavailableforusebyanyproject.OpenandRuntheSpringJPAProject
DownloadTheSpringJPAapplication.Unzipthecode.FromNetbeansdoOpenProjectandselecttheNetbeansprojectSpringJPAfromtheunzippeddirectory.TheSpringJPAapplicationisaNetBeansEnterpriseApplicationProject,whichisactuallycomprisedof2projects:SpringJPAandSpringJPA-war.SpringJPA-warisaJavaEEModuleoftheSpringJPAproject.SpringJPA-wargeneratesthewarfileandSpringJPAgeneratestheearfilewhichcontainsthewar.OpentheSpringJPAproject.Youwillseethisdialogwhenyouopentheproject,becausetheEnterpriseApplicationProjectstorestheabsolutelocationtoitsJ2EEModules,youneedtoconfigurethelocationfortheSpringJPA-war.ClickClose.TheSpringJPAprojectwillbeinboldred.RightclicktheprojectandselectResolveReferenceProblemsfromthecontextmenu.UsetheResolveReferenceProblemsdialogtomaptheSpringJPA-warmoduletoitsproject,whichyou'llfindisasubdirectorybeneaththeSpringJPAdirectory.Afterthereferencesareresolved,right-clicktheSpringJPAprojectandselectOpenRequiredProjects(nowthatthedependenciesarecorrect,theSpringJPA-warprojectwillalwaysopenwiththeSpringJPAproject).Therearestilladditionalreferencesproblemswiththewebmodule,sinceitreferencestheSpringjarfilesthatareneededtobuildtheproject.addthenewSpringlibrarytotheSpringJPA-war...intheprojectwindowunderSpringJPA-war:rightclickonLibrairies,AddLibrarySelecttheSpringLibrary(thatyoucreatedabove)fromthelist,thenclickAddLibrary.ThiswilladdtheSpringjarfilestoyourSpringJPA-warproject.Allreferencesshouldnowberesolved.Right-clicktheSpringJPAprojectandselectcleanandbuildproject.PressF6totestruntheproject.NetBeanswillbuild,package,deployandlaunchtheapplication.CreatingyourownNetbeanswithSpring&GlassfishProject:
Ifyouwanttocreateyourownapplication,CreateanewNetbeansEnterpriseApplication:InNetbeansselectFileNewProject,thenselectEnterprise..EnterpriseApplication,ontheNewEnterpriseApplicationWindow,forServerselectSunJavaSystemApplicatonserver,JavaEE5Version,andSelecttheCreateWebApplicationModuleasshownbelow:changeyourNetbeansprojectpropertiestoaddthenewSpringlibrary...intheprojectwindowunderyourapplication'swar:rightclickonLibrairies,AddLibrarySelectSpringLibraryfromthelist,thenclickAddLibrary.toGenerateEntityclassesfromthedatabasetables:Intheprojectwindow,rightclickonthewar,selectnewFile..PersistenceEntityclassesfromdatabase.Clicknext,thenselectyourdatasource,tablesandcreateyourpersistenceunit.FormoreinfoonhowtodothistryoutthefollowingHandsOnLab:JavaEE5,EJB3.0,JavaPersistenceAPI(JPA)ForSpringconfigurationaddtheapplicationConfiguration.xmlandmodifytheweb.xmlandfaces-config.xmlasdescribedbelow.ConfigurationoftheXMLfilesforSpring2.0,JSF,andJPA,runningonGlassfishAddthefile/WEB-INF/applicationContext.xmltothewarWEB-INFdirectory.ThisfileiswhereyoudefineyourSpringservicebeans,andresources.BelowistheapplicationContext.xmlforthesampleapp.FormoreinformationaboutconfiguringtheSpringapplicationContext.xmlforJPAseethisarticle:UsingtheJavaPersistenceAPI(JPA)withSpring2.0CodeSamplefrom:applicationContext.xml |
<?xmlversion="1.0"encoding="UTF-8"?><beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:aop="http://www.springframework.org/schema/aop"xmlns:tx="http://www.springframework.org/schema/tx"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.0.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx-2.0.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-2.0.xsd"><beanid="catalogService"class="service.CatalogDAO"/><beanid="entityManagerFactory"class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"><propertyname="dataSource"ref="dataSource"/><propertyname="loadTimeWeaver"><beanclass="org.springframework.instrument.classloading.glassfish.GlassFishLoadTimeWeaver"/></property><propertyname="jpaVendorAdapter"><beanclass="org.springframework.orm.jpa.vendor.TopLinkJpaVendorAdapter"><propertyname="showSql"value="true"/><propertyname="generateDdl"value="false"/><propertyname="databasePlatform"value="oracle.toplink.essentials.platform.database.DerbyPlatform"/></bean></property></bean><beanid="dataSource"class="org.springframework.jdbc.datasource.DriverManagerDataSource"><propertyname="driverClassName"value="org.apache.derby.jdbc.ClientDriver"/><propertyname="url"value="jdbc:derby://localhost:1527/pet-catalog"/><propertyname="username"value="app"/><propertyname="password"value="app"/></bean><beanclass="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/><beanclass="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/><beanid="transactionManager"class="org.springframework.orm.jpa.JpaTransactionManager"><propertyname="entityManagerFactory"ref="entityManagerFactory"/><propertyname="dataSource"ref="dataSource"/></bean><tx:annotation-driven/><beanname="itemController"class="sessionpagination.ItemController"scope="session"><propertyname="catalogService"><refbean="catalogService"/></property></bean></beans> |
AddthespringframeworkContextLoaderListenerandcontextparametertoyourapplication'sweb.xmlasshownbelow.FormoreinformationonconfiguringSpringseethesereferences:UsingSpring2withJSF,Spring-Java/J2EEApplicationFrameworkIntegratingwithJavaServerFaces,AdvancedConfigurationoftheSpringMVCFrameworkCodeSamplefrom:web.xml |
<context-param><param-name>contextConfigLocation</param-name><param-value>/WEB-INF/applicationContext.xml</param-value></context-param><listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener><listener><listener-class>org.springframework.web.context.request.RequestContextListener</listener-class></listener> |
AddtheDelegatingVariableResolver
andanySpringbeans(i.e.catalogService)
referencedasJSFManagedBean(i.e.ItemController
)
propertiestothefaces-config.xml:CodeSamplefrom:faces-config.xml |
<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> |
References
UsingtheJavaPersistenceAPI(JPA)withSpring2.0DataAccesswithSpringandJPAonGlassfishUsingJPAinSpringwithoutreferencingSpringSpring-Java/J2EEApplicationFrameworkIntegratingwithJavaServerFacesUsingSpring2withJSFBuildingJavaServerFacesApplicationswithSpringandHibernateSpringandHibernateinGlassFishHarnessingthePowerofJavaPlatform,EnterpriseEdition(JavaEE)TechnologyWithSpringJavaEEtutorial(includesgreattutorialforJSFandJPA)ProEJB3:JavaPersistenceAPIbookJavaBluePrintsSolutionsCatalogfortheJavaPersistenceAPIscontainsacollectionoftopicsandexampleapplications.JavaPersistencereferencepageonGlassFishProjectBuildareal-worldWebapplicationwithJavaServerFaces,theSpringFramework,andHibernate