11 Replies Latest reply on Jan 5, 2011 4:40 PM by gebuh

    dropdowns and state

    gebuh

      We have a search page with several dropdowns for user search parameters.  When a user selects something from the dropdown and performs a search or sorts the results or navigates to a nested conversation, the values in the dropdown are reset.  We're resorted to some session object gymnastics to pass this information back and forth-I know this is less than ideal.  But since we started this project with no knowledge of Seam I'm wondering if maybe we missed some basic construct or process that would store this information without doing that.  I've been tasked with adding a save search facility, but right now we can't even maintain state between conversations(a user selecting a nested conversation upon returning would have to re-enter all their search criteria).  Can anyone point me in the right direction?

        • 1. Re: dropdowns and state
          kragoth

          Can you please provide the code that you are using that causes this problem.


          Sounds like you have missed something pretty basic, but without showing your work it is hard to know. :)

          • 2. Re: dropdowns and state
            gebuh

            Tim Evers wrote on Dec 02, 2010 00:05:


            Can you please provide the code that you are using that causes this problem.

            Sounds like you have missed something pretty basic, but without showing your work it is hard to know. :)


            That's just it, I'm not sure where the problem is, would this be at the component level, or the backing bean, or somewhere else?  I think it's something we've gotten fundamentally wrong, but not sure what.
            I'm using Seam 2.2.0 with richfaces 3.3.1, here's one of my dropdown components:



            <s:decorate id="areasSelectOne" template="../layout/display.xhtml">
               <ui:define name="label">Area:</ui:define>
               <h:selectOneMenu value="#{employeeVCriteria.area}">
                 <s:selectItems var="_areas" value="#{areasList}"
                 label="#{_areas.areaName}" noSelectionLabel="All Areas"/>
                   <s:convertEntity/>
                   <a:support event="onchange" ajaxSingle = "true" reRender = "hubSelectOne" bypassUpdates="false" ></a:support>
               </h:selectOneMenu>
            </s:decorate>



            • 3. Re: dropdowns and state
              kragoth

              Can you please show the relevant sections of code for the SeamBean employeeVCriteria.


              What scope is the bean.


              Also show the method that gets called when a user performs a search.


              Provide as much relevant information and code that you can. This will speed up the resolution. Also, what have you tried with regards to solving the problem?

              • 4. Re: dropdowns and state
                gebuh

                Tim, thanx for taking the time to look at this.  Here goes, don't judge me.
                EmployeeVCriteria is a conversation scoped bean, we use it for managing the dropdowns.  So for maintaining the area dropdown we have this component:



                <s:decorate id="areasSelectOne" template="../layout/display.xhtml">
                   <ui:define name="label">Area:</ui:define>
                   <h:selectOneMenu value="#{employeeVCriteria.area}">
                     <s:selectItems var="_areas" value="#{areasList}"
                     label="#{_areas.areaName}" noSelectionLabel="All Areas"/>
                       <s:convertEntity/>
                       <a:support event="onchange" ajaxSingle = "true" reRender = "hubSelectOne" bypassUpdates="false" ></a:support>
                   </h:selectOneMenu>
                </s:decorate>



                relevant page.xml:



                 <param name="sort" value="#{employeeVList.orderColumn}"/>
                 <param name="dir" value="#{employeeVList.orderDirection}"/>
                 <param name="logic" value="#{employeeVList.restrictionLogicOperator}"/>
                 <param name="from"/>
                 <param name="areaName" value="#{employeeVCriteria.areaSelected}"/>



                areaName getter/setter from employeeVCriteria:



                public Area getArea() {          
                
                FacesContext facesContext = FacesContext.getCurrentInstance();       
                HttpServletRequest request = (HttpServletRequest)facesContext.getExternalContext().getRequest();
                
                if(this.area != null)
                {
                
                request.getSession().setAttribute("area",area);          
                
                return this.area;
                }
                else
                {
                Area oarea;                           
                if(request.getSession().getAttribute("area") != null)
                {
                oarea = (Area) request.getSession().getAttribute("area");
                String prevareasel = null;
                if(oarea != null)
                {
                prevareasel =  oarea.getAreaName().toString();
                request.getSession().setAttribute("prevareasel", prevareasel);
                }          
                
                
                }
                //send the previous selection to the new object                              
                if(request.getSession().getAttribute("prevAreaObj")!= null)
                {               
                this.area = (Area) request.getSession().getAttribute("prevAreaObj");
                request.getSession().setAttribute("prevAreaObj", null);
                if((request.getSession().getAttribute("areaSort") == null) && (request.getSession().getAttribute("areanext") == null))
                {
                
                setareaSelected(null);          
                this.area = null;
                request.getSession().setAttribute("area",null);
                request.getSession().setAttribute("prevareasel", null);
                
                }
                request.getSession().setAttribute("areaSort", null);
                request.getSession().setAttribute("areanext", null);
                }
                
                }
                
                return this.area;
                
                
                }
                
                public void setArea(Area area) {
                FacesContext facesContext = FacesContext.getCurrentInstance();       
                HttpServletRequest request = (HttpServletRequest)facesContext.getExternalContext().getRequest();
                
                this.area = area;
                if(area != null)
                {
                areaSelected = area.getAreaName();
                setareaSelected(area.getAreaName());
                request.getSession().setAttribute("areaSelected", this.area.getAreaName());
                request.getSession().setAttribute("domainSelected", null);
                }
                else
                {
                request.getSession().setAttribute("areaSelected", null);
                this.areaSelected = null;
                this.area = null;
                }
                
                }






                search and reset components:



                <div class="actionButtons" >
                <h:commandButton id="search" value="Search" action="/web/EmployeeVList.xhtml"/>
                <s:button id="reset" value="Reset" includePageParams="false" action="#{employeeVHome.clearDropDown}"/>
                </div>



                clearDropDown method from employeeVHome used for reset button:



                     public void clearDropDown()
                {
                FacesContext facesContext = FacesContext.getCurrentInstance();       
                HttpServletRequest request = (HttpServletRequest)facesContext.getExternalContext().getRequest();
                request.getSession().setAttribute("prevAreaObj", null);
                request.getSession().setAttribute("prevareasel", null);
                request.getSession().setAttribute("area",null);
                          /*areaSelected is used by hubV1List and domainV1List*/
                request.getSession().setAttribute("areaSelected", null);
                }



                So what all this stuff does is save dropdown state to session variables when they're set and then retrieve them when the page is reloaded or sorted or pages changed.  I didn't write this so detailed questions about it will be met with a vacant stare, I can't say what my compadre tried beforehand, but this does work.  But I've been tasked with creating a way to save users' search parameters and that's going to be problematic doing things the way we currently do.  I can't help thinking we've missed something basic.

                • 5. Re: dropdowns and state
                  kragoth

                  Can I just say WOW.


                  I have never seen so much use of the request or session objects in a JSF app ever!


                  I'm a little confused where to start here....


                  For starters you really really really should not be using getters and setters like this. JSF calls the getter multiple times during the JSF Lifecycle and modifying the value of an attribute in the getter is really not a good idea.


                  Secondly, if you are using conversations there is no need to store things in the session unless it really is a session variable. Which from what I gather these are not. Session variables would be things like LoggedInUser, ListOfActiveConversations. Not variables that are used on a single page.


                  Seam is extremely good at storing the state of a conversation. There is no need to be shoving this stuff into a session variable.


                  So, for starters this is what I recommend.



                  1. Fix your getters and setters so that all they contain is the simple lines of a getter and setter.

                  2. Remove any dependence on session vars from your page. Make them use your conversation scoped bean.

                  3. Take the time to check that you are using Long Running Conversations. If you are not using long running conversations then it is essentially the same as PAGE scope and that would mean that the state is not being stored across redirects.

                  4. Last but not least. When dealing with something like this take the time to have a look at the Seam examples in the Seam download. It is very good at showing some of the basics about Seam.



                  Something important to remember is that Session variables are a really bad way to store things. There is no protection on these values and thus any new developer could accidentally write some code that will make these pages break because he is overwriting your session variables. Stick to conversation scoped bean and learn how to use them properly.


                  If you don't know what I mean by long running conversations then read the Seam doco. It explains it reasonably well. :)


                  If you get stuck just post here again. I'll keep an eye on it :)

                  • 6. Re: dropdowns and state
                    gebuh

                    ok, so I went back to step 1, picked a component and started reworking it.  I Created a search action class that will eventually handle all the search parameters.  It has a method to populate the area dropdown:



                    @Factory("rawAreaList")
                         //@Observer("populateOtherDDs")
                         public List<Area> getRawAreaList(){
                              log.debug("getting a rawAreaList");
                              if(this.rawAreaList == null){
                                   this.rawAreaList = entityManager.createQuery("select a from Area a order by a.areaName").getResultList();
                                   log.debug("going to db for rawAreaList, total db hits = " + this.countDbHits);
                              }
                              return this.rawAreaList;
                         }
                    



                    a field to get the area selected with a getter and setter:



                    public Area getAreaSelected() {
                              log.debug("getting areaSelected: " + this.areaSelected);
                              return areaSelected;
                         }



                    a component to display it:



                    <s:decorate id="areasSelectOne" template="../layout/display.xhtml">
                    <ui:define name="label">Area:</ui:define>
                    <h:selectOneMenu value="#{employeeListSearchAction.areaSelected}">
                    <s:selectItems var="_areas" value="#{rawAreaList}"
                    label="#{_areas.areaName}" noSelectionLabel="All Areas"/>
                    <s:convertEntity/>
                    <a:support event="onchange" ajaxSingle = "true" reRender = "hubSelectOne" bypassUpdates="false" ></a:support>
                    </h:selectOneMenu>
                    </s:decorate>




                    The page loads, I can select an area from the dropdown, but when hit the search button(as of now it just reloads the page):
                    <h:commandButton id="search" value="Search" action="/web/EmployeeVList.xhtml"/>


                    I get Exception during request processing:
                    Caused by javax.el.ELException with message: "java.lang.IllegalArgumentException: argument type mismatch"

                    The entire stack trace is below.  When I use the back button and reload the page the page comes up with the search completed correctly.  I have the action class scoped conversation or session, doesn't matter.  I don't have this class in the action package and it's not based on a single model class.  The actual model class that returns data is an employeeView model.


                    I'm confused as to how I should configure this, the seam examples don't really fit.  I know this isn't rocket science, but I'm having a lot of trouble getting this to function correctly.



                    seam debug stack trace:



                    Exception during request processing:
                    Caused by javax.el.ELException with message: "java.lang.IllegalArgumentException: argument type mismatch"
                    
                    javax.el.BeanELResolver.setValue(BeanELResolver.java:116)
                    javax.el.CompositeELResolver.setValue(CompositeELResolver.java:69)
                    com.sun.faces.el.FacesCompositeELResolver.setValue(FacesCompositeELResolver.java:100)
                    org.jboss.el.parser.AstPropertySuffix.setValue(AstPropertySuffix.java:73)
                    org.jboss.el.parser.AstValue.setValue(AstValue.java:84)
                    org.jboss.el.ValueExpressionImpl.setValue(ValueExpressionImpl.java:249)
                    org.jboss.seam.core.Expressions$1.setValue(Expressions.java:117)
                    org.jboss.seam.navigation.Pages.applyConvertedValidatedValuesToModel(Pages.java:846)
                    org.jboss.seam.navigation.Pages.postRestore(Pages.java:443)
                    org.jboss.seam.jsf.SeamPhaseListener.postRestorePage(SeamPhaseListener.java:545)
                    org.jboss.seam.jsf.SeamPhaseListener.afterRestoreView(SeamPhaseListener.java:394)
                    org.jboss.seam.jsf.SeamPhaseListener.afterServletPhase(SeamPhaseListener.java:230)
                    org.jboss.seam.jsf.SeamPhaseListener.afterPhase(SeamPhaseListener.java:196)
                    com.sun.faces.lifecycle.Phase.handleAfterPhase(Phase.java:175)
                    com.sun.faces.lifecycle.Phase.doPhase(Phase.java:114)
                    com.sun.faces.lifecycle.RestoreViewPhase.doPhase(RestoreViewPhase.java:103)
                    com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
                    javax.faces.webapp.FacesServlet.service(FacesServlet.java:265)
                    org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
                    org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
                    org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:83)
                    org.jboss.seam.web.RewriteFilter.doFilter(RewriteFilter.java:63)
                    org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
                    org.jboss.seam.web.MultipartFilter.doFilter(MultipartFilter.java:90)
                    org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
                    org.jboss.seam.web.ExceptionFilter.doFilter(ExceptionFilter.java:64)
                    org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
                    org.jboss.seam.web.RedirectFilter.doFilter(RedirectFilter.java:45)
                    org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
                    org.ajax4jsf.webapp.BaseXMLFilter.doXmlFilter(BaseXMLFilter.java:178)
                    org.ajax4jsf.webapp.BaseFilter.handleRequest(BaseFilter.java:290)
                    org.ajax4jsf.webapp.BaseFilter.processUploadsAndHandleRequest(BaseFilter.java:368)
                    org.ajax4jsf.webapp.BaseFilter.doFilter(BaseFilter.java:495)
                    org.jboss.seam.web.Ajax4jsfFilter.doFilter(Ajax4jsfFilter.java:56)
                    org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
                    org.jboss.seam.web.LoggingFilter.doFilter(LoggingFilter.java:60)
                    org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
                    org.jboss.seam.web.HotDeployFilter.doFilter(HotDeployFilter.java:53)
                    org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
                    org.jboss.seam.servlet.SeamFilter.doFilter(SeamFilter.java:158)
                    org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
                    org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
                    com.raytheon.MyEmployee.criteria.DisableUrlSessionFilter.doFilter(DisableUrlSessionFilter.java:72)
                    org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
                    org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
                    org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96)
                    org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
                    org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
                    org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:235)
                    org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
                    org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:190)
                    org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:433)
                    org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:92)
                    org.jboss.web.tomcat.security.SecurityContextEstablishmentValve.process(SecurityContextEstablishmentValve.java:126)
                    org.jboss.web.tomcat.security.SecurityContextEstablishmentValve.invoke(SecurityContextEstablishmentValve.java:70)
                    org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
                    org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
                    org.jboss.web.tomcat.service.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:158)
                    org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
                    com.jamonapi.http.JAMonTomcatValve.invoke(JAMonTomcatValve.java:72)
                    org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:330)
                    org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:829)
                    org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:598)
                    org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
                    java.lang.Thread.run(Thread.java:619)
                    
                    Caused by java.lang.IllegalArgumentException with message: "argument type mismatch"
                    
                    sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
                    sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
                    sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
                    java.lang.reflect.Method.invoke(Method.java:597)
                    javax.el.BeanELResolver.setValue(BeanELResolver.java:108)
                    javax.el.CompositeELResolver.setValue(CompositeELResolver.java:69)
                    com.sun.faces.el.FacesCompositeELResolver.setValue(FacesCompositeELResolver.java:100)
                    org.jboss.el.parser.AstPropertySuffix.setValue(AstPropertySuffix.java:73)
                    org.jboss.el.parser.AstValue.setValue(AstValue.java:84)
                    org.jboss.el.ValueExpressionImpl.setValue(ValueExpressionImpl.java:249)
                    org.jboss.seam.core.Expressions$1.setValue(Expressions.java:117)
                    org.jboss.seam.navigation.Pages.applyConvertedValidatedValuesToModel(Pages.java:846)
                    org.jboss.seam.navigation.Pages.postRestore(Pages.java:443)
                    org.jboss.seam.jsf.SeamPhaseListener.postRestorePage(SeamPhaseListener.java:545)
                    org.jboss.seam.jsf.SeamPhaseListener.afterRestoreView(SeamPhaseListener.java:394)
                    org.jboss.seam.jsf.SeamPhaseListener.afterServletPhase(SeamPhaseListener.java:230)
                    org.jboss.seam.jsf.SeamPhaseListener.afterPhase(SeamPhaseListener.java:196)
                    com.sun.faces.lifecycle.Phase.handleAfterPhase(Phase.java:175)
                    com.sun.faces.lifecycle.Phase.doPhase(Phase.java:114)
                    com.sun.faces.lifecycle.RestoreViewPhase.doPhase(RestoreViewPhase.java:103)
                    com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
                    javax.faces.webapp.FacesServlet.service(FacesServlet.java:265)
                    org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
                    org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
                    org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:83)
                    org.jboss.seam.web.RewriteFilter.doFilter(RewriteFilter.java:63)
                    org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
                    org.jboss.seam.web.MultipartFilter.doFilter(MultipartFilter.java:90)
                    org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
                    org.jboss.seam.web.ExceptionFilter.doFilter(ExceptionFilter.java:64)
                    org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
                    org.jboss.seam.web.RedirectFilter.doFilter(RedirectFilter.java:45)
                    org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
                    org.ajax4jsf.webapp.BaseXMLFilter.doXmlFilter(BaseXMLFilter.java:178)
                    org.ajax4jsf.webapp.BaseFilter.handleRequest(BaseFilter.java:290)
                    org.ajax4jsf.webapp.BaseFilter.processUploadsAndHandleRequest(BaseFilter.java:368)
                    org.ajax4jsf.webapp.BaseFilter.doFilter(BaseFilter.java:495)
                    org.jboss.seam.web.Ajax4jsfFilter.doFilter(Ajax4jsfFilter.java:56)
                    org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
                    org.jboss.seam.web.LoggingFilter.doFilter(LoggingFilter.java:60)
                    org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
                    org.jboss.seam.web.HotDeployFilter.doFilter(HotDeployFilter.java:53)
                    org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
                    org.jboss.seam.servlet.SeamFilter.doFilter(SeamFilter.java:158)
                    org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
                    org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
                    com.raytheon.MyEmployee.criteria.DisableUrlSessionFilter.doFilter(DisableUrlSessionFilter.java:72)
                    org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
                    org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
                    org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96)
                    org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
                    org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
                    org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:235)
                    org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
                    org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:190)
                    org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:433)
                    org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:92)
                    org.jboss.web.tomcat.security.SecurityContextEstablishmentValve.process(SecurityContextEstablishmentValve.java:126)
                    org.jboss.web.tomcat.security.SecurityContextEstablishmentValve.invoke(SecurityContextEstablishmentValve.java:70)
                    org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
                    org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
                    org.jboss.web.tomcat.service.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:158)
                    org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
                    com.jamonapi.http.JAMonTomcatValve.invoke(JAMonTomcatValve.java:72)
                    org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:330)
                    org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:829)
                    org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:598)
                    org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
                    java.lang.Thread.run(Thread.java:619)
                    
                    



                    • 7. Re: dropdowns and state
                      gebuh

                      if I remove areaSelected param from EmployeeVList.page.xml the application doesn't blow up, but then the area dropdown isn't maintained and it doesn't search for an area- just reloads the page.


                      this is just one of the various incarntions, I tried using employeeListSearchAction.areaSelected as a param but that doesn't work either.


                      <param name="areaSelected" value="#{employeeVList.employeeV.areaSelected}"/>



                      • 8. Re: dropdowns and state
                        kragoth

                        OK, getting better but let's go a step further.


                        There really isn't any need for any params in your pages.xml and I'm pretty sure you don't need any param tags in your xhtml either. Unless of course you plan on making these pages bookmarkable. In which case we'll work on that later.


                        First off, let's go back to a basic getter, setter action method combination.


                        This is fine I think...I don't use factories in my app but from what I can remember when playing around with them I can't see any real issue here.


                        @Factory("rawAreaList")
                        //@Observer("populateOtherDDs")
                        public List<Area> getRawAreaList(){
                            log.debug("getting a rawAreaList");
                            if(this.rawAreaList == null){
                                this.rawAreaList = entityManager.createQuery("select a from Area a order by a.areaName").getResultList();
                                log.debug("going to db for rawAreaList, total db hits = " + this.countDbHits);
                            }
                            return this.rawAreaList;
                        }
                        



                        Please verify you have a setter to go with your getter, because if your setter isn't right this would be what gives the exception. Post the code for it if you can please.


                        public Area getAreaSelected() {
                            log.debug("getting areaSelected: " + this.areaSelected);
                            return areaSelected;
                        }
                        



                        As for the command button


                        <h:commandButton id="search" value="Search" action="/web/EmployeeVList.xhtml"/>
                        



                        Change this to actually have an action.


                        <h:commandButton id="search" value="Search" action="#{MyBean.doSearch()}"/>
                        



                        public String doSearch() {
                            log.debug("The value for areaSelected was: " + this.areaSelected);
                            return "";
                        }
                        



                        You said:



                        if I remove areaSelected param from EmployeeVList.page.xml the application doesn't blow up, but then the area dropdown isn't maintained and it doesn't search for an area- just reloads the page.


                        I think this is because your button isn't right. Can you post the relevant pages.xml fragment that is getting used for this button? I'm going to go test my theory about why it's broken while I wait for your to reply. :P


                        Obviously tomorrow will be my last day I will be able to reply for about a week or so as I'll be off for the Christmas holidays. So, if I don't catch up with you tomorrow I'll check back in in the new year.

                        • 9. Re: dropdowns and state
                          gebuh

                          I removed the params from EmployeeVList.page.xml, but I've had problems elsewhere with state and not including params in page.xml.
                          My setter for areaSelected is:



                          public void setAreaSelected(Area areaSelected) {
                               log.debug("setting areaSelected to " + areaSelected);
                               this.areaSelected = areaSelected;
                          }






                          Tim Evers wrote on Dec 22, 2010 23:58:



                          There really isn't any need for any params in your pages.xml and I'm pretty sure you don't need any param tags in your xhtml either. Unless of course you plan on making these pages bookmarkable. In which case we'll work on that later.

                          Please verify you have a setter to go with your getter, because if your setter isn't right this would be what gives the exception. Post the code for it if you can please.

                          public Area getAreaSelected() {
                              log.debug("getting areaSelected: " + this.areaSelected);
                              return areaSelected;
                          }
                          




                          added the action to the command button, but there isn't any other code behind this button, it just reloaded the page.  pages.xml just has a restrict tag for any files in the web folder:



                          <page view-id="/web/*" login-required="false">
                                    <restrict>#{sessionCriteria.authStatus(sessionCriteria.user, ctsConstants.APPLICATION_ACCESS)}</restrict>
                                    
                               </page>



                          and a bunch of exception redirects and EmployeeVList.page.xml(the entire file is at the end) is chock full of params.


                          wow, it works!  It wash the action in the commandButton, why would a page reload vs an action cause that?  I scoped EmployeeListSearchAction as a session type and now I can go anywhere and the search parameters for Area are still there.  Are there any ramifications to keeping this as scopeType session?  Or should I do this another way?  Ideally I'd like the search parameters to stay the same until the user resets them or logs off.  I have to connect other dropdowns to each other, make sure paging works correctly.  I'll update as I go along. 
                          Should my EmployeeListSearchAction class be in the action package?  Right now it's in src/main/criteria.


                          thanks again for the help.




                          EmployeeVList.page.xml:



                          <?xml version="1.0" encoding="UTF-8"?>
                          <page login-required="false"
                           xmlns="http://jboss.com/products/seam/pages"
                           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
                           xsi:schemaLocation="http://jboss.com/products/seam/pages http://jboss.com/products/seam/pages-2.2.xsd">
                           
                           <param name="firstResult" value="#{employeeVList.firstResult}"/>
                           <param name="sort" value="#{employeeVList.orderColumn}"/>
                           <param name="dir" value="#{employeeVList.orderDirection}"/>
                           <param name="logic" value="#{employeeVList.restrictionLogicOperator}"/>
                           <param name="from"/>
                          
                           <param name="jobSysid" value="#{employeeVCriteria.jobSelected}"/>
                           <param name="hubSysid" value="#{employeeVCriteria.hubIdSelected}"/>
                           <param name="companySysid" value="#{employeeVCriteria.selCompSysId}"/>
                           <param name="costCenter" value="#{employeeVCriteria.costSelected}"/>
                           <param name="myJobId" value="#{employeeVList.employeeV.myJobId}"/>
                           <param name="canBeRehired" value="#{employeeVList.employeeV.canBeRehired}"/>
                           <param name="commonName" value="#{employeeVList.employeeV.commonName}"/>
                           <param name="company" value="#{employeeVList.employeeV.company}"/>
                           <param name="currentEmp" value="#{employeeVList.employeeV.currentEmp}"/>
                           <param name="districtName" value="#{employeeVList.employeeV.districtName}"/>
                           <param name="faaBadgeNo" value="#{employeeVList.employeeV.faaBadgeNo}"/>
                           <param name="facilityId" value="#{employeeVList.employeeV.facilityId}"/>
                           <param name="facilityName" value="#{employeeVList.employeeV.facilityName}"/>
                           <param name="firstname" value="#{employeeVList.employeeV.firstname}"/>
                           <param name="lastname" value="#{employeeVList.employeeV.lastname}"/>
                           <param name="leaveType" value="#{employeeVList.employeeV.leaveType}"/>
                           <param name="middleinit" value="#{employeeVList.employeeV.middleinit}"/>
                           <param name="onLoa" value="#{employeeVList.employeeV.onLoa}"/>
                           <param name="peoplesoftId" value="#{employeeVList.employeeV.peoplesoftId}"/>
                           <param name="ptFt" value="#{employeeVList.employeeV.ptFt}"/>
                           <param name="sca" value="#{employeeVList.employeeV.sca}"/>
                           <param name="endSeparationDate" value="#{employeeVList.employeeV.beforeDate}"/>
                           <param name="startSeparationDate" value="#{employeeVList.employeeV.afterDate}"/>
                           <param name="separationDate" value="#{employeeVList.employeeV.separationDate}"/>
                           <param name="hireDate" value="#{employeeVList.employeeV.hireDate}"/>
                           <param name="startHireDate" value="#{employeeVList.employeeV.startHireDate}"/>
                           <param name="endHireDate" value="#{employeeVList.employeeV.endHireDate}"/>
                           
                          
                          </page>
                          



                          • 10. Re: dropdowns and state
                            kragoth

                            I haven't had time to prove this but I think the reason why you were having so much trouble is because you were using the param tags incorrectly. This is why I asked you to change it to an action rather then a straight refresh.


                            I would recommend getting to the point where you have nothing but redirect outcomes in your pages.xml. Remove all the param tags.


                            Start with the most basic setup and then as functionality requirements dictate add features. Things like param tags are only necessary when seeking certain functionality. (Check the Seam doco on how to use them properly as I don't use them at all).


                            I'm not really a guru with Seam when it comes to pages.xml and param tags. I came to the conclusion that the current Seam navigation system is very poorly implemented. So I wrote my own navigation manager that handles all navigation in our system.


                            Going to this extreme is obviously not necessary for everyone as many people have built successful applications using the default navigation framework.


                            I guess the biggest tip I can give you is this. When dealing with problems like this it is a good idea to abstract yourself away from your actual application and just have a small example area where you do things to increase your understanding of Seam. I have a scratch area in our codebase where I build dummy pages and Seam beans to test functionality and ideas. Trying to build things directly into your app over complicates things.


                            Another very useful thing to do is download the Seam source and using remote debug mode on your server step through what Seam is doing so you get to understand why things are not working. (You'll probly want the JSF source as well and any other dependent libs that make stepping through the code a bit easier).


                            I can tell you that once I took the time to understand Seam from the inside out I was able to identify and solve problems a lot faster.


                            I'm not a guru though. :) I think Leo van den Berg is probably one of the most knowledgeable people on this forum and is a wealth of information in many Seam related topics. So, if I can't be of much help in some areas hopefully he can enlighten us. :)


                            • 11. Re: dropdowns and state
                              gebuh

                              Ok, it's all working. 
                              I did dropdowns, dropdowns that populated other dropdowns, radios, checkboxes, some excel stuff, etc.
                              I removed most of the params from page.xml, it looks like this now:
                              EmployeeVList.page.xml:



                              <?xml version="1.0" encoding="UTF-8"?>
                              <page login-required="false"
                               xmlns="http://jboss.com/products/seam/pages"
                               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jboss.com/products/seam/pages http://jboss.com/products/seam/pages-2.2.xsd">
                               <param name="firstResult" value="#{employeeVList.firstResult}"/>
                               <param name="sort" value="#{employeeVList.orderColumn}"/>
                               <param name="dir" value="#{employeeVList.orderDirection}"/>
                               <param name="logic" value="#{employeeVList.restrictionLogicOperator}"/>
                               <param name="from"/>
                              </page>



                              all of my search fields are in a single, session scoped  class - it's not in the action package, but it still works.  Eventually this will have to be turned into a model class for users to save to the database.
                              So, area dropdown backing:



                              @Factory("rawAreaList")
                                   public List<Area> getRawAreaList(){
                                        log.debug("getting a rawAreaList");
                                        if(this.rawAreaList == null){
                                             this.rawAreaList = entityManager.createQuery("select a from Area a order by a.areaName").getResultList();
                                             log.debug("going to db for rawAreaList, total db hits = " + this.countDbHits);
                                        }
                                        return this.rawAreaList;
                                   }




                              area component:



                              <s:decorate id="areasSelectOne" template="../layout/display.xhtml">
                                                  <ui:define name="label">Area:</ui:define>
                                                  <h:selectOneMenu value="#{employeeListSearchAction.areaSelected}">
                                                       <s:selectItems var="_areas" value="#{rawAreaList}"
                                                       label="#{_areas.areaName}" noSelectionLabel="All Areas" />
                                                       <s:convertEntity/>
                                                       <a:support event="onchange" ajaxSingle = "true"  
                                                            bypassUpdates="false" process="hubSelectOne" reRender = "hubSelectOne">
                                                       </a:support>
                                                  </h:selectOneMenu>
                                                  </s:decorate>




                              For a dropdown dependent on area dropdown I did:



                              @Factory("hubList")
                                   //@Observer("areaSelectectedUpdated")
                                   public List<HubV> getHubList() { //TODO can I limit the trips to the db?
                                        log.debug("getting a hubList");
                                        if(this.areaSelected != null){
                                             log.debug("area selected is " + this.areaSelected.getAreaName() + " for hublist");
                                             this.hubList =  entityManager.createQuery("select h from HubV h where areaSysid = ?1 order by h.hubId")
                                             .setParameter(1, this.areaSelected.getSysid()).getResultList();
                                        } else {
                                             log.debug("no area selected, getting raw hublist");
                                             this.hubList =  entityManager.createQuery("select h from HubV h order by h.hubId").getResultList();
                                        }
                                        for(HubV hub : this.hubList){
                                             log.debug(hub.getAreaName() + " " + hub.getHubName());
                                        }
                                        return this.hubList;
                                   }



                              It's corresponding component:



                              <s:decorate id="hubSelectOne" template="../layout/display.xhtml">
                                             <ui:define name="label">Hub:</ui:define>
                                             <h:selectOneMenu value="#{employeeListSearchAction.hubSelected}">
                                             <s:selectItems var="_hubs" value="#{employeeListSearchAction.hubList}"
                                             label="#{_hubs.hubId} - #{_hubs.hubName}" noSelectionLabel="All Hubs"/>                    
                                             <s:convertEntity/>
                                             </h:selectOneMenu>
                                             </s:decorate>



                              to reset the search page I use a reset method that clears all the Selected fields:





                              public String reset(){
                                        this.areaSelected = null;
                                        this.hubSelected = null;
                                        this.jobTypeSelected = null;
                                        this.jobSelected = null;
                                        this.companySelected = null;
                                        this.costCenterSelected = null;
                                        this.lastNameSelected = null;
                                        this.peopleSoftIdSelected = null;
                                        this.sepDateFromSelected = null;
                                        this.sepDateToSelected  = null;
                                        this.hireDateFromSelected = null;
                                        this.hireDateToSelected = null;
                                        this.ptFtSelected = null;
                                        this.scaSelected = null;
                                        this.statusSelected = "Y";
                                        return "";
                                        
                                   }





                              and the reset component:



                              <s:button id="reset" value="Reset" includePageParams="false" action="#{employeeListSearchAction.reset}"/>




                              Something that turned out to be uber-important and stumped me for hours(it was actually more than hours, but I'd like to keep a small shred of dignity) was the importance of an equals method in the model class - this was probably the reason we got in to this mess in the 1st place. I used this for the overridden equals and hashcode methods:



                              public boolean equals(Object other) {
                                        if ((this == other))
                                             return true;
                                        if ((other == null))
                                             return false;
                                        if (!(other instanceof HubV))
                                             return false;
                                        HubV castOther = (HubV) other;
                              
                                        return ((this.getHubSysid() == castOther.getHubSysid()) || (this
                                                  .getHubSysid() != null
                                                  && castOther.getHubSysid() != null && this.getHubSysid()
                                                  .equals(castOther.getHubSysid())));
                                   }
                              
                                   public int hashCode() {
                                        int result = 17;
                              
                                        result = 37
                                                  * result
                                                  + (getHubSysid() == null ? 0 : this.getHubSysid()
                                                            .hashCode());
                                        return result;
                                   }