Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JSF ajax event queue doesn't work on action-event after change-event

The supported JSF 2.x feature of sequential processing of multiple ajax-events doesn't work for me. I got the following scenario:

  1. h:inputText (CHANGE)

    <h:inputText id="consumption_input"
       value="#{cc.attrs.consumptionInfo.consumption}">
      <f:ajax
         render="#{cc.attrs.outerRenderString}"
         event="change" listener="#{cc.handleAjaxRequest}" />
    </h:inputText>
    
  2. h:commandButton (ACTION)

    <h:commandButton
        id="startComparisonButton"
        action="#{rateComparisonBean.startRateComparison()}"
        value="#{bundle.rateResultOverview_startComparison}">
        <!-- This is to avoid mixed requests, ajax and full requests -->
           <f:ajax render="@form"/>
        </h:commandButton>
    

The events of both elements are handled correctly if triggered on it's own.

Problem occurs when both events are triggered within one click (Enter a value in textInput and afterwards click on the button). I expected this lead to two ajax request fired synchronously (CHANGE-TextField and ACTION-commandButton).

Unfortunatelly there's only one Ajax-Request (Change-TextField), the second event seems to be lost completely.

I already ensured that all pre-conditions for a h:commandButton are full filled, as pointed out here: commandButton/commandLink/ajax action/listener method not invoked or input value not updated

I would appreciate to get any hints on how to solve this problem.

Environment: Glassfish 3, Mojarra 2.1.3-FCS

like image 268
Mischa Höchsmann Avatar asked May 03 '13 16:05

Mischa Höchsmann


1 Answers

The JSF AJAX calls are asynchronous. Sending one AJAX request, in this case generated by <h:inputText> onchange event, doesn't stop JavaScipt to continue its execution and, in this case, trigger submit button click, which in its turn fires another AJAX request. Still, AJAX requests are really queued on the client, to be processed in the exact order that they were sent, which is guranteed by JSF 2.0 specification, chapter 13.3.2.

Below is my test case:

The view:

<h:form id="form">
    <h:inputText id="text" value="#{q16363737Bean.text1}">
        <f:ajax render="text2" event="change" listener="#{q16363737Bean.ajaxListenerText}"/>
    </h:inputText>
    <h:commandButton id="button" action="#{q16363737Bean.actionButton}" value="Submit">
        <f:ajax render="text1 text3" listener="#{q16363737Bean.ajaxListenerButton}"/>
    </h:commandButton>
    <br/>
    <h:outputText id="text1" value="Text 1: #{q16363737Bean.text1}."/>
    <h:outputText id="text2" value="Text 2: #{q16363737Bean.text2}."/>
    <h:outputText id="text3" value="Text 3: #{q16363737Bean.text3}."/>
</h:form>

The bean:

@ManagedBean
@ViewScoped
public class Q16363737Bean implements Serializable {

    private String text1 = "I'm text 1";//getter + setter
    private String text2 = "I'm text 2";//getter + setter
    private String text3 = "I'm text 3";//getter + setter

    public void ajaxListenerText(AjaxBehaviorEvent abe) {
        text2 = "I was modified after inputText AJAX call";
    }

    public void ajaxListenerButton(AjaxBehaviorEvent abe) {
        text1 = "I was modified after AJAX listener call of commandButton";
    }

    public void actionButton() {
        text3 = "I was modified after commandButton AJAX call";
    }

}

After examining the question for some time I indeed figured out that very rarely the command button's AJAX call had been swallowed and no UI updates were done. It seems that there should be some race conditions somewhere. It is a great question and it needs to be investigated further.

So, this is probably not an answer (although I thought it would be initially), but a proposition for a test case. And despite the fact that I faced this behaviour very infrequently, it is a real use case, and it's worth fully understanding what's going on.

like image 107
skuntsel Avatar answered Nov 04 '22 13:11

skuntsel