title: Using a4j:support to update the model and view, ready for the next button/submit action
body: <h1>The Problem</h1>
  
  <p>We have a swing based front end for an enterprise application and now are implementing a (for now simpler) JSF/Seam/Richfaces front end for it.</p>
  
  <p>Some of the pages include fields that, when edited, should cause other fields to change as a result. We need this change to be shown to the user immediately (i.e. they should not have to press a button or anything).</p>
  
  <p>I have implemented this successfully using <code>h:commandButton</code> and by adding <code>onchange="submit()"</code> to the fields that cause other fields to change. That way, a form submit occurs when they edit the field, and the other fields are updated as a result.</p>
  
  <p>This works fine functionally, but especially when the server is under significant load (which happens often) the form submits can take a long time and our users have been continuing to edit fields in the meantime which then get reverted when the responses to the <code>onchange="submit()"</code> requests are rendered.</p>
  
  <p>To solve this problem, I was hoping to achieve something where:</p>
  
  <ol>
  <li>Upon editing the field, if required, <strong>only that field</strong> is processed and <strong>only the fields it modifies</strong> are re-rendered (so that any other edits the user has made in the meantime do not get lost).</li>
  <li>Upon pressing a button, <strong>all fields</strong> are processed and re-rendered as normal.</li>
  </ol>
  
  <h1>The (Unstable) Solution</h1>
  
  <p>Okay, I think it might be easiest to show a bit of my page first. Note that this is only an excerpt and that some pages will have many fields and many buttons.</p>
  
  <pre><code>&lt;a4j:form id="mainForm"&gt;
      ...
      &lt;a4j:commandButton id="calculateButton" value="Calculate" action="#{illustrationManager.calculatePremium()}" reRender="mainForm" /&gt;
      ...
      &lt;h:outputLabel for="firstName" value=" First Name" /&gt;
      &lt;h:inputText id="firstName" value="#{life.firstName}" /&gt;
      ...
      &lt;h:outputLabel for="age" value=" Age" /&gt;
      &lt;h:inputText id="age" value="#{life.age}"&gt;
          &lt;f:convertNumber type="number" integerOnly="true" /&gt;
          &lt;a4j:support event="onchange" ajaxSingle="true" reRender="dob" /&gt;
      &lt;/h:inputText&gt;
      &lt;h:outputLabel for="dob" value=" DOB" /&gt;
      &lt;h:inputText id="dob" value="#{life.dateOfBirth}" styleClass="date"&gt;
          &lt;f:convertDateTime pattern="dd/MM/yyyy" timeZone="#{userPreference.timeZone}" /&gt;
          &lt;a4j:support event="onchange" ajaxSingle="true" reRender="age,dob" /&gt;
      &lt;/h:inputText&gt;
      ...        
  &lt;/a4j:form&gt;
  </code></pre>
  
  <p>Changing the value of <code>age</code> causes the value of <code>dob</code> to change in the model and vice versa. I use <code>reRender="dob"</code> and <code>reRender="age,dob"</code> to display the changed values from the model. This works fine.</p>
  
  <p>I am also using the global queue to ensure ordering of AJAX requests.</p>
  
  <p>However, the <code>onchange</code> event does not occur until I click somewhere else on the page or press tab or something. This causes problems when the user enters a value in say, <code>age</code>, and then presses <code>calculateButton</code> <strong>without</strong> clicking somewhere else on the page or pressing tab.</p>
  
  <p>The <code>onchange</code> event does appear to occur first as I can see the value of <code>dob</code> change but the two values are then reverted when the <code>calculateButton</code> request is performed.</p>
  
  <p>So, finally, to the question: Is there a way to ensure that the model and view are updated completely before the <code>calculateButton</code> request is made so that it does not revert them? Why is that not happening already since I am using the AJAX queue?</p>
  
  <h1>The Workarounds</h1>
  
  <p>There are two strategies to get around this <em>limitation</em> but they both require bloat in the facelet code which could be confusing to other developers and cause other problems.</p>
  
  <h2>Workaround 1: Using a4j:support</h2>
  
  <p>This strategy is as follows:</p>
  
  <ol>
  <li>Add the <code>ajaxSingle="true"</code> attribute to <code>calculateButton</code>.</li>
  <li>Add the <code>a4j:support</code> tag with the <code>ajaxSingle="true"</code> attribute to <code>firstName</code>.</li>
  </ol>
  
  <p>The first step ensures that <code>calculateButton</code> does not overwrite the values in <code>age</code> or <code>dob</code> since it no longer processes them. Unfortunately it has the side effect that it no longer processes <code>firstName</code> either. The second step is added to counter this side effect by processing <code>firstName</code> before <code>calculateButton</code> is pressed.</p>
  
  <p>Keep in mind though that there could be 20+ fields like <code>firstName</code>. A user filling out a form could then cause 20+ requests to the server! Like I mentioned before this is also bloat that may confuse other developers.</p>
  
  <h2>Workaround 2: Using the process list</h2>
  
  <p>Thanks to @DaveMaple and @MaxKatz for suggesting this strategy, it is as follows:</p>
  
  <ol>
  <li>Add the <code>ajaxSingle="true"</code> attribute to <code>calculateButton</code>.</li>
  <li>Add the <code>process="firstName"</code> attribute to <code>calculateButton</code>.</li>
  </ol>
  
  <p>The first step achieves the same as it did in the first workaround but has the same side effect. This time the second step ensures that <code>firstName</code> is processed with <code>calculateButton</code> when it is pressed.</p>
  
  <p>Again, keep in mind though that there could be 20+ fields like <code>firstName</code> to include in this list. Like I mentioned before this is also bloat that may confuse other developers, especially since the list must include some fields but not others.</p>
  
  <h1>Age and DOB Setters and Getters (just in case they are the cause of the issue)</h1>
  
  <pre><code>public Number getAge() {
      Long age = null;
  
      if (dateOfBirth != null) {
          Calendar epochCalendar = Calendar.getInstance();
          epochCalendar.setTimeInMillis(0L);
          Calendar dobCalendar = Calendar.getInstance();
          dobCalendar.setTimeInMillis(new Date().getTime() - dateOfBirth.getTime());
          dobCalendar.add(Calendar.YEAR, epochCalendar.get(Calendar.YEAR) * -1);
  
          age = new Long(dobCalendar.get(Calendar.YEAR));
      }
  
      return (age);
  }
  
  public void setAge(Number age) {
      if (age != null) {
          // This only gives a rough date of birth at 1/1/&lt;this year minus &lt;age&gt; years&gt;.
          Calendar calendar = Calendar.getInstance();
          calendar.set(calendar.get(Calendar.YEAR) - age.intValue(), Calendar.JANUARY, 1, 0, 0, 0);
  
          setDateOfBirth(calendar.getTime());
      }
  }
  
  public Date getDateOfBirth() {
      return dateOfBirth;
  }
  
  public void setDateOfBirth(Date dateOfBirth) {
      if (notEqual(this.dateOfBirth, dateOfBirth)) {
          // If only two digits were entered for the year, provide useful defaults for the decade.
          Calendar calendar = Calendar.getInstance();
          calendar.setTime(dateOfBirth);
          if (calendar.get(Calendar.YEAR) &lt; 50) {
              // If the two digits entered are in the range 0-49, default the decade 2000.
              calendar.set(Calendar.YEAR, calendar.get(Calendar.YEAR) + 2000);
          } else if (calendar.get(Calendar.YEAR) &lt; 100) {
              // If the two digits entered are in the range 50-99, default the decade 1900.
              calendar.set(Calendar.YEAR, calendar.get(Calendar.YEAR) + 1900);
          }
          dateOfBirth = calendar.getTime();
  
          this.dateOfBirth = dateOfBirth;
          changed = true;
      }
  }
  </code></pre>