3

Basically, I need to call a method after RENDER_RESPONSE phase. I tried this:

<f:phaseListener type="com.examples.MyPhaseListener"/>

The above listener is listenening all the time even for ajax calls. I tried

rendered="#{!facesContext.postback}" 

but its not applicable here I guess. So I tried this as mentioned in this post Is it possible to disable f:event type="preRenderView" listener on postback?:

public void beforePhase(PhaseEvent pe) {
 if (!FacesContext.getCurrentInstance().isPostback()) {
          //do nothing
      }
}

public void afterPhase(PhaseEvent pe) {
      if (!FacesContext.getCurrentInstance().isPostback()) {
           if (pe.getPhaseId() == PhaseId.RENDER_RESPONSE) {
               //call a method
            }
      }
}

It is working but is there any other way to disable the listener after the initial response? I also tried preRenderComponent but it is called in before RENDER_RESPONSE phase and it looks like it is not rendering response until the method is out of the stack ( basically it is not asynchronous). So I feel there is not much advantage of SystemEvents like preRenderView and preRenderComponent when compared to calling them in PostConstruct.

Community
  • 1
  • 1
Ravi Kadaboina
  • 8,494
  • 3
  • 30
  • 42
  • "Not on ajax-requests" and "not on postback" are not the same, which one do you need? Also, what exactly do you mean by "asynchronous"? JSF is implemented as a servlet, and all JSF code assumes it will run in the request processing thread, so asynchronously interacting with JSF is not intended usage. – meriton Mar 15 '12 at 22:23
  • And what do you mean by "calling events in PostConstruct"? – meriton Mar 15 '12 at 22:26
  • 2
    Ajax requests are implicitly always postbacks. But not all postbacks are necessarily ajax requests. – BalusC Mar 15 '12 at 22:30

1 Answers1

3

There's not really another way to achieve the functional requirement. A Filter wherein you do the job after the chain.doFilter(request, response) call should also work, but this doesn't give you access to the faces context (although a lot of JSF specific data is also available by the standard Servlet API).

As to your phase listener, if you need to get it to listen on render response only, then add

public PhaseId getPhaseId() {
    return PhaseId.RENDER_RESPONSE;
}

This way you don't need to check the current phase in the listener methods.

public void afterPhase(PhaseEvent event) {
    if (!FacesContext.getCurrentInstance().isPostback()) {
        // ...
   }
}

In the upcoming JSF 2.2 there will by the way be a new tag which understands isPostback(), the <f:viewAction>:

<f:viewAction action="#{bean.action}" onPostback="false" />

However, it runs during invoke action phase only.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • Thank you for the hint, I will atleast use it to listen on render response only and phase listener was a better option for me than a filter. – Ravi Kadaboina Mar 15 '12 at 23:34
  • 2
    @BalusC you made JSF easy to deal with I'm following all your answers thanks so much ;) – Youans Nov 19 '13 at 11:43