Spring MVC does not provide out of the box Ajax support. However it provides suitable extension points through its template based design to enable Ajax support very easily. Here is the step by step account of adding Ajax support to your Spring MVC application with jQuery javascript library.
Step 1 - Getting the JSP ready
To keep things simple I will use a JSP to build a simple form. The JSP is shown in Listing 1.
Listing 1 - index.jsp
<!-- other parts of the JSP -->
<h2><a href="#">Sign In</a></h2>
<div>
<form id="loginForm" >
<label>
<span>Email: </span>
<input
text-input" type="text"
name="email" id="email" /> </label>
<label> <span>Password : </span> <input type="password" name="password"
id="password" /> </label>
<input type="button"
value="Sign In" onClick="callSigninUser()"/></form>
</div>
Step 2 -Add jQuery to sprinkle Ajax form post
Now I will add a bit of jQuery Ajax support to submit the login form in Ajax. This is shown in Listing 2.
Listing 2 - index.jsp
<script type="text/javascript" src="/js/jquery-1.3.2.min.js"></script>
<script>
function callSigninUser(){
var queryString = $('#loginForm').formSerialize(); $.post('signin.htm', queryString,
function(data){
alert(data);
});
}
</script>
Now we are done on the client side. Its time to setup code and configuration on the server side. On the server side, I ran the example on Tomcat 6 with Spring 2.5.x
Step 3 - Adding a view resolver
In order to enable Ajax support, you will need to extend Spring MVC by adding an Ajax view resolver. This is shown in Listing 3.
Listing 3 - AjaxViewResolver.java
/**
*
*/
package com.kenai.openmall.springframework.view.extn;
import java.util.Locale;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.view.AbstractCachingViewResolver;
/**
* @author dhrubo
*
*/
public class AjaxViewResolver extends AbstractCachingViewResolver {private static final Log log = LogFactory.getLog(AjaxViewResolver.class);
private String ajaxPrefix;
private View ajaxView;
/* (non-Javadoc)
* @see org.springframework.web.servlet.view.AbstractCachingViewResolver#loadView(java.lang.String, java.util.Locale)
*/
@Override
protected View loadView(String viewName, Locale locale) throws Exception { log.info("viewName==>"+viewName);View view = null;
if(viewName.startsWith(this.ajaxPrefix)){view = ajaxView;
}
return view;
}
public String getAjaxPrefix() {return ajaxPrefix;
}
public void setAjaxPrefix(String ajaxPrefix) {this.ajaxPrefix = ajaxPrefix;
}
public View getAjaxView() {return ajaxView;
}
public void setAjaxView(View ajaxView) {this.ajaxView = ajaxView;
}
}
I will discuss more about this in Step 5 and 6.
Step 4 - Adding support for Ajax view
Now we will add support for Ajax view. This is shown in Listing 4. AjaxView just transforms the model objects into JSON using Flex-JSON library (http://flexjson.sourceforge.net/) and passes it in response to the jQuery handler in Listing 2.
Listing 4 - AjaxView.java
/**
*
*/
package com.kenai.openmall.springframework.view.extn;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.web.servlet.view.AbstractView;
import flexjson.JSONSerializer;
/**
* @author dhrubo
*
*/
public class AjaxView extends AbstractView {private static final Log log = LogFactory.getLog(AjaxView.class);
/* (non-Javadoc)
* @see org.springframework.web.servlet.view.AbstractView#renderMergedOutputModel(java.util.Map, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
*/
@Override
protected void renderMergedOutputModel(Map map, HttpServletRequest request,
HttpServletResponse response) throws Exception { log.info("Resolving ajax request view -"+map);JSONSerializer serializer = new JSONSerializer();
String jsonString = serializer.serialize(map );
response.setContentType( "text/plain; charset=UTF-8" );
response.getOutputStream().write( jsonString.getBytes() );
}
}
Step 5 - Getting ready the Spring controller
Even with Ajax request we can leverage the Spring page controller to handle the unit task. Listing 5 - below shows the simple sign in controller.
Listing 5 - SignInController.java
/**
*
*/
package com.kenai.openmall.presentation.pagecontroller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
/**
* @author dhrubo
*
*/
public class SignInController implements Controller {protected final Log log = LogFactory.getLog(getClass());
public ModelAndView handleRequest(HttpServletRequest request,
HttpServletResponse response) throws Exception { log.info("Returning ajax view"); return new ModelAndView("ajax_foo","user",new User());
}
}
The sign in controller is just a demo class which returns a model and view object. The model now has the authenticated object and the view name. In order to determine that this was an Ajax view request we have prefixed the view name with "ajax". This is utlized by ajax view resolver and configured in Spring context.
Step 6 - Wiring up things
As always its time to wire up things in spring configuration file shown in Listing 6.
Listing 6 - spring-presentation-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<!--
the application context definition for the springapp DispatcherServlet
-->
<bean id="handlerMapping" class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping">
<property name="alwaysUseFullPath" value="true"/>
</bean>
<bean name="/hello.htm"
class="com.kenai.openmall.presentation.pagecontroller.SigninController" />
<bean id="ajaxViewResolver"
class="com.kenai.openmall.springframework.view.extn.AjaxViewResolver">
<property name="ajaxView">
<bean class="com.kenai.openmall.springframework.view.extn.AjaxView" />
</property>
<property name="ajaxPrefix" value="ajax_"></property>
</bean>
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass"
value="org.springframework.web.servlet.view.JstlView"></property>
<property name="prefix" value="/WEB-INF/jsp/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
</beans>
Step 7 -Tomcat web application configuration
Some of you may be interested in the Tomcat web application configuration as well. It is shownin Listing 7.
Listing 7 - web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">
<display-name>PLUTO</display-name>
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>/WEB-INF/log4j.xml</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring-presentation-config.xml</param-value>
</context-param>
<context-param>
<param-name>log4jRefreshInterval</param-name>
<param-value>1000</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
<servlet>
<servlet-name>plutoapp</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring-presentation-config.xml</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>plutoapp</servlet-name>
<url-pattern>*.htm</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
Further reading
- Spring MVC Primer - http://static.springsource.org/spring/docs/2.5.x/reference/mvc.html
- Spring MVC Step by Step - http://static.springframework.org/docs/Spring-MVC-step-by-step/
- Spring MVC Book - http://www.apress.com/book/view/159059584X
- Spring MVC Patterns and internals - http://www.apress.com/book/view/1430210095

written by ellayararwhy, December 18, 2009
You are missing any reference to the User class in Listing 5 - SignInController.java . Just which springframework (or other equivalent) should I be referencing?
Otherwise, this is very good (just not runnable in present form) - thx.
written by ellayararwhy, December 18, 2009
there are several items missing (ajax_foo.jsp, jars, etc) and so many things wrong (
written by ellayararwhy, December 18, 2009
Looks like my parentheses got misintepreted - try again:
dhrubo:
there are several items missing
(ajax_foo.jsp, jars, etc)and so many things wrong
(
written by a guest, January 19, 2010
This is good one..
I have used Spring 3 REST support
By the way, How you handle validation errors, I mean I am using spring validation, so how to show them.
written by rendiarta, February 16, 2010
java.lang.IllegalAccessException: Class flexjson.JSONSerializer$ObjectVisitor can not access a member of class com.kenai.openmall.presentation.pagecontroller.User with modifiers "public"
Any hints?
public class User {
private String username;
private String password;
//getter setter method with public modifier
}
Rgds,
Rendi Arta
Home
Community
