13 Replies Latest reply on Mar 27, 2009 8:33 PM by sublette131

    Hotel Booking example, how to get search to work outside of session scope

    chadws

      I have been looking at the Hotel Booking example and have a question about the search functionality.


      In the Hotel Booking example it appears that you can not have multiple windows open and have the search windows operate independently. What would one have to change to make it possible for a user to open up two search windows at the same time and have the next and previous page buttons operate independently on each page?


      For example, currently if a search returns 5 pages and the user has one browser tab open on page 1 and then opens a second tab and clicks the next button to advance to page 4,  returning to the first tab and clicking next advances it to page 5 not page 2.


      I am certain this has to do with using a Stateful session bean in the Session scope, but I am not certain what combination of SCOPE and EJB type will allow the two tabs to operate independently of each other.


      Any insight or pointers to other examples appreciated as I have been unable to find a search or listing example where this is not the case.

        • 1. Re: Hotel Booking example, how to get search to work outside of session scope
          pmuir

          Take a look at what seam-gen generates.

          • 2. Re: Hotel Booking example, how to get search to work outside of session scope
            chadws

            Ok, So I ran seam-gen and it generated an action for me that has the following class declaration:


            @Stateless
            @Name("Ping")
            public class PingBean implements Ping {
               ...
            }
            



            The action I am using is very similar


            @Stateless
            @Name("tagList")
            public class TagListingAction implements TagListingLocal {
               private int page = 0;
               private int pageSize = 10;
               ...
               nextPage() {
                  ++page;
                  list();
               }
               previousPage() {
                  --page;
                  list();
               }
            }
            



            In my facelets file I am using the following component to call the previous and next page methods:


            <s:link action="#{tagList.previousPage}"
                    value="[previous Page]"
                    rendered="#{tagList.previousPageAvailable}">
               <f:param name="page" value="#{tagList.page}" />
               <f:param name="pageSize" value="#{tagList.pageSize}" />
            </s:link>
            



            I have changed the list method on my action to a factory method and it checks the external context for the request parameters and sets them if found.


            private void list() {
               FacesContext lFacesContext = FacesContext.getCurrentInstance();
               ExternalContext lExternalContext = lFacesContext.getExternalContext();
               Map<String, String> lRequestParameters = lExternalContext.getRequestParameterMap();
            
               String lPage = lRequestParameters.get("page"); 
               if( lPage != null ) {
                  page = Integer.parseInt(lPage);
               }
            
               String lPageSize = lRequestParameters.get("pageSize"); 
               if( lPage != null ) {
                  pageSize = Integer.parseInt(lPageSize);
               }
               ... Do Work ...
            }
            



            After doing this I can use the standard h:link, but this seems like a hack to me and I would like to know the correct method of fixing this so that to separate browser tabs or windows operate independently.

            • 3. Re: Hotel Booking example, how to get search to work outside of session scope
              pmuir

              Ah, sorry, you need to reverse engineer some entities (or the ui from existing entities) to see the pattern I am discussing.

              • 4. Re: Hotel Booking example, how to get search to work outside of session scope
                chadws

                Pete, Thank you for taking the time to reply. I have been reading through the forum, jira and a few external references that have been referred to and am still having difficulty understanding exactly what is going on. I believe that my problem lies with a fundamental misunderstanding of JSF, seam and how state is managed.


                From what I have read I believe that I have two options Quoted from Step 1 on http://blog.hibernate.org/Bloggers/RaptureDisillusionInsight:



                1. Go stateless (use a redirect with request parameters and pull MVC)

                2. Put the results in the page context (which is serialized to the client)



                My requirements are fairly simple:



                1. Present a paginated list of items in multiple windows or tabs.

                2. Display the selected Item.



                I believe that Option 1 is the best solution for this scenario since there is no defined exit path and I don't want to leave a number of long running conversations open.


                In fact, Gavin King, while describing a very similar scenario in the forum stated:



                I usually go stateless, and use page parameters for this.

                I am not entirely certain how one go(es) stateless. I made the assumption that using a stateless sessionbean, and placing it in a non-stateful state would be sufficient, but upon opening a second window this proves false since the values for the page and pageNumber bean members are used for both windows/tabs.


                I have been reading through the blog, and wiki examples, but have not yet been able to understand what I am doing wrong.


                Is the following correct?



                1. Make a request to an itemlist.xhtml file.

                2. The datatable on the itemlist.xhtml file requests the items from the SLSB

                3. A factory method on the SLSB verifies the pageSize and pageNumber members and then populates the results

                4. A user clicks the Next Page button which calls the SLSB.nextPage action



                This is where I get confused as to what is happening as I believe that at this point JSF restores the view which sets the previous pageSize and pageNumber fields and then calls the desired action which increments the pageNumber member and redirects the user to the itemlist.xhtml file. I have the pages.xml file configured to have the pageSize and pageNumber parameters to my listItems.xhtml file and this does indeed redirect and display the request.


                The problem is that if I open a second browser tab and navigate to another page clicking the first link on the original browser tab selects and opens the first item in the second tab telling me that the SLSB infact has the state saved in it and I have something configured or coded wrong.


                Sorry for the length of this, but this is beyond me and I could really use some help.


                Thanks!

                • 5. Re: Hotel Booking example, how to get search to work outside of session scope
                  pmuir

                  Try using a Seam POJO.

                  • 6. Re: Hotel Booking example, how to get search to work outside of session scope
                    chadws

                    We are using Toplink JPA on Glassfish and when I attempted to change my SLSB to a POJO I now get the Error



                    For use of FlushMode.MANUAL, please use Hibernate as the persistence provider or use a custom PersistenceProvider.

                    I thought that I read seam would work with JPA and did not require hibernate, but after reading I can not find any documentation for getting it to work with toplink. Do you know if this is supported and if so what I do to configure the custom PersistenceProvider?

                    • 7. Re: Hotel Booking example, how to get search to work outside of session scope
                      nickarls

                      For use of FlushMode.MANUAL, please use Hibernate as the persistence provider or use a custom PersistenceProvider.

                      I thought that I read seam would work with JPA and did not require hibernate, but after reading I can not find any documentation for getting it to work with toplink. Do you know if this is supported and if so what I do to configure the custom PersistenceProvider?


                      Seam works with JPA without Hibernate but section 8.3.3 in the manual states that the manual flushmode isn't JPA.


                      Not sure about the status of the "equivalent vendor extensions"

                      • 8. Re: Hotel Booking example, how to get search to work outside of session scope
                        pmuir

                        Chad Skinner wrote on Mar 14, 2008 05:28 AM:


                        I thought that I read seam would work with JPA and did not require hibernate, but after reading I can not find any documentation for getting it to work with toplink. Do you know if this is supported and if so what I do to configure the custom PersistenceProvider?


                        You need to create a custom TopLinkPersistenceProvider component:


                        @Name("org.jboss.seam.persistence.persistenceProvider")
                        @Scope(ScopeType.STATELESS)
                        @BypassInterceptors
                        @Install(precedence=FRAMEWORK, classDependencies={"some.toplink.class", "javax.persistence.EntityManager"})
                        public class TopLinkPersistenceProvider extends PersistenceProvider
                        {



                        and implement the setFlushModeManual method (don't know if this is possible in TopLink at all).

                        • 9. Re: Hotel Booking example, how to get search to work outside of session scope
                          chadws

                          Since We are trying to use JPA and not specifically hibernate I decided to try injecting my EJB into my POJO and using EJB transactions. I am now getting an error that I can not explain at all.


                          I now have the following in my POJO


                          @Name("tagList")
                          @Scope(ScopeType.EVENT)
                          public class TagListingAction {
                          
                               @In(create=true)
                               private TagManagerLocal tagManager;
                          
                               @Factory("tags")
                               public void list() {
                                    Integer lInitial = page * pageSize;
                                        Integer lMaxRecords = pageSize;
                                        tags = tagManager.findAll(lInitial, lMaxRecords);
                               }
                               
                               public String nextPage() {
                                    page++;
                                    return "/application/seam/tag/index.xhtml";
                                    return "/application/seam/tag/index.xhtml";
                               }
                              
                               public String previousPage() {
                                    page--;
                                    return "/application/seam/tag/index.xhtml";
                               }
                          
                               ...
                          }
                          



                          It appears that my EJB is being injected and the results are being returned, but upon clicking the next page button or an item in the presented listing I get the following exception:


                          [#|2008-03-17T23:02:13.419-0500|SEVERE|sun-appserver9.1|javax.enterprise.system.container.web|_ThreadID=23;_ThreadName=httpSSLWorkerThread-8080-0;_RequestID=89d26ad3-12ed-4de8-acc3-5f7ef3c10dad;|StandardWrapperValve[Faces Servlet]: PWC1406: Servlet.service() for servlet Faces Servlet threw exception
                          java.lang.NoClassDefFoundError: org/hibernate/MappingException
                               at org.jboss.seam.core.Validators.createValidator(Validators.java:122)
                               at org.jboss.seam.core.Validators.getValidator(Validators.java:105)
                               at org.jboss.seam.core.Validators.getValidator(Validators.java:88)
                               at org.jboss.seam.core.Validators$ValidatingResolver.setValue(Validators.java:199)
                               at org.jboss.el.parser.AstPropertySuffix.setValue(AstPropertySuffix.java:73)
                               at org.jboss.el.parser.AstValue.setValue(AstValue.java:84)
                               at org.jboss.el.ValueExpressionImpl.setValue(ValueExpressionImpl.java:249)
                               at org.jboss.seam.core.Validators.validate(Validators.java:140)
                               at org.jboss.seam.navigation.Param.validateConvertedValue(Param.java:239)
                               at org.jboss.seam.navigation.Pages.convertAndValidateStringValuesInPageContext(Pages.java:746)
                               at org.jboss.seam.navigation.Pages.postRestore(Pages.java:393)
                               at org.jboss.seam.jsf.SeamPhaseListener.postRestorePage(SeamPhaseListener.java:533)
                               at org.jboss.seam.jsf.SeamPhaseListener.afterRestoreView(SeamPhaseListener.java:379)
                               at org.jboss.seam.jsf.SeamPhaseListener.afterServletPhase(SeamPhaseListener.java:216)
                               at org.jboss.seam.jsf.SeamPhaseListener.afterPhase(SeamPhaseListener.java:182)
                          
                          ...
                          



                          Does this mean that hibernate is somehow in my classpath as if it does I have been unable to find out how or where. We are using maven for our build system and are including the following libraries:



                          • jboss-seam - 2.0.1.GA

                          • jboss-seam-ui - 2.0.1.GA

                          • jboss-seam-debug - 2.0.1.GA

                          • hibernate-commons-annotations - 3.3.0.ga



                          and for each of these I am excluding the hibernate jar file.

                          • 10. Re: Hotel Booking example, how to get search to work outside of session scope
                            chadws

                            I may be looking in the wrong direction. It appears that the POJO works on the first request to /index.xhtml, but when the next page is submitted and the request parameters page and pageSize are added the NoClassDefFoundError: org.hibernate.MappingException is thrown.


                            In my POJO I have to private Integer properties page and pageSize, each with getters and setters. In my pages.xml I have the following:


                            <pages>
                                 <page view-id="/application/seam/tag/index.xhtml" action="#{tagList.list}">
                                      <param name="page" value="#{tagList.page}" />
                                      <param name="pageSize" value="#{tagList.page}" />
                                 </page>
                            </pages>



                            If I remove the param elements from this entry the page will load without error, but neither  loads the correct entry when clicked nor does it navigate forward or backwards. My faces-config.xml file contains the following:


                            <navigation-rule>
                                 <display-name>Tag Listing</display-name>
                                 <from-view-id>/application/seam/tag/index.xhtml</from-view-id>
                                      <navigation-case>
                                           <from-outcome>Add</from-outcome>
                                           <to-view-id>/application/seam/tag/adminForm.xhtml</to-view-id>
                                      </navigation-case>     
                                      <navigation-case>
                                           <from-outcome>Edit</from-outcome>
                                           <to-view-id>/application/seam/tag/adminForm.xhtml</to-view-id>
                                      </navigation-case>
                                      <navigation-case>
                                           <from-outcome>nextPage</from-outcome>
                                           <to-view-id>/application/seam/tag/index.xhtml</to-view-id>
                                           <redirect/>
                                      </navigation-case>
                                      <navigation-case>
                                           <from-outcome>previousPage</from-outcome>
                                           <to-view-id>/application/seam/tag/index.xhtml</to-view-id>
                                           <redirect/>
                                      </navigation-case>
                                 </navigation-rule>



                            Anyone have any idea what I would have done to goof up the conversion of the parameter values?

                            • 11. Re: Hotel Booking example, how to get search to work outside of session scope
                              pmuir

                              You are on the right track looking at libraries. Maven has a habit of putting too much into your archive. Post the contents of your deployed archive.

                              • 12. Re: Hotel Booking example, how to get search to work outside of session scope
                                chadws

                                Ok, so I had maven build the ear and here is a listing of all the jar files in its lib directory and the war/WEB-INF/lib: (Note: I removed the underscores in the jar names and replaced them with -- to prevent conflicts with the wiki text).



                                • architecture-1.0-SNAPSHOT.jar

                                • commons-beanutils-1.7.0.jar

                                • commons-codec-1.3.jar

                                • commons-collections-3.1.jar

                                • commons-digester-1.6.jar

                                • commons-digester-1.7.jar

                                • commons-el-1.0.jar

                                • commons-fileupload-1.0.jar

                                • commons-lang-2.1.jar

                                • commons-logging-1.0.4.jar

                                • commons-validator-1.1.4.jar

                                • commons-validator-1.3.1.jar

                                • dom4j-1.6.1-jboss.jar

                                • el-api-1.0.jar

                                • hibernate-commons-annotations-3.3.0.ga.jar

                                • hibernate-validator-3.0.0.GA.jar

                                • javassist-3.3.ga.jar

                                • jboss-el-2.0.1.GA.jar

                                • jboss-seam-2.0.1.GA.jar

                                • jboss-seam-debug-2.0.1.GA.jar

                                • jboss-seam-ui-2.0.1.GA.jar

                                • jdom-1.0.jar

                                • jsf-api-1.2--07.jar

                                • jsf-facelets-1.1.9.jar

                                • jsf-impl-1.2--07.jar

                                • jsp-api-2.1.jar

                                • jstl-1.1.0.jar

                                • jstl-1.1.2.jar

                                • log4j-1.2.14.jar

                                • myfaces-all-1.1.1.jar

                                • myfaces-api-1.2.2.jar

                                • mysql-connector-java-5.1.5.jar

                                • oro-2.0.8.jar

                                • persistence-api-1.0.jar

                                • rome-0.8.jar

                                • richfaces-api-3.1.3.GA.jar

                                • richfaces-impl-3.1.3.GA.jar

                                • richfaces-ui-3.1.3.GA.jar

                                • rome-0.8.jar

                                • standard-1.1.2.jar

                                • tomahawk-1.1.6.jar

                                • toplink-essentials-2.0.41.jar

                                • WebsiteBusinessModel-1.0-SNAPSHOT.jar

                                • WebsiteEJB-1.0-SNAPSHOT.jar

                                • xml-apis-1.0.b2.jar



                                Thanks for any help, as this is stumping me big time.

                                • 13. Re: Hotel Booking example, how to get search to work outside of session scope
                                  sublette131

                                  Hopefully you've found your solution in the past year, but if not... The missing class can be found in hibernate.jar.  Something about validating parameters in the pages.xml file seems to be causing seam to go through code that eventually requires both hibernate.jar and I think hibernate-annotations.jar.  You should be able to write and attach a custom validator for your parameters and avoid those references.