4 Replies Latest reply on Apr 28, 2009 6:00 AM by Nick Belaevski

    Inversion of re-render (subscription based re-rendering): Wh

    Francisco Jose Peredo Noguez Master

      Anyone that has used Richfaces knows that to rerender something, oneneeds to refer to it by id.

      Now, this is (in my opinion) an useful approach but also a very limited one, specially if componentization and code reuse are important goals during development

      Lets say I build a page (lets call it root page), that has a subview with a modalPanel, that includes a facelet component, that has a subview with modalPanel that includes another facelet component, and, when something is done here, I one another control, in the root page to be rerendered

      Now, I could of course pass along the ids of the component I need to be re-rendered, but... what if I need another component to be re-rendered too? do I pass along its id too? and what if the other component is also inside (a different) subview with a modalPanel, that includes a different facelet component... then all this id "passing" gets really messy, and creates dependencies in components that could otherwise be decoupled... and to make things worse, using meaningful ids in JSF is not considered a good practice, because meaningful ids (specially if used in name container like the subviews) rapidly increase the size of the pages (because they concatenate to ids of all the contained controls), contributing to bandwidth waste .

      Now, I have a proposal, what if re-rendering were to work in an "inversed" way: instead of "A" saying that it will re-render "B", we say that "B" will be re-rendered when something (maybe "A") says so by broadcasting event "C".

      This would mean that "A" no longer needs to know the name of "B" and "B" wouldn’t need to know the name of "A" either, it would only need to know that it should re-render itself it something, somewhere broadcasted the event "C"

      Am I making sense here? Is this doable? Or am I not seem a major limitation in JSF technology that prevents this from being built? (I am no expert in JSF, so I really can not say, but I do know that an event subscription based re-rendering engine would be a really nice tool to have)

      What do you think?

        • 1. Re: Inversion of re-render (subscription based re-rendering)
          Francisco Jose Peredo Noguez Master

          So, for example, instead of saying:

          
           <a4j:commandButton value="update" reRender="infoBlock"/>
          
           ...
          
           <h:panelGrid id="infoBlock">
          
           ...
          
           </h:panelGrid>
          
          



          we would be able to say



          
           <a4j:commandButton value="update" reRenderEvent="stuffIsUpdated"/>
          
           ...
           <a4j:region reRenderEvent="stuffIsUpdated">
           <h:panelGrid >
          
           ...
          
           </h:panelGrid>
           </a4j:region>
          



          o maybe:


           <a4j:commandButton value="update" reRenderEvent="stuffIsUpdated"/>
          
           ...
           <h:panelGrid >
           <a4j:support reRenderEvent="stuffIsUpdated"/>
          
           ...
          
           </h:panelGrid>
          
          
          


          This approach, has (IMHO) some key advantages:

          First there is no need to have an id for the panelGrid (we can leave it as a short bandwith saving autogenerated id), another (decoupling) advantage is that the commandButton does not need to know that the panelGrid exists, it does not care if it is in the same .xhtml file, if it is inside many calls to ui:include, and new "subscribers" to the stuffIsUpdated can be easily added, without having to modified the code of the commandButton.

          So.... what do you think about this? Is it doable?

          • 2. Re: Inversion of re-render (subscription based re-rendering)
            Nick Belaevski Master

            Hello,

            Here is the idea just from the top of head:

            <a4j:commandLink value="First">
             <f:setPropertyActionListener value="firstEvent" target="#{eventBean.event}"/>
             </a4j:commandLink>
             <br />
             <a4j:commandLink value="Second">
             <f:setPropertyActionListener value="secondEvent" target="#{eventBean.event}"/>
             </a4j:commandLink>
            
             <a4j:outputPanel layout="block">
             <f:attribute name="ajaxRendered" value="#{eventBean.event == 'firstEvent'}"/>
            
             First event panel:
             <h:outputText value="#{time}">
             <f:convertDateTime type="time" timeStyle="long" />
             </h:outputText>
             </a4j:outputPanel>
            
             <a4j:outputPanel layout="block">
             <f:attribute name="ajaxRendered" value="#{eventBean.event == 'secondEvent'}"/>
            
             Second event panel:
             <h:outputText value="#{time}">
             <f:convertDateTime type="time" timeStyle="long" />
             </h:outputText>
             </a4j:outputPanel>
            

            <managed-bean>
             <managed-bean-name>time</managed-bean-name>
             <managed-bean-class>java.util.Date</managed-bean-class>
             <managed-bean-scope>request</managed-bean-scope>
             </managed-bean>
            
             <managed-bean>
             <managed-bean-name>eventBean</managed-bean-name>
             <managed-bean-class>EventBean</managed-bean-class>
             <managed-bean-scope>request</managed-bean-scope>
             </managed-bean>


            EventBean holds generated events (in my simple case it stores only one event):
            public class EventBean {
            
             private String event;
            
             public String getEvent() {
             return event;
             }
            
             public void setEvent(String event) {
             this.event = event;
             }
            }


            The whole thing should be easy to implement creating two Facelets tags: one for event producer, the other for event consumer.

            Disadvantages of this approach: explicit setting of IDs to re-render together with limitToList="true" is a workaround suggested for this issue: https://jira.jboss.org/jira/browse/RF-3341. So you won't be able to apply this workaround using the code I've posted.

            What do you think?

            • 3. Re: Inversion of re-render (subscription based re-rendering)
              Francisco Jose Peredo Noguez Master

               

              "nbelaevski" wrote:
              Hello,

              Here is the idea just from the top of head:
              
              
              
              Very interesting, I didn't know it was possible to do something like this. I'll test it ASAP :-) .
              
              
              
              
              The whole thing should be easy to implement creating two Facelets tags: one for event producer, the other for event consumer.
              
              
              
              Just to be clear on this: All that would have to be done would be wrapping the code you just write with those faceletes tags (and creating the "EventBean" class?
              
              
              
              
              
              Disadvantages of this approach: explicit setting of IDs to re-render together with limitToList="true" is a workaround suggested for this issue: https://jira.jboss.org/jira/browse/RF-3341. So you won't be able to apply this workaround using the code I've posted.
              
              
              I am sorry but I don't really get what are you saying here, in you example code none of you tags has is IDs explicitly set... Could you please post an example that shows when IDs would need to be explicitly set?
              
              Assuming there is a case when IDs will need to be explicitly set...
              
              
              
              
              What do you think?
              
              
              Great, thanks for the answer
              
              
              
              
              
              


              • 4. Re: Inversion of re-render (subscription based re-rendering)
                Nick Belaevski Master

                 

                "luxspes" wrote:

                Just to be clear on this: All that would have to be done would be wrapping the code you just write with those faceletes tags (and creating the "EventBean" class?

                Yes.

                "luxspes" wrote:
                I am sorry but I don't really get what are you saying here, in you example code none of you tags has is IDs explicitly set... Could you please post an example that shows when IDs would need to be explicitly set?

                Assuming there is a case when IDs will need to be explicitly set...

                The approach provided uses dynamic "ajaxRendered" attribute to implement re-render on event. But if limitToList=true then ajaxRendered=true components are not re-rendered if they are not explicitly specified in a set of components to be re-rendered, so this approach will break in this case.