JSF2 preRenderComponent is called always when f:ajax is executed

Mohsen picture Mohsen · Dec 19, 2011 · Viewed 10.4k times · Source

I have an JSF page backed by NewsBean.java which has <f:event type="preRenderComponent" listener="#{newsBean.init}" /> as bean initializer.

There is a button at the bottom of the page for sending comments which has: <f:ajax event="click" execute="@form" render="@form" listener="#{newsBean.sendComment}" /> and is surrounded by an <h:form>. When button is clicked, NewsBean.init() is always called.

My bean scope is view. Is this a valid behavior (calling always init())? How can I prevent always calling init()?

Answer

BalusC picture BalusC · Dec 19, 2011

A preRender listener is always invoked on pre render event, regardless of if it's an initial request or a postback request. Every single request has a render response phase, regardless of if it's a normal request or ajax request. So this behaviour is by specification. You need to check yourself in the listener method if it's a postback request or not by checking FacesContext#isPostback().

public void sendComment() {
    if (!FacesContext.getCurrentInstance().isPostback()) {
        // ...
    }
}

The <f:event type="preRenderXxx"> (where Xxx can be View or Component) is by the way in essence a "workaround approach" for the functional requirement of being able to invoke a bean action method after the view parameters are been processed on the initial request. In the upcoming JSF 2.2 a new <f:viewAction> tag will be introduced which should do exactly the job as intented:

<f:viewAction action="#{newsBean.sendComment}" />

This tag supports an onPostback attribute which already defaults to false:

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

JSF 2.2 will be released the first quart of 2012. Snapshot releases of JSF 2.2 are currently already available.