8

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

Community
  • 1
  • 1

2 Answers2

4

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.

skuntsel
  • 11,624
  • 11
  • 44
  • 67
0

First thanks allot for the fast and sophisticated reply.

A second test from the scratch pointed out that ajax-events are queued properly.

So again I checked the more complex scenario described above. The cause for the skipped event seams to be related to our 'busy overlay'. Think of it as a bunch of JavaScript which disables form-elements and applies an overlay during long runing ajax requests. This is done by applying an jsf.ajax.addOnEvent call-back.

Anyway, even we disable some controls, after 'success' the form is in a proper state and the second event could be handled.

Currently I assume that the 'temporarily' disabled button compromises the related action event which should be carried out afterwards.

We are currently analyzing the issue and I will post the final result asap.

  • Did you find a solution? I know this was posted quite a bit back but I am facing the same issue. I can't find a solution without removing the "busy overlay" or putting a delay on it. – Mitchell Brooks Dec 26 '17 at 21:30
  • Unfortunatelly not and the business we wanted to run it for doesn't exist anymore. But it's not only because the overlay:-) – Mischa Höchsmann Jun 15 '19 at 19:37