[ajax4jsf-svn-commits] JBoss Ajax4JSF SVN: r164 - in trunk: framework/src/main/config/component and 10 other directories.

ajax4jsf-svn-commits at lists.jboss.org ajax4jsf-svn-commits at lists.jboss.org
Thu May 3 16:06:28 EDT 2007


Author: alexsmirnov
Date: 2007-05-03 16:06:28 -0400 (Thu, 03 May 2007)
New Revision: 164

Added:
   trunk/framework/src/main/config/component/push.xml
   trunk/framework/src/main/java/org/ajax4jsf/ajax/PushEventListener.java
   trunk/framework/src/main/java/org/ajax4jsf/ajax/PushEventsCounter.java
   trunk/framework/src/main/java/org/ajax4jsf/ajax/UIPush.java
   trunk/framework/src/main/java/org/ajax4jsf/framework/ajax/AjaxSingleEvent.java
   trunk/framework/src/main/java/org/ajax4jsf/framework/ajax/AjaxSingleException.java
   trunk/framework/src/main/java/org/ajax4jsf/framework/ajax/xmlfilter/PollEventsManager.java
   trunk/framework/src/main/java/org/ajax4jsf/renderkit/html/AjaxPushRenderer.java
   trunk/samples/seamIntegration/.exadelproject
   trunk/samples/useCases/src/main/java/org/ajax4jsf/A4jTestBean.java
   trunk/samples/useCases/src/main/java/org/ajax4jsf/MessageBean.java
   trunk/samples/useCases/src/main/webapp/pages/actionparam.xhtml
   trunk/samples/useCases/src/main/webapp/pages/ajaxSingle.xhtml
   trunk/samples/useCases/src/main/webapp/pages/push.xhtml
Modified:
   trunk/framework/pom.xml
   trunk/framework/src/main/java/org/ajax4jsf/ajax/UIAjaxRegion.java
   trunk/framework/src/main/java/org/ajax4jsf/ajax/UIAjaxSupport.java
   trunk/framework/src/main/java/org/ajax4jsf/framework/ajax/AjaxActionComponent.java
   trunk/framework/src/main/java/org/ajax4jsf/framework/ajax/AjaxContext.java
   trunk/framework/src/main/java/org/ajax4jsf/framework/ajax/AjaxViewRoot.java
   trunk/framework/src/main/java/org/ajax4jsf/framework/ajax/ComponentInvoker.java
   trunk/framework/src/main/java/org/ajax4jsf/framework/ajax/JsfOneOneInvoker.java
   trunk/framework/src/main/java/org/ajax4jsf/framework/ajax/xmlfilter/BaseFilter.java
   trunk/framework/src/main/java/org/ajax4jsf/framework/renderer/AjaxRendererUtils.java
   trunk/framework/src/main/javascript/ajaxjsf/JSFAJAX.js
   trunk/samples/useCases/src/main/java/org/ajax4jsf/Bean.java
   trunk/samples/useCases/src/main/webapp/WEB-INF/faces-config.xml
Log:
First implementation of the a4j:push component.
Fix ajaxSingle problems.

Modified: trunk/framework/pom.xml
===================================================================
--- trunk/framework/pom.xml	2007-05-03 13:55:52 UTC (rev 163)
+++ trunk/framework/pom.xml	2007-05-03 20:06:28 UTC (rev 164)
@@ -1,4 +1,6 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
 	<parent>
 		<artifactId>master</artifactId>
 		<groupId>org.ajax4jsf</groupId>
@@ -57,9 +59,11 @@
 						</goals>
 						<configuration>
 							<tasks>
-								<ant antfile="${basedir}/generatescript.xml" inheritRefs="true">
+								<ant
+									antfile="${basedir}/generatescript.xml" inheritRefs="true">
 									<target name="assembly" />
-									<property name="target-dir" value="${project.build.directory}/javascript">
+									<property name="target-dir"
+										value="${project.build.directory}/javascript">
 									</property>
 								</ant>
 							</tasks>
@@ -70,6 +74,17 @@
 					</execution>
 				</executions>
 			</plugin>
+			<plugin>
+				<artifactId>maven-source-plugin</artifactId>
+				<executions>
+					<execution>
+						<id>attach-source</id>
+						<goals>
+							<goal>jar</goal>
+						</goals>
+					</execution>
+				</executions>
+			</plugin>
 		</plugins>
 	</build>
 	<reporting>
@@ -247,27 +262,27 @@
 							<target>1.5</target>
 						</configuration>
 					</plugin>
-			<!-- append JSF 1.2 related sources -->
-			<plugin>
-				<groupId>org.codehaus.mojo</groupId>
-				<artifactId>build-helper-maven-plugin</artifactId>
-				<executions>
-					<execution>
-						<id>add-source</id>
-						<phase>process-sources</phase>
-						<goals>
-							<goal>add-source</goal>
-						</goals>
-						<configuration>
-							<sources>
-								<source>
-									src/main/jsf12
-								</source>
-							</sources>
-						</configuration>
-					</execution>
-				</executions>
-			</plugin>
+					<!-- append JSF 1.2 related sources -->
+					<plugin>
+						<groupId>org.codehaus.mojo</groupId>
+						<artifactId>
+							build-helper-maven-plugin
+						</artifactId>
+						<executions>
+							<execution>
+								<id>add-source</id>
+								<phase>process-sources</phase>
+								<goals>
+									<goal>add-source</goal>
+								</goals>
+								<configuration>
+									<sources>
+										<source>src/main/jsf12</source>
+									</sources>
+								</configuration>
+							</execution>
+						</executions>
+					</plugin>
 				</plugins>
 			</build>
 			<dependencies>

Added: trunk/framework/src/main/config/component/push.xml
===================================================================
--- trunk/framework/src/main/config/component/push.xml	                        (rev 0)
+++ trunk/framework/src/main/config/component/push.xml	2007-05-03 20:06:28 UTC (rev 164)
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE components 
+        PUBLIC "-//AJAX4JSF//CDK Generator config/EN"
+        "https://ajax4jsf.dev.java.net/nonav/dtds/component-config.dtd" [
+<!ENTITY universal_html_attributes   SYSTEM "html_universal_attributes.xml">	
+]>
+
+<components>
+     	<component>
+		<name>org.ajax4jsf.ajax.Push</name>
+		<family>org.ajax4jsf.components.AjaxPush</family>
+		<classname>org.ajax4jsf.ajax.html.AjaxPush</classname>
+		<superclass>org.ajax4jsf.ajax.UIPush</superclass>
+		<description>
+			Periodically perform AJAX request to server, to simulate
+			'push' data.
+			<br />
+		</description>
+		<displayname>Ajax Push</displayname>
+		<icon>icon</icon>
+		<renderer generate="false" override="false">
+			<name>org.ajax4jsf.components.AjaxPushRenderer</name>
+			<classname>
+				org.ajax4jsf.renderkit.html.AjaxPushRenderer
+			</classname>
+			<!-- 
+				<superclass>javax.faces.renderer.Renderer</superclass>
+			-->
+			<description>
+				Perform functions for decoding AJAX requests and
+				building client script for events.
+			</description>
+			<displayname>renderer for Ajax Push</displayname>
+			<icon>icon</icon>
+		</renderer>
+		<tag>
+			<name>push</name>
+			<classname>org.ajax4jsf.taglib.ajax.AjaxPushTag</classname>
+			<superclass>
+				org.ajax4jsf.framework.taglib.UIComponentTagBase
+			</superclass>
+			<displayname>Ajax Push</displayname>
+			<icon>icon</icon>
+		</tag>
+		<taghandler generate="true">
+			<classname>org.ajax4jsf.taglib.html.facelets.AjaxPushHandler</classname>
+			<superclass>org.ajax4jsf.taglib.html.facelets.AjaxComponentHandler</superclass>
+		</taghandler>
+		&ui_component_attributes;
+		&ui_command_attributes;
+		&ajax_component_attributes;
+	    <property elonly="true"  attachedstate="true">
+        	<name>eventProducer</name>
+        	<classname>javax.faces.el.MethodBinding</classname>
+        	<description>
+            MethodBinding pointing at method accepting  an PushEventListener with return type void.
+            User bean must register this listener and send EventObject to this listener on ready.
+        </description>
+        <methodargs>java.util.EventListener.class</methodargs>
+    </property>
+		<property>
+			<name>onsubmit</name>
+			<classname>java.lang.String</classname>
+			<description>
+				JavaScript code for call before submission of ajax
+				event
+			</description>
+		</property>
+		<property>
+			<name>interval</name>
+			<classname>int</classname>
+			<description>
+				Interval (in ms) for call push requests. Default value
+				1000 (1 sec)
+			</description>
+		</property>
+		<property>
+			<name>enabled</name>
+			<classname>boolean</classname>
+			<description>
+				<![CDATA[Enable/disable pushing]]>
+			</description>
+			<defaultvalue>true</defaultvalue>
+		</property>
+		<property hidden="true">
+			<name>value</name>
+			<classname>java.lang.Object</classname>
+		</property>
+		<property hidden="true">
+			<name>submitted</name>
+			<classname>boolean</classname>
+		</property>
+		<property hidden="true">
+			<name>requestDelay</name>
+			<classname>int</classname>
+		</property>
+		<property>
+			<name>ignoreDupResponses</name>
+			<classname>boolean</classname>
+			<description>If true, unfinished request will be aborted on new event.</description>
+		</property>
+		<property>
+			<name>timeout</name>
+			<classname>int</classname>
+			<description>Timeout (in ms) for request</description>
+		</property>
+	</component>     
+</components>
\ No newline at end of file

Added: trunk/framework/src/main/java/org/ajax4jsf/ajax/PushEventListener.java
===================================================================
--- trunk/framework/src/main/java/org/ajax4jsf/ajax/PushEventListener.java	                        (rev 0)
+++ trunk/framework/src/main/java/org/ajax4jsf/ajax/PushEventListener.java	2007-05-03 20:06:28 UTC (rev 164)
@@ -0,0 +1,10 @@
+package org.ajax4jsf.ajax;
+
+import java.util.EventListener;
+import java.util.EventObject;
+
+public interface PushEventListener extends EventListener {
+    
+    public void onEvent(EventObject event);
+
+}

Added: trunk/framework/src/main/java/org/ajax4jsf/ajax/PushEventsCounter.java
===================================================================
--- trunk/framework/src/main/java/org/ajax4jsf/ajax/PushEventsCounter.java	                        (rev 0)
+++ trunk/framework/src/main/java/org/ajax4jsf/ajax/PushEventsCounter.java	2007-05-03 20:06:28 UTC (rev 164)
@@ -0,0 +1,32 @@
+package org.ajax4jsf.ajax;
+
+import java.io.Serializable;
+import java.util.EventObject;
+
+public class PushEventsCounter implements PushEventListener,Serializable {
+    
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 4060284352186710009L;
+    private boolean performed = false;
+
+    public void onEvent(EventObject event) {
+	performed = true;
+    }
+
+    /**
+     * @return the performed
+     */
+    public boolean isPerformed() {
+        return performed;
+    }
+
+    /**
+     */
+    public void processed() {
+        this.performed = false;
+    }
+
+    
+}

Modified: trunk/framework/src/main/java/org/ajax4jsf/ajax/UIAjaxRegion.java
===================================================================
--- trunk/framework/src/main/java/org/ajax4jsf/ajax/UIAjaxRegion.java	2007-05-03 13:55:52 UTC (rev 163)
+++ trunk/framework/src/main/java/org/ajax4jsf/ajax/UIAjaxRegion.java	2007-05-03 20:06:28 UTC (rev 164)
@@ -33,7 +33,6 @@
 import javax.faces.el.MethodBinding;
 import javax.faces.event.AbortProcessingException;
 import javax.faces.event.FacesEvent;
-import javax.faces.event.PhaseId;
 
 import org.ajax4jsf.framework.ajax.AjaxContainer;
 import org.ajax4jsf.framework.ajax.AjaxContext;
@@ -113,8 +112,7 @@
 				(viewRoot instanceof AjaxViewRoot) &&
 				((AjaxViewRoot) viewRoot).isHavePage() &&
 				(ajaxContext.isAjaxRequest())) {
-			AjaxContext.invokeOnRegionOrRoot((AjaxViewRoot) viewRoot, context, _ajaxInvoker,
-					PhaseId.RENDER_RESPONSE);
+			AjaxContext.invokeOnRegionOrRoot((AjaxViewRoot) viewRoot, context, _ajaxInvoker);
 		} else {
 			super.encodeChildren(context);
 		}

Modified: trunk/framework/src/main/java/org/ajax4jsf/ajax/UIAjaxSupport.java
===================================================================
--- trunk/framework/src/main/java/org/ajax4jsf/ajax/UIAjaxSupport.java	2007-05-03 13:55:52 UTC (rev 163)
+++ trunk/framework/src/main/java/org/ajax4jsf/ajax/UIAjaxSupport.java	2007-05-03 20:06:28 UTC (rev 164)
@@ -225,5 +225,9 @@
         }
 
     }
+    
+    protected UIComponent getSingleComponent() {
+        return getParent();
+    }
 
 }

Added: trunk/framework/src/main/java/org/ajax4jsf/ajax/UIPush.java
===================================================================
--- trunk/framework/src/main/java/org/ajax4jsf/ajax/UIPush.java	                        (rev 0)
+++ trunk/framework/src/main/java/org/ajax4jsf/ajax/UIPush.java	2007-05-03 20:06:28 UTC (rev 164)
@@ -0,0 +1,112 @@
+/**
+ * License Agreement.
+ *
+ * Ajax4jsf 1.1 - Natural Ajax for Java Server Faces (JSF)
+ *
+ * Copyright (C) 2007 Exadel, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ */
+
+package org.ajax4jsf.ajax;
+
+import java.io.IOException;
+
+import javax.faces.component.NamingContainer;
+import javax.faces.context.FacesContext;
+import javax.faces.el.MethodBinding;
+import javax.servlet.http.HttpSession;
+
+import org.ajax4jsf.framework.ajax.AjaxActionComponent;
+import org.ajax4jsf.framework.ajax.AjaxContext;
+import org.ajax4jsf.framework.ajax.xmlfilter.PollEventsManager;
+
+/**
+ * Component for periodically call AJAX events on server ( poll actions )
+ * @author shura
+ *
+ */
+public abstract class UIPush extends AjaxActionComponent  {
+	
+	public static final String COMPONENT_TYPE="org.ajax4jsf.ajax.Push";
+	
+
+	private transient boolean _submitted = false;
+
+	/**
+	 * @return the submitted
+	 */
+	public boolean isSubmitted() {
+		return _submitted;
+	}
+
+	public void encodeBegin(FacesContext context) throws IOException {
+	    MethodBinding producer = getEventProducer();
+	    // Subscribe events producer to push status listener.
+	    if(null != producer){
+		producer.invoke(context, new Object[]{getListener(context)});
+	    }
+	    super.encodeBegin(context);
+	}
+	
+	private PushEventsCounter getListener(FacesContext context){
+	    PollEventsManager eventsManeger = (PollEventsManager) context.getExternalContext().getApplicationMap().get(PollEventsManager.EVENTS_MANAGER_KEY);
+	    return eventsManeger.getListener(getListenerId(context));
+	}
+
+	public String getListenerId(FacesContext context){
+	    Object session = context.getExternalContext().getSession(false);
+	    StringBuffer id = new StringBuffer();
+	    if(null != session && session instanceof HttpSession){
+		HttpSession httpSession = (HttpSession) session;
+		id.append(httpSession.getId());
+	    }
+	    id.append(context.getViewRoot().getViewId());
+	    id.append(NamingContainer.SEPARATOR_CHAR);
+	    id.append(getClientId(context));
+	    return id.toString();
+	}
+	/**
+	 * @param submitted the submitted to set
+	 */
+	public void setSubmitted(boolean submitted) {
+		_submitted = submitted;
+	}
+
+	public abstract MethodBinding getEventProducer();
+	
+	public abstract void setEventProducer(MethodBinding producer);
+	/**
+	 * @return time in mc for polling interval.
+	 */
+	public abstract int getInterval();
+	
+	/**
+	 * @param interval time in mc for polling interval.
+	 */
+	public abstract void setInterval(int interval);
+	
+	public abstract boolean isEnabled();
+	
+	public abstract void setEnabled(boolean enable);
+	
+	protected void setupReRender(FacesContext facesContext) {
+		super.setupReRender(facesContext);
+//		AjaxContext.getCurrentInstance(facesContext).addComponentToAjaxRender(this);
+		//
+		getListener(facesContext).processed();
+	}
+	
+
+}

Modified: trunk/framework/src/main/java/org/ajax4jsf/framework/ajax/AjaxActionComponent.java
===================================================================
--- trunk/framework/src/main/java/org/ajax4jsf/framework/ajax/AjaxActionComponent.java	2007-05-03 13:55:52 UTC (rev 163)
+++ trunk/framework/src/main/java/org/ajax4jsf/framework/ajax/AjaxActionComponent.java	2007-05-03 20:06:28 UTC (rev 164)
@@ -47,6 +47,10 @@
          * @see javax.faces.component.UIComponentBase#broadcast(javax.faces.event.FacesEvent)
          */
     public void broadcast(FacesEvent event) throws AbortProcessingException {
+	// Hack - throw exception to AjaxViewRoot, to fix state of all iterable components.
+	if (event instanceof AjaxSingleEvent) {
+	    throw new AjaxSingleException(getSingleComponent());	    
+	}
 	// perform default
 	super.broadcast(event);
 	if (event instanceof AjaxEvent) {
@@ -106,6 +110,9 @@
 		event.setPhaseId(PhaseId.INVOKE_APPLICATION);
 	    }
 	    getParent().queueEvent(event);
+	    if(isAjaxSingle()){
+		super.queueEvent(new AjaxSingleEvent(this));
+	    }
 	} else {
 	    super.queueEvent(event);
 	}
@@ -140,5 +147,9 @@
 	removeFacesListener(listener);
 
     }
+    
+    protected UIComponent getSingleComponent(){
+	return this;
+    }
 
 }

Modified: trunk/framework/src/main/java/org/ajax4jsf/framework/ajax/AjaxContext.java
===================================================================
--- trunk/framework/src/main/java/org/ajax4jsf/framework/ajax/AjaxContext.java	2007-05-03 13:55:52 UTC (rev 163)
+++ trunk/framework/src/main/java/org/ajax4jsf/framework/ajax/AjaxContext.java	2007-05-03 20:06:28 UTC (rev 164)
@@ -48,7 +48,6 @@
 import javax.faces.context.ResponseWriter;
 import javax.faces.el.VariableResolver;
 import javax.faces.event.AbortProcessingException;
-import javax.faces.event.PhaseId;
 import javax.faces.render.RenderKit;
 import javax.faces.render.RenderKitFactory;
 import javax.faces.render.Renderer;
@@ -181,17 +180,15 @@
 
     /**
          * @param viewRoot
-         * @param context
-         * @param callback
-         * @param phase
+     * @param context
+     * @param callback
          * @see org.ajax4jsf.framework.ajax.JsfOneOneInvoker#invokeOnRegionOrRoot(org.ajax4jsf.framework.ajax.AjaxViewRoot,
          *      javax.faces.context.FacesContext,
-         *      org.ajax4jsf.framework.ajax.InvokerCallback,
-         *      javax.faces.event.PhaseId)
+         *      org.ajax4jsf.framework.ajax.InvokerCallback)
          */
     public static void invokeOnRegionOrRoot(AjaxViewRoot viewRoot,
-	    FacesContext context, InvokerCallback callback, PhaseId phase) {
-	invoker.invokeOnRegionOrRoot(viewRoot, context, callback, phase);
+	    FacesContext context, InvokerCallback callback) {
+	invoker.invokeOnRegionOrRoot(viewRoot, context, callback);
     }
 
     private InvokerCallback _ajaxInvoker = new InvokerCallback() {

Added: trunk/framework/src/main/java/org/ajax4jsf/framework/ajax/AjaxSingleEvent.java
===================================================================
--- trunk/framework/src/main/java/org/ajax4jsf/framework/ajax/AjaxSingleEvent.java	                        (rev 0)
+++ trunk/framework/src/main/java/org/ajax4jsf/framework/ajax/AjaxSingleEvent.java	2007-05-03 20:06:28 UTC (rev 164)
@@ -0,0 +1,40 @@
+/**
+ * 
+ */
+package org.ajax4jsf.framework.ajax;
+
+import javax.faces.component.UIComponent;
+import javax.faces.event.FacesEvent;
+import javax.faces.event.FacesListener;
+import javax.faces.event.PhaseId;
+
+/**
+ * @author asmirnov
+ *
+ */
+public class AjaxSingleEvent extends FacesEvent {
+
+    /**
+     * @param arg0
+     */
+    public AjaxSingleEvent(UIComponent arg0) {
+	super(arg0);
+    }
+
+    /* (non-Javadoc)
+     * @see javax.faces.event.FacesEvent#isAppropriateListener(javax.faces.event.FacesListener)
+     */
+    public boolean isAppropriateListener(FacesListener arg0) {
+	return false;
+    }
+
+    /* (non-Javadoc)
+     * @see javax.faces.event.FacesEvent#processListener(javax.faces.event.FacesListener)
+     */
+    public void processListener(FacesListener arg0) {
+    }
+
+    public PhaseId getPhaseId() {
+        return PhaseId.APPLY_REQUEST_VALUES;
+    }
+}

Added: trunk/framework/src/main/java/org/ajax4jsf/framework/ajax/AjaxSingleException.java
===================================================================
--- trunk/framework/src/main/java/org/ajax4jsf/framework/ajax/AjaxSingleException.java	                        (rev 0)
+++ trunk/framework/src/main/java/org/ajax4jsf/framework/ajax/AjaxSingleException.java	2007-05-03 20:06:28 UTC (rev 164)
@@ -0,0 +1,31 @@
+/**
+ * 
+ */
+package org.ajax4jsf.framework.ajax;
+
+import javax.faces.component.UIComponent;
+
+/**
+ * @author asmirnov
+ *
+ */
+public class AjaxSingleException extends RuntimeException {
+    
+    private UIComponent component;
+
+    /**
+     * @param component
+     */
+    public AjaxSingleException(UIComponent componemt) {
+//	super();
+	this.component = componemt;
+    }
+
+    /**
+     * @return the component
+     */
+    public UIComponent getComponent() {
+        return component;
+    }
+
+}

Modified: trunk/framework/src/main/java/org/ajax4jsf/framework/ajax/AjaxViewRoot.java
===================================================================
--- trunk/framework/src/main/java/org/ajax4jsf/framework/ajax/AjaxViewRoot.java	2007-05-03 13:55:52 UTC (rev 163)
+++ trunk/framework/src/main/java/org/ajax4jsf/framework/ajax/AjaxViewRoot.java	2007-05-03 20:06:28 UTC (rev 164)
@@ -52,498 +52,511 @@
  */
 public class AjaxViewRoot extends UIViewRoot implements AjaxContainer {
 
-	public static final String ROOT_ID = "_viewRoot";
+    public static final String ROOT_ID = "_viewRoot";
 
-	private AjaxRegionBrige _brige;
-	
+    private AjaxRegionBrige _brige;
 
-	/**
-	 * 
-	 */
-	public AjaxViewRoot() {
-		super();
-		super.setId(ROOT_ID);
-		_brige = new AjaxRegionBrige(this);
-	}
+    /**
+         * 
+         */
+    public AjaxViewRoot() {
+	super();
+	super.setId(ROOT_ID);
+	_brige = new AjaxRegionBrige(this);
+    }
 
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see javax.faces.component.UIComponentBase#getId()
-	 */
-	// public String getId() {
-	// return ROOT_ID;
-	// }
-	public String getRendererType() {
-		return (COMPONENT_FAMILY);
-	}
+    /*
+         * (non-Javadoc)
+         * 
+         * @see javax.faces.component.UIComponentBase#getId()
+         */
+    // public String getId() {
+    // return ROOT_ID;
+    // }
+    public String getRendererType() {
+	return (COMPONENT_FAMILY);
+    }
 
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.ajax4jsf.framework.ajax.AjaxViewBrige#broadcast(javax.faces.event.FacesEvent)
-	 */
-	public void broadcast(FacesEvent event) throws AbortProcessingException {
-		super.broadcast(event);
-		getBrige().broadcast(event);
-	}
+    /*
+         * (non-Javadoc)
+         * 
+         * @see org.ajax4jsf.framework.ajax.AjaxViewBrige#broadcast(javax.faces.event.FacesEvent)
+         */
+    public void broadcast(FacesEvent event) throws AbortProcessingException {
+	super.broadcast(event);
+	getBrige().broadcast(event);
+    }
 
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.ajax4jsf.framework.ajax.AjaxViewBrige#getAjaxListener()
-	 */
-	public MethodBinding getAjaxListener() {
-		return getBrige().getAjaxListener();
-	}
+    /*
+         * (non-Javadoc)
+         * 
+         * @see org.ajax4jsf.framework.ajax.AjaxViewBrige#getAjaxListener()
+         */
+    public MethodBinding getAjaxListener() {
+	return getBrige().getAjaxListener();
+    }
 
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.ajax4jsf.framework.ajax.AjaxViewBrige#isImmediate()
-	 */
-	public boolean isImmediate() {
-		return getBrige().isImmediate();
-	}
+    /*
+         * (non-Javadoc)
+         * 
+         * @see org.ajax4jsf.framework.ajax.AjaxViewBrige#isImmediate()
+         */
+    public boolean isImmediate() {
+	return getBrige().isImmediate();
+    }
 
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.ajax4jsf.framework.ajax.AjaxViewBrige#isSubmitted()
-	 */
-	public boolean isSubmitted() {
-		return getBrige().isSubmitted();
-	}
+    /*
+         * (non-Javadoc)
+         * 
+         * @see org.ajax4jsf.framework.ajax.AjaxViewBrige#isSubmitted()
+         */
+    public boolean isSubmitted() {
+	return getBrige().isSubmitted();
+    }
 
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see javax.faces.component.UIComponent#queueEvent(javax.faces.event.FacesEvent)
-	 */
-	public void queueEvent(FacesEvent event) {
-		if (event == null)
-			throw new NullPointerException(Messages
-					.getMessage(Messages.NULL_EVENT_SUBMITTED_ERROR));
-		if (event.getPhaseId().compareTo(PhaseId.RENDER_RESPONSE) == 0) {
-			// HACK - Special case - Ajax Events to RenderResponse phase queue.
-			// in future, with JSF 1.2 it must be done by invokeOnComponent
-			// method.
-			// In 1.1 , events to RENDER_RESPONSE phase not used.
-			getAjaxEventsQueue(getFacesContext()).add(event);
-		} else {
-			getEventsQueue(getFacesContext(), event.getPhaseId()).add(event);
-		}
+    /*
+         * (non-Javadoc)
+         * 
+         * @see javax.faces.component.UIComponent#queueEvent(javax.faces.event.FacesEvent)
+         */
+    public void queueEvent(FacesEvent event) {
+	if (event == null)
+	    throw new NullPointerException(Messages
+		    .getMessage(Messages.NULL_EVENT_SUBMITTED_ERROR));
+	if (event.getPhaseId().compareTo(PhaseId.RENDER_RESPONSE) == 0) {
+	    // HACK - Special case - Ajax Events to RenderResponse phase
+	    // queue.
+	    // in future, with JSF 1.2 it must be done by invokeOnComponent
+	    // method.
+	    // In 1.1 , events to RENDER_RESPONSE phase not used.
+	    getAjaxEventsQueue(getFacesContext()).add(event);
+	} else {
+	    getEventsQueue(getFacesContext(), event.getPhaseId()).add(event);
 	}
+    }
 
-	/**
-	 * Broadcast events for specified Phase
-	 * 
-	 * @param context
-	 * @param phaseId -
-	 *            phase, for wich events must be processed.
-	 */
-	void broadcastEvents(FacesContext context, PhaseId phaseId) {
-		Buffer[] events = getEvents(context);
-		Buffer anyPhaseEvents = events[PhaseId.ANY_PHASE.getOrdinal()];
-		Buffer phaseEvents = events[phaseId.getOrdinal()];
-		if (phaseEvents.isEmpty() && anyPhaseEvents.isEmpty())
-			return;
-		// FacesEvent event = null;
-		boolean haveAnyPhaseEvents = !anyPhaseEvents.isEmpty();
-		boolean havePhaseEvents = !phaseEvents.isEmpty();
-		do {
-			// ANY_PHASE first
-			processEvents(anyPhaseEvents, haveAnyPhaseEvents);
+    /**
+         * Broadcast events for specified Phase
+         * 
+         * @param context
+         * @param phaseId -
+         *                phase, for wich events must be processed.
+         */
+    void broadcastEvents(FacesContext context, PhaseId phaseId) {
+	Buffer[] events = getEvents(context);
+	Buffer anyPhaseEvents = events[PhaseId.ANY_PHASE.getOrdinal()];
+	Buffer phaseEvents = events[phaseId.getOrdinal()];
+	if (phaseEvents.isEmpty() && anyPhaseEvents.isEmpty())
+	    return;
+	// FacesEvent event = null;
+	boolean haveAnyPhaseEvents = !anyPhaseEvents.isEmpty();
+	boolean havePhaseEvents = !phaseEvents.isEmpty();
+	do {
+	    // ANY_PHASE first
+	    processEvents(anyPhaseEvents, haveAnyPhaseEvents);
 
-			processEvents(phaseEvents, havePhaseEvents);
-			// Events can queued in other events processing
-			haveAnyPhaseEvents = !anyPhaseEvents.isEmpty();
-			havePhaseEvents = !phaseEvents.isEmpty();
-		} while (haveAnyPhaseEvents || havePhaseEvents);
-		if (context.getRenderResponse() || context.getResponseComplete()) {
-			clearEvents(context);
-		}
-
+	    processEvents(phaseEvents, havePhaseEvents);
+	    // Events can queued in other events processing
+	    haveAnyPhaseEvents = !anyPhaseEvents.isEmpty();
+	    havePhaseEvents = !phaseEvents.isEmpty();
+	} while (haveAnyPhaseEvents || havePhaseEvents);
+	if (context.getRenderResponse() || context.getResponseComplete()) {
+	    clearEvents(context);
 	}
 
-	/**
-	 * @param phaseEventsQueue
-	 * @param havePhaseEvents
-	 */
-	public void processEvents(Buffer phaseEventsQueue, boolean havePhaseEvents) {
-		FacesEvent event;
-		while (havePhaseEvents) {
-			try {
-				event = (FacesEvent) phaseEventsQueue.remove();
-				UIComponent source = event.getComponent();
-				try {
-					source.broadcast(event);
-				} catch (AbortProcessingException e) {
-					// abort event processing
-					// Page 3-30 of JSF 1.1 spec: "Throw an
-					// AbortProcessingException, to tell the JSF implementation
-					// that no further broadcast of this event, or any further
-					// events, should take place."
-					// clearEvents();
-					// return;
-				}
-			} catch (BufferUnderflowException e) {
-				havePhaseEvents = false;
-			}
+    }
+
+    /**
+         * @param phaseEventsQueue
+         * @param havePhaseEvents
+         */
+    public void processEvents(Buffer phaseEventsQueue, boolean havePhaseEvents) {
+	FacesEvent event;
+	while (havePhaseEvents) {
+	    try {
+		event = (FacesEvent) phaseEventsQueue.remove();
+		UIComponent source = event.getComponent();
+		try {
+		    source.broadcast(event);
+		} catch (AbortProcessingException e) {
+		    // abort event processing
+		    // Page 3-30 of JSF 1.1 spec: "Throw an
+		    // AbortProcessingException, to tell the JSF
+		    // implementation
+		    // that no further broadcast of this event, or any
+		    // further
+		    // events, should take place."
+		    // clearEvents();
+		    // return;
 		}
+	    } catch (BufferUnderflowException e) {
+		havePhaseEvents = false;
+	    }
 	}
+    }
 
-	public void broadcastAjaxEvents(FacesContext context) {
-		Buffer queue = getAjaxEventsQueue(context);
-		processEvents(queue, !queue.isEmpty());
-	}
+    public void broadcastAjaxEvents(FacesContext context) {
+	Buffer queue = getAjaxEventsQueue(context);
+	processEvents(queue, !queue.isEmpty());
+    }
 
-	private Buffer[] events;
+    private Buffer[] events;
 
-	private Buffer ajaxEvents = new UnboundedFifoBuffer();
+    private Buffer ajaxEvents = new UnboundedFifoBuffer();
 
-	/**
-	 * Use FIFO buffers for hold Faces Events. Hold this buffers in Request
-	 * scope parameters for support any concurrent requests for same component
-	 * tree ( since RI hold component tree in session ).
-	 * 
-	 * @param context
-	 * @param phase
-	 * @return
-	 */
-	protected Buffer getEventsQueue(FacesContext context, PhaseId phase) {
-		return getEvents(context)[phase.getOrdinal()];
-	}
+    /**
+         * Use FIFO buffers for hold Faces Events. Hold this buffers in Request
+         * scope parameters for support any concurrent requests for same
+         * component tree ( since RI hold component tree in session ).
+         * 
+         * @param context
+         * @param phase
+         * @return
+         */
+    protected Buffer getEventsQueue(FacesContext context, PhaseId phase) {
+	return getEvents(context)[phase.getOrdinal()];
+    }
 
-	/**
-	 * @return
-	 */
-	protected Buffer[] getEvents(FacesContext context) {
-		if (events == null) {
-			clearEvents(context);
-		}
-		return events;
+    /**
+         * @return
+         */
+    protected Buffer[] getEvents(FacesContext context) {
+	if (events == null) {
+	    clearEvents(context);
 	}
+	return events;
+    }
 
-	/**
-	 * Special Fifo Buffer for ajax events to Render Responce phase.
-	 * 
-	 * @param context
-	 * @return
-	 */
-	protected Buffer getAjaxEventsQueue(FacesContext context) {
+    /**
+         * Special Fifo Buffer for ajax events to Render Responce phase.
+         * 
+         * @param context
+         * @return
+         */
+    protected Buffer getAjaxEventsQueue(FacesContext context) {
 
-		return ajaxEvents;
-	}
+	return ajaxEvents;
+    }
 
-	public void clearEvents(FacesContext context) {
-		int len;
-		events = new Buffer[len = PhaseId.VALUES.size()];
-		for (int i = 0; i < len; i++) {
-			events[i] = new UnboundedFifoBuffer();
-		}
+    public void clearEvents(FacesContext context) {
+	int len;
+	events = new Buffer[len = PhaseId.VALUES.size()];
+	for (int i = 0; i < len; i++) {
+	    events[i] = new UnboundedFifoBuffer();
 	}
+    }
 
-	private InvokerCallback _decodeInvoker = new InvokerCallback() {
+    private InvokerCallback _decodeInvoker = new InvokerCallback() {
 
-		public void invoke(FacesContext context, UIComponent component) {
-			component.processDecodes(context);
-		}
+	public void invoke(FacesContext context, UIComponent component) {
+	    component.processDecodes(context);
+	}
 
-		public void invokeRoot(FacesContext context) {
-			AjaxViewRoot.super.processDecodes(context);
-		}
-
-	};
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.ajax4jsf.framework.ajax.AjaxViewBrige#processDecodes(javax.faces.context.FacesContext)
-	 */
-	public void processDecodes(FacesContext context) {
-		if (context == null)
-			throw new NullPointerException("context");
-		AjaxContext.invokeOnRegionOrRoot(this, context, _decodeInvoker,
-				PhaseId.APPLY_REQUEST_VALUES);
+	public void invokeRoot(FacesContext context) {
+	    AjaxViewRoot.super.processDecodes(context);
 	}
 
-	private InvokerCallback _updatesInvoker = new InvokerCallback() {
+    };
 
-		public void invoke(FacesContext context, UIComponent component) {
-			component.processUpdates(context);
-		}
+    private UIComponent singleComponent = null;
 
-		public void invokeRoot(FacesContext context) {
-			AjaxViewRoot.super.processUpdates(context);
-		}
+    /*
+         * (non-Javadoc)
+         * 
+         * @see org.ajax4jsf.framework.ajax.AjaxViewBrige#processDecodes(javax.faces.context.FacesContext)
+         */
+    public void processDecodes(FacesContext context) {
+	if (context == null)
+	    throw new NullPointerException("context");
+	singleComponent = null;
+	AjaxContext.invokeOnRegionOrRoot(this, context, _decodeInvoker);
+	try {
+	    broadcastEvents(context, PhaseId.APPLY_REQUEST_VALUES);
+	} catch (AjaxSingleException e) {
+	    singleComponent = e.getComponent();
+	}
+    }
 
-	};
+    private InvokerCallback _updatesInvoker = new InvokerCallback() {
 
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.ajax4jsf.framework.ajax.AjaxViewBrige#processUpdates(javax.faces.context.FacesContext)
-	 */
-	public void processUpdates(FacesContext context) {
-		if (context == null)
-			throw new NullPointerException("context");
-		AjaxContext.invokeOnRegionOrRoot(this, context, _updatesInvoker,
-				PhaseId.UPDATE_MODEL_VALUES);
+	public void invoke(FacesContext context, UIComponent component) {
+	    component.processUpdates(context);
 	}
 
-	private InvokerCallback _validatorsInvoker = new InvokerCallback() {
+	public void invokeRoot(FacesContext context) {
+	    AjaxViewRoot.super.processUpdates(context);
+	}
 
-		public void invoke(FacesContext context, UIComponent component) {
-			component.processValidators(context);
-		}
+    };
 
-		public void invokeRoot(FacesContext context) {
-			AjaxViewRoot.super.processValidators(context);
-		}
+    /*
+         * (non-Javadoc)
+         * 
+         * @see org.ajax4jsf.framework.ajax.AjaxViewBrige#processUpdates(javax.faces.context.FacesContext)
+         */
+    public void processUpdates(FacesContext context) {
+	if (context == null)
+	    throw new NullPointerException("context");
+	if (null == singleComponent) {
+	    AjaxContext.invokeOnRegionOrRoot(this, context, _updatesInvoker);
+	} else {
+	    singleComponent.processUpdates(context);
+	}
+	broadcastEvents(context, PhaseId.UPDATE_MODEL_VALUES);
+    }
 
-	};
+    private InvokerCallback _validatorsInvoker = new InvokerCallback() {
 
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.ajax4jsf.framework.ajax.AjaxViewBrige#processValidators(javax.faces.context.FacesContext)
-	 */
-	public void processValidators(FacesContext context) {
-		if (context == null)
-			throw new NullPointerException("context");
-		AjaxContext.invokeOnRegionOrRoot(this, context, _validatorsInvoker,
-				PhaseId.PROCESS_VALIDATIONS);
+	public void invoke(FacesContext context, UIComponent component) {
+	    component.processValidators(context);
 	}
 
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see javax.faces.component.UIViewRoot#processApplication(javax.faces.context.FacesContext)
-	 */
-	public void processApplication(FacesContext context) {
-		if (context == null)
-			throw new NullPointerException("context");
-		// UIComponent component = getSubmittedRegion(context);
-		// TODO - process JSF 1.2 listeners
-		broadcastEvents(context, PhaseId.INVOKE_APPLICATION);
-		if (context.getRenderResponse() || context.getResponseComplete()) {
-			clearEvents(context);
-		}
+	public void invokeRoot(FacesContext context) {
+	    AjaxViewRoot.super.processValidators(context);
 	}
 
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see javax.faces.component.UIViewRoot#encodeBegin(javax.faces.context.FacesContext)
-	 */
-	// public void encodeBegin(FacesContext context) throws IOException {
-	// UIComponent submittedComponent = getSubmittedRegion(context);
-	// if(null == submittedComponent){
-	// super.encodeBegin(context);
-	// } else {
-	// submittedComponent.encodeBegin(context);
-	// }
-	// }
+    };
 
-	private InvokerCallback _ajaxInvoker = new InvokerCallback() {
+    /*
+         * (non-Javadoc)
+         * 
+         * @see org.ajax4jsf.framework.ajax.AjaxViewBrige#processValidators(javax.faces.context.FacesContext)
+         */
+    public void processValidators(FacesContext context) {
+	if (context == null)
+	    throw new NullPointerException("context");
+	if (null == singleComponent) {
+	    AjaxContext.invokeOnRegionOrRoot(this, context, _validatorsInvoker);
+	} else {
+	    singleComponent.processValidators(context);
+	}
+	broadcastEvents(context, PhaseId.PROCESS_VALIDATIONS);
+    }
 
-		public void invoke(FacesContext context, UIComponent component) {
-			try {
-				if (component instanceof AjaxContainer) {
-					AjaxContainer ajax = (AjaxContainer) component;
-					ajax.encodeAjax(context);
-				} else {
-					// Container not found, use Root for encode.
-					encodeAjax(context);
-				}
-			} catch (IOException e) {
-				throw new FacesException(e);
-			}
-		}
+    /*
+         * (non-Javadoc)
+         * 
+         * @see javax.faces.component.UIViewRoot#processApplication(javax.faces.context.FacesContext)
+         */
+    public void processApplication(FacesContext context) {
+	if (context == null)
+	    throw new NullPointerException("context");
+	// UIComponent component = getSubmittedRegion(context);
+	// TODO - process JSF 1.2 listeners
+	broadcastEvents(context, PhaseId.INVOKE_APPLICATION);
+    }
 
-		public void invokeRoot(FacesContext context) {
-			try {
-				encodeAjax(context);
-			} catch (IOException e) {
-				throw new FacesException(e);
-			}
-		}
+    /*
+         * (non-Javadoc)
+         * 
+         * @see javax.faces.component.UIViewRoot#encodeBegin(javax.faces.context.FacesContext)
+         */
+    // public void encodeBegin(FacesContext context) throws IOException {
+    // UIComponent submittedComponent = getSubmittedRegion(context);
+    // if(null == submittedComponent){
+    // super.encodeBegin(context);
+    // } else {
+    // submittedComponent.encodeBegin(context);
+    // }
+    // }
+    private InvokerCallback _ajaxInvoker = new InvokerCallback() {
 
-	};
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see javax.faces.component.UIComponentBase#encodeChildren(javax.faces.context.FacesContext)
-	 */
-	public void encodeChildren(FacesContext context) throws IOException {
-		if ( !isHavePage() && AjaxContext.getCurrentInstance(context).isAjaxRequest(context)) {
-			AjaxContext.invokeOnRegionOrRoot(this, context, _ajaxInvoker,
-					PhaseId.RENDER_RESPONSE);
+	public void invoke(FacesContext context, UIComponent component) {
+	    try {
+		if (component instanceof AjaxContainer) {
+		    AjaxContainer ajax = (AjaxContainer) component;
+		    ajax.encodeAjax(context);
 		} else {
-			super.encodeChildren(context);
+		    // Container not found, use Root for encode.
+		    encodeAjax(context);
 		}
+	    } catch (IOException e) {
+		throw new FacesException(e);
+	    }
 	}
 
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see javax.faces.component.UIComponentBase#encodeEnd(javax.faces.context.FacesContext)
-	 */
-//	public void encodeEnd(FacesContext context) throws IOException {
-//		UIComponent submittedComponent = getSubmittedRegion(context);
-//		if (null == submittedComponent) {
-//			super.encodeEnd(context);
-//		} else {
-//			submittedComponent.encodeEnd(context);
-//		}
-//	}
-
-	public void restoreState(FacesContext context, Object state) {
-		Object[] mystate = (Object[]) state;
-		super.restoreState(context, mystate[0]);
-		getBrige().restoreState(context, mystate[1]);
+	public void invokeRoot(FacesContext context) {
+	    try {
+		encodeAjax(context);
+	    } catch (IOException e) {
+		throw new FacesException(e);
+	    }
 	}
 
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.ajax4jsf.framework.ajax.AjaxViewBrige#saveState(javax.faces.context.FacesContext)
-	 */
-	public Object saveState(FacesContext context) {
-		Object[] state = new Object[2];
-		state[0] = super.saveState(context);
-		state[1] = getBrige().saveState(context);
-		return state;
-	}
+    };
 
-	public String getViewId() {
-		ViewIdHolder viewIdHolder = AjaxContext.getCurrentInstance()
-				.getViewIdHolder();
-		String viewId;
-		if (null != viewIdHolder) {
-			viewId = viewIdHolder.getViewId();
-		} else {
-			viewId = super.getViewId();
-		}
-		return viewId;
+    /*
+         * (non-Javadoc)
+         * 
+         * @see javax.faces.component.UIComponentBase#encodeChildren(javax.faces.context.FacesContext)
+         */
+    public void encodeChildren(FacesContext context) throws IOException {
+	if (!isHavePage()
+		&& AjaxContext.getCurrentInstance(context).isAjaxRequest(
+			context)) {
+	    AjaxContext.invokeOnRegionOrRoot(this, context, _ajaxInvoker);
+	} else {
+	    super.encodeChildren(context);
 	}
+    }
 
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.ajax4jsf.framework.ajax.AjaxViewBrige#setAjaxListener(javax.faces.el.MethodBinding)
-	 */
-	public void setAjaxListener(MethodBinding ajaxListener) {
-		getBrige().setAjaxListener(ajaxListener);
-	}
+    /*
+         * (non-Javadoc)
+         * 
+         * @see javax.faces.component.UIComponentBase#encodeEnd(javax.faces.context.FacesContext)
+         */
+    // public void encodeEnd(FacesContext context) throws IOException {
+    // UIComponent submittedComponent = getSubmittedRegion(context);
+    // if (null == submittedComponent) {
+    // super.encodeEnd(context);
+    // } else {
+    // submittedComponent.encodeEnd(context);
+    // }
+    // }
+    public void restoreState(FacesContext context, Object state) {
+	Object[] mystate = (Object[]) state;
+	super.restoreState(context, mystate[0]);
+	getBrige().restoreState(context, mystate[1]);
+    }
 
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.ajax4jsf.framework.ajax.AjaxViewBrige#setImmediate(boolean)
-	 */
-	public void setImmediate(boolean immediate) {
-		getBrige().setImmediate(immediate);
-	}
+    /*
+         * (non-Javadoc)
+         * 
+         * @see org.ajax4jsf.framework.ajax.AjaxViewBrige#saveState(javax.faces.context.FacesContext)
+         */
+    public Object saveState(FacesContext context) {
+	Object[] state = new Object[2];
+	state[0] = super.saveState(context);
+	state[1] = getBrige().saveState(context);
+	return state;
+    }
 
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.ajax4jsf.framework.ajax.AjaxViewBrige#setSubmitted(boolean)
-	 */
-	public void setSubmitted(boolean submitted) {
-		getBrige().setSubmitted(submitted);
+    public String getViewId() {
+	ViewIdHolder viewIdHolder = AjaxContext.getCurrentInstance()
+		.getViewIdHolder();
+	String viewId;
+	if (null != viewIdHolder) {
+	    viewId = viewIdHolder.getViewId();
+	} else {
+	    viewId = super.getViewId();
 	}
+	return viewId;
+    }
 
-	public void addAjaxListener(AjaxListener listener) {
-		addFacesListener(listener);
-	}
+    /*
+         * (non-Javadoc)
+         * 
+         * @see org.ajax4jsf.framework.ajax.AjaxViewBrige#setAjaxListener(javax.faces.el.MethodBinding)
+         */
+    public void setAjaxListener(MethodBinding ajaxListener) {
+	getBrige().setAjaxListener(ajaxListener);
+    }
 
-	public AjaxListener[] getAjaxListeners() {
-		return (AjaxListener[]) getFacesListeners(AjaxListener.class);
-	}
+    /*
+         * (non-Javadoc)
+         * 
+         * @see org.ajax4jsf.framework.ajax.AjaxViewBrige#setImmediate(boolean)
+         */
+    public void setImmediate(boolean immediate) {
+	getBrige().setImmediate(immediate);
+    }
 
-	public void removeAjaxListener(AjaxListener listener) {
-		removeFacesListener(listener);
+    /*
+         * (non-Javadoc)
+         * 
+         * @see org.ajax4jsf.framework.ajax.AjaxViewBrige#setSubmitted(boolean)
+         */
+    public void setSubmitted(boolean submitted) {
+	getBrige().setSubmitted(submitted);
+    }
 
-	}
+    public void addAjaxListener(AjaxListener listener) {
+	addFacesListener(listener);
+    }
 
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.ajax4jsf.framework.ajax.AjaxViewBrige#isSelfRendered()
-	 */
-	public boolean isSelfRendered() {
-		return false;// _brige.isSelfRendered();
-	}
+    public AjaxListener[] getAjaxListeners() {
+	return (AjaxListener[]) getFacesListeners(AjaxListener.class);
+    }
 
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.ajax4jsf.framework.ajax.AjaxViewBrige#setSelfRendered(boolean)
-	 */
-	public void setSelfRendered(boolean selfRendered) {
-		// _brige.setSelfRendered(selfRendered);
-	}
+    public void removeAjaxListener(AjaxListener listener) {
+	removeFacesListener(listener);
 
-	/**
-	 * Check for AjaxContainer component in childreh. This is workaround for
-	 * MyFaces JSP tag implementation, not called any encode... methods in
-	 * <f:view> tag. If only one AjaxContainer present as children for viewRoot,
-	 * decoding methods delegated to them.
-	 * 
-	 * @return Returns the havePage.
-	 */
-	public boolean isHavePage() {
-		return (getChildCount() == 1 && getChildren().get(0) instanceof AjaxContainer);
-	}
+    }
 
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see javax.faces.component.UIComponentBase#getRendersChildren()
-	 */
-	public boolean getRendersChildren() {
-		FacesContext context = FacesContext.getCurrentInstance();
-		// For non Ajax request, view root not render children
-		if (!AjaxContext.getCurrentInstance(context).isAjaxRequest(context)) {
-			return false;
-		}
-		// Also, if have page component as clild - delegate rendering of
-		// children to it.
-		if (isHavePage()) {
-			return false;
-		}
-		// Ajax Request. Control all output.
-		return true;
-	}
+    /*
+         * (non-Javadoc)
+         * 
+         * @see org.ajax4jsf.framework.ajax.AjaxViewBrige#isSelfRendered()
+         */
+    public boolean isSelfRendered() {
+	return false;// _brige.isSelfRendered();
+    }
 
-	public boolean isRenderRegionOnly() {
-		// for viewroot it not applicable.
-		return false;
-	}
+    /*
+         * (non-Javadoc)
+         * 
+         * @see org.ajax4jsf.framework.ajax.AjaxViewBrige#setSelfRendered(boolean)
+         */
+    public void setSelfRendered(boolean selfRendered) {
+	// _brige.setSelfRendered(selfRendered);
+    }
 
-	public void setRenderRegionOnly(boolean reRenderPage) {
-		// TODO Auto-generated method stub
+    /**
+         * Check for AjaxContainer component in childreh. This is workaround for
+         * MyFaces JSP tag implementation, not called any encode... methods in
+         * <f:view> tag. If only one AjaxContainer present as children for
+         * viewRoot, decoding methods delegated to them.
+         * 
+         * @return Returns the havePage.
+         */
+    public boolean isHavePage() {
+	return (getChildCount() == 1 && getChildren().get(0) instanceof AjaxContainer);
+    }
 
+    /*
+         * (non-Javadoc)
+         * 
+         * @see javax.faces.component.UIComponentBase#getRendersChildren()
+         */
+    public boolean getRendersChildren() {
+	FacesContext context = FacesContext.getCurrentInstance();
+	// For non Ajax request, view root not render children
+	if (!AjaxContext.getCurrentInstance(context).isAjaxRequest(context)) {
+	    return false;
 	}
+	// Also, if have page component as clild - delegate rendering of
+	// children to it.
+	if (isHavePage()) {
+	    return false;
+	}
+	// Ajax Request. Control all output.
+	return true;
+    }
 
-	public void encodeAjax(FacesContext context) throws IOException {
-		String rendererType = getRendererType();
-		if (rendererType != null) {
-			((AjaxContainerRenderer) getRenderer(context)).encodeAjax(context,
-					this);
-		}
+    public boolean isRenderRegionOnly() {
+	// for viewroot it not applicable.
+	return false;
+    }
 
-	}
+    public void setRenderRegionOnly(boolean reRenderPage) {
+	// TODO Auto-generated method stub
 
-	/**
-	 * @return the brige
-	 */
-	protected AjaxRegionBrige getBrige() {
-		return _brige;
+    }
+
+    public void encodeAjax(FacesContext context) throws IOException {
+	String rendererType = getRendererType();
+	if (rendererType != null) {
+	    ((AjaxContainerRenderer) getRenderer(context)).encodeAjax(context,
+		    this);
 	}
 
+    }
+
+    /**
+         * @return the brige
+         */
+    protected AjaxRegionBrige getBrige() {
+	return _brige;
+    }
+
 }

Modified: trunk/framework/src/main/java/org/ajax4jsf/framework/ajax/ComponentInvoker.java
===================================================================
--- trunk/framework/src/main/java/org/ajax4jsf/framework/ajax/ComponentInvoker.java	2007-05-03 13:55:52 UTC (rev 163)
+++ trunk/framework/src/main/java/org/ajax4jsf/framework/ajax/ComponentInvoker.java	2007-05-03 20:06:28 UTC (rev 164)
@@ -23,7 +23,6 @@
 
 import javax.faces.component.UIComponent;
 import javax.faces.context.FacesContext;
-import javax.faces.event.PhaseId;
 
 /**
  * Interface for call lifecycle methods on component with known clientId
@@ -39,10 +38,9 @@
 	 * @param viewRoot
 	 * @param context
 	 * @param callback
-	 * @param phase
 	 */
 	public abstract void invokeOnRegionOrRoot(AjaxViewRoot viewRoot,
-			FacesContext context, InvokerCallback callback, PhaseId phase);
+			FacesContext context, InvokerCallback callback);
 
 	/**
 	 * Recursive call for all children for search component with same clientId as target region

Modified: trunk/framework/src/main/java/org/ajax4jsf/framework/ajax/JsfOneOneInvoker.java
===================================================================
--- trunk/framework/src/main/java/org/ajax4jsf/framework/ajax/JsfOneOneInvoker.java	2007-05-03 13:55:52 UTC (rev 163)
+++ trunk/framework/src/main/java/org/ajax4jsf/framework/ajax/JsfOneOneInvoker.java	2007-05-03 20:06:28 UTC (rev 164)
@@ -26,7 +26,6 @@
 import javax.faces.component.UIComponent;
 import javax.faces.component.UIViewRoot;
 import javax.faces.context.FacesContext;
-import javax.faces.event.PhaseId;
 
 /**
  * @author shura
@@ -46,7 +45,7 @@
 	/* (non-Javadoc)
 	 * @see org.ajax4jsf.framework.ajax.AjaxInvoker#invokeOnRegionOrRoot(org.ajax4jsf.framework.ajax.AjaxViewRoot, javax.faces.context.FacesContext, org.ajax4jsf.framework.ajax.InvokerCallback, javax.faces.event.PhaseId)
 	 */
-	public void invokeOnRegionOrRoot(AjaxViewRoot viewRoot, FacesContext context, InvokerCallback callback, PhaseId phase) {
+	public void invokeOnRegionOrRoot(AjaxViewRoot viewRoot, FacesContext context, InvokerCallback callback) {
 		AjaxContext ajaxContext = AjaxContext.getCurrentInstance(context);
 		String submittedRegionClientId = ajaxContext.getSubmittedRegionClientId(context);
 		if(null == submittedRegionClientId || viewRoot.getId().equals(submittedRegionClientId)){
@@ -59,10 +58,6 @@
 				callback.invokeRoot(context);
 			}
 		}
-		viewRoot.broadcastEvents(context, phase);
-		if (context.getRenderResponse() || context.getResponseComplete()) {
-			viewRoot.clearEvents(context);
-		}
 
 	}
 	
@@ -70,6 +65,8 @@
 		UIViewRoot viewRoot = context.getViewRoot();
 		invokeOnComponent(viewRoot,context,callback,regionId);
 	}
+	
+	
 	/* (non-Javadoc)
 	 * @see org.ajax4jsf.framework.ajax.AjaxInvoker#invokeOnComponent(javax.faces.component.UIComponent, javax.faces.context.FacesContext, org.ajax4jsf.framework.ajax.InvokerCallback, java.lang.String)
 	 */

Modified: trunk/framework/src/main/java/org/ajax4jsf/framework/ajax/xmlfilter/BaseFilter.java
===================================================================
--- trunk/framework/src/main/java/org/ajax4jsf/framework/ajax/xmlfilter/BaseFilter.java	2007-05-03 13:55:52 UTC (rev 163)
+++ trunk/framework/src/main/java/org/ajax4jsf/framework/ajax/xmlfilter/BaseFilter.java	2007-05-03 20:06:28 UTC (rev 164)
@@ -38,6 +38,8 @@
 import javax.servlet.http.HttpServletResponse;
 import javax.servlet.http.HttpSession;
 
+import org.ajax4jsf.ajax.PushEventsCounter;
+import org.ajax4jsf.cache.Cache;
 import org.ajax4jsf.framework.renderer.AjaxContainerRenderer;
 import org.ajax4jsf.framework.resource.InternetResourceService;
 import org.ajax4jsf.framework.util.message.Messages;
@@ -54,6 +56,8 @@
  */
 public abstract class BaseFilter implements Filter {
 
+    private static final String AJAX_PUSH_KEY_HEADER = "Ajax-Push-Key";
+
     private static final Log log = LogFactory.getLog(BaseFilter.class);
 
     public static final boolean DEBUG = true;
@@ -91,31 +95,35 @@
     public static final String CACHEABLE_PREFIX = "/cache";
 
     // private static final Pattern rendererPattern =
-        // Pattern.compile(RENDERER_PREFIX+"/([^/]+)/([^/]+)/([^/]+)/(.*)");
+    // Pattern.compile(RENDERER_PREFIX+"/([^/]+)/([^/]+)/([^/]+)/(.*)");
     // private static final Pattern builderPattern =
-        // Pattern.compile(CACHEABLE_PREFIX+"/(.*)");
+    // Pattern.compile(CACHEABLE_PREFIX+"/(.*)");
     public static final String FILTER_PERFORMED = "com.exade.vcp.Filter.done";
 
     public static final String RESPONSE_WRAPPER_ATTRIBUTE = "com.exade.vcp.Filter.ResponseWrapper";
 
     protected BaseXMLFilter xmlFilter = null;
 
-    InternetResourceService resourceService = null;
+    protected InternetResourceService resourceService = null;
 
+    protected PollEventsManager eventsManager;
+
     /**
          * Initialize the filter.
          */
     public void init(FilterConfig config) throws ServletException {
-	if(log.isDebugEnabled()){
-	    log.debug("Init ajax4jsf filter with nane: "+config.getFilterName());
+	if (log.isDebugEnabled()) {
+	    log.debug("Init ajax4jsf filter with nane: "
+		    + config.getFilterName());
 	    Enumeration parameterNames = config.getInitParameterNames();
 	    StringBuffer parameters = new StringBuffer("Init parameters :\n");
 	    while (parameterNames.hasMoreElements()) {
 		String name = (String) parameterNames.nextElement();
-		parameters.append(name).append(" : '").append(config.getInitParameter(name)).append('\n');		
+		parameters.append(name).append(" : '").append(
+			config.getInitParameter(name)).append('\n');
 	    }
 	    log.debug(parameters);
-//	    log.debug("Stack Trace", new Exception());
+	    // log.debug("Stack Trace", new Exception());
 	}
 	// Save config
 	filterConfig = config;
@@ -139,6 +147,8 @@
 	resourceService = new InternetResourceService();
 	// Caching initialization.
 	resourceService.init(filterConfig);
+	eventsManager = new PollEventsManager();
+	eventsManager.init(filterConfig.getServletContext());
     }
 
     /**
@@ -228,12 +238,31 @@
 	if (request.getAttribute(FILTER_PERFORMED) != Boolean.TRUE) {
 	    // mark - and not processing same request twice.
 	    request.setAttribute(FILTER_PERFORMED, Boolean.TRUE);
+	    String ajaxPushHeader = httpServletRequest.getHeader(AJAX_PUSH_KEY_HEADER);
+	    // check for a push check request.
+	    if (httpServletRequest.getMethod().equals("HEAD")
+		    && null != ajaxPushHeader) {
+			PushEventsCounter listener = eventsManager.getListener(ajaxPushHeader);
+			if(listener.isPerformed()){
+			    listener.processed();
+			    httpServletResponse.setStatus(200);
+			    if (log.isDebugEnabled()) {
+				log.debug("Occurs event for a id "+ajaxPushHeader);
+			    }
+			} else {
+			    // Response code - 'No content'
+			    httpServletResponse.setStatus(204);			    
+			    if (log.isDebugEnabled()) {
+				log.debug("No event for a id "+ajaxPushHeader);
+			    }
+			}
+	    } else
 	    // check for resource request
 	    if (!getResourceService().serviceResource(httpServletRequest,
 		    httpServletResponse)) {
 		// Not request to resource - perform filtering.
 		// first stage - detect/set encoding of request. Same as in
-                // Myfaces External Context.
+		// Myfaces External Context.
 		setupRequestEncoding(httpServletRequest);
 		// check ajax request parameter
 		// TODO - check for JSF page.
@@ -244,7 +273,7 @@
 		    }
 
 		    // Execute the rest of the filter chain, including the
-                        // JSP
+		    // JSP
 		    xmlFilter.doXmlFilter(chain, httpServletRequest,
 			    httpServletResponse);
 		} else {
@@ -304,12 +333,12 @@
          */
     protected synchronized InternetResourceService getResourceService()
 	    throws ServletException {
-//	if (resourceService == null) {
-//	    resourceService = new InternetResourceService();
-//	    // Caching initialization.
-//	    resourceService.init(filterConfig);
-//
-//	}
+	// if (resourceService == null) {
+	// resourceService = new InternetResourceService();
+	// // Caching initialization.
+	// resourceService.init(filterConfig);
+	//
+	// }
 	return resourceService;
     }
 

Added: trunk/framework/src/main/java/org/ajax4jsf/framework/ajax/xmlfilter/PollEventsManager.java
===================================================================
--- trunk/framework/src/main/java/org/ajax4jsf/framework/ajax/xmlfilter/PollEventsManager.java	                        (rev 0)
+++ trunk/framework/src/main/java/org/ajax4jsf/framework/ajax/xmlfilter/PollEventsManager.java	2007-05-03 20:06:28 UTC (rev 164)
@@ -0,0 +1,64 @@
+/**
+ * 
+ */
+package org.ajax4jsf.framework.ajax.xmlfilter;
+
+import java.io.Serializable;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.faces.FacesException;
+import javax.servlet.ServletContext;
+
+import org.ajax4jsf.ajax.PushEventsCounter;
+import org.ajax4jsf.cache.Cache;
+import org.ajax4jsf.cache.CacheConfigurationLoader;
+import org.ajax4jsf.cache.CacheException;
+import org.ajax4jsf.cache.CacheFactory;
+import org.ajax4jsf.cache.CacheLoader;
+import org.ajax4jsf.cache.CacheManager;
+import org.ajax4jsf.cache.ServletContextInitMap;
+
+/**
+ * @author asmirnov
+ *
+ */
+public class PollEventsManager implements Serializable, CacheLoader, CacheConfigurationLoader {
+
+    public static final String EVENTS_MANAGER_KEY=PollEventsManager.class.getName();
+
+    private Cache cache;
+    
+    public void init(ServletContext servletContext) {
+	    try {
+		CacheManager cacheManager = CacheManager.getInstance();
+		Map env = new ServletContextInitMap(servletContext);
+		CacheFactory cacheFactory = cacheManager.getCacheFactory(env);
+		this.cache = cacheFactory.createCache(env, this, this);
+		servletContext.setAttribute(EVENTS_MANAGER_KEY, this);
+	} catch (CacheException e) {
+		throw new FacesException(e.getMessage(), e);
+	}
+
+    }
+    
+    public PushEventsCounter getListener(String key){
+	if(null == cache){
+	    throw new FacesException("Poll events manager not initialized");	    
+	}
+	try {
+	    return (PushEventsCounter) cache.get(key, null);
+	} catch (CacheException e) {
+	    throw new FacesException("error get push events listener for key "+key,e);
+	}
+    }
+
+    public Object load(Object key, Object context) throws CacheException {
+	// TODO Auto-generated method stub
+	return new PushEventsCounter();
+    }
+
+    public Properties loadProperties(String name) {
+	return new Properties();
+    }
+}

Modified: trunk/framework/src/main/java/org/ajax4jsf/framework/renderer/AjaxRendererUtils.java
===================================================================
--- trunk/framework/src/main/java/org/ajax4jsf/framework/renderer/AjaxRendererUtils.java	2007-05-03 13:55:52 UTC (rev 163)
+++ trunk/framework/src/main/java/org/ajax4jsf/framework/renderer/AjaxRendererUtils.java	2007-05-03 20:06:28 UTC (rev 164)
@@ -230,9 +230,10 @@
 		controlName = clientId;
 		controlValue = clientId;
 		parameters.put(controlName, controlValue);
-		if (ajaxSingle) {
-			options.put("single", JSReference.TRUE);
-		}
+		// Move processing of a 'single' attribute to a server-side.
+//		if (ajaxSingle) {
+//			options.put("single", JSReference.TRUE);
+//		}
 		AjaxContext ajaxContext = AjaxContext.getCurrentInstance(facesContext);
 		// Setup action URL. For portlet environment, it will be different from
 		// page.

Added: trunk/framework/src/main/java/org/ajax4jsf/renderkit/html/AjaxPushRenderer.java
===================================================================
--- trunk/framework/src/main/java/org/ajax4jsf/renderkit/html/AjaxPushRenderer.java	                        (rev 0)
+++ trunk/framework/src/main/java/org/ajax4jsf/renderkit/html/AjaxPushRenderer.java	2007-05-03 20:06:28 UTC (rev 164)
@@ -0,0 +1,118 @@
+/**
+ * License Agreement.
+ *
+ * Ajax4jsf 1.1 - Natural Ajax for Java Server Faces (JSF)
+ *
+ * Copyright (C) 2007 Exadel, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ */
+
+package org.ajax4jsf.renderkit.html;
+
+import java.io.IOException;
+import java.util.Map;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.context.ResponseWriter;
+
+import org.ajax4jsf.ajax.UIPush;
+import org.ajax4jsf.framework.renderer.AjaxRendererUtils;
+import org.ajax4jsf.framework.renderer.RendererUtils;
+import org.ajax4jsf.framework.renderer.RendererUtils.HTML;
+import org.ajax4jsf.framework.util.javascript.JSFunction;
+import org.ajax4jsf.framework.util.javascript.JSReference;
+import org.ajax4jsf.renderkit.AjaxCommandRendererBase;
+
+/**
+ * @author shura
+ *
+ */
+public class AjaxPushRenderer extends AjaxCommandRendererBase {
+	
+	public static final String PUSH_INTERVAL_PARAMETER = "A4J.AJAX.Push.INTERVAL";
+
+	public static final String PUSH_WAIT_PARAMETER = "A4J.AJAX.Push.WAIT";
+
+	public static final String PUSH_URL_PARAMETER = "A4J.AJAX.Push.URL";
+
+	public static final int DEFAULT_PUSH_INTERVAL = 1000;
+
+	public static final int DEFAULT_PUSH_WAIT = Integer.MIN_VALUE;
+	
+	private static final String AJAX_PUSH_FUNCTION = "A4J.AJAX.Push";
+
+	/* (non-Javadoc)
+	 * @see org.ajax4jsf.framework.renderer.RendererBase#doEncodeEnd(javax.faces.context.ResponseWriter, javax.faces.context.FacesContext, javax.faces.component.UIComponent)
+	 */
+	protected void doEncodeEnd(ResponseWriter writer, FacesContext context, UIComponent component) throws IOException {
+		UIPush push = (UIPush) component;
+		writer.startElement(HTML.SPAN_ELEM, component);
+		writer.writeAttribute(HTML.style_ATTRIBUTE, "display:none;", null);
+		getUtils().encodeId(context, component);
+		getUtils().encodeBeginFormIfNessesary(context, component);
+			// pushing script.
+				writer.startElement(HTML.SCRIPT_ELEM, component);
+				writer.writeAttribute(HTML.TYPE_ATTR, "text/javascript", null);
+				StringBuffer script = new StringBuffer("\n");
+				if(push.isEnabled()){
+				JSFunction function = AjaxRendererUtils.buildAjaxFunction(component, context, AJAX_PUSH_FUNCTION);
+				// Set dummy form id, if nessesary.
+				Map options = AjaxRendererUtils.buildEventOptions(context, component);
+				options.put("dummyForm", component.getClientId(context)+RendererUtils.DUMMY_FORM_ID);
+				int interval = push.getInterval();
+				if(interval == Integer.MIN_VALUE){
+				    String intervalInitParameter = context.getExternalContext().getInitParameter(PUSH_INTERVAL_PARAMETER);
+				    if(null != intervalInitParameter){
+					interval = Integer.parseInt(intervalInitParameter);
+				    } else {
+					interval = DEFAULT_PUSH_INTERVAL;
+				    }
+				}
+				options.put("pushinterval", new Integer(interval));
+				options.put("pushId", push.getListenerId(context));
+				String pushUrl = context.getExternalContext().getInitParameter(PUSH_URL_PARAMETER);
+				if(null != pushUrl){
+				    options.put("pushUrl", pushUrl);
+				}
+				//				options.put("timeout", interval);
+				function.addParameter(options);
+				function.appendScript(script);
+				} else {
+					script.append("A4J.AJAX.StopPush('").append(push.getListenerId(context)).append("')");
+				}
+				script.append(";\n");
+				writer.writeText(script.toString(),null);
+				writer.endElement(HTML.SCRIPT_ELEM);
+		getUtils().encodeEndFormIfNessesary(context, component);
+		writer.endElement(HTML.SPAN_ELEM);
+	}
+
+	/* (non-Javadoc)
+	 * @see org.ajax4jsf.framework.renderer.RendererBase#getComponentClass()
+	 */
+	protected Class getComponentClass() {
+		// only push component is allowed.
+		return UIPush.class;
+	}
+	
+	protected boolean isSubmitted(FacesContext facesContext, UIComponent uiComponent) {
+		boolean submitted = super.isSubmitted(facesContext, uiComponent);
+		UIPush push = (UIPush) uiComponent;
+		push.setSubmitted(submitted);
+		return submitted;
+	}
+
+}

Modified: trunk/framework/src/main/javascript/ajaxjsf/JSFAJAX.js
===================================================================
--- trunk/framework/src/main/javascript/ajaxjsf/JSFAJAX.js	2007-05-03 13:55:52 UTC (rev 163)
+++ trunk/framework/src/main/javascript/ajaxjsf/JSFAJAX.js	2007-05-03 20:06:28 UTC (rev 164)
@@ -397,7 +397,57 @@
 	}
 };
 
+/*
+ * 
+ * 
+ */
+A4J.AJAX.Push =  function( containerId, form, options ) {
+	A4J.AJAX.StopPush(options.pushId);
+	options.onerror = function(){
+		// For error, re-submit request.
+		A4J.AJAX.Push(containerId,form,options);
+	};
+	A4J.AJAX._pollers[options.pushId] = window.setTimeout(function(){
+		var request = new XMLHttpRequest();
+		request.onreadystatechange =  function(){
+		      	if (request.readyState == 4  ) {
+		      		try {
+		      		if(request.status == 200){
+//		      			A4J.AJAX._pollers[options.pushId]=undefined;
+				        A4J.AJAX.SubmitRequest(containerId,form||options.dummyForm,null,options);
+		      		}
+		      		} catch(e){
+		      			// Network error.
+		      		}
+		      		// Re-send request.
+					A4J.AJAX._pollers[options.pushId] = window.setTimeout(function(){
+						A4J.AJAX.SendPush( request,options );
+					},options.pushinterval);
+		      	}
+		}
+		A4J.AJAX.SendPush( request,options );
+	},options.pushinterval);
+};
 
+A4J.AJAX.SendPush =  function( request,options ) {
+	    var url = options.pushUrl || options.actionUrl;
+		request.open('HEAD', url , true);
+		request.setRequestHeader( "Ajax-Push-Key", options.pushId);
+		if(options.timeout){
+			request.setRequestHeader( "Timeout", options.timeout);			
+		}
+		request.send();	
+}
+
+A4J.AJAX.StopPush =  function( Id ) {
+	if(A4J.AJAX._pollers[Id]){
+		window.clearTimeout(A4J.AJAX._pollers[Id]);
+		A4J.AJAX._pollers[Id] = undefined;
+	}
+};
+
+
+
 A4J.AJAX.CloneObject =  function( obj, noFunctions ) {
 	var cloned = {};
 	for( var n in obj ){
@@ -675,9 +725,9 @@
         	  	}
         	  }
         	  // Set focus, if nessesary.
-        	  var responseFocus = req.getElementById("_A4J.AJAX.focus");
-        	  if(responseFocus){
-        	  	var focusId = Sarissa.getText(responseFocus,true);
+        	  var focusId = req.getJSON("_A4J.AJAX.focus");
+        	  if(focusId){
+        	  	LOG.debug("focus must be set to control "+focusId);
         	  	var focusElement=false;
         	  	if(req.form){
         	  		// Attempt to get form control for name. By Richfaces naming convensions, 
@@ -687,11 +737,17 @@
         	  	}
         	  	if(!focusElement){
         	  		// If not found as control element, search in DOM.
+        	  		LOG.debug("No control element "+focusId+" in submitted form");
         	  		focusElement = document.getElementById(focusId);
         	  	}
         	  	if(focusElement){
+        	  		LOG.debug("Set focus to control ");
         	  		focusElement.focus();
+        	  	} else {
+        	  		LOG.warn("Element for set focus not found");
         	  	}
+        	  } else {
+        	  	LOG.debug("No focus information in response");        	  	
         	  }
            } else {
            // No response XML

Added: trunk/samples/seamIntegration/.exadelproject
===================================================================
--- trunk/samples/seamIntegration/.exadelproject	                        (rev 0)
+++ trunk/samples/seamIntegration/.exadelproject	2007-05-03 20:06:28 UTC (rev 164)
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<FILESYSTEMS APPLICATION_NAME="seamIntegration" ENTITY="FileSystems"
+ VERSION="8.0.4" WORKSPACE_HOME="./src/main/webapp/WEB-INF">
+ <FILESYSTEM ENTITY="FileSystemFolder" LOCATION="%exadel.workspace%" NAME="WEB-INF"/>
+ <FILESYSTEM ENTITY="FileSystemFolder" INFO="Content-Type=Web"
+  LOCATION="%exadel.workspace%/.." NAME="WEB-ROOT"/>
+ <FILESYSTEM ENTITY="FileSystemFolder"
+  LOCATION="%exadel.workspace%/../../java" NAME="src"/>
+ <FILESYSTEM ENTITY="FileSystemFolder"
+  LOCATION="%exadel.workspace%/../../resources" NAME="src2"/>
+ <FILESYSTEM ENTITY="FileSystemFolder"
+  LOCATION="%exadel.workspace%/../../../test/java" NAME="src3"/>
+ <FILESYSTEM ENTITY="FileSystemFolder"
+  LOCATION="%exadel.workspace%/../../../../target/classes" NAME="classes"/>
+ <FILESYSTEM ENTITY="FileSystemFolder"
+  LOCATION="%exadel.eclipse.project%" NAME="seamIntegration"/>
+ <WEB ENTITY="ExadelWeb" MODEL_PATH="/web.xml" SERVLET_VERSION="2.4">
+  <MODULE ENTITY="WebJSFModule" ROOT="WEB-ROOT" SRC="src,src2,src3" URI="/WEB-INF/faces-config.xml"/>
+ </WEB>
+</FILESYSTEMS>

Added: trunk/samples/useCases/src/main/java/org/ajax4jsf/A4jTestBean.java
===================================================================
--- trunk/samples/useCases/src/main/java/org/ajax4jsf/A4jTestBean.java	                        (rev 0)
+++ trunk/samples/useCases/src/main/java/org/ajax4jsf/A4jTestBean.java	2007-05-03 20:06:28 UTC (rev 164)
@@ -0,0 +1,45 @@
+package org.ajax4jsf;
+
+import java.util.Map;
+
+import javax.faces.context.FacesContext;
+import javax.faces.event.ActionEvent;
+
+public class A4jTestBean {
+
+	private String param = "Not set yet";
+	private boolean checked;
+
+	public String getParam() {
+		return param;
+	}
+
+	public void setParam(String param) {
+		this.param = param;
+	}
+	
+	private void checkMap() {
+		Map<String, String> params = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();
+		for (String key : params.keySet()) {
+			System.out.println(key + "=" + params.get(key));
+		}
+	}
+	
+	public void perform(ActionEvent actionEvent) {
+		System.out.println("A4jTestBean.perform(ActionEvent) = " + param);
+		checkMap();
+	}
+
+	public void perform() {
+		System.out.println("A4jTestBean.perform() = " + param);
+		checkMap();
+	}
+	
+	public boolean isChecked() {
+		return checked;
+	}
+
+	public void setChecked(boolean checked) {
+		this.checked = checked;
+	}
+}

Modified: trunk/samples/useCases/src/main/java/org/ajax4jsf/Bean.java
===================================================================
--- trunk/samples/useCases/src/main/java/org/ajax4jsf/Bean.java	2007-05-03 13:55:52 UTC (rev 163)
+++ trunk/samples/useCases/src/main/java/org/ajax4jsf/Bean.java	2007-05-03 20:06:28 UTC (rev 164)
@@ -21,8 +21,11 @@
 
 package org.ajax4jsf;
 
+import javax.faces.application.FacesMessage;
+import javax.faces.component.UIComponent;
 import javax.faces.context.ExternalContext;
 import javax.faces.context.FacesContext;
+import javax.faces.event.ValueChangeEvent;
 import javax.servlet.http.Cookie;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
@@ -35,6 +38,8 @@
 
     private java.lang.String text;
     
+    private String text2;
+    
     private String[] array = {"one]","two]]>"};
 
     private String[][] array2 = {{"one","two"},{"three","four"}};
@@ -100,5 +105,49 @@
 	    public void setArray2(String[][] array2) {
 	        this.array2 = array2;
 	    }
+
+	    /**
+	     * @return the text2
+	     */
+	    public String getText2() {
+	        return text2;
+	    }
+
+	    /**
+	     * @param text2 the text2 to set
+	     */
+	    public void setText2(String test2) {
+	        this.text2 = test2;
+	    }
+	    
+	    public void validate(FacesContext context, UIComponent input,Object newValue) {
+		FacesMessage msg = new FacesMessage("#{bean.validate} called");
+		context.addMessage(input.getClientId(context), msg);
+		System.out.println("validate");
+	    }
+	    
+	    public void onChange(ValueChangeEvent event) {
+		FacesContext context = FacesContext.getCurrentInstance();
+		UIComponent input = event.getComponent();
+		FacesMessage msg = new FacesMessage("#{bean.onChange} called");
+		context.addMessage(input.getClientId(context), msg);
+		System.out.println("onChange");
+		
+	    }
 	
+	    public void validate2(FacesContext context, UIComponent input,Object newValue) {
+		FacesMessage msg = new FacesMessage("#{bean.validate2} called");
+		context.addMessage(input.getClientId(context), msg);
+		System.out.println("validate2");
+
+	    }
+	    
+	    public void onChange2(ValueChangeEvent event) {
+		FacesContext context = FacesContext.getCurrentInstance();
+		UIComponent input = event.getComponent();
+		FacesMessage msg = new FacesMessage("#{bean.onChange2} called");
+		context.addMessage(input.getClientId(context), msg);
+		System.out.println("onChange2");
+
+	    }
 }
\ No newline at end of file

Added: trunk/samples/useCases/src/main/java/org/ajax4jsf/MessageBean.java
===================================================================
--- trunk/samples/useCases/src/main/java/org/ajax4jsf/MessageBean.java	                        (rev 0)
+++ trunk/samples/useCases/src/main/java/org/ajax4jsf/MessageBean.java	2007-05-03 20:06:28 UTC (rev 164)
@@ -0,0 +1,97 @@
+package org.ajax4jsf;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.EventListener;
+import java.util.EventObject;
+import java.util.List;
+
+import org.ajax4jsf.ajax.PushEventListener;
+
+public class MessageBean implements Runnable {
+
+    private String result;
+
+    private boolean running = true;
+
+    private PushEventListener listener;
+    
+    private List messages = new ArrayList();
+
+    public MessageBean() {
+	// TODO Auto-generated constructor stub
+    }
+
+    /**
+         * @return the result
+         */
+    public String getResult() {
+	return result;
+    }
+
+    /**
+         * @param result
+         *                the result to set
+         */
+    public void setResult(String result) {
+	this.result = result;
+    }
+
+    public void addListener(EventListener listener) {
+	synchronized (listener) {
+	    if (this.listener != listener) {
+		this.listener = (PushEventListener) listener;
+		Thread th = new Thread(this);
+		th.start();
+
+	    }
+	}
+    }
+
+    public void run() {
+	try {
+	    while (isRunning()) {
+		Thread.sleep(10000);
+		Date current = new Date(System.currentTimeMillis());
+		messages.add(current);
+		System.out.println("event occurs");
+		synchronized (listener) {
+		    listener.onEvent(new EventObject(this));
+		}
+	    }
+	} catch (InterruptedException e) {
+	    e.printStackTrace();
+	}
+
+    }
+
+    /**
+         * @return the running
+         */
+    public synchronized boolean isRunning() {
+	return running;
+    }
+
+    /**
+         * @param running
+         *                the running to set
+         */
+    public synchronized void setRunning(boolean running) {
+	this.running = running;
+    }
+
+    /**
+     * @return the messages
+     */
+    public List getMessages() {
+        return messages;
+    }
+
+    /**
+     * @param messages the messages to set
+     */
+    public void setMessages(List messages) {
+        this.messages = messages;
+    }
+
+}

Modified: trunk/samples/useCases/src/main/webapp/WEB-INF/faces-config.xml
===================================================================
--- trunk/samples/useCases/src/main/webapp/WEB-INF/faces-config.xml	2007-05-03 13:55:52 UTC (rev 163)
+++ trunk/samples/useCases/src/main/webapp/WEB-INF/faces-config.xml	2007-05-03 20:06:28 UTC (rev 164)
@@ -17,11 +17,21 @@
   <managed-bean-class>org.ajax4jsf.RepeatData</managed-bean-class>
   <managed-bean-scope>session</managed-bean-scope>
  </managed-bean>
-   <navigation-rule>
-    <navigation-case>
-      <from-outcome>verify_cookie</from-outcome>
-      <to-view-id>/pages/testCookie.xhtml</to-view-id>
-      <redirect/>
-    </navigation-case>
-  </navigation-rule>
+ <managed-bean>
+  <managed-bean-name>a4jTestBean</managed-bean-name>
+  <managed-bean-class>org.ajax4jsf.A4jTestBean</managed-bean-class>
+  <managed-bean-scope>request</managed-bean-scope>
+ </managed-bean>
+ <managed-bean>
+  <managed-bean-name>messageBean</managed-bean-name>
+  <managed-bean-class>org.ajax4jsf.MessageBean</managed-bean-class>
+  <managed-bean-scope>session</managed-bean-scope>
+ </managed-bean>
+ <navigation-rule>
+  <navigation-case>
+   <from-outcome>verify_cookie</from-outcome>
+   <to-view-id>/pages/testCookie.xhtml</to-view-id>
+   <redirect/>
+  </navigation-case>
+ </navigation-rule>
 </faces-config>

Added: trunk/samples/useCases/src/main/webapp/pages/actionparam.xhtml
===================================================================
--- trunk/samples/useCases/src/main/webapp/pages/actionparam.xhtml	                        (rev 0)
+++ trunk/samples/useCases/src/main/webapp/pages/actionparam.xhtml	2007-05-03 20:06:28 UTC (rev 164)
@@ -0,0 +1,36 @@
+<!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:ui="http://java.sun.com/jsf/facelets"
+	xmlns:h="http://java.sun.com/jsf/html"
+	xmlns:f="http://java.sun.com/jsf/core"
+	xmlns:a4j="https://ajax4jsf.dev.java.net/ajax">
+<body>
+<a4j:outputPanel id="messages">
+	<h:messages />
+</a4j:outputPanel>
+<h:form id="testForm">
+	<h:selectBooleanCheckbox value="#{a4jTestBean.checked}">
+		<a4j:support event="onchange" actionListener="#{a4jTestBean.perform}"
+			reRender="output, messages">
+			<a4j:actionparam name="param" value="Checkbox clicked"
+				assignTo="#{a4jTestBean.param}" />
+		</a4j:support>
+	</h:selectBooleanCheckbox>
+	<br />
+	<a4j:commandButton limitToList="true" reRender="output, messages"
+		actionListener="#{a4jTestBean.perform}" value="a4j:commandButton">
+		<a4j:actionparam name="param" value="Command Button clicked"
+			assignTo="#{a4jTestBean.param}" />
+	</a4j:commandButton>
+	<br />
+	<a4j:outputPanel id="output">
+	       <h:outputText value="a4jTestBean.param:   #{a4jTestBean.param}"/>
+	       <h:outputText value=" Request parameter 'param':   #{params.param}"/>
+	  </a4j:outputPanel>
+	<br />
+	<h:commandButton action="#{a4jTestBean.perform}"
+		value="h:commandButton" />
+</h:form>
+<a4j:log popup="false"></a4j:log>
+</body>
+</html>

Added: trunk/samples/useCases/src/main/webapp/pages/ajaxSingle.xhtml
===================================================================
--- trunk/samples/useCases/src/main/webapp/pages/ajaxSingle.xhtml	                        (rev 0)
+++ trunk/samples/useCases/src/main/webapp/pages/ajaxSingle.xhtml	2007-05-03 20:06:28 UTC (rev 164)
@@ -0,0 +1,61 @@
+<!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:f="http://java.sun.com/jsf/core"
+	xmlns:h="http://java.sun.com/jsf/html"
+	xmlns:ui="http://java.sun.com/jsf/facelets"
+	xmlns:a4j="https://ajax4jsf.dev.java.net/ajax"
+	xmlns:c="http://java.sun.com/jsp/jstl/core">
+<f:view>
+	<h:form>
+		<h:panelGrid columns="2">
+			<h:inputText id="text" value="#{bean.text}"
+				validator="#{bean.validate}" valueChangeListener="#{bean.onChange}">
+				<a4j:support event="onkeyup" ajaxSingle="true"></a4j:support>
+			</h:inputText>
+			<a4j:outputPanel ajaxRendered="true">
+				<h:outputText value="#{bean.text}"></h:outputText>
+				<h:message for="text"></h:message>
+			</a4j:outputPanel>
+			<h:inputText id="text2" value="#{bean.text2}"
+				validator="#{bean.validate2}"
+				valueChangeListener="#{bean.onChange2}">
+				<a4j:support event="onkeyup" ajaxSingle="true"></a4j:support>
+			</h:inputText>
+			<a4j:outputPanel ajaxRendered="true">
+				<h:outputText value="#{bean.text2}"></h:outputText>
+				<h:message for="text2"></h:message>
+			</a4j:outputPanel>
+		</h:panelGrid>
+		<h2>Ajax support with 'ajaxSingle="true"' in a4j:repeat</h2>
+		<ul>
+			<a4j:repeat value="#{repeatData.data}" var="row">
+				<li><h:inputText id="repeattext" value="#{row.text}"
+					validator="#{bean.validate}" valueChangeListener="#{bean.onChange}">
+					<a4j:support event="onkeyup" ajaxSingle="true"></a4j:support>
+				</h:inputText> <a4j:outputPanel ajaxRendered="true">
+					<h:outputText value="#{row.text}"></h:outputText>
+					<h:message for="repeattext"></h:message>
+				</a4j:outputPanel></li>
+			</a4j:repeat>
+		</ul>
+		<h2>Ajax support with 'ajaxSingle="true"' in h:dataTeble</h2>
+		<a4j:outputPanel ajaxRendered="true">
+		<h:dataTable value="#{repeatData.data}" var="row" border="1" id="table">
+			<h:column>
+				<h:inputText id="tabletext" value="#{row.text}"
+					validator="#{bean.validate}" valueChangeListener="#{bean.onChange}">
+					<a4j:support event="onkeyup" ajaxSingle="true" focus="tabletext"></a4j:support>
+				</h:inputText>
+			</h:column>
+			<h:column>
+					<h:outputText value="#{row.text}"></h:outputText>
+					<h:message for="tabletext"></h:message>
+			</h:column>
+		</h:dataTable>
+		</a4j:outputPanel>
+		<a4j:commandButton value="Ajax Button"></a4j:commandButton>
+		<a4j:commandButton value="Ajax Single Button" ajaxSingle="true"></a4j:commandButton>
+	</h:form>
+	<a4j:log hotkey="M"></a4j:log>
+</f:view>
+</html>

Added: trunk/samples/useCases/src/main/webapp/pages/push.xhtml
===================================================================
--- trunk/samples/useCases/src/main/webapp/pages/push.xhtml	                        (rev 0)
+++ trunk/samples/useCases/src/main/webapp/pages/push.xhtml	2007-05-03 20:06:28 UTC (rev 164)
@@ -0,0 +1,28 @@
+<!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:f="http://java.sun.com/jsf/core"
+      xmlns:h="http://java.sun.com/jsf/html"
+      xmlns:ui="http://java.sun.com/jsf/facelets"
+      xmlns:a4j="https://ajax4jsf.dev.java.net/ajax"
+      xmlns:c="http://java.sun.com/jsp/jstl/core"  
+      >
+      <body>
+	<f:view>
+	<a4j:push reRender="msg" eventProducer="#{messageBean.addListener}" interval="3000"/>
+	
+	<h:dataTable  id="msg" value="#{messageBean.messages}" var="msg">
+	    <f:facet name="header"><h2>Messags : </h2></f:facet>
+	    <h:column>
+	      Message :
+	    </h:column>
+	    <h:column>
+	    <h:outputText value="#{msg}"></h:outputText>
+	    </h:column>
+	</h:dataTable>
+	<h:form>
+	<a4j:status startText="Request started" stopText="stop."></a4j:status>
+	</h:form>
+	<a4j:log hotkey="M"></a4j:log>
+	</f:view>
+	</body>
+</html>	
\ No newline at end of file




More information about the ajax4jsf-svn-commits mailing list