7 Replies Latest reply on Sep 24, 2009 8:04 PM by Susanne Jarl

    Why is all content on page reloaded when form is submitted? Problem with urlrewrite.

    Susanne Jarl Newbie

      If I have code like this:


      <h:outputText value="#{myBean.findText}"/>
      
      <h:form>
      <h:commandButton value="submit" action="#{anotherBean.execute} />
      </h:form>



      Then when the user click the button in the form, the findText method in myBean is executed first. After that the execute method in anotherBean is executed.


      My problem is why the findText method is being executed just because I post the form? Why must all content on the page be reloaded when form is submitted? Is there some way I can prevent this?


      The reason why this is a problem is because I use urlrewrite and if I post the form, the request parameter I use for urlrewrite is null and the only solution is then to include the request parameter as a inputHidden in the form. But that seems kind of stupid because, say for instance that I have a login form that are available on all pages on a website, then I have to include different inputhidden fields in the login form depending on which page I am at, since the urlrewrite parameter is different on different pages and all content is reloaded when form is submitted.


      I hope someone understands my question and thanks to all those in advance that have an answer to me.

        • 1. Re: Why is all content on page reloaded when form is submitted? Problem with urlrewrite.
          Susanne Jarl Newbie

          Maybe I should also say that I have a navigation rule after the button is clicked in the form, where I redirect the user to another page. So there is really no idea of rerendering the current page content again when the form is submitted.


          How do all you other people solve this problem? I mean it must be quite common use case to have for example a search form or a login form on all pages where you also use url rewrite. Then you would also get the same problem as I have?

          • 2. Re: Why is all content on page reloaded when form is submitted? Problem with urlrewrite.
            Leo van den berg Master

            Susanne, can you explain a bit more. It seems that you're not using Seam's full potential at the moment you are doing things like url rewrite in you pages. Try to start with the samples and see how to do this in Seam.


            Leo

            • 3. Re: Why is all content on page reloaded when form is submitted? Problem with urlrewrite.
              Susanne Jarl Newbie

              Thanks for your answer!
              I use urlrewrite because of search engine optimizations reasons. It is a lot of content of my website (a swedish recipes website) and the content must have nice URL's. For example I have a recipe of the famous swedish cake: kladdkaka and the url is www.recepten.se/recept/kladdkaka.html. If I would use the real url it would be www.recepten.se/pages/recipe.xhtml?filename=kladdkaka. I hope you understand now why I use urlrewrite - to get nice URL's.


              On the page recipe.xhtml I use the seam outjected component #{recipe} and in the Bean I have the following code:



              @RequestParameter
              private String urlId;
              
              @Out(required = false)
              private Recipe recipe;
              
              @Factory(value = "recipe")
              public void initRecipe() throws PageNotFoundException {
                 if (urlId == null) {
                   throw new PageNotFoundException(PageNotFoundException.PageType.Recipe, urlId);
                 }
                 try {
                   recipe = (Recipe) entityManager
                       .createNamedQuery(Recipe.FindBySeoUrlId)
                       .setParameter(Recipe.ParamSeoUrlId, urlId).getSingleResult();
                   }
                 catch (NoResultException e) {                    
                   throw new PageNotFoundException(PageNotFoundException.PageType.Recipe, urlId);
              }
              



              In pages.xml:


              <page view-id="/pages/recipe.xhtml">
                   <rewrite pattern="/recept/{urlId}.html"/>
              </page>




              In the xhtml that shows the recipe I would like to add a search form, like the following code:



              <h1><h:outputText escape="false" value="#{recipe.title}"/></h1>
              
              <h:form id="searchFormSidebar">
                <s:validateAll>
                   <h:inputText id="searchRecipeInput"
                        value="#{searchAction.searchString}" />
                   <h:commandButton action="#{searchAction.searchRecipes}" value="Search"/>
                </s:validateAll>
              </h:form>
              



              In pages.xml I also have this navigation rule to redirect the user to the searchresult page after clicking the Search button:


              <page view-id="/pages/*">
                 <navigation from-action="#{searchAction.searchRecipes}">
                   <redirect view-id="/pages/searchResult.xhtml" />
                 </navigation>
              </page>




              So if the user goes to the url www.recepten.se/recept/kladdkaka.html the page is rendered just fine, the urlId parameter will be kladdkaka (because of the rewrite rule) and therefore the initRecipe method will work fine.


              Then when the user click the search button the first thing that happens is that the initRecipe method is executed and the urlId is null which leads to PageNotFoundException.


              I do not really understand why the initRecipe method has to be run at all just because I post a form on the same page.


              One solution is otherwise to add the urlId as inputHidden to the form. But is that really the only way to solve this? I don't like this solution because I would like to include the searchForm with facelets on all different kind of pages (which use urlrewrite), not just the recipe type of pages and that would mean I have to make different inputHidden fields for different type of pages so I would have to implement one searchForm for each type of page.  


              Please give me some suggestions on how to solve this problem and I will appreciate it very much!


              If I have used seam in a bad way please tell me so. The code above is in production (except for the commandButton in the form which is temporarly a s:button which does not submit the form) so you can always visit the urls above if you want to see the searchForm for real. If you want more information just tell me so.


              Thanks in advance!


              • 4. Re: Why is all content on page reloaded when form is submitted? Problem with urlrewrite.
                Leo van den berg Master

                Hi Susanne,


                By no means I am an Seam-expert so I am not in the position to say if you use Seam in a bad way or not.


                The only thing I can mention is that it takes time to get the most out of Seam. At the moment I am developing a TrafficIncident site which shows all active incidents in a specific area. The application is a combination of facelets, Ajax and fully backed by Seam.


                I am trying to get rid of all rerendring to give the use an idea of using a desktop application. Some things we're doing at the moment:


                Searching for data is done through a query-component in combination with restrictions coming from the forms. An example:




                <!-- Retrieve all closed Incidents -->
                     <framework:entity-query name="incidentClosedQuery"
                          entity-manager="#{entityManager}"
                          ejbql="select i from TrafficIncident i where i.closureTimestamp is not null"
                          order="i.startTimestamp desc">
                          <framework:restrictions>
                               <value>i.startTimestamp &gt;= #{incidentCriteria.after}</value>
                               <value>i.startTimestamp &lt;= #{incidentCriteria.before}</value>
                               <value>i.eventType = #{incidentCriteria.eventType}</value>
                               <value>i.injuries = #{incidentCriteria.injuries}</value>
                               <value>i.location.road = #{incidentCriteria.road}</value>
                               <value>i.eventSeverity = #{incidentCriteria.eventSeverity}</value>
                               <value>i.dangerousGoods = #{incidentCriteria.dangerousGoods}</value>
                               <value>i.weatherCondition = #{incidentCriteria.weatherCondition}</value>
                          </framework:restrictions>
                     </framework:entity-query>
                
                



                The incident Criteria bean:




                @Name("incidentCriteria")
                @Scope(ScopeType.CONVERSATION)
                public class IncidentCriteria {
                
                     private Date          before;
                     private Date          after;
                     
                     private Road                    road;
                     
                     private EventType                eventType;
                     private BooleanEnum               injuries;
                     private WeatherCondition      weatherCondition;
                     private EventSeverity          eventSeverity;
                     private BooleanEnum               dangerousGoods;
                     
                ......
                }




                The criteria values are filled in and we're using the ajax4sf support on every change, resulting in firing the query again. The same ajax support tag contains a rerender and we create the (clickable) list of results in the same page; No page rerender, a bit of CSS-ing does the rest.


                Hopefully this helps a bit,


                If you need some additional example code , just ask,


                Tack (the only swedish I know!)


                Leo


                 

                • 5. Re: Why is all content on page reloaded when form is submitted? Problem with urlrewrite.
                  Duncan Stockdill Newbie

                  Susanne, as far as I can see you are using the rewrite functionality in the correct way. 


                  Unfortunately JSF drops the page parameters on the form submit.  This would also happen without url rewritting. By the way, your call to initRecipe is likely to be happening during the page re-rendering rather than before the form is submitted.


                  One solution is to ajax the search as follows:


                  <h1><h:outputText escape="false" value="#{recipe.title}"/></h1>
                  
                   <a:region renderRegionOnly="true">
                    <a:outputPanel id="searchResults">
                     show search results here...
                    </a:outputPanel>
                  
                    <a:form id="searchFormSidebar">
                     <s:validateAll>
                      <h:inputText id="searchRecipeInput" value="#{searchAction.searchString}" />
                      <a:commandButton action="#{searchAction.searchRecipes}" value="Search" reRender="searchResults"/>
                     </s:validateAll>
                    </a:form>
                  </a:region>
                  



                  In this example only the area inside the a:region will be processed and rendered on a search request. This has the added bonus of being faster than a full page submit/render.


                  • 6. Re: Why is all content on page reloaded when form is submitted? Problem with urlrewrite.
                    Andy Gibson Novice

                    Then when the user click the button in the form, the findText method in myBean is executed first. After that the execute method in anotherBean is executed.

                    That would probably be the JSF lifecycle, when you submit, it rebuilds the view which includes setting the values in the JSF component tree from your model. It then applies the values from the view to your component tree (applying conversion and validation) and then it calls the application and then finally renders the response.


                    Cheers,


                    Andy Gibson



                    • 7. Re: Why is all content on page reloaded when form is submitted? Problem with urlrewrite.
                      Susanne Jarl Newbie

                      I just realised that I forgot to thank you all for your help!
                      The solution works fine and I have been using it now for a couple of months.


                      So a little late: Thank you again!