9 Replies Latest reply on Apr 29, 2011 12:02 PM by nbelaevski

    How to walk the viewroot before render response?

    tomba

      For various reasons, I need to change some attributes on a few components before my facelet is rendered to the browser. Hence, I'm doing this in beforePhase of RENDER_RESPONSE, and it works nicely on a POST request (so when running through the completely JSF lifecycle).

       

      However... I want to also apply my rules when I request a page for the first time. In that case, jsf processing jumps immediately to render_response, and in the beforephase of that, the ViewRoot is not filled in (it doesn't have any child components).

       

      I tried adding a public buildView() method to the faceletviewhandler, but I have now found that org.ajax4jsf.event.InitPhaseListener wraps it with an AjaxViewHandler, hard coded in the phase listener.

       

      Hence a few questions:

      - Is there a way that I can build the viewroot earlier, even on a normal GET request?

      - Or how can I implement my own InitPhaseListener to make sure it can use my own ViewHandler?

       

       

      Thanks,

      Steven

        • 1. How to walk the viewroot before render response?
          tomba

          No straightforward solution then?

          • 2. Re: How to walk the viewroot before render response?
            boy18nj

            Hi Steven,

             

            If you want to walk the viewroot before rendering response, you need to use system event, do something like this-

             

            <f:view>

            <f:event type="preRenderView" listener="#{user.changeLocale}"/>

            <h:head>

            <title>...</title>

            </h:head>

            <h:body>

            ...

            </h:body>

            </f:view>

             

             

             

            public String changeLocale(ComponentSystemEvent event) {

            FacesContext context = FacesContext.getCurrentInstance();

            context.getViewRoot().setLocale(new Locale(languageCode));

            return null;

            }

             

             

             

            Note that system events are available only in JSF 2.0

            • 3. How to walk the viewroot before render response?
              nbelaevski

              Hi Steven,

               

              Try specifying phaseListener via view root attribute (f:view tag). This will work in JSF 1.2

              • 4. How to walk the viewroot before render response?
                tomba

                Aman, I'm aware of the system but I'm stuck with JSF1.2 for now.

                 

                Anyway, in my case context.getViewRoot() is not null either, so I could do a setLocale() without problems. However, context.getViewRoot().getChildren() is empty in beforephase(RENDER) when it's a regular GET request. And my problem is exactly that I need to loop the children in the beforephase or RENDER_RESPONSE...

                 

                Nick, will a phaselistener on f:view make a difference from one specified in faces-config? I would find that very odd, but I can try...

                 

                 

                Thanks

                • 5. How to walk the viewroot before render response?
                  nbelaevski

                  Yes, different. As a complete solution, you can use PhaseListener declared in faces-config.xml to add PhaseListener to created view root,

                  • 6. Re: How to walk the viewroot before render response?
                    tomba

                    Nick, I'm stunned.

                    Previously I had my listener added to the faces-config.xml, but my viewroot had 0 children every time I was in beforephase (render) on a GET request.

                     

                    Now, by adding <f:phaseListener type="...."/> within the <f:view>...</f:view>, things are now working properly.

                    I'm still curious to know why this is. Can you explain that?

                    It's also annoying, as this would require me to add this <f:phaseListener> element to each of my pages

                    • 7. Re: How to walk the viewroot before render response?
                      nbelaevski

                      Steven,

                       

                      This is how JSF works - see details in spec.

                       

                      And once again:

                       

                      >> As a complete solution, you can use PhaseListener declared in faces-config.xml to add PhaseListener to created view root/

                      • 8. Re: How to walk the viewroot before render response?
                        tomba

                        After running this solution for a bit, I have bumped into a strange problem where ui:repeat appears not to be expanded when my phaselistener in before RENDER_RESPONSE kicks in. Hence, at the time I run through the components in the phaselistener, I have only one component in the repeat, whereas on screen I get 8 elements in the repeat (the latter being correct as I have 8 elements in the list).

                         

                        Still trying to work out why exactly, but do you have any idea why ui:repeat seems to behave differently from other JSF components?

                        • 9. How to walk the viewroot before render response?
                          nbelaevski

                          Steven,

                           

                          ui:repeat is one of so-called 'stamped' components - only one instance of component (with children components) is present in component tree, and nested components are processed inside iteration.