You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by jk...@apache.org on 2007/06/19 01:25:21 UTC

svn commit: r548530 - in /tapestry/tapestry4/trunk: tapestry-annotations/src/java/org/apache/tapestry/annotations/ tapestry-framework/src/java/org/apache/tapestry/services/impl/ tapestry-framework/src/js/tapestry/ tapestry-framework/src/test/org/apache...

Author: jkuhnert
Date: Mon Jun 18 16:25:19 2007
New Revision: 548530

URL: http://svn.apache.org/viewvc?view=rev&rev=548530
Log:
Fixes rather nasty little bug of having duplicate form event connections on deferred form connections pointing to a single target with multiple event types. (also crashes safari apparently)

Modified:
    tapestry/tapestry4/trunk/tapestry-annotations/src/java/org/apache/tapestry/annotations/EventListenerAnnotationWorker.java
    tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/impl/ComponentEventConnectionWorker.java
    tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/impl/HiveMindExpressionCompiler.java
    tapestry/tapestry4/trunk/tapestry-framework/src/js/tapestry/core.js
    tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/services/impl/ComponentEventConnectionWorkerTest.java

Modified: tapestry/tapestry4/trunk/tapestry-annotations/src/java/org/apache/tapestry/annotations/EventListenerAnnotationWorker.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-annotations/src/java/org/apache/tapestry/annotations/EventListenerAnnotationWorker.java?view=diff&rev=548530&r1=548529&r2=548530
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-annotations/src/java/org/apache/tapestry/annotations/EventListenerAnnotationWorker.java (original)
+++ tapestry/tapestry4/trunk/tapestry-annotations/src/java/org/apache/tapestry/annotations/EventListenerAnnotationWorker.java Mon Jun 18 16:25:19 2007
@@ -23,26 +23,26 @@
 
 /**
  * Performs {@link EventListener} annotation enhancements on components.
- * 
+ *
  * @author jkuhnert
  */
 public class EventListenerAnnotationWorker implements SecondaryAnnotationWorker
 {
-    /** 
+    /**
      * {@inheritDoc}
      */
     public boolean canEnhance(Method method)
     {
         return method.getAnnotation(EventListener.class) != null;
     }
-    
-    /** 
+
+    /**
      * {@inheritDoc}
      */
     public void peformEnhancement(EnhancementOperation op, IComponentSpecification spec, Method method, Resource classResource)
     {
         EventListener listener = method.getAnnotation(EventListener.class);
-        
+
         String[] targets = listener.targets();
         String[] elements = listener.elements();
         String formId = listener.submitForm();
@@ -50,20 +50,20 @@
         boolean async = listener.async();
         boolean focus = listener.focus();
         boolean autoSubmit = listener.autoSubmit();
-        
+
         if (targets.length < 1 && elements.length < 1)
             throw new ApplicationRuntimeException(AnnotationMessages.targetsNotFound(method));
 
-        for (int i=0; i < targets.length; i++) {
-
+        for (int i=0; i < targets.length; i++)
+        {
             spec.addEventListener(targets[i], listener.events(),
-                    method.getName(), formId, validateForm, async, focus, autoSubmit);
+                                  method.getName(), formId, validateForm, async, focus, autoSubmit);
         }
-        
-        for (int i=0; i < elements.length; i++) {
-            
-            spec.addElementEventListener(elements[i], listener.events(), 
-                    method.getName(), formId, validateForm, async, focus);
+
+        for (int i=0; i < elements.length; i++)
+        {
+            spec.addElementEventListener(elements[i], listener.events(),
+                                         method.getName(), formId, validateForm, async, focus);
         }
     }
 }

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/impl/ComponentEventConnectionWorker.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/impl/ComponentEventConnectionWorker.java?view=diff&rev=548530&r1=548529&r2=548530
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/impl/ComponentEventConnectionWorker.java (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/impl/ComponentEventConnectionWorker.java Mon Jun 18 16:25:19 2007
@@ -36,41 +36,82 @@
 /**
  * Implementation that handles connecting events to listener
  * method invocations.
- * 
+ *
  * @author jkuhnert
  */
 public class ComponentEventConnectionWorker implements ComponentRenderWorker, PoolManageable
 {
     /** Stored in {@link IRequestCycle} with associated forms. */
     public static final String FORM_NAME_LIST =  "org.apache.tapestry.services.impl.ComponentEventConnectionFormNames-";
-    
+
     // holds mapped event listener info
     private IComponentEventInvoker _invoker;
-    
+
     // generates links for scripts
     private IEngineService _eventEngine;
-    
+
     // handles resolving and loading different component event 
     // connection script types
     private IScriptSource _scriptSource;
-    
+
     // script path references
     private String _componentScript;
     private String _widgetScript;
     private String _elementScript;
-    
+
     // resolves classpath relative resources
     private ClassResolver _resolver;
-    
+
     // wrappers around resolved script templates
     private ClasspathResource _componentResource;
     private ClasspathResource _widgetResource;
     private ClasspathResource _elementResource;
-    
-    // For event connections referencing forms that have not 
-    // been rendered yet.
+
+    /**
+     * For event connections referencing forms that have not been rendered yet.
+     */
     private Map _deferredFormConnections = new HashMap(24);
 
+    /**
+     * Used to store deferred form connection information, but most importantly is used
+     * to provide unique equals/hashcode semantics.
+     */
+    class DeferredFormConnection {
+
+        String _formId;
+        Map _scriptParms;
+        Boolean _async;
+        Boolean _validate;
+        String _uniqueHash;
+        
+        public DeferredFormConnection(String formId, Map scriptParms, Boolean async,
+                                      Boolean validate, String uniqueHash)
+        {
+            _formId = formId;
+            _scriptParms = scriptParms;
+            _async = async;
+            _validate = validate;
+            _uniqueHash = uniqueHash;
+        }
+
+        public boolean equals(Object o)
+        {
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
+
+            DeferredFormConnection that = (DeferredFormConnection) o;
+
+            if (_uniqueHash != null ? !_uniqueHash.equals(that._uniqueHash) : that._uniqueHash != null) return false;
+
+            return true;
+        }
+
+        public int hashCode()
+        {
+            return (_uniqueHash != null ? _uniqueHash.hashCode() : 0);
+        }
+    }
+
     public void activateService()
     {
         _deferredFormConnections.clear();
@@ -98,41 +139,41 @@
         IComponent field = (IComponent)cycle.getAttribute(TapestryUtils.FIELD_PRERENDER);
         if (field != null && field == component)
             return;
-        
+
         linkComponentEvents(cycle, component);
-        
+
         linkElementEvents(cycle, component);
-        
+
         if (IForm.class.isInstance(component))
             mapFormNames(cycle, (IForm)component);
-        
+
         if (isDeferredForm(component))
             linkDeferredForm(cycle, (IForm)component);
     }
-    
+
     void linkComponentEvents(IRequestCycle cycle, IComponent component)
     {
         ComponentEventProperty[] props = _invoker.getEventPropertyListeners(component.getExtendedId());
         if (props == null)
             return;
-        
+
         for (int i=0; i < props.length; i++) {
-            
+
             String clientId = component.getClientId();
-            
+
             Map parms = new HashMap();
             parms.put("clientId", clientId);
             parms.put("component", component);
-            
+
             Object[][] events = getEvents(props[i], clientId);
             Object[][] formEvents = filterFormEvents(props[i], parms, cycle);
-            
+
             if (events.length < 1 && formEvents.length < 1)
                 continue;
-            
+
             DirectEventServiceParameter dsp =
-                new DirectEventServiceParameter((IDirectEvent)component, new Object[] {}, new String[] {}, false);
-            
+              new DirectEventServiceParameter((IDirectEvent)component, new Object[] {}, new String[] {}, false);
+
             parms.put("url", _eventEngine.getLink(false, dsp).getURL());
             parms.put("events", events);
             parms.put("formEvents", formEvents);
@@ -143,42 +184,42 @@
             _scriptSource.getScript(resource).execute(component, cycle, prs, parms);
         }
     }
-    
+
     void linkElementEvents(IRequestCycle cycle, IComponent component)
     {
         if (!component.getSpecification().hasElementEvents())
             return;
-        
-        DirectEventServiceParameter dsp = 
-            new DirectEventServiceParameter((IDirectEvent)component, new Object[] {}, new String[] {}, false);
-        
+
+        DirectEventServiceParameter dsp =
+          new DirectEventServiceParameter((IDirectEvent)component, new Object[] {}, new String[] {}, false);
+
         String url = _eventEngine.getLink(false, dsp).getURL();
-        
+
         PageRenderSupport prs = TapestryUtils.getPageRenderSupport(cycle, component);
         Resource resource = getElementScript();
-        
+
         Map elements = component.getSpecification().getElementEvents();
         Iterator keys = elements.keySet().iterator();
-        
+
         // build our list of targets / events
         while (keys.hasNext()) {
-            
+
             Map parms = new HashMap();
-            
+
             String target = (String)keys.next();
-            
+
             ComponentEventProperty prop = (ComponentEventProperty)elements.get(target);
-            
+
             parms.put("component", component);
             parms.put("target", target);
             parms.put("url", url);
             parms.put("events", getEvents(prop, target));
             parms.put("formEvents", filterFormEvents(prop, parms, cycle));
-            
+
             _scriptSource.getScript(resource).execute(component, cycle, prs, parms);
         }
     }
-    
+
     /**
      * {@inheritDoc}
      */
@@ -186,70 +227,70 @@
     {
         if (cycle.isRewinding())
             return;
-        
+
         renderComponent(cycle, component);
-        
+
         // just in case
         _deferredFormConnections.clear();
     }
-    
+
     void mapFormNames(IRequestCycle cycle, IForm form)
     {
         List names = (List)cycle.getAttribute(FORM_NAME_LIST + form.getExtendedId());
-        
+
         if (names == null) {
             names = new ArrayList();
-            
+
             cycle.setAttribute(FORM_NAME_LIST + form.getExtendedId(), names);
         }
-        
+
         names.add(form.getName());
     }
-    
+
     void linkDeferredForm(IRequestCycle cycle, IForm form)
     {
         List deferred = (List)_deferredFormConnections.remove(form.getExtendedId());
-        
-        for (int i=0; i < deferred.size(); i++) {
-            
-            Object[] val = (Object[])deferred.get(i);
-            
-            Map scriptParms = (Map)val[0];
-            
+
+        for (int i=0; i < deferred.size(); i++)
+        {
+            DeferredFormConnection fConn = (DeferredFormConnection)deferred.get(i);
+            Map scriptParms = fConn._scriptParms;
+
             // don't want any events accidently connected again
             scriptParms.remove("events");
-            
+
             IComponent component = (IComponent)scriptParms.get("component");
-            
+
             // fire off element based events first
-            
+
             linkElementEvents(cycle, component);
-            
+
             ComponentEventProperty[] props = _invoker.getEventPropertyListeners(component.getExtendedId());
             if (props == null)
                 continue;
-            
+
             for (int e=0; e < props.length; e++) {
-                
-                Object[][] formEvents = buildFormEvents(cycle, form.getExtendedId(), 
-                        props[e].getFormEvents(), (Boolean)val[1], (Boolean)val[2], val[3]);
-                
+
+                Object[][] formEvents = buildFormEvents(cycle, form.getExtendedId(),
+                                                        props[e].getFormEvents(), fConn._async,
+                                                        fConn._validate, fConn._uniqueHash);
+
                 scriptParms.put("formEvents", formEvents);
-                
+
                 // execute script
-                
+
                 PageRenderSupport prs = TapestryUtils.getPageRenderSupport(cycle, component);
                 Resource resource = getScript(component);
-                
+
                 _scriptSource.getScript(resource).execute(form, cycle, prs, scriptParms);
             }
         }
     }
-    
+
     /**
      * Generates a two dimensional array containing the event name in the first
      * index and a unique hashcode for the event binding in the second.
-     * 
+     *
      * @param prop The component event properties object the events are managed in.
      * @return A two dimensional array containing all events, or empty array if none exist.
      */
@@ -257,148 +298,151 @@
     {
         Set events = prop.getEvents();
         List ret = new ArrayList();
-        
+
         Iterator it = events.iterator();
-        while (it.hasNext()) {
-            
+        while (it.hasNext())
+        {
             String event = (String)it.next();
-            
+
             int hash = 0;
             List listeners = prop.getEventListeners(event);
-            for (int i=0; i < listeners.size(); i++){
+
+            for (int i=0; i < listeners.size(); i++)
                 hash += listeners.get(i).hashCode();
-            }
-            
+
             ret.add(new Object[]{ event, ScriptUtils.functionHash(event + hash + clientId) });
         }
-        
+
         return (Object[][])ret.toArray(new Object[ret.size()][2]);
     }
-    
-    Object[][] buildFormEvents(IRequestCycle cycle, String formId, Set events, Boolean async, 
-            Boolean validate, Object uniqueHash)
+
+    Object[][] buildFormEvents(IRequestCycle cycle, String formId, Set events,
+                               Boolean async, Boolean validate, Object uniqueHash)
     {
         List formNames = (List)cycle.getAttribute(FORM_NAME_LIST + formId);
         List retval = new ArrayList();
-        
+
         Iterator it = events.iterator();
-        
-        while (it.hasNext()) {
-            
+
+        while (it.hasNext())
+        {
             String event = (String)it.next();
-            
+
             retval.add(new Object[]{event, formNames, async, validate,
-                    ScriptUtils.functionHash(new String(uniqueHash + event)) });
+                                    ScriptUtils.functionHash(new String(uniqueHash + event)) });
         }
-        
+
         return (Object[][])retval.toArray(new Object[retval.size()][5]);
     }
-    
+
     Resource getScript(IComponent component)
     {
         if (IWidget.class.isInstance(component)) {
-            
-            if (_widgetResource == null) 
+
+            if (_widgetResource == null)
                 _widgetResource = new ClasspathResource(_resolver, _widgetScript);
-            
+
             return _widgetResource;
         }
-        
-        if (_componentResource == null) 
+
+        if (_componentResource == null)
             _componentResource = new ClasspathResource(_resolver, _componentScript);
-        
+
         return _componentResource;
     }
-    
+
     Resource getElementScript()
     {
-        if (_elementResource == null) 
+        if (_elementResource == null)
             _elementResource = new ClasspathResource(_resolver, _elementScript);
-        
+
         return _elementResource;
     }
-    
+
     boolean isDeferredForm(IComponent component)
     {
-        if (IForm.class.isInstance(component) 
-                && _deferredFormConnections.get(((IForm)component).getExtendedId()) != null)
+        if (IForm.class.isInstance(component)
+            && _deferredFormConnections.get(((IForm)component).getExtendedId()) != null)
             return true;
-        
+
         return false;
     }
-    
+
     /**
      * For each form event attempts to find a rendered form name list that corresponds
      * to the actual client ids that the form can be connected to. If the form hasn't been
      * rendered yet the events will be filtered out and deferred for execution <i>after</i>
      * the form has rendererd.
-     * 
+     *
      * @param prop
+     *          The configured event properties.
      * @param scriptParms
+     *          The parameters to eventually be passed in to the javascript tempate.
      * @param cycle
-     * 
-     * @return A set of events that can be connected "now".
+     *          The current cycle.
+     *
+     * @return A set of events that can be connected now because the form has already rendered.
      */
     Object[][] filterFormEvents(ComponentEventProperty prop, Map scriptParms, IRequestCycle cycle)
     {
         Set events = prop.getFormEvents();
-        
-        if (events.size() < 1) 
+
+        if (events.size() < 1)
             return new Object[0][0];
-        
+
         List retval = new ArrayList();
-        
+
         Iterator it = events.iterator();
-        while (it.hasNext()) {
-            
+        while (it.hasNext())
+        {
             String event = (String)it.next();
             Iterator lit = prop.getFormEventListeners(event).iterator();
-            
-            while (lit.hasNext()) {
+
+            while (lit.hasNext())
+            {
                 EventBoundListener listener = (EventBoundListener)lit.next();
-                
+
                 String formId = listener.getFormId();
                 List formNames = (List)cycle.getAttribute(FORM_NAME_LIST + formId);
-                
+
                 // defer connection until form is rendered
-                if (formNames == null) {
-                    
-                    deferFormConnection(formId, scriptParms, 
-                            listener.isAsync(), 
-                            listener.isValidateForm(), 
-                            ScriptUtils.functionHash(listener));
+                if (formNames == null)
+                {
+                    deferFormConnection(formId, scriptParms,
+                                        listener.isAsync(),
+                                        listener.isValidateForm(),
+                                        ScriptUtils.functionHash(listener));
 
                     // re-looping over the same property -> event listener list would
                     // result in duplicate bindings so break out 
-
                     break;
                 }
-                
+
                 // form has been rendered so go ahead
                 retval.add(new Object[] {
-                        event, formNames, 
-                        Boolean.valueOf(listener.isAsync()), 
-                        Boolean.valueOf(listener.isValidateForm()),
-                        ScriptUtils.functionHash(listener)
+                  event, formNames,
+                  Boolean.valueOf(listener.isAsync()),
+                  Boolean.valueOf(listener.isValidateForm()),
+                  ScriptUtils.functionHash(listener)
                 });
             }
         }
-        
+
         return (Object[][])retval.toArray(new Object[retval.size()][5]);
     }
-    
+
     /**
      * Temporarily stores the data needed to perform script evaluations that
      * connect a component event to submitting a particular form that hasn't
      * been rendered yet. We can't reliably connect to a form until its name has
      * been set by a render, which could happen multiple times if it's in a list.
-     * 
+     *
      * <p>
      * The idea here is that when the form actually ~is~ rendered we will look for 
      * any pending deferred operations and run them while also clearing out our
      * deferred list.
      * </p>
-     * 
+     *
      * @param formId The form to defer event connection for.
      * @param scriptParms The initial map of parameters for the connection @Script component.
      * @param async Whether or not the action taken should be asynchronous.
@@ -406,28 +450,29 @@
      * @param uniqueHash Represents a hashcode() value that will help make client side function name
      *                  unique.
      */
-    void deferFormConnection(String formId, Map scriptParms, 
-            boolean async, boolean validate, String uniqueHash)
+    void deferFormConnection(String formId, Map scriptParms,
+                             boolean async, boolean validate, String uniqueHash)
     {
         List deferred = (List)_deferredFormConnections.get(formId);
-        
-        if (deferred == null) {
-            
+        if (deferred == null)
+        {
             deferred = new ArrayList();
-            
             _deferredFormConnections.put(formId, deferred);
         }
         
-        deferred.add(new Object[] {scriptParms, Boolean.valueOf(async), 
-                Boolean.valueOf(validate), uniqueHash});
+        DeferredFormConnection connection = new DeferredFormConnection(formId, scriptParms, Boolean.valueOf(async),
+                                                                       Boolean.valueOf(validate), uniqueHash);
+        
+        if (!deferred.contains(connection))
+            deferred.add(connection);
     }
-    
+
     // for testing
     Map getDefferedFormConnections()
     {
         return _deferredFormConnections;
     }
-    
+
     /**
      * Sets the invoker to use/manage event connections.
      * @param invoker
@@ -436,18 +481,18 @@
     {
         _invoker = invoker;
     }
-    
+
     /**
      * Sets the engine service that will be used to construct callback
      * URL references to invoke the specified components event listener.
-     * 
+     *
      * @param eventEngine
      */
     public void setEventEngine(IEngineService eventEngine)
     {
         _eventEngine = eventEngine;
     }
-    
+
     /**
      * The javascript that will be used to connect the component
      * to its configured events. (if any)
@@ -457,7 +502,7 @@
     {
         _componentScript = script;
     }
-    
+
     /**
      * The javascript that will be used to connect the widget component
      * to its configured events. (if any)
@@ -467,7 +512,7 @@
     {
         _widgetScript = script;
     }
-    
+
     /**
      * The javascript that connects html elements to direct
      * listener methods.
@@ -477,7 +522,7 @@
     {
         _elementScript = script;
     }
-    
+
     /**
      * The service that parses script files.
      * @param scriptSource
@@ -486,7 +531,7 @@
     {
         _scriptSource = scriptSource;
     }
-    
+
     public void setClassResolver(ClassResolver resolver)
     {
         _resolver = resolver;

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/impl/HiveMindExpressionCompiler.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/impl/HiveMindExpressionCompiler.java?view=diff&rev=548530&r1=548529&r2=548530
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/impl/HiveMindExpressionCompiler.java (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/impl/HiveMindExpressionCompiler.java Mon Jun 18 16:25:19 2007
@@ -307,7 +307,11 @@
 
         String castExpression = (String) context.get(PRE_CAST);
 
-        if (context.getCurrentType() == null || context.getCurrentType().isPrimitive() || Character.class.isAssignableFrom(context.getCurrentType())) {
+        if (context.getCurrentType() == null
+            || context.getCurrentType().isPrimitive()
+            || Character.class.isAssignableFrom(context.getCurrentType())
+            || Object.class == context.getCurrentType())
+        {
             pre = pre + " ($w) (";
             post = post + ")";
         }

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/js/tapestry/core.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/tapestry/core.js?view=diff&rev=548530&r1=548529&r2=548530
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/tapestry/core.js (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/tapestry/core.js Mon Jun 18 16:25:19 2007
@@ -320,7 +320,7 @@
 		}
 
 		var text=tapestry.html.getContentAsString(element);
-	    var response = text.replace(this.GlobalScriptFragment, '');
+	    text.replace(this.GlobalScriptFragment, '');
 	    var scripts = text.match(this.GlobalScriptFragment);
 
 		if (!scripts) { return; }
@@ -570,7 +570,7 @@
 
 	_processCompactElements:function(htmlData)
  	{
-            return htmlData.replace(this.CompactElementRegexp, this.CompactElementReplacer);
+		 return htmlData.replace(this.CompactElementRegexp, this.CompactElementReplacer);
  	}
 }
 

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/services/impl/ComponentEventConnectionWorkerTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/services/impl/ComponentEventConnectionWorkerTest.java?view=diff&rev=548530&r1=548529&r2=548530
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/services/impl/ComponentEventConnectionWorkerTest.java (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/services/impl/ComponentEventConnectionWorkerTest.java Mon Jun 18 16:25:19 2007
@@ -257,7 +257,6 @@
         expect(comp1.getClientId()).andReturn("comp1").anyTimes();
         
         expect(cycle.getAttribute(ComponentEventConnectionWorker.FORM_NAME_LIST + "form1")).andReturn(null).times(2);
-        
         expect(comp1.getSpecification()).andReturn(comp1Spec);
         
         // render of comp2
@@ -270,7 +269,6 @@
         expect(comp2.getClientId()).andReturn("comp2").anyTimes();
         
         expect(cycle.getAttribute(ComponentEventConnectionWorker.FORM_NAME_LIST + "form1")).andReturn(null);
-        
         expect(comp2.getSpecification()).andReturn(comp2Spec);
         
         // render of component
@@ -295,18 +293,15 @@
         List deferred = (List)worker.getDefferedFormConnections().get("form1");
         
         assert deferred != null;
-        assertEquals(deferred.size(), 3);
-        
-        Object[] parms = (Object[])deferred.get(0);
-        assertEquals(4, parms.length);
+        assertEquals(deferred.size(), 2);
+
+        ComponentEventConnectionWorker.DeferredFormConnection fConn = (ComponentEventConnectionWorker.DeferredFormConnection)deferred.get(0);
         
         // assert async is false
-        assert (Boolean)parms[1] == true;
+        assert fConn._async;
+        assert fConn._validate;
         
-        // assert validate form is true
-        assert (Boolean)parms[2] == true;
-        
-        Map parm = (Map)parms[0];
+        Map parm = fConn._scriptParms;
         
         assert parm.get("clientId") != null;
         assert parm.get("component") != null;
@@ -317,27 +312,15 @@
         assertEquals("comp1", parm.get("clientId"));
         assertEquals(comp1, parm.get("component"));
 
-        // just make sure second element is targeted at comp1 to handle the two events we gave it
+        // test comp2 connections
 
-        parms = (Object[])deferred.get(1);
-        assertEquals(parms.length, 4);
+        fConn = (ComponentEventConnectionWorker.DeferredFormConnection)deferred.get(1);
+        
+        parm = fConn._scriptParms;
 
-        parm = (Map)parms[0];
-        assertEquals(parm.get("clientId"), "comp1");
+        assert fConn._async;
+        assert fConn._validate;
 
-        // test comp2 connections
-        
-        parms = (Object[])deferred.get(2);
-        assertEquals(4, parms.length);
-        
-        // assert async is false
-        assert (Boolean)parms[1] == true;
-        
-        // assert validate form is true
-        assert (Boolean)parms[2] == true;
-        
-        parm = (Map)parms[0];
-        
         assert parm.get("clientId") != null;
         assert parm.get("component") != null;
         assert parm.get("url") == null;
@@ -347,6 +330,7 @@
         assertEquals(parm.get("clientId"), "comp2");
         assertEquals(parm.get("component"), comp2);
     }
+
     
     
     public void test_Form_Render_Deffered()