dev@jsf-extensions.java.net

Jacob: Seeking Review: 7-Immediate

From: Ed Burns <ed.burns_at_sun.com>
Date: Tue, 15 Aug 2006 12:22:43 -0700

https://jsf-extensions.dev.java.net/issues/show_bug.cgi?id=7

This is checked in on branch IMMEDIATE_20060815

I'd like to get everyone's feedback on this issue.

Issue: DynaFaces-7-immediate

This change-bundle adds the 'immediate' option to the set of supported
options for the associative array passed as the last argument to
DynaFaces.fireAjaxTransaction() and
DynaFaces.installDeferredAjaxTransaction(). For example:

+ DynaFaces.installDeferredAjaxTransaction($('immediate'), 'click', {
+ execute: "immediate",
+ immediate: true
+ });

This will end up locating the component with clientId 'immediate' and
calling setImmediate(true) on it *if* the component is an instance of
EditableValueHolder or ActionSource. This call is made before the
partial tree list is traversed for processDecodes, and naturally, the
'immediate' property is persisted as part of the component instance's
view state.

SECTION: Changes

M run-time/samples/simple-partial-update/src/main/webapp/home.jsp

- modify to showcase immediate vs non-immediate usage.

M run-time/common/src/main/java/com/sun/faces/extensions/common/util/Util.java

- copy over prefixViewTraversal from Sun JSF Impl.

M run-time/avatar/src/main/java/com/sun/faces/extensions/avatar/lifecycle/AsyncResponse.java

- add isImmediateAjaxRequest() method.

+ * <p>Return <code>true</code> if and only if the request headers include
+ * an entry for {_at_link #PARTIAL_HEADER} and the value for that header is
+ * <code>immediate</code>. Otherwise return <code>false</code>.

M run-time/avatar/src/main/java/com/sun/faces/extensions/avatar/components/PartialTraversalViewRoot.java

- in processDecodes(), handle the case where this is an immediate request
  but no partial trees have been identified. In this case, the entire
  tree is traversed and all ActionSource or EditableValueHolder
  instances are set to immediate == true.


- in the partial traversal ContextCallback, if this is
  APPLY_REQUEST_VALUES, and the current component instance is an
  ActionSource or EditableValueHolder, and this is an immediate request,
  set immediate == true.

M run-time/avatar/src/main/resources/com_sun_faces_ajax.js

- If the user specified an immediate option, set the value of the
  partial header to be 'immediate'.

M pom.xml

- add common and simple-partial-update to samples profile.

SECTION: Diffs

Index: run-time/samples/simple-partial-update/src/main/webapp/home.jsp
===================================================================
--- run-time/samples/simple-partial-update/src/main/webapp/home.jsp (revision 187)
+++ run-time/samples/simple-partial-update/src/main/webapp/home.jsp (working copy)
@@ -42,11 +42,26 @@
 
 </tr>
 
+<tr>
+
+<td>Same as above but with immediate set to true.</td>
+
+<td><h:commandButton id="immediate" actionListener="#{testBean.changeText}"
+ value="submit"/>
+</td>
+
+</tr>
+
+
 </table>
             
             </h:form>
   <script type='text/javascript'>
     DynaFaces.installDeferredAjaxTransaction($('button'), 'click');
+ DynaFaces.installDeferredAjaxTransaction($('immediate'), 'click', {
+ execute: "immediate",
+ immediate: true
+ });
   </script>
 
 
Index: run-time/common/src/main/java/com/sun/faces/extensions/common/util/Util.java
===================================================================
--- run-time/common/src/main/java/com/sun/faces/extensions/common/util/Util.java (revision 187)
+++ run-time/common/src/main/java/com/sun/faces/extensions/common/util/Util.java (working copy)
@@ -25,7 +25,9 @@
 
 package com.sun.faces.extensions.common.util;
 
+import java.util.Iterator;
 import java.util.List;
+import javax.faces.FacesException;
 import javax.faces.FactoryFinder;
 import javax.faces.application.Application;
 import javax.faces.component.UIComponent;
@@ -137,4 +139,25 @@
        RenderKit curRenderKit = fact.getRenderKit(context, renderKitId);
        return curRenderKit;
     }
+
+ public static boolean prefixViewTraversal(FacesContext context,
+ UIComponent root,
+ TreeTraversalCallback action) throws FacesException {
+ boolean keepGoing = false;
+ if (keepGoing = action.takeActionOnNode(context, root)) {
+ Iterator<UIComponent> kids = root.getFacetsAndChildren();
+ while (kids.hasNext() && keepGoing) {
+ keepGoing = prefixViewTraversal(context,
+ kids.next(),
+ action);
+ }
+ }
+ return keepGoing;
+ }
+
+ public static interface TreeTraversalCallback {
+ public boolean takeActionOnNode(FacesContext context,
+ UIComponent curNode) throws FacesException;
+ }
+
 }
Index: run-time/avatar/src/main/java/com/sun/faces/extensions/avatar/lifecycle/AsyncResponse.java
===================================================================
--- run-time/avatar/src/main/java/com/sun/faces/extensions/avatar/lifecycle/AsyncResponse.java (revision 187)
+++ run-time/avatar/src/main/java/com/sun/faces/extensions/avatar/lifecycle/AsyncResponse.java (working copy)
@@ -314,7 +314,32 @@
         }
         return result;
     }
+
+ /**
+ * <p>Return <code>true</code> if and only if the request headers include
+ * an entry for {_at_link #PARTIAL_HEADER} and the value for that header is
+ * <code>immediate</code>. Otherwise return <code>false</code>.
+ */
     
+ public static boolean isImmediateAjaxRequest() {
+ ExternalContext ext = FacesContext.getCurrentInstance().getExternalContext();
+ Map<String, Object> requestMap = ext.getRequestMap();
+ final String immediateFlag = FACES_PREFIX + "IsImmediate";
+ if (requestMap.containsKey(immediateFlag)) {
+ return true;
+ }
+
+ Map<String, String> p = ext.getRequestHeaderMap();
+ String partialValue = p.get(PARTIAL_HEADER);
+ boolean result = false;
+ if (null != partialValue) {
+ result = partialValue.equalsIgnoreCase("immediate");
+ }
+ if (result) {
+ requestMap.put(immediateFlag, Boolean.TRUE);
+ }
+ return result;
+ }
     private Object origResponse = null;
     
     /**
Index: run-time/avatar/src/main/java/com/sun/faces/extensions/avatar/components/PartialTraversalViewRoot.java
===================================================================
--- run-time/avatar/src/main/java/com/sun/faces/extensions/avatar/components/PartialTraversalViewRoot.java (revision 187)
+++ run-time/avatar/src/main/java/com/sun/faces/extensions/avatar/components/PartialTraversalViewRoot.java (working copy)
@@ -31,13 +31,16 @@
 
 import com.sun.faces.extensions.avatar.event.EventParser;
 import com.sun.faces.extensions.avatar.lifecycle.AsyncResponse;
+import com.sun.faces.extensions.common.util.Util;
 import java.io.IOException;
 import java.io.Serializable;
 import java.util.Iterator;
 import java.util.List;
 import javax.faces.FacesException;
 import javax.faces.application.FacesMessage;
+import javax.faces.component.ActionSource;
 import javax.faces.component.ContextCallback;
+import javax.faces.component.EditableValueHolder;
 import javax.faces.component.UIComponent;
 import javax.faces.component.UIViewRoot;
 import javax.faces.component.UIViewRootCopy;
@@ -137,11 +140,35 @@
             super.processDecodes(context);
             return;
         }
+ AsyncResponse async = AsyncResponse.getInstance();
+
+ // If this is an immediate "render all" request and there are
+ // no explicit execute subtrees and the user didn't request
+ // execute: none...
+ if (async.isImmediateAjaxRequest() && async.isRenderAll() &&
+ async.getExecuteSubtrees().isEmpty() &&
+ !async.isExecuteNone()) {
+ // Traverse the entire view and mark every ActionSource or
+ // EditableValueHolder as immediate.
+ Util.TreeTraversalCallback markImmediate = new Util.TreeTraversalCallback() {
+ public boolean takeActionOnNode(FacesContext context, UIComponent comp) throws FacesException {
+ if (comp instanceof ActionSource) {
+ ((ActionSource)comp).setImmediate(true);
+ } else if (comp instanceof EditableValueHolder) {
+ ((EditableValueHolder)comp).setImmediate(true);
+ }
+
+ return true;
+ }
+
+ };
+ Util.prefixViewTraversal(context, this, markImmediate);
+ }
+
         invokedCallback = invokeContextCallbackOnSubtrees(context,
                 new PhaseAwareContextCallback(PhaseId.APPLY_REQUEST_VALUES));
         
         // Queue any events for this request in a context aware manner
- AsyncResponse async = AsyncResponse.getInstance();
         ResponseWriter writer = null;
         try {
             writer = async.getResponseWriter();
@@ -384,15 +411,22 @@
                 ConverterException converterException = null;
                 
                 if (curPhase == PhaseId.APPLY_REQUEST_VALUES) {
+ // If the user requested an immediate request
+ // Make sure to set the immediate flag.
+ if (AsyncResponse.isImmediateAjaxRequest()) {
+ if (comp instanceof ActionSource) {
+ ((ActionSource)comp).setImmediate(true);
+ } else if (comp instanceof EditableValueHolder) {
+ ((EditableValueHolder)comp).setImmediate(true);
+ }
+ }
+
                     comp.processDecodes(facesContext);
- }
- else if (curPhase == PhaseId.PROCESS_VALIDATIONS) {
+ } else if (curPhase == PhaseId.PROCESS_VALIDATIONS) {
                     comp.processValidators(facesContext);
- }
- else if (curPhase == PhaseId.UPDATE_MODEL_VALUES) {
+ } else if (curPhase == PhaseId.UPDATE_MODEL_VALUES) {
                     comp.processUpdates(facesContext);
- }
- else if (curPhase == PhaseId.RENDER_RESPONSE) {
+ } else if (curPhase == PhaseId.RENDER_RESPONSE) {
                     ResponseWriter writer = AsyncResponse.getInstance().getResponseWriter();
 
                     writer.startElement("render", comp);
Index: run-time/avatar/src/main/resources/com_sun_faces_ajax.js
===================================================================
--- run-time/avatar/src/main/resources/com_sun_faces_ajax.js (revision 187)
+++ run-time/avatar/src/main/resources/com_sun_faces_ajax.js (working copy)
@@ -481,7 +481,12 @@
         
         // guarantee our header
         this.options.requestHeaders.push(gPartial);
- this.options.requestHeaders.push('true');
+ if (this.options.immediate) {
+ this.options.requestHeaders.push('immediate');
+ }
+ else {
+ this.options.requestHeaders.push('true');
+ }
         
         // add methodName
         if (this.options.methodName) {
Index: pom.xml
===================================================================
--- pom.xml (revision 187)
+++ pom.xml (working copy)
@@ -145,11 +145,13 @@
     <profile>
       <id>samples</id>
       <modules>
+ <module>run-time/common</module>
         <module>run-time/avatar</module>
         <module>run-time/samples/j1</module>
         <module>run-time/samples/cardemo</module>
         <module>run-time/samples/jmaki</module>
         <module>run-time/samples/simple-events</module>
+ <module>run-time/samples/simple-partial-update</module>
       </modules>
     </profile>
     <profile>


-- 
| ed.burns_at_sun.com  | {home: 407 869 9587, office: 408 884 9519 OR x31640}
| homepage:         | http://purl.oclc.org/NET/edburns/
| aim: edburns0sunw | iim: ed.burns_at_sun.com