diff --git a/spring-faces/.classpath b/spring-faces/.classpath
index 44873627..41a2ed77 100644
--- a/spring-faces/.classpath
+++ b/spring-faces/.classpath
@@ -27,5 +27,6 @@
+
diff --git a/spring-faces/src/main/java/org/springframework/faces/mvc/richfaces/RichFacesAjaxHandler.java b/spring-faces/src/main/java/org/springframework/faces/mvc/richfaces/RichFacesAjaxHandler.java
index c9f4aeb2..94f00fb1 100644
--- a/spring-faces/src/main/java/org/springframework/faces/mvc/richfaces/RichFacesAjaxHandler.java
+++ b/spring-faces/src/main/java/org/springframework/faces/mvc/richfaces/RichFacesAjaxHandler.java
@@ -26,7 +26,7 @@ import javax.servlet.http.HttpServletResponse;
import org.ajax4jsf.context.AjaxContext;
import org.springframework.faces.webflow.FlowLifecycle;
-import org.springframework.webflow.mvc.servlet.SpringJavascriptAjaxHandler;
+import org.springframework.js.mvc.servlet.SpringJavascriptAjaxHandler;
/**
* Ajax handler that works with Rich Faces, allowing support for Web Flow ajax features with the Rich Faces toolkit.
diff --git a/spring-faces/src/main/java/org/springframework/faces/ui/AjaxEventInterceptorRenderer.java b/spring-faces/src/main/java/org/springframework/faces/ui/AjaxEventInterceptorRenderer.java
index 442af4e0..7117491b 100644
--- a/spring-faces/src/main/java/org/springframework/faces/ui/AjaxEventInterceptorRenderer.java
+++ b/spring-faces/src/main/java/org/springframework/faces/ui/AjaxEventInterceptorRenderer.java
@@ -17,12 +17,12 @@ package org.springframework.faces.ui;
import java.io.IOException;
+import javax.faces.FacesException;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.faces.event.ActionEvent;
-import org.springframework.faces.webflow.JsfUtils;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
@@ -38,32 +38,37 @@ public class AjaxEventInterceptorRenderer extends DojoRenderer {
writer.writeAttribute("type", "text/javascript", null);
String processIds = (String) component.getAttributes().get("processIds");
- String renderIds = (String) component.getAttributes().get("renderIds");
if (StringUtils.hasText(processIds) && !processIds.contains(component.getClientId(context))) {
processIds = component.getClientId(context) + ", " + processIds;
} else if (!StringUtils.hasText(processIds)) {
processIds = component.getClientId(context);
}
- if (!StringUtils.hasText(renderIds)) {
- renderIds = processIds;
- }
+ String childId = getElementId(context, component);
StringBuffer script = new StringBuffer();
- script.append("Spring.advisors.push(new Spring.RemoteEventAdvisor({");
+ script.append("Spring.addDecoration(new Spring.AjaxEventDecoration({");
script.append("event:'" + event + "'");
- script.append(", targetId: '" + ((UIComponent) component.getChildren().get(0)).getClientId(context) + "'");
- script.append(", sourceId : '" + component.getClientId(context) + "'");
+ script.append(", elementId: '" + childId + "'");
script.append(", formId : '" + RendererUtils.getFormId(context, component) + "'");
- script.append(", processIds : '" + processIds + "'");
- script.append(", renderIds : '" + renderIds + "'})");
- if (JsfUtils.isAsynchronousFlowRequest()) {
- script.append(".apply()");
- }
- script.append(");");
+ script.append(", params: {processIds : '" + processIds + "'");
+ script.append(", ajaxSource : '" + component.getClientId(context) + "'} }));");
writer.writeText(script.toString(), null);
writer.endElement("script");
}
+ private String getElementId(FacesContext context, UIComponent component) {
+ if (component.getChildCount() > 0) {
+ UIComponent child = (UIComponent) component.getChildren().get(0);
+ if (!(child instanceof DojoAdvisor)) {
+ return child.getClientId(context);
+ } else {
+ return getElementId(context, child);
+ }
+ } else {
+ throw new FacesException("Could not locate a proper child element to trigger the ajax event.");
+ }
+ }
+
public void decode(FacesContext context, UIComponent component) {
if (context.getExternalContext().getRequestParameterMap().containsKey("ajaxSource")
&& context.getExternalContext().getRequestParameterMap().get("ajaxSource").equals(
diff --git a/spring-faces/src/main/java/org/springframework/faces/ui/DojoAdvisorRenderer.java b/spring-faces/src/main/java/org/springframework/faces/ui/DojoAdvisorRenderer.java
index b0be9932..ae279c0a 100644
--- a/spring-faces/src/main/java/org/springframework/faces/ui/DojoAdvisorRenderer.java
+++ b/spring-faces/src/main/java/org/springframework/faces/ui/DojoAdvisorRenderer.java
@@ -25,7 +25,6 @@ import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import org.springframework.faces.ui.resource.ResourceHelper;
-import org.springframework.faces.webflow.JsfUtils;
import org.springframework.util.StringUtils;
public class DojoAdvisorRenderer extends DojoRenderer {
@@ -48,11 +47,10 @@ public class DojoAdvisorRenderer extends DojoRenderer {
writer.startElement(SCRIPT_ELEMENT, component);
writer.writeAttribute("type", "text/javascript", null);
StringBuffer script = new StringBuffer();
- script.append(" Spring.advisors.push(new Spring.ValidatingFieldAdvisor({ ");
- script.append(" targetElId : '" + advisedChild.getClientId(context) + "', ");
- script.append(" msgElId : '" + advisedChild.getClientId(context) + ":msg', ");
- script.append(" decoratorType : '" + ((DojoAdvisor) component).getDojoComponentType() + "', ");
- script.append(" decoratorAttrs : \"{ ");
+ script.append(" Spring.addDecoration(new Spring.ElementDecoration({ ");
+ script.append(" elementId : '" + advisedChild.getClientId(context) + "', ");
+ script.append(" widgetType : '" + ((DojoAdvisor) component).getDojoComponentType() + "', ");
+ script.append(" widgetAttrs : { ");
String nodeAttrs = getNodeAttributesAsString(context, advisedChild);
String dojoAttrs = getDojoAttributesAsString(context, component);
@@ -63,13 +61,7 @@ public class DojoAdvisorRenderer extends DojoRenderer {
}
script.append(dojoAttrs);
- script.append(" }\"})");
-
- if (JsfUtils.isAsynchronousFlowRequest()) {
- script.append(".apply()");
- }
-
- script.append("); ");
+ script.append(" }}));");
writer.writeText(script, null);
writer.endElement(SCRIPT_ELEMENT);
diff --git a/spring-faces/src/main/java/org/springframework/faces/ui/ProgressiveCommandButtonRenderer.java b/spring-faces/src/main/java/org/springframework/faces/ui/ProgressiveCommandButtonRenderer.java
index 6f0d7f35..8216a1fc 100644
--- a/spring-faces/src/main/java/org/springframework/faces/ui/ProgressiveCommandButtonRenderer.java
+++ b/spring-faces/src/main/java/org/springframework/faces/ui/ProgressiveCommandButtonRenderer.java
@@ -69,20 +69,16 @@ public class ProgressiveCommandButtonRenderer extends BaseDojoParentComponentRen
Boolean ajaxEnabled = (Boolean) component.getAttributes().get("ajaxEnabled");
String processIds = (String) component.getAttributes().get("processIds");
- String renderIds = (String) component.getAttributes().get("renderIds");
if (Boolean.TRUE.equals(ajaxEnabled)) {
if (StringUtils.hasText(processIds) && !processIds.contains(component.getClientId(context))) {
processIds = component.getClientId(context) + ", " + processIds;
} else if (!StringUtils.hasText(processIds)) {
processIds = component.getClientId(context);
}
- if (!StringUtils.hasText(renderIds)) {
- renderIds = processIds;
- }
- onclick.append("Spring.RemotingHandler.submitForm('" + component.getClientId(context) + "', ");
+ onclick.append("Spring.remoting.submitForm('" + component.getClientId(context) + "', ");
onclick.append("'" + RendererUtils.getFormId(context, component) + "', ");
- onclick.append("'" + processIds + "', '" + renderIds + "', " + encodeParams(context, component)
- + "); return false;");
+ onclick.append("{processIds: '" + processIds + "'" + encodeParams(context, component)
+ + "}); return false;");
} else {
onclick.append(getOnClickNoAjax(context, component));
}
@@ -142,20 +138,15 @@ public class ProgressiveCommandButtonRenderer extends BaseDojoParentComponentRen
protected String encodeParams(FacesContext context, UIComponent component) {
StringBuffer paramArray = new StringBuffer();
- paramArray.append("[");
for (int i = 0; i < component.getChildCount(); i++) {
if (component.getChildren().get(i) instanceof UIParameter) {
UIParameter param = (UIParameter) component.getChildren().get(i);
Assert.hasText(param.getName(),
"UIParameter requires a name when used as a child of a UICommand component");
- if (paramArray.length() > 1) {
- paramArray.append(", ");
- }
- paramArray.append("{name : '" + param.getName() + "'");
- paramArray.append(", value : '" + param.getValue() + "'}");
+
+ paramArray.append(", " + param.getName() + ": '" + param.getValue() + "'");
}
}
- paramArray.append("]");
return paramArray.toString();
}
diff --git a/spring-faces/src/main/java/org/springframework/faces/ui/ProgressiveCommandLinkRenderer.java b/spring-faces/src/main/java/org/springframework/faces/ui/ProgressiveCommandLinkRenderer.java
index e36db99f..a9503511 100644
--- a/spring-faces/src/main/java/org/springframework/faces/ui/ProgressiveCommandLinkRenderer.java
+++ b/spring-faces/src/main/java/org/springframework/faces/ui/ProgressiveCommandLinkRenderer.java
@@ -101,9 +101,9 @@ public class ProgressiveCommandLinkRenderer extends ProgressiveCommandButtonRend
public void encodeEnd(FacesContext context, UIComponent component) throws IOException {
super.encodeEnd(context, component);
- StringBuffer advisorParams = new StringBuffer();
- advisorParams.append("{");
- advisorParams.append("targetElId : '" + component.getClientId(context) + "'");
+ StringBuffer decorationParams = new StringBuffer();
+ decorationParams.append("{");
+ decorationParams.append("elementId : '" + component.getClientId(context) + "'");
ResponseWriter writer = context.getResponseWriter();
// Close the script variable started in encodeBegin if this is not an AJAX request
@@ -117,18 +117,14 @@ public class ProgressiveCommandLinkRenderer extends ProgressiveCommandButtonRend
String scriptVarEnd = "\";\n";
writer.writeText(scriptVarEnd, null);
- advisorParams.append(", linkHtml : " + component.getClientId(context).replaceAll(":", "_") + "_link");
+ decorationParams.append(", linkHtml : " + component.getClientId(context).replaceAll(":", "_") + "_link");
writer.endElement("script");
}
- advisorParams.append("}");
+ decorationParams.append("}");
StringBuffer advisorScript = new StringBuffer();
- advisorScript.append("Spring.advisors.push(new Spring.CommandLinkAdvisor(" + advisorParams.toString() + ")");
- // Apply the advisor immediately if this is an AJAX request
- if (JsfUtils.isAsynchronousFlowRequest()) {
- advisorScript.append(".apply()");
- }
- advisorScript.append(");");
+ advisorScript.append("Spring.addDecoration(new Spring.CommandLinkDecoration(" + decorationParams.toString()
+ + "));");
writer.startElement("script", component);
writer.writeText(advisorScript, null);
writer.endElement("script");
diff --git a/spring-faces/src/main/java/org/springframework/faces/ui/ValidateAllRenderer.java b/spring-faces/src/main/java/org/springframework/faces/ui/ValidateAllRenderer.java
index 5ccea918..72b960ce 100644
--- a/spring-faces/src/main/java/org/springframework/faces/ui/ValidateAllRenderer.java
+++ b/spring-faces/src/main/java/org/springframework/faces/ui/ValidateAllRenderer.java
@@ -44,8 +44,8 @@ public class ValidateAllRenderer extends SpringFacesRenderer {
writer.startElement(SCRIPT_ELEMENT, component);
writer.writeAttribute("type", "text/javascript", null);
StringBuffer script = new StringBuffer();
- script.append("Spring.advisors.push(new Spring.ValidateAllAdvisor({" + "event : 'onclick', " + "targetId : '"
- + advisedChild.getClientId(context) + "'}));");
+ script.append("Spring.addDecoration(new Spring.ValidateAllDecoration({" + "event : 'onclick', "
+ + "elementId : '" + advisedChild.getClientId(context) + "'}));");
writer.writeText(script, null);
writer.endElement(SCRIPT_ELEMENT);
}
diff --git a/spring-faces/src/main/java/org/springframework/faces/webflow/JsfViewFactory.java b/spring-faces/src/main/java/org/springframework/faces/webflow/JsfViewFactory.java
index 588ee9ee..6c9e7e4d 100644
--- a/spring-faces/src/main/java/org/springframework/faces/webflow/JsfViewFactory.java
+++ b/spring-faces/src/main/java/org/springframework/faces/webflow/JsfViewFactory.java
@@ -35,12 +35,12 @@ import org.springframework.context.ApplicationContext;
import org.springframework.core.io.ContextResource;
import org.springframework.core.io.Resource;
import org.springframework.faces.ui.AjaxViewRoot;
+import org.springframework.js.mvc.servlet.AjaxHandler;
+import org.springframework.js.mvc.servlet.SpringJavascriptAjaxHandler;
import org.springframework.webflow.context.ExternalContext;
import org.springframework.webflow.execution.RequestContext;
import org.springframework.webflow.execution.View;
import org.springframework.webflow.execution.ViewFactory;
-import org.springframework.webflow.mvc.servlet.AjaxHandler;
-import org.springframework.webflow.mvc.servlet.SpringJavascriptAjaxHandler;
/**
* JSF-specific {@link ViewFactory} implementation.
diff --git a/spring-js/.classpath b/spring-js/.classpath
index 0447daa0..8546b382 100644
--- a/spring-js/.classpath
+++ b/spring-js/.classpath
@@ -5,7 +5,6 @@
-
@@ -14,5 +13,12 @@
+
+
+
+
+
+
+
diff --git a/spring-js/ivy.xml b/spring-js/ivy.xml
index 8ca7c976..d25a89e4 100644
--- a/spring-js/ivy.xml
+++ b/spring-js/ivy.xml
@@ -23,9 +23,15 @@
+
+
+
+
+
+
diff --git a/spring-js/src/main/java/org/springframework/js/ajax/view/TilesAjaxView.java b/spring-js/src/main/java/org/springframework/js/ajax/view/TilesAjaxView.java
new file mode 100644
index 00000000..3a4d489c
--- /dev/null
+++ b/spring-js/src/main/java/org/springframework/js/ajax/view/TilesAjaxView.java
@@ -0,0 +1,77 @@
+package org.springframework.js.ajax.view;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.tiles.Attribute;
+import org.apache.tiles.Definition;
+import org.apache.tiles.Attribute.AttributeType;
+import org.apache.tiles.access.TilesAccess;
+import org.apache.tiles.context.TilesRequestContext;
+import org.apache.tiles.impl.BasicTilesContainer;
+import org.springframework.js.mvc.servlet.AjaxHandler;
+import org.springframework.js.mvc.servlet.SpringJavascriptAjaxHandler;
+import org.springframework.web.servlet.support.JstlUtils;
+import org.springframework.web.servlet.support.RequestContext;
+import org.springframework.web.servlet.view.tiles2.TilesView;
+
+public class TilesAjaxView extends TilesView {
+
+ public static final String FRAGMENTS_PARAM = "fragments";
+
+ private AjaxHandler ajaxHandler = new SpringJavascriptAjaxHandler();
+
+ protected void renderMergedOutputModel(Map model, HttpServletRequest request, HttpServletResponse response)
+ throws Exception {
+
+ ServletContext servletContext = getServletContext();
+ if (ajaxHandler.isAjaxRequest(servletContext, request, response)) {
+ BasicTilesContainer container = (BasicTilesContainer) TilesAccess.getContainer(servletContext);
+ if (container == null) {
+ throw new ServletException("Tiles container is not initialized. "
+ + "Have you added a TilesConfigurer to your web application context?");
+ }
+
+ exposeModelAsRequestAttributes(model, request);
+ JstlUtils.exposeLocalizationContext(new RequestContext(request, servletContext));
+
+ TilesRequestContext tilesRequestContext = container.getContextFactory().createRequestContext(
+ container.getApplicationContext(), new Object[] { request, response });
+ Definition compositeDefinition = container.getDefinitionsFactory().getDefinition(getUrl(),
+ tilesRequestContext);
+ Map flattenedAttributeMap = new HashMap();
+ flattenAttributeMap(container, tilesRequestContext, flattenedAttributeMap, compositeDefinition);
+
+ String attrName = request.getParameter(FRAGMENTS_PARAM);
+
+ Attribute attributeToRender = (Attribute) flattenedAttributeMap.get(attrName);
+
+ container.render(attributeToRender, response.getWriter(), new Object[] { request, response });
+ } else {
+ super.renderMergedOutputModel(model, request, response);
+ }
+ }
+
+ private void flattenAttributeMap(BasicTilesContainer container, TilesRequestContext requestContext, Map resultMap,
+ Definition compositeDefinition) throws Exception {
+ Iterator i = compositeDefinition.getAttributes().keySet().iterator();
+ while (i.hasNext()) {
+ Object key = i.next();
+ Attribute attr = (Attribute) compositeDefinition.getAttributes().get(key);
+ if (attr.getType() == AttributeType.DEFINITION) {
+ Definition nestedDefinition = container.getDefinitionsFactory().getDefinition(
+ attr.getValue().toString(), requestContext);
+ flattenAttributeMap(container, requestContext, resultMap, nestedDefinition);
+ } else {
+ resultMap.put(key, attr);
+ }
+ }
+ }
+
+}
diff --git a/spring-webflow/src/main/java/org/springframework/webflow/mvc/servlet/AjaxHandler.java b/spring-js/src/main/java/org/springframework/js/mvc/servlet/AjaxHandler.java
similarity index 97%
rename from spring-webflow/src/main/java/org/springframework/webflow/mvc/servlet/AjaxHandler.java
rename to spring-js/src/main/java/org/springframework/js/mvc/servlet/AjaxHandler.java
index c7152bd1..3c752571 100644
--- a/spring-webflow/src/main/java/org/springframework/webflow/mvc/servlet/AjaxHandler.java
+++ b/spring-js/src/main/java/org/springframework/js/mvc/servlet/AjaxHandler.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.springframework.webflow.mvc.servlet;
+package org.springframework.js.mvc.servlet;
import java.io.IOException;
diff --git a/spring-webflow/src/main/java/org/springframework/webflow/mvc/servlet/SpringJavascriptAjaxHandler.java b/spring-js/src/main/java/org/springframework/js/mvc/servlet/SpringJavascriptAjaxHandler.java
similarity index 82%
rename from spring-webflow/src/main/java/org/springframework/webflow/mvc/servlet/SpringJavascriptAjaxHandler.java
rename to spring-js/src/main/java/org/springframework/js/mvc/servlet/SpringJavascriptAjaxHandler.java
index f0989a26..fe79f05f 100644
--- a/spring-webflow/src/main/java/org/springframework/webflow/mvc/servlet/SpringJavascriptAjaxHandler.java
+++ b/spring-js/src/main/java/org/springframework/js/mvc/servlet/SpringJavascriptAjaxHandler.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.springframework.webflow.mvc.servlet;
+package org.springframework.js.mvc.servlet;
import java.io.IOException;
@@ -34,22 +34,22 @@ public class SpringJavascriptAjaxHandler implements AjaxHandler {
/**
* The response header to be set on an Ajax redirect
*/
- private static final String FLOW_REDIRECT_URL_HEADER = "Flow-Redirect-URL";
+ public static final String REDIRECT_URL_HEADER = "Spring-Redirect-URL";
/**
* The response header to be set on an redirect that should be issued from a popup window.
*/
- private static final String POPUP_VIEW_HEADER = "Flow-Modal-View";
+ public static final String POPUP_VIEW_HEADER = "Spring-Modal-View";
/**
* The accept header value that signifies an Ajax request.
*/
- private static final String AJAX_ACCEPT_CONTENT_TYPE = "text/html;type=ajax";
+ public static final String AJAX_ACCEPT_CONTENT_TYPE = "text/html;type=ajax";
/**
* Alternate request parameter to indicate an Ajax request for cases when control of the header is not available.
*/
- private static final String AJAX_SOURCE_PARAM = "ajaxSource";
+ public static final String AJAX_SOURCE_PARAM = "ajaxSource";
public boolean isAjaxRequest(ServletContext context, HttpServletRequest request, HttpServletResponse response) {
String acceptHeader = request.getHeader("Accept");
@@ -66,7 +66,7 @@ public class SpringJavascriptAjaxHandler implements AjaxHandler {
if (popup) {
response.setHeader(POPUP_VIEW_HEADER, "true");
}
- response.setHeader(FLOW_REDIRECT_URL_HEADER, response.encodeRedirectURL(targetUrl));
+ response.setHeader(REDIRECT_URL_HEADER, response.encodeRedirectURL(targetUrl));
}
}
\ No newline at end of file
diff --git a/spring-js/src/main/resources/META-INF/spring/Spring-Dojo.js b/spring-js/src/main/resources/META-INF/spring/Spring-Dojo.js
index b973fb81..733bf158 100644
--- a/spring-js/src/main/resources/META-INF/spring/Spring-Dojo.js
+++ b/spring-js/src/main/resources/META-INF/spring/Spring-Dojo.js
@@ -13,4 +13,4 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-Spring.DojoValidatingFieldAdvisor=function(_1){dojo.mixin(this,_1);};Spring.DojoValidatingFieldAdvisor.prototype={targetElId:"",decoratorType:"",decorator:null,decoratorAttrs:"",apply:function(){if(dijit.byId(this.targetElId)){dijit.byId(this.targetElId).destroyRecursive(false);}this.decorator=eval("new "+this.decoratorType+"("+this.decoratorAttrs+", dojo.byId('"+this.targetElId+"'));");this.decorator.startup();return this;},validate:function(){var _2=this.decorator.isValid(false);if(!_2){this.decorator.state="Error";this.decorator._setStateClass();}return _2;}};Spring.ValidatingFieldAdvisor=Spring.DojoValidatingFieldAdvisor;Spring.DojoRemoteEventAdvisor=function(_3){dojo.mixin(this,_3);};Spring.DojoRemoteEventAdvisor.prototype={event:"",targetId:"",sourceId:"",formId:"",processIds:"",renderIds:"",params:[],connection:null,apply:function(){this.connection=dojo.connect(dojo.byId(this.targetId),this.event,this,"submit");return this;},cleanup:function(){dojo.disconnect(this.connection);},submit:function(){Spring.RemotingHandler.submitForm(this.sourceId,this.formId,this.processIds,this.renderIds,this.params);}};Spring.RemoteEventAdvisor=Spring.DojoRemoteEventAdvisor;Spring.DojoValidateAllAdvisor=function(_4){dojo.mixin(this,_4);};Spring.DojoValidateAllAdvisor.prototype={event:"",targetId:"",originalHandler:null,connection:null,apply:function(){var _5=dojo.byId(this.targetId);this.originalHandler=_5[this.event];var _6=this;_5[this.event]=function(_7){_6.handleEvent(_7,_6);};return this;},cleanup:function(){dojo.disconnect(this.connection);},handleEvent:function(_8,_9){if(!Spring.validateAll()){dojo.stopEvent(_8);}else{var _a=_9.originalHandler(_8);if(_a==false){dojo.stopEvent(_8);}}}};Spring.ValidateAllAdvisor=Spring.DojoValidateAllAdvisor;Spring.DojoRemotingHandler=function(){};Spring.DojoRemotingHandler.prototype={submitForm:function(_b,_c,_d,_e,_f){var _10=new Object();var _11=dojo.byId(_b);_10["processIds"]=_d;_10["renderIds"]=_e;if(_11!=null){if(_11.value){_10[_b]=_11.value;}else{_10[_b]=_b;}}dojo.forEach(_f,function(_12){_10[_12.name]=_12.value;});_10["ajaxSource"]=_b;dojo.xhrPost({content:_10,form:_c,handleAs:"text",headers:{"Accept":"text/html;type=ajax"},load:this.handleResponse,error:this.handleError});},getLinkedResource:function(_13,_14){this.getResource(dojo.byId(_13).href,_14);},getResource:function(_15,_16){dojo.xhrGet({url:_15,handleAs:"text",load:this.handleResponse,error:this.handleError,modal:_16});},handleResponse:function(_17,_18){var _19=_18.xhr.getResponseHeader("Flow-Redirect-URL");var _1a=_18.xhr.getResponseHeader("Flow-Modal-View");var _1b=((dojo.isString(_1a)&&_1a.length>0)||_18.args.modal);if(dojo.isString(_19)&&_19.length>0){if(_1b){Spring.RemotingHandler.renderURLToModalDialog(_19,_18);return _17;}else{window.location=window.location.protocol+"//"+window.location.host+_19;return _17;}}var _1c="(?:)((\n|\r|.)*?)(?:)";var _1d=[];var _1e=new RegExp(_1c,"img");var _1f=new RegExp(_1c,"im");var _20=_17.match(_1e);if(_20!=null){for(var i=0;i<_20.length;i++){var _22=(_20[i].match(_1f)||["",""])[1];_22=_22.replace(//mg,"");_1d.push(_22);}}_17=_17.replace(_1e,"");var _23=dojo.doc.createElement("div");_23.id="ajaxResponse";_23.style.visibility="hidden";document.body.appendChild(_23);var _24=new dojo.NodeList(_23);var _25=_24.addContent(_17,"first").query("#ajaxResponse > *").orphan();_24.orphan();if(_1b){Spring.RemotingHandler.renderNodeListToModalDialog(_25);}else{_25.forEach(function(_26){if(_26.id!=null&&_26.id!=""){var _27=dojo.byId(_26.id);_27.parentNode.replaceChild(_26,_27);}});}dojo.forEach(_1d,function(_28){dojo.eval(_28);});return _17;},handleError:function(_29,_2a){console.error("HTTP status code: ",_2a.xhr.status);return _29;},renderURLToModalDialog:function(url,_2c){url=url+"&"+dojo.objectToQuery(_2c.args.content);Spring.RemotingHandler.getResource(url,true);},renderNodeListToModalDialog:function(_2d){dojo.require("dijit.Dialog");var _2e=new dijit.Dialog({});_2e.setContent(_2d);dojo.connect(_2e,"hide",_2e,function(){this.destroyRecursive(false);});_2e.show();}};Spring.RemotingHandler=new Spring.DojoRemotingHandler();Spring.DojoCommandLinkAdvisor=function(_2f){dojo.mixin(this,_2f);};Spring.DojoCommandLinkAdvisor.prototype={targetElId:"",linkHtml:"",apply:function(){var _30=dojo.byId(this.targetElId);if(!dojo.hasClass(_30,"progressiveLink")){var _31=new dojo.NodeList(_30);_31.addContent(this.linkHtml,"after").orphan("*");_30=dojo.byId(this.targetElId);}_30.submitFormFromLink=this.submitFormFromLink;return this;},submitFormFromLink:function(_32,_33,_34){var _35=[];var _36=dojo.byId(_32);var _37=document.createElement("input");_37.name=_33;_37.value="submitted";_35.push(_37);dojo.forEach(_34,function(_38){var _39=document.createElement("input");_39.name=_38.name;_39.value=_38.value;_35.push(_39);});dojo.forEach(_35,function(_3a){dojo.addClass(_3a,"SpringLinkInput");dojo.place(_3a,_36,"last");});if((_36.onsubmit?!_36.onsubmit():false)||!_36.submit()){dojo.forEach(_35,function(_3b){_36.removeChild(_3b);});}}};Spring.CommandLinkAdvisor=Spring.DojoCommandLinkAdvisor;dojo.addOnLoad(Spring.applyAdvisors);
\ No newline at end of file
+dojo.declare("Spring.ElementDecoration",Spring.AbstractElementDecoration,{constructor:function(_1){this.copyFields=new Array("name","value","type","checked","selected","readOnly","disabled","alt","maxLength");dojo.mixin(this,_1);if(this.widgetModule==""){this.widgetModule=this.widgetType;}},apply:function(){if(dijit.byId(this.elementId)){dijit.byId(this.elementId).destroyRecursive(false);}var _2=dojo.byId(this.elementId);for(var _3 in this.copyFields){_3=this.copyFields[_3];if(!this.widgetAttrs[_3]&&_2[_3]&&(typeof _2[_3]!="number"||(typeof _2[_3]=="number"&&_2[_3]>=0))){this.widgetAttrs[_3]=_2[_3];}}dojo.require(this.widgetModule);var _4=dojo.eval(this.widgetType);this.widget=new _4(this.widgetAttrs,_2);this.widget.startup();return this;},validate:function(){if(!this.widget.isValid){return true;}var _5=this.widget.isValid(false);if(!_5){this.widget.state="Error";this.widget._setStateClass();}return _5;}});dojo.declare("Spring.ValidateAllDecoration",Spring.AbstractValidateAllDecoration,{constructor:function(_6){this.originalHandler=null;this.connection=null;dojo.mixin(this,_6);},apply:function(){var _7=dojo.byId(this.elementId);this.originalHandler=_7[this.event];var _8=this;_7[this.event]=function(_9){_8.handleEvent(_9,_8);};return this;},cleanup:function(){dojo.disconnect(this.connection);},handleEvent:function(_a,_b){if(!Spring.validateAll()){dojo.stopEvent(_a);}else{if(dojo.isFunction(_b.originalHandler)){var _c=_b.originalHandler(_a);if(_c==false){dojo.stopEvent(_a);}}}}});dojo.declare("Spring.AjaxEventDecoration",Spring.AbstractAjaxEventDecoration,{constructor:function(_d){this.connection=null;dojo.mixin(this,_d);},apply:function(){this.connection=dojo.connect(dojo.byId(this.elementId),this.event,this,"submit");return this;},cleanup:function(){dojo.disconnect(this.connection);},submit:function(_e){if(this.sourceId==""){this.sourceId=this.elementId;}if(this.formId==""){Spring.remoting.getLinkedResource(this.sourceId,this.params,false);}else{Spring.remoting.submitForm(this.sourceId,this.formId,this.params);}dojo.stopEvent(_e);}});dojo.declare("Spring.RemotingHandler",Spring.AbstractRemotingHandler,{constructor:function(){},submitForm:function(_f,_10,_11){var _12=new Object();for(var key in _11){_12[key]=_11[key];}var _14=dojo.byId(_f);if(_14!=null){if(_14.value!=undefined){_12[_f]=_14.value;}else{_12[_f]=_f;}}if(!_12["ajaxSource"]){_12["ajaxSource"]=_f;}dojo.xhrPost({content:_12,form:_10,handleAs:"text",headers:{"Accept":"text/html;type=ajax"},load:this.handleResponse,error:this.handleError});},getLinkedResource:function(_15,_16,_17){this.getResource(dojo.byId(_15).href,_16,_17);},getResource:function(_18,_19,_1a){dojo.xhrGet({url:_18,content:_19,handleAs:"text",headers:{"Accept":"text/html;type=ajax"},load:this.handleResponse,error:this.handleError,modal:_1a});},handleResponse:function(_1b,_1c){var _1d=_1c.xhr.getResponseHeader("Spring-Redirect-URL");var _1e=_1c.xhr.getResponseHeader("Spring-Modal-View");var _1f=((dojo.isString(_1e)&&_1e.length>0)||_1c.args.modal);if(dojo.isString(_1d)&&_1d.length>0){if(_1f){Spring.remoting.renderURLToModalDialog(_1d,_1c);return _1b;}else{window.location=window.location.protocol+"//"+window.location.host+_1d;return _1b;}}var _20="(?:)((\n|\r|.)*?)(?:)";var _21=[];var _22=new RegExp(_20,"img");var _23=new RegExp(_20,"im");var _24=_1b.match(_22);if(_24!=null){for(var i=0;i<_24.length;i++){var _26=(_24[i].match(_23)||["",""])[1];_26=_26.replace(//mg,"");_21.push(_26);}}_1b=_1b.replace(_22,"");var _27=dojo.doc.createElement("div");_27.id="ajaxResponse";_27.style.visibility="hidden";document.body.appendChild(_27);var _28=new dojo.NodeList(_27);var _29=_28.addContent(_1b,"first").query("#ajaxResponse > *").orphan();_28.orphan();if(_1f){Spring.remoting.renderNodeListToModalDialog(_29);}else{_29.forEach(function(_2a){if(_2a.id!=null&&_2a.id!=""){var _2b=dojo.byId(_2a.id);_2b.parentNode.replaceChild(_2a,_2b);}});}dojo.forEach(_21,function(_2c){dojo.eval(_2c);});return _1b;},handleError:function(_2d,_2e){console.error("HTTP status code: ",_2e.xhr.status);return _2d;},renderURLToModalDialog:function(url,_30){url=url+"&"+dojo.objectToQuery(_30.args.content);Spring.remoting.getResource(url,{},true);},renderNodeListToModalDialog:function(_31){dojo.require("dijit.Dialog");var _32=new dijit.Dialog({});_32.setContent(_31);dojo.connect(_32,"hide",_32,function(){this.destroyRecursive(false);});_32.show();}});dojo.declare("Spring.CommandLinkDecoration",Spring.AbstractCommandLinkDecoration,{constructor:function(_33){dojo.mixin(this,_33);},apply:function(){var _34=dojo.byId(this.elementId);if(!dojo.hasClass(_34,"progressiveLink")){var _35=new dojo.NodeList(_34);_35.addContent(this.linkHtml,"after").orphan("*");_34=dojo.byId(this.elementId);}_34.submitFormFromLink=this.submitFormFromLink;return this;},submitFormFromLink:function(_36,_37,_38){var _39=[];var _3a=dojo.byId(_36);var _3b=document.createElement("input");_3b.name=_37;_3b.value="submitted";_39.push(_3b);dojo.forEach(_38,function(_3c){var _3d=document.createElement("input");_3d.name=_3c.name;_3d.value=_3c.value;_39.push(_3d);});dojo.forEach(_39,function(_3e){dojo.addClass(_3e,"SpringLinkInput");dojo.place(_3e,_3a,"last");});if((_3a.onsubmit?!_3a.onsubmit():false)||!_3a.submit()){dojo.forEach(_39,function(_3f){_3a.removeChild(_3f);});}}});dojo.addOnLoad(Spring.initialize);
\ No newline at end of file
diff --git a/spring-js/src/main/resources/META-INF/spring/Spring-Dojo.js.uncompressed b/spring-js/src/main/resources/META-INF/spring/Spring-Dojo.js.uncompressed
index 7956c816..f39af88c 100644
--- a/spring-js/src/main/resources/META-INF/spring/Spring-Dojo.js.uncompressed
+++ b/spring-js/src/main/resources/META-INF/spring/Spring-Dojo.js.uncompressed
@@ -13,88 +13,62 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-Spring.DojoValidatingFieldAdvisor = function(config){
-
- dojo.mixin(this, config);
-};
-
-Spring.DojoValidatingFieldAdvisor.prototype = {
-
- targetElId : "",
- decoratorType : "",
- decorator : null,
- decoratorAttrs : "",
-
- apply : function(){
- if (dijit.byId(this.targetElId)) {
- dijit.byId(this.targetElId).destroyRecursive(false);
+
+dojo.declare("Spring.ElementDecoration", Spring.AbstractElementDecoration, {
+ constructor : function(config) {
+ this.copyFields = new Array('name', 'value', 'type', 'checked', 'selected', 'readOnly', 'disabled', 'alt', 'maxLength');
+ dojo.mixin(this, config);
+ if(this.widgetModule == "") {
+ this.widgetModule = this.widgetType;
}
- this.decorator = eval("new "+ this.decoratorType + "(" + this.decoratorAttrs +", dojo.byId('"+this.targetElId+"'));" );
- this.decorator.startup();
-
+ },
+
+ apply : function(){
+ if (dijit.byId(this.elementId)) {
+ dijit.byId(this.elementId).destroyRecursive(false);
+ }
+ var element = dojo.byId(this.elementId);
+ for (var copyField in this.copyFields) {
+ copyField = this.copyFields[copyField];
+ if (!this.widgetAttrs[copyField] && element[copyField] && (typeof element[copyField] != 'number' ||
+ (typeof element[copyField] == 'number' && element[copyField] >= 0))) {
+ this.widgetAttrs[copyField] = element[copyField];
+ }
+ }
+ dojo.require(this.widgetModule);
+ var widgetConstructor = dojo.eval(this.widgetType);
+ this.widget = new widgetConstructor(this.widgetAttrs, element);
+ this.widget.startup();
//return this to support method chaining
return this;
},
validate : function(){
- var isValid = this.decorator.isValid(false);
+ if (!this.widget.isValid) {
+ // some widgets cannot be validated
+ return true;
+ }
+ var isValid = this.widget.isValid(false);
if (!isValid) {
- this.decorator.state = "Error";
- this.decorator._setStateClass();
+ this.widget.state = "Error";
+ this.widget._setStateClass();
}
return isValid;
}
-};
+});
-Spring.ValidatingFieldAdvisor = Spring.DojoValidatingFieldAdvisor;
-
-Spring.DojoRemoteEventAdvisor = function(config){
- dojo.mixin(this, config);
-};
-
-Spring.DojoRemoteEventAdvisor.prototype = {
-
- event : "",
- targetId : "",
- sourceId : "",
- formId : "",
- processIds : "",
- renderIds : "",
- params : [],
- connection : null,
-
- apply : function() {
- this.connection = dojo.connect(dojo.byId(this.targetId), this.event, this, "submit");
- return this;
+dojo.declare("Spring.ValidateAllDecoration", Spring.AbstractValidateAllDecoration, {
+ constructor : function(config) {
+ this.originalHandler = null;
+ this.connection = null;
+ dojo.mixin(this, config);
},
- cleanup : function(){
- dojo.disconnect(this.connection);
- },
-
- submit : function(){
- Spring.RemotingHandler.submitForm(this.sourceId, this.formId, this.processIds, this.renderIds, this.params);
- }
-};
-
-Spring.RemoteEventAdvisor = Spring.DojoRemoteEventAdvisor;
-
-Spring.DojoValidateAllAdvisor = function(config){
- dojo.mixin(this, config);
-};
-
-Spring.DojoValidateAllAdvisor.prototype = {
-
- event : "",
- targetId : "",
- originalHandler : null,
- connection : null,
-
apply : function() {
- var targetEl = dojo.byId(this.targetId);
- this.originalHandler = targetEl[this.event];
+ var element = dojo.byId(this.elementId);
+ this.originalHandler = element[this.event];
var context = this;
- targetEl[this.event] = function(event){
+ element[this.event] = function(event){
context.handleEvent(event, context);
};
return this;
@@ -107,40 +81,65 @@ Spring.DojoValidateAllAdvisor.prototype = {
handleEvent : function(event, context){
if (!Spring.validateAll()) {
dojo.stopEvent(event);
- } else {
+ } else if(dojo.isFunction(context.originalHandler)) {
var result = context.originalHandler(event);
if (result == false) {
dojo.stopEvent(event);
}
}
}
-};
+});
-Spring.ValidateAllAdvisor = Spring.DojoValidateAllAdvisor;
-
-Spring.DojoRemotingHandler = function(){};
-
-Spring.DojoRemotingHandler.prototype = {
+dojo.declare("Spring.AjaxEventDecoration", Spring.AbstractAjaxEventDecoration, {
+ constructor : function(config){
+ this.connection = null;
+ dojo.mixin(this, config);
+ },
- submitForm : function(/*String */ sourceId, /*String*/formId, /*String*/ processIds, /*String*/renderIds, /*Array*/ params) {
+ apply : function() {
+ this.connection = dojo.connect(dojo.byId(this.elementId), this.event, this, "submit");
+ return this;
+ },
+
+ cleanup : function(){
+ dojo.disconnect(this.connection);
+ },
+
+ submit : function(event){
+ if (this.sourceId == ""){
+ this.sourceId = this.elementId;
+ }
+ if(this.formId == ""){
+ Spring.remoting.getLinkedResource(this.sourceId, this.params, false);
+ } else {
+ Spring.remoting.submitForm(this.sourceId, this.formId, this.params);
+ }
+ dojo.stopEvent(event);
+ }
+});
+
+dojo.declare("Spring.RemotingHandler", Spring.AbstractRemotingHandler, {
+ constructor : function(){},
+
+ submitForm : function(/*String */ sourceId, /*String*/formId, /*Object*/ params) {
var content = new Object();
+ for (var key in params) {
+ content[key] = params[key];
+ }
+
var sourceComponent = dojo.byId(sourceId);
- content['processIds'] = processIds;
- content['renderIds'] = renderIds;
if (sourceComponent != null){
- if(sourceComponent.value) {
+ if(sourceComponent.value != undefined) {
content[sourceId] = sourceComponent.value;
} else {
content[sourceId] = sourceId;
}
}
- dojo.forEach(params, function(param){
- content[param.name] = param.value;
- });
-
- content['ajaxSource'] = sourceId;
+ if (!content['ajaxSource']) {
+ content['ajaxSource'] = sourceId;
+ }
dojo.xhrPost({
@@ -161,18 +160,22 @@ Spring.DojoRemotingHandler.prototype = {
},
- getLinkedResource: function(/*String */ linkId, /*boolean*/ modal) {
- this.getResource(dojo.byId(linkId).href, modal);
+ getLinkedResource: function(/*String */ linkId, /*Object*/params, /*boolean*/ modal) {
+ this.getResource(dojo.byId(linkId).href, params, modal);
},
- getResource: function(/*String */ resourceUri, /*boolean*/ modal) {
+ getResource: function(/*String */ resourceUri, /*Object*/params, /*boolean*/ modal) {
dojo.xhrGet({
url: resourceUri,
+ content: params,
+
handleAs: "text",
+ headers: {"Accept" : "text/html;type=ajax"},
+
load: this.handleResponse,
error: this.handleError,
@@ -184,14 +187,14 @@ Spring.DojoRemotingHandler.prototype = {
handleResponse: function(response, ioArgs) {
//First check if this response should redirect
- var redirectURL = ioArgs.xhr.getResponseHeader('Flow-Redirect-URL');
- var modalViewHeader = ioArgs.xhr.getResponseHeader('Flow-Modal-View');
+ var redirectURL = ioArgs.xhr.getResponseHeader('Spring-Redirect-URL');
+ var modalViewHeader = ioArgs.xhr.getResponseHeader('Spring-Modal-View');
var modalView = ((dojo.isString(modalViewHeader) && modalViewHeader.length > 0) || ioArgs.args.modal);
if (dojo.isString(redirectURL) && redirectURL.length > 0) {
if (modalView) {
//render a popup with the new URL
- Spring.RemotingHandler.renderURLToModalDialog(redirectURL, ioArgs);
+ Spring.remoting.renderURLToModalDialog(redirectURL, ioArgs);
return response;
}
else {
@@ -229,7 +232,7 @@ Spring.DojoRemotingHandler.prototype = {
//For a modal view, just dump the new nodes into a modal dialog
if (modalView) {
- Spring.RemotingHandler.renderNodeListToModalDialog(newNodes);
+ Spring.remoting.renderNodeListToModalDialog(newNodes);
}
else {
@@ -258,7 +261,7 @@ Spring.DojoRemotingHandler.prototype = {
renderURLToModalDialog: function(url, ioArgs) {
url = url + "&"+dojo.objectToQuery(ioArgs.args.content);
- Spring.RemotingHandler.getResource(url, true);
+ Spring.remoting.getResource(url, {}, true);
},
renderNodeListToModalDialog: function(nodes) {
@@ -271,28 +274,21 @@ Spring.DojoRemotingHandler.prototype = {
});
dialog.show();
}
-};
+});
-Spring.RemotingHandler = new Spring.DojoRemotingHandler();
-
-Spring.DojoCommandLinkAdvisor = function(config){
- dojo.mixin(this, config);
-};
-
-Spring.DojoCommandLinkAdvisor.prototype = {
-
- targetElId : "",
-
- linkHtml : "",
+dojo.declare("Spring.CommandLinkDecoration", Spring.AbstractCommandLinkDecoration, {
+ constructor : function(config){
+ dojo.mixin(this, config);
+ },
apply : function(){
- var advisedNode = dojo.byId(this.targetElId);
+ var advisedNode = dojo.byId(this.elementId);
if (!dojo.hasClass(advisedNode, "progressiveLink")) {
//Node must be replaced
var nodeToReplace = new dojo.NodeList(advisedNode);
nodeToReplace.addContent(this.linkHtml, "after").orphan("*");
//Get the new node
- advisedNode = dojo.byId(this.targetElId);
+ advisedNode = dojo.byId(this.elementId);
}
advisedNode.submitFormFromLink = this.submitFormFromLink;
//return this to support method chaining
@@ -325,8 +321,6 @@ Spring.DojoCommandLinkAdvisor.prototype = {
});
}
}
-};
+});
-Spring.CommandLinkAdvisor = Spring.DojoCommandLinkAdvisor;
-
-dojo.addOnLoad(Spring.applyAdvisors);
\ No newline at end of file
+dojo.addOnLoad(Spring.initialize);
\ No newline at end of file
diff --git a/spring-js/src/main/resources/META-INF/spring/Spring.js b/spring-js/src/main/resources/META-INF/spring/Spring.js
index 0f7b9c8e..633368de 100644
--- a/spring-js/src/main/resources/META-INF/spring/Spring.js
+++ b/spring-js/src/main/resources/META-INF/spring/Spring.js
@@ -13,4 +13,4 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-Spring={};Spring.advisors=[];Spring.advisors.applied=false;Spring.applyAdvisors=function(){if(!Spring.advisors.applied){for(var x=0;x
+
diff --git a/spring-webflow/ivy.xml b/spring-webflow/ivy.xml
index 9dd6aefb..9468080d 100644
--- a/spring-webflow/ivy.xml
+++ b/spring-webflow/ivy.xml
@@ -28,6 +28,7 @@
+
diff --git a/spring-webflow/src/main/java/org/springframework/webflow/mvc/servlet/FlowController.java b/spring-webflow/src/main/java/org/springframework/webflow/mvc/servlet/FlowController.java
index e86bbe0c..4271d784 100644
--- a/spring-webflow/src/main/java/org/springframework/webflow/mvc/servlet/FlowController.java
+++ b/spring-webflow/src/main/java/org/springframework/webflow/mvc/servlet/FlowController.java
@@ -25,6 +25,8 @@ import javax.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.springframework.js.mvc.servlet.AjaxHandler;
+import org.springframework.js.mvc.servlet.SpringJavascriptAjaxHandler;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractController;
import org.springframework.web.servlet.view.RedirectView;
diff --git a/spring-webflow/src/main/java/org/springframework/webflow/mvc/servlet/FlowHandlerAdapter.java b/spring-webflow/src/main/java/org/springframework/webflow/mvc/servlet/FlowHandlerAdapter.java
index 80c12707..0f6b3d59 100644
--- a/spring-webflow/src/main/java/org/springframework/webflow/mvc/servlet/FlowHandlerAdapter.java
+++ b/spring-webflow/src/main/java/org/springframework/webflow/mvc/servlet/FlowHandlerAdapter.java
@@ -24,6 +24,8 @@ import javax.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.springframework.js.mvc.servlet.AjaxHandler;
+import org.springframework.js.mvc.servlet.SpringJavascriptAjaxHandler;
import org.springframework.web.context.support.WebApplicationObjectSupport;
import org.springframework.web.servlet.HandlerAdapter;
import org.springframework.web.servlet.ModelAndView;
diff --git a/spring-webflow/src/test/java/org/springframework/webflow/mvc/servlet/FlowControllerTests.java b/spring-webflow/src/test/java/org/springframework/webflow/mvc/servlet/FlowControllerTests.java
index d14b86f1..66528911 100644
--- a/spring-webflow/src/test/java/org/springframework/webflow/mvc/servlet/FlowControllerTests.java
+++ b/spring-webflow/src/test/java/org/springframework/webflow/mvc/servlet/FlowControllerTests.java
@@ -9,6 +9,7 @@ import javax.servlet.http.HttpServletResponse;
import junit.framework.TestCase;
import org.easymock.EasyMock;
+import org.springframework.js.mvc.servlet.SpringJavascriptAjaxHandler;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.mock.web.MockServletContext;