1 Reply Latest reply on Jun 22, 2009 4:10 PM by christophea

    page parameters side effect

    christophea

      I sometimes had strange behaviors with page parameters and only recently found out where they come from.


      Let's take a simple example.


      I have an application for managing events - amongst other. I want to use GET pages with page parameters, some that pages can be bookmarked, etc... Every page mapped under /event/ requires an eventId used to initialize the context of the event (session or conversation mapped bean).


      <page view-id="/event/*" login-required="true">
         <param name="eventId" value="#{eventContext.eventId}" required="true"/>
      </page>
      



      Then some page (/event/.../somePage.xhtml) in the event directory used some bean defined as following


      @Name("someBean")
      public class SomeBean
      {
           
           @In
           EventContext eventContext
           
           @Create
           public void init()
           {
                // do some initialization based on context
                doSomeInitBasedOnContext(eventContext); // eventContext has correctly bean initialized with eventId
           }
           
      }
      



      And everything works fine.


      Now, let's imagine that we want to set some properties of someBean via page parameters


      <page view-id="/event/../somePage.xhtml">
           <param name="mode" value="#{someBean.mode}"/>
      </page>
      

       


       
      @Name("someBean")
      public class SomeBean
      {
           
           @In
           EventContext eventContext
           
           @Create
           public void init()
           {
                // do some initialization based on context
                doSomeInitBasedOnContext(eventContext); // eventContext has not been initialized with eventId !
           }
           
           public String getMode() { ... }
           public void setMode() { ... }
           
      }  
      



      Use of a page parameter breaked the code.


      In Pages.java Seam applies parameters from the least specific view to the most specific, so one's could expect that when someBean calls eventContext, this last one has correctly been initialized.


      But it is not.



      In Pages.java:


      public void postRestore(FacesContext facesContext)
      {
           // ...
           
           if ( convertAndValidateStringValuesInPageContext(facesContext) ) 
            {
               Validation.instance().fail();
               //and don't apply them to the model
            }
            else
            {   
               //finally apply page parameters to the model
               //(after checking permissions)
               applyConvertedValidatedValuesToModel(facesContext);
            }
      }
      



      and converting and validating has an unexpected side effect : they instanciate components.


      First, when no converter is specified :


      In Expression.java:


      public Class<T> getType()
      {
           // QUESTION shouldn't we use the type provided in the constructor?
           return (Class<T>) toUnifiedValueExpression().getType( getELContext() );
      }
      



      Then, for validation (retrieving hibernate validator annotations) :


      In Param.java:


      invalidValues = Validators.instance().validate( valueExpression.toUnifiedValueExpression(), elContext, value );
      



      Is instanciation mandatory for validating and converting ?


      Or isn't it possible to swap things :


      instead of doing: convertion+validation for every pages, then applying param value for every pages.


      do: for every pages, convert+validate then apply param value.


      Any one faced with such a problem ? any thought on the matter ?