JTraining Blog

Share your knowledge.
dhrubo
dhrubo

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

 

 


Tagged in: Untagged 
Trackback(0)
Comments (9)Add Comment
david
...
written by david, August 03, 2009
great step by step tutorial. Makes it look simple, thanks!
ellayararwhy
...
written by ellayararwhy, December 18, 2009
dhrubo:

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.
ellayararwhy
...
written by ellayararwhy, December 18, 2009
dhrubo:

there are several items missing (ajax_foo.jsp, jars, etc) and so many things wrong (
ellayararwhy
...
written by ellayararwhy, December 18, 2009
smilies/sad.gif
Looks like my parentheses got misintepreted - try again:
dhrubo:

there are several items missing
(ajax_foo.jsp, jars, etc)
and so many things wrong
(
dhrubo
...
written by dhrubo, December 18, 2009
1> ajax_foo.jsp will be the simplest JSP on earth showing a hello world
2> User.java will be just any Java bean style class with just 2 String attributes - username, password = I am sure it will be cake walk for you
3> The Jars can be found with Spring distribution. Why dont you take this as an exercise and post it here.
Thanks ...dhrubo
nachiket
...
written by a guest, January 19, 2010
Hi,
This is good one..
I have used Spring 3 REST support smilies/smiley.gif
By the way, How you handle validation errors, I mean I am using spring validation, so how to show them.
rendiarta
...
written by rendiarta, February 16, 2010
Found this :

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
dhrubo
...
written by dhrubo, February 16, 2010
Friends, request all of you to switch to JSON view now added in Spring 3 MVC.
dhrubo
...
written by dhrubo, February 16, 2010
@Rendi - please ensure you have the getter setter methods in your class User

Write comment
You must be logged in to post a comment. Please register if you do not have an account yet.

busy

Tags:

Sponsers