1

We have complex JSF page composed of repeatable primefaces components like p:dataTable, p:tabView, ui:repeat, c:foreach, javascript, etc. The page consists of two separate forms with ids formHeader and formBPM What is strange, execution of h:commandButton, which is placed in form formHeader, results in calling all getter, render and test expressions in form formBPM. Expressions are called both in RestoreView and RenderResponse phases.

<h:form id="formHeader" enctype="multipart/form-data;charset=UTF-8">            
 <h:commandButton value="Call this"  type="button">
                        <f:ajax execute="@this"  />
 </h:commandButton>
</h:form>
<h:form id="formBpm">
 <p:tabView...>
  <p:dataTable....>
  </p:dataTable>
 ....
 </p:tabView>
</h:form>

Original page is too complex and is overloaded by dynamic components and java scripts. But I have modeled the above page in simplified structure and checked logging

<h:form id="formHeader" enctype="multipart/form-data;charset=UTF-8">            
    <h:commandButton value="Call this"  type="button">
                <f:ajax execute="@this"  />
    </h:commandButton>
    <h:commandButton value="Call form render form"  type="button">
                <f:ajax execute="@form" render="@form"/>
    </h:commandButton>
    <h:commandButton value="Call formBpm"  type="button">
                <f:ajax execute=":formBpm"/>
    </h:commandButton>
    <h:commandButton value="Call formBpm render formBpm"  type="button">
                <f:ajax execute=":formBpm" render=":formBpm"/>
    </h:commandButton>
    <p:outputLabel id="labelThisid" value="#{testBean.varThis}"></p:outputLabel>
</h:form>
<h:form id="formBpm">
    <p:outputLabel id="labelid" value="#{testBean.var1}"></p:outputLabel>
    <p:tabView  id="tabViewId" >
        <p:tab id="tabId1" title="#{testBean.tab1}">
        </p:tab>
        <p:tab id="tabId2" title="#{testBean.tab2}" rendered="#{testBean.tab2Show}">
        </p:tab>
    </p:tabView>
</h:form>

According to log, on simplified page no getters are executed on "Call this" click, they are executed only if appropriate form is rendered, not executed. Moreover, getters are called only on RenderResponse phase. What may be the reason of inappropriate getters calling on original complex page?

Primefaces 6.1 jBoss EAP 6.4 JSF Mojarra 2.1.28

Alister
  • 91
  • 8
  • This might be interesting although not telling why an interaction in form A triggers stuff in form B: https://stackoverflow.com/questions/2090033/why-jsf-calls-getters-multiple-times – Selaron Jan 30 '19 at 20:07
  • Add a jsf lifecycle debugger and check in which lifecycle this happens, Restoreview most likely – Kukeltje Jan 31 '19 at 07:20
  • Thank for the proposition, there is already the jsf lifecycle debugger. Getters are called both at RESTORE_VIEW and RENDER_RESPONSE phases. – Alister Jan 31 '19 at 07:52
  • I expected the RESTORE_VIEW (not that my expectation is right, just with my limited knowledge I just expected it). The RENDER_RESPONSE I did not expect. Is there by chance a form around these forms. – Kukeltje Jan 31 '19 at 09:27
  • And can you try making an [mcve] with explicit id's on each jsf tag so it shows better in the http request/response when debugging? And what is your JSF implementation and version? And the PF one? And does it work when not using PrimeFaces elements in the page or PF not at all? – Kukeltje Jan 31 '19 at 09:38
  • I have added information about PF and JSF versions. My modeled simplified good working page, where getter expressions are called only in rendered containers, contains PF too. So, PF itself does not influence the behaviour. We have p:layout in complex page, I will try to ad them on modelled page. – Alister Jan 31 '19 at 10:22
  • Like requested before: Is there by chance a form around these forms in the 'complex page'? – Kukeltje Jan 31 '19 at 10:24
  • And if the simplified page does not show the problem, you over-simplified it, try making a [mcve] – Kukeltje Jan 31 '19 at 10:34
  • There is no outer form, only divs p:layoutUnits and p:layout. I am transferring main components from original page to model. – Alister Jan 31 '19 at 10:50
  • Is the enctype form attribute relevant for your issue? How does it behave without? – Selaron Jan 31 '19 at 12:57
  • I have found at least one case when expression is executed outside container, it is when is used. In this case expressions from test tag are executed. – Alister Jan 31 '19 at 14:43
  • Selaron, you are right, enctype attribute is neither relevant no principal in the above case. – Alister Jan 31 '19 at 15:56

1 Answers1

0

The solution is that expressions in jstl tags are executed regardless of execution container of clicked commandButton. In our original page the same expressions were used sometimes both as value getters and in test expressions of jstl tags. So, in below code expression #{testBean.tab2Show} is executed when button "Call this" is clicked. Besides, test expressions are called twice in RestoreView and in RenderResponse phases.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html 
    xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:c="http://java.sun.com/jsp/jstl/core"
    xmlns:p="http://primefaces.org/ui"
    >     
    <h:head>
        <h2>Check jstl with AJAX </h2>
    </h:head>    
    <h:body>
        <h:form id="formHeader" enctype="multipart/form-data;charset=UTF-8">            
            <h:commandButton value="Call this">
                        <f:ajax execute="@this"  />
            </h:commandButton>
            <p:outputLabel id="labelThisid" value="#{testBean.varThis}"></p:outputLabel>
        </h:form>
        <h:form id="formBpm">
            <c:if test="#{testBean.tab2Show}">
                <p:outputLabel id="labelid" value="#{testBean.var1}"></p:outputLabel>
            </c:if>
            <p:tabView  id="tabViewId" >
                <p:tab id="tabId1" title="#{testBean.tab1}">
                </p:tab>
                <p:tab id="tabId2" title="#{testBean.tab2}">
                </p:tab>
            </p:tabView>
        </h:form>
    </h:body>
</html>

TestBean

public String getVar1() {
    log.debug("getVar1");
    return "getVar1";
}

public String getVarThis() {
    log.debug("getVarThis");
    return "getVarThis";
}

public String getTab1() {
    log.debug("getTab1");
    return "getTab1";
}

public String getTab2() {
    log.debug("getTab2");
    return "getTab2";
}

public boolean isTab2Show() {
    log.debug("isTab2Show");
    return true;
}

PhaseListener log on clicking button "Call this"

18:30:27,298 DEBUG [utils.LifeCycleListener:26] - START PHASE RESTORE_VIEW 1
18:30:27,300 DEBUG [utils.TestBean:48] - isTab2Show
18:30:27,300 DEBUG [utils.LifeCycleListener:30] - END PHASE RESTORE_VIEW 1
18:30:27,301 DEBUG [utils.LifeCycleListener:26] - START PHASE APPLY_REQUEST_VALUES 2
18:30:27,302 DEBUG [utils.LifeCycleListener:30] - END PHASE APPLY_REQUEST_VALUES 2
18:30:27,303 DEBUG [utils.LifeCycleListener:26] - START PHASE PROCESS_VALIDATIONS 3
18:30:27,303 DEBUG [utils.LifeCycleListener:30] - END PHASE PROCESS_VALIDATIONS 3
18:30:27,303 DEBUG [utils.LifeCycleListener:26] - START PHASE UPDATE_MODEL_VALUES 4
18:30:27,303 DEBUG [utils.LifeCycleListener:30] - END PHASE UPDATE_MODEL_VALUES 4
18:30:27,303 DEBUG [utils.LifeCycleListener:24] - START INVOKE_APPLICATION
18:30:27,303 DEBUG [utils.LifeCycleListener:26] - START PHASE INVOKE_APPLICATION 5
18:30:27,303 DEBUG [utils.LifeCycleListener:30] - END PHASE INVOKE_APPLICATION 5
18:30:27,303 DEBUG [utils.LifeCycleListener:26] - START PHASE RENDER_RESPONSE 6
18:30:27,303 DEBUG [utils.TestBean:48] - isTab2Show
18:30:27,304 DEBUG [utils.LifeCycleListener:30] - END PHASE RENDER_RESPONSE 6
Kukeltje
  • 12,223
  • 4
  • 24
  • 47
Alister
  • 91
  • 8
  • I would not have expected this when ajax is used... Sure there is not something else that makes the ajax fail and do a full page refresh? – Kukeltje Jan 31 '19 at 16:11
  • I have added full code to the answer, so you can check. – Alister Jan 31 '19 at 16:37
  • Thanks, I might try. Very curious https://stackoverflow.com/questions/3342984/jstl-in-jsf2-facelets-makes-sense states jstl is 'run' in view-build and https://stackoverflow.com/questions/31890433/whats-the-view-build-time says the view build is not a phase. And what if you remove the `type="button" on the commandButton? – Kukeltje Jan 31 '19 at 20:27
  • They state that view build can happen on different phases. In my case of post request view build is executed during the restore view phase and render response phase. Removing type="button" does not change the log. – Alister Feb 01 '19 at 09:37
  • Where is that stated? I seem to not be able to find that info. Update, I did find it, somewhere else... Hmmm... new info for me. But then the question remains, why does it not always happen... – Kukeltje Feb 01 '19 at 09:39