13 Replies Latest reply on Feb 8, 2011 3:00 AM by baz

    Brain Teaser! JSF is broken!!!

    hurzeler

      Here it goes. Consider the simple form below that collects first and lastname. Except we don't show the lastname input field to start off with. Once switching to Advanced the input field for lastname shows up but does not get submitted when the Go button is clicked.


      Wierd or what? I guess this happens because the lastname input field is not rendered to start off with.


      Does anyone know how to get this working?


      BTW it is JSF1.2, SEAM.2.2.1.Final, JBoss5.1.


      <!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
          "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
      <ui:composition xmlns="http://www.w3.org/1999/xhtml"
           xmlns:ui="http://java.sun.com/jsf/facelets"
           xmlns:f="http://java.sun.com/jsf/core"
           xmlns:h="http://java.sun.com/jsf/html">
      
           <h:form>
                <h:selectOneRadio value="#{miniBean.searchType}">
                     <f:selectItem itemLabel="Basic" itemValue="Basic" />
                     <f:selectItem itemLabel="Advanced" itemValue="Advanced" />
                </h:selectOneRadio>
                <h:outputLabel value="Firstname:" for="firstname" />
                <h:inputText id="firstname" value="#{miniBean.firstName}" />
                <h:outputLabel value="Lastname:" for="lastname"
                     rendered="#{miniBean.searchType.equals('Advanced')}" />
                <h:inputText id="lastname" value="#{miniBean.lastName}"
                     rendered="#{miniBean.searchType.equals('Advanced')}" />
      
                <h:commandButton value="Go" view="/searchRules.xhtml" />
           </h:form>
           <h:outputText value="Firstname: #{miniBean.firstName}" />
           <h:outputText value="Lastname: #{miniBean.lastName}" />
      </ui:composition>
      



      with a backing bean


      import org.jboss.seam.annotations.Name;
      
      @Name("miniBean")
      public class MiniBean  {
           
           private String firstName;
           private String lastName;
           private String searchType = "Basic";
      
           public void setSearchType(String searchType) {
                this.searchType = searchType;
           }
      
           public String getSearchType() {
                return searchType;
           }
      
           public void setFirstName(String firstName) {
                this.firstName = firstName;
           }
      
           public String getFirstName() {
                return firstName;
           }
      
           public void setLastName(String lastName) {
                this.lastName = lastName;
           }
      
           public String getLastName() {
                return lastName;
           }
           
      }
      



        • 1. Re: Brain Teaser! JSF is broken!!!
          yahawari

          - try @Autocreate after @Name(miniBean)
          - h:command button does NOT have view attribute. use action instead

          • 2. Re: Brain Teaser! JSF is broken!!!
            hurzeler

            Yes my mistake.
            It should be just:



            <h:commandButton value="Go" />



            I tried your suggestion but the behavior is still as originally observed i.e. not working.


            Further I can't see why @AutoCreate would be necessary. Seam does create the MiniBean correctly and JSF propagates the values ok (with the exception of the lastname of course).
            :-(

            • 3. Re: Brain Teaser! JSF is broken!!!
              baz

              Hello,
              First, before you use so manch Bangs please think twice.


              Look at your backing bean. This bean will be recreated for each request.
              Your Example will work when you use a longer Scope. E.g. Session
              Hope this helps

              • 4. Re: Brain Teaser! JSF is broken!!!
                monkeyden

                How can you tell it's not submitted?  You have no action attribute in your commandButton.


                http://www.jsftoolbox.com/documentation/help/12-TagReference/html/h_commandButton.html

                • 5. Re: Brain Teaser! JSF is broken!!!
                  hurzeler
                  Well you just have to set a breakpoint at the setLastName method and you will see that it does NOT get called. The setFirstName however does. This means that <h:commandButton value="Go"/> submits the form correctly but JSF seems to be unaware of the previously not rendered input field i.e. lastName.
                  Extending the scope of the bean to a page scope seems to fix the problem.
                  • 6. Re: Brain Teaser! JSF is broken!!!
                    hurzeler

                    Hi Carsten,
                    You are the winner! Extending the scope of the bean to a page scope fixes the issue.


                    However I am a little unclear why this is necessary. As you say the bean gets reinstantiated (event scope) and JSF sets the fields. JSF also restores the page on the way out with all the values very much as SeamGen pages work. But this only seems to work if the input fields are rendered from the start. Hence something in the restore mechanism of JSF is not working the why I would expect it to work. Any ideas?


                    Thanks again!

                    • 7. Re: Brain Teaser! JSF is broken!!!
                      bashan

                      Hi Bernhard,


                      I usually use request scope beans and encountered the same problem many times. I agree there is some kind of a problematic behavior of JSF. You can workaround this issue using the display: none property of the style property.

                      • 8. Re: Brain Teaser! JSF is broken!!!
                        hurzeler

                        “display: none” is a great idea! Request scope however is not a Seam scope as far as I know?

                        • 9. Re: Brain Teaser! JSF is broken!!!
                          yahawari

                          does ur view has a corresponding .page.xml file ?.


                          we need to look at the



                              <param name="..." value="..."/>
                          



                          • 10. Re: Brain Teaser! JSF is broken!!!
                            hurzeler

                            No xxx.page.xml file required.


                            Just annotate the bean with @Scope(ScopeType.PAGE) and the problem goes away.


                            JSF just does something wierd in the restore phase...

                            • 11. Re: Brain Teaser! JSF is broken!!!
                              baz

                              Hi Bernhard,
                              Your bean sets the value of searchtype to basic whenever it is created.
                              That is the problem.
                              You expect a kind of state saving, am i right.

                              • 12. Re: Brain Teaser! JSF is broken!!!
                                hurzeler

                                Yes I expect the state to be saved. JSF actually rebuilds the new instance of the bean with the correct values from the DOM (with the exception of the non-rendered input field). Try it! it actually works. That is the trick actually. Normally an Event scope is sufficient for these beans. If you have thousands of concurrent users that is actually a cruitial point. Don't keep instantiated objects laying around.

                                • 13. Re: Brain Teaser! JSF is broken!!!
                                  baz

                                  For my knowledge, rstoring of the view and restoring of the beans are two different concepts.
                                  A bean is restored from the scope(session or page)
                                  And the view is restored from a saved state(client or server)


                                  What you do expect is: The view should restore all values, even if they are not rendered.


                                  If you have such a requirement, you must fiddle with your beans. Assign them the correct scope or initialize them in a better way.
                                  Try to use a constructor and a method annotated with @Create to see what is going on.