Spring MVC (using Spring Framework 2.5)

Sang Shin, sang.shin@sun.com, www.javapassion.com/j2ee



In this lab, you are going to learn the basics of Spring MVC such as handler mapping, interceptor, various controller types, method resolver for MultiActionController, and view resolver.

Expected duration: 210 minutes (excluding homework)


Prerequisites

This hands-on lab assumes you have some basic knowledge or programming experience on the following  technologies.


Software Needed

Before you begin, you need to install the following software on your computer. 

OS platforms you can use


Change Log


Things to do (by Sang Shin)


Lab Exercises


Exercise 0: Install Spring Framework Plug-in's to NetBeans IDE

In this exercise, you are going to install Spring framework plug-in to the NetBeans IDE.  The plug-in basically provides Spring framework library files.  In other words, you can manually add the library files yourself to your project if you are not using this plug-in.

In case you do not have an internet connection, the plug-in's are also provided under the directory of <LAB_UNZIPPED_DIRECTORY>/spring25mvc/NetBeansPlugins.  

(0.1) Install Spring MVC Plug-in to NetBeans IDE through update center (Internet connection required)

1. Select Tools from the menu bar and select Plugins. (Figure-0.11 below)


Figure-0.11: Select Plugins

2.  Select Available Plugins tab and then select Spring Framework Support and then click Install button.  (Figure-0.12 below)


Figure-0.12: Install Spring Framework Support plug-in

3. Follow through the installation instruction. (Figure-0.13 below)


Figure-0.13: Follow through the plug-in installation

Exercise 1: Build and run "springMVCskeletonSimpleUrlHandlerMapping" sample application

Acknowledgment: This exercise is based on the "Basic Spring Web MVC Example" tutorial  from memestorm.com.

Here’s a simple project, which doesn’t use all of Spring’s features, but serves as a good helloworld-like sample application.
When you’re putting together a simple web application, you need a few essentials:

The simple application here, springMVCskeletonSimpleUrlHandlerMapping, doesn’t have a model at all, has a single controller (DispatchController), and a single view (myview.jsp)

Tasks to be performed:

  1. Open, build, and run "springMVCskeletonSimpleUrlHandlerMapping" sample application
  2. Study the configuration files
  3. Study the code
  4. Study the control flow

(1.1) Open, build, and run "springMVCskeletonSimpleUrlHandlerMapping" sample application

0. Start NetBeans IDE. 
1. Open springMVCskeletonSimpleUrlHandlerMapping NetBeans project. 

2. Make sure the Spring Framework libraries are configured for the project. (This is an optional step.)



3. Build and run springMVCskeletonSimpleUrlHandlerMapping project. 


Figure-1.15: Result is displayed

Figure-1.16: Result is displayed

                                                                                                      return to top of the exercise

(1.2) Study the configuration files


1. web.xml under springMVCskeletonSimpleUrlHandlerMapping->Web Pages->WEB-INF

The configuration in the web.xml specifies the following - Create the servlet, call it dispatch, and map all incoming URLs that start with send to the dispatch servlet. So for example, a URL such as http://.../skeleton1/send/foobar would activate the dispatch servlet.

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
    <display-name>foo</display-name>
   
    <context-param>
        <param-name>log4jConfigLocation</param-name>
        <param-value>/WEB-INF/log4j.properties</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>
   
    <listener>
        <listener-class>
            org.springframework.web.context.ContextLoaderListener
        </listener-class>
    </listener>
   
    <servlet>
        <servlet-name>dispatch</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
   
    <servlet-mapping>
        <servlet-name>dispatch</servlet-name>
        <url-pattern>/send/*</url-pattern>
    </servlet-mapping>
   
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
</web-app>
Code-1.21: web.xml

2. dispatch-servlet.xml under springMVCskeletonSimpleUrlHandlerMapping->Web Pages->WEB-INF

The rest of the configuration is done in the Spring MVC application configuration file. Spring automatically looks for it using the name of the servlet as a hint. Since our servlet is called dispatch, it looks for a file called dispatch-servlet.xml in your WEB-INF directory. This configuration file will have three bits to it: the controller(s), the url mapping and the view resolver.

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>
   
    <bean id="urlMapping"
          class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="mappings">
            <props>
                <prop key="/actionNa*">dispatchController</prop>          
            </props>
        </property>
    </bean>
   
    <bean id="dispatchController"
          class="com.memestorm.web.DispatchController">
    </bean>
   
    <bean id="viewResolver"
          class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix">
            <value>/WEB-INF/views/</value>
        </property>
        <property name="suffix">
            <value>.jsp</value>
        </property>
    </bean>
   
</beans>
Code-1.22: dispatch-servlet.xml

2. applicationContext.xml under springMVCskeletonSimpleUrlHandlerMapping->Web Pages->WEB-INF

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

<!--
  - A simple root application context.  See dispatch-servlet.xml for the
  - Web context.
-->
<beans>
    <bean id="a" class="com.memestorm.A"/>
    <bean id="b" class="com.memestorm.B">
        <property name="a" ref="a"/>
    </bean>
   
</beans>
Code-1.23: applicationContext.xml

return to top of the exercise

(1.3) Study the code


1. DispatchController.java

package com.memestorm.web;

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.context.support.WebApplicationContextUtils;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.multiaction.MultiActionController;

import com.memestorm.B;

public class DispatchController extends MultiActionController {

    public ModelAndView actionName(HttpServletRequest request,
            HttpServletResponse response) throws Exception {

        Log log = LogFactory.getLog(this.getClass());
        log.info("Controller calling Earth.  Come in Earth.");

        String msg = ((B) (WebApplicationContextUtils.getWebApplicationContext(getServletContext()).getBean("b"))).getA().foo();

        ModelAndView mav = new ModelAndView("myview");
        mav.addObject("message", msg);
        return mav;
    }
}

2. Display context sensitive Javadoc on MultiActionController class.



Trouble-shooting: If you are experiencing a problem in displaying the Javadoc, it is highly likely because you have not configured the Javadoc document  with the Spring framework libraries as described here.

                                                                                                      return to top of the exercise

(1.4) Study the control flow


1. index.jsp is accessed because it is specified in the <welcome-file-list> of the web.xml as shown in Code-1.30 below.

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
    <display-name>foo</display-name>
   
    <context-param>
        <param-name>log4jConfigLocation</param-name>
        <param-value>/WEB-INF/log4j.properties</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>
   
    <listener>
        <listener-class>
            org.springframework.web.context.ContextLoaderListener
        </listener-class>
    </listener>
   
    <servlet>
        <servlet-name>dispatch</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
   
    <servlet-mapping>
        <servlet-name>dispatch</servlet-name>
        <url-pattern>/send/*</url-pattern>
    </servlet-mapping>
   
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
</web-app>
Code-1.30: web.xml

2. index.jsp is displayed.


Figure-1.31: index.jsp is displayed

3. When you click this link  hyperlink in the index.jsp, the control goes to send/actionName, which will be handled by the DispatchServlet of the Spring MVC framework.  (Figure-1.32 below)

<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
<html>
    <head>
        <title>Spring Skeleton</title>
    </head>
    <body>
        Try accessing the controller by going to <a href="send/actionName">this link</a>.
    </body>
</html>
Code-1.32: send/actionName will be the target

4. The com.memestorm.web.DispatchController class is now assigned to handle the request - any request whose URL ends with actionNa* - according to the configuration in the dispatch-servlet.xml as shown below.

    <bean id="urlMapping"
          class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="mappings">
            <props>
                <prop key="/actionNa*">dispatchController</prop>          
            </props>
        </property>
    </bean>
   
    <bean id="dispatchController"
          class="com.memestorm.web.DispatchController">
    </bean>
Code-1.33: SimpleUrlHandlerMapping is used for mapping a URL to a controller

5. The DispatchController class is MultiActionController type.

<Study point> Because there is no specific methodNameResolver property specified for the DispatchController class, it will use InternalPathMethodNameResolver, in which the method name is taken from the last part of the path - actionName() method in this case.  (Code-1.35 below)  For more information on view resolving, please see "Views and Resolving Them" section of the Spring froamework document.

6. The actionName() method selects myview as the View to display.  It also creates model object in which it added message. 

package com.memestorm.web;

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.context.support.WebApplicationContextUtils;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.multiaction.MultiActionController;

import com.memestorm.B;

public class DispatchController extends MultiActionController {
   
    public ModelAndView actionName(HttpServletRequest request,
            HttpServletResponse response) throws Exception {
       
        Log log = LogFactory.getLog(this.getClass());
        log.info("Controller calling Earth.  Come in Earth.");
       
        String msg = ((B) (WebApplicationContextUtils
                .getWebApplicationContext(getServletContext()).getBean("b")))
                .getA().foo();
       
        ModelAndView mav = new ModelAndView("myview");
        mav.addObject("message", msg);
        return mav;
    }
   
}
Code-1.35: DispatchController.java

7. The viewResolver selects /WEB-INF/views/myview.jsp as the view to display based on the configuration below.

    <bean id="viewResolver"
          class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix">
            <value>/WEB-INF/views/</value>
        </property>
        <property name="suffix">
            <value>.jsp</value>
        </property>
    </bean>
Code-1.36: InternalResourceViewResolver

8. The /WEB-INF/views/myview.jsp is displayed. 


Figure-1.39: myview.jsp is displayed

9. Take a look at the source of myview.jsp. (Code-1.40 below)

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
        <title>Welcome!</title>
    </head>
    <body>
        Hello, you're in myview.jsp! <br />
        The controller sent me some data, here it is: <b> <%=request.getAttribute("message") %> </b>
       
    </body>
</html>
Code-1.40: Source code of myview.jsp


return to top of the exercise

Summary

In this exercise,  you learned how a controller is selected based on mapping configuration.  You also learned how the controller selects a view.

                                                                                                                        return to the top




Exercise 2: Build and run "springMVCskeletonSimpleUrlHandlerMapping2" sample application

The "springMVCskeletonSimpleUrlHandlerMapping2" sample application is a slightly modified version of the springMVCskeletonSimpleUrlHandlerMapping application.  It uses the 2nd controller.

  1. Open, build, and run "springMVCskeletonSimpleUrlHandlerMapping2" sample application
  2. Study the configuration files
  3. Study the control flow


(2.1) Open, build, and run "springMVCskeletonSimpleUrlHandlerMapping2" sample application

1. Open springMVCskeletonSimpleUrlHandlerMapping2 NetBeans project. 

2. Build and run springMVCskeletonSimpleUrlHandlerMapping2 project. 


Figure-2.11: Result of running the application

Figure-2.12: Result of clicking the 2nd link

                                                                                                                               return to top of the exercise


(2.2) Study the configuration files


1. dispatch-servlet.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>
   
    <bean id="urlMapping"
   class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="mappings">
            <props>
                <prop key="/actionName2">dispatchController2</prop>
                <prop key="/*">dispatchController</prop>
            </props>
        </property>
    </bean>
   
    <bean id="dispatchController"
   class="com.memestorm.web.DispatchController">
    </bean>
   
    <bean id="dispatchController2"
   class="com.memestorm.web.DispatchController2">
    </bean>
   
    <bean id="viewResolver"
   class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix">
            <value>/WEB-INF/views/</value>
        </property>
        <property name="suffix">
            <value>.jsp</value>
        </property>
    </bean>
   
</beans>
Code-2.21: dispatch-servlet.xml

2. web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4"
         xmlns="http://java.sun.com/xml/ns/j2ee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
    <display-name>foo</display-name>
   
    <context-param>
        <param-name>log4jConfigLocation</param-name>
        <param-value>/WEB-INF/log4j.properties</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>
   
    <listener>
        <listener-class>
            org.springframework.web.context.ContextLoaderListener
        </listener-class>
    </listener>
   
    <servlet>
        <servlet-name>dispatch</servlet-name>
        <servlet-class>
            org.springframework.web.servlet.DispatcherServlet
        </servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
   
    <servlet-mapping>
        <servlet-name>dispatch</servlet-name>
        <url-pattern>/send/*</url-pattern>
    </servlet-mapping>
   
    <servlet-mapping>
        <servlet-name>dispatch</servlet-name>
        <url-pattern>/send2/*</url-pattern>
    </servlet-mapping>
   
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
</web-app>
Code-2.22: web.xml

                                                                                                                               return to top of the exercise


(2.3) Study the control flow


1. index.jsp is displayed.

Welcome.

Try accessing the 1st controller by going to <a href="send/actionName">this link</a>.
<p>
Try accessing the 2nd controller by going to <a href="send/actionName2">this link</a>.
Code-2.31: index.jsp

2. When the link for send/actionName2 is clicked, the displatchController2 is used to handle the request according to the configuration below.  The class of the displatchController2 is com.memestorm.web.DispatchController2.

    <bean id="urlMapping"
   class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="mappings">
            <props>
                <prop key="/actionName2">dispatchController2</prop>
                <prop key="/*">dispatchController</prop>
            </props>
        </property>
    </bean>

    <bean id="dispatchController"
   class="com.memestorm.web.DispatchController">
    </bean>
   
    <bean id="dispatchController2"
   class="com.memestorm.web.DispatchController2">
    </bean>

3. The actionName2() method of the com.memestorm.web.DispatchController2 class is invoked because the class is the type of MultiActionController.  Because there is no specific methodNameResolver property specified for the DispatchController2 class, it will use InternalPathMethodNameResolver, in which the method name is taken from the last part of the path - actionName2() method in this case.

package com.memestorm.web;

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.context.support.WebApplicationContextUtils;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.multiaction.MultiActionController;

import com.memestorm.B;

public class DispatchController2 extends MultiActionController {
   
    public ModelAndView actionName2(HttpServletRequest request,
            HttpServletResponse response) throws Exception {
       
        Log log = LogFactory.getLog(this.getClass());
        log.info("Controller calling Earth.  Come in Earth.");
       
        String msg = ((B) (WebApplicationContextUtils
                .getWebApplicationContext(getServletContext()).getBean("b")))
                .getA().foo();
       
        ModelAndView mav = new ModelAndView("myview2");
        mav.addObject("message2", msg);
        return mav;
    }
   
}
Code-2.32: DispatchController2.java

4. The actionName2() method selects myview2 as the view to display.  The viewResolver will select /WEB-INF/views/myview2.jsp as the page to display accoring to the configuration below.

    <bean id="viewResolver"
   class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix">
            <value>/WEB-INF/views/</value>
        </property>
        <property name="suffix">
            <value>.jsp</value>
        </property>
    </bean>


5. myview2.jsp is displayed

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
        <title>Welcome!</title>
    </head>
    <body>
        Hello, you're in myview2.jsp! <br />
        The controller sent me some data, here it is: <b> <%=request.getAttribute("message2") %> </b>
       
    </body>
</html>
Code-2.33: myview2.jsp

                                                                                                                               return to top of the exercise

Summary

In this exercise,  you learned how to use two different controllers.

                                                                                                                               return to the top


Exercise 3: Build and run "springMVCskeletonBeanNameUrlHandlerMapping" sample application

The "springMVCskeletonBeanNameUrlHandlerMapping" sample application uses BeanNameUrlHanlderMapping.

  1. Open, build, and run "springMVCskeletonBeanNameUrlHandlerMapping" sample application
  2. Study the configuration files
  3. Study the control flow


(3.1) Open, build, and run "springMVCskeletonBeanNameUrlHandlerMapping" sample application

1. Open springMVCskeletonBeanNameUrlHandlerMapping NetBeans project. 

2. Build and run springMVCskeletonBeanNameUrlHandlerMapping project. 






(3.2) Study the configuration files


1. dispatch-servlet.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
   
    <!-- Maps URLs to beans with names or aliases that start with a slash ("/")  -->
    <bean id="urlMapping"
          class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping">
    </bean>
    <bean id="dispatchController" name="/actionName"
          class="com.memestorm.web.DispatchController">
    </bean>
    <bean id="viewResolver"
          class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix">
            <value>/WEB-INF/views/</value>
        </property>
        <property name="suffix">
            <value>.jsp</value>
        </property>
    </bean>
</beans>
Code-3.21: dispatch-servlet.xml

2. web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
    <display-name>foo</display-name>
    <context-param>
        <param-name>log4jConfigLocation</param-name>
        <param-value>/WEB-INF/log4j.properties</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>
    <listener>
        <listener-class>
            org.springframework.web.context.ContextLoaderListener
        </listener-class>
    </listener>
    <servlet>
        <servlet-name>dispatch</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatch</servlet-name>
        <url-pattern>/send/*</url-pattern>
    </servlet-mapping>
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
</web-app>
Code-3.22: web.xml

                                                                                                                               return to top of the exercise


(3.3) Study the control flow


1. index.jsp is displayed.

<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
<html>
    <head>
        <title>Spring Skeleton</title>
    </head>
    <body>
        Try accessing the controller by going to <a href="send/actionName">this link</a>.
        URL to controller mapping is done through BeanNameUrlHandlerMapping.
    </body>
</html>
Code-2.31: index.jsp

2. When you click this link  hyperlink in the index.jsp, the control goes to send/actionName, which will be handled by the DispatchServlet of the Spring MVC framework. 

3. The com.memestorm.web.DispatchController class is now assigned to handle the request according to the configuration in the dispatch-servlet.xml as shown below.   Any URL that ends with /actionName is handled by this controller.

    <bean id="urlMapping"
          class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping">
    </bean>
    <bean id="dispatchController" name="/actionName"
          class="com.memestorm.web.DispatchController">
    </bean>


4. The actionName() method selects myview as the View to display.  It also creates model object in which it added message. 

package com.memestorm.web;

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.context.support.WebApplicationContextUtils;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.multiaction.MultiActionController;

import com.memestorm.B;

public class DispatchController extends MultiActionController {

    public ModelAndView actionName(HttpServletRequest request,
            HttpServletResponse response) throws Exception {

        Log log = LogFactory.getLog(this.getClass());
        log.info("Controller calling Earth.  Come in Earth.");

        String msg = ((B) (WebApplicationContextUtils.getWebApplicationContext(getServletContext()).getBean("b"))).getA().foo();

        ModelAndView mav = new ModelAndView("myview");
        mav.addObject("message", msg);
        return mav;
    }
}


5. The viewResolver selects /WEB-INF/views/myview.jsp as the view to display based on the configuration below.

    <bean id="viewResolver"
          class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix">
            <value>/WEB-INF/views/</value>
        </property>
        <property name="suffix">
            <value>.jsp</value>
        </property>
    </bean>


6. The /WEB-INF/views/myview.jsp is displayed. 


                                                                                                                               return to top of the exercise

Summary

In this exercise,  you learned how to use BeanNameUrlHanlderMapping.

                                                                                                                               return to the top


Exercise 4: Build and run "springMVCSimpleFormController" sample application

Acknowledgment: This exercise is based on the "Spring Series, Part 3: Swing into Spring MVC" tutorial  written by Naveen Balani.

  1. Open, build, and run "springMVCskeletonSimpleUrlHandlerMapping2" sample application
  2. Study the configuration files
  3. Study the code
  4. Study the control flow

(4.1) Open, build, and run "springMVCSimpleFormController" sample application

1. Open springMVCSimpleFormController NetBeans project. 

2. Build and run springMVCSimpleFormController project. 


Figure-4.11: Enter User id and Password

Figure-4.12: Account Details

                                                                                                                               return to top of the exercise


(4.2) Study the configuration files


1. web.xml

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/sampleBanking-services.xml</param-value>
    </context-param>
    <servlet>
        <servlet-name>context</servlet-name>
        <servlet-class>
            org.springframework.web.context.ContextLoaderServlet
        </servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet>
        <servlet-name>sampleBankingServlet</servlet-name>
        <servlet-class>
            org.springframework.web.servlet.DispatcherServlet
        </servlet-class>
        <load-on-startup>2</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>sampleBankingServlet</servlet-name>
        <url-pattern>*.html</url-pattern>
    </servlet-mapping>
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
    <taglib>
        <taglib-uri>/spring</taglib-uri>
        <taglib-location>/WEB-INF/spring.tld</taglib-location>
    </taglib>
</web-app>

2. sampleBankingServlet-servlet.xml

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>
   
    <bean id="simpleUrlMapping"
               class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="mappings">
            <props>
                <prop key="/login.html">loginBankController</prop>
            </props>
        </property>
    </bean>
   
   
    <bean id="loginBankController"
   class="springexample.contoller.LoginBankController">
        <property name="sessionForm">
            <value>true</value>
        </property>
        <property name="commandName">
            <value>loginCommand</value>
        </property>
        <property name="commandClass">
            <value>springexample.commands.LoginCommand</value>
        </property>
       
        <property name="authenticationService">
            <ref bean="authenticationService" />
        </property>
        <property name="accountServices">
            <ref bean="accountServices" />
        </property>
        <property name="formView">
            <value>login</value>
        </property>
        <property name="successView">
            <value>accountdetail</value>
        </property>
       
    </bean>
   
    <bean id="viewResolver"
               class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="viewClass">
            <value>org.springframework.web.servlet.view.JstlView</value>
        </property>
        <property name="prefix">
            <value>/jsp/</value>
        </property>
        <property name="suffix">
            <value>.jsp</value>
        </property>
    </bean>
   
</beans>

3. simpleBanking-services.xml

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>
   
    <bean id="accountServices"
          class="springexample.services.AccountServices">
    </bean>
   
    <bean id="authenticationService"
          class="springexample.services.AuthenticationService">
    </bean>
   
</beans>

                                                                                                                               return to top of the exercise

(4.3) Study the code


1. LoginBankController.java

package springexample.contoller;

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.SimpleFormController;

import springexample.commands.AccountDetail;
import springexample.commands.LoginCommand;
import springexample.services.AccountServices;
import springexample.services.AuthenticationService;

/**
 * SimpleFormController is a concrete FormController implementation that
 * provides configurable form and success views, and an onSubmit chain for
 * convenient overriding. Automatically resubmits to the form view in case
 * of validation errors, and renders the success view in case of a valid
 * submission.
 */
public class LoginBankController extends SimpleFormController {

    public LoginBankController() {
    }
    // The submit behavior can be customized by overriding one of the onSubmit methods.
    protected ModelAndView onSubmit(Object command) throws Exception {

        LoginCommand loginCommand = (LoginCommand) command;
        authenticationService.authenticate(loginCommand);
        AccountDetail accountdetail = accountServices.getAccountSummary(loginCommand.getUserId());
        return new ModelAndView(getSuccessView(), "accountdetail", accountdetail);
    }
    private AuthenticationService authenticationService;
    private AccountServices accountServices;

    /**
     * @return Returns the accountServices.
     */
    public AccountServices getAccountServices() {
        return accountServices;
    }

    /**
     * @param accountServices The accountServices to set.
     */
    public void setAccountServices(AccountServices accountServices) {
        this.accountServices = accountServices;
    }

    /**
     * @return Returns the authenticationService.
     */
    public AuthenticationService getAuthenticationService() {
        return authenticationService;
    }

    /**
     * @param authenticationService The authenticationService to set.
     */
    public void setAuthenticationService(
            AuthenticationService authenticationService) {
        this.authenticationService = authenticationService;
    }
}

2. Display context-sensitive Javadoc on SimpleFormController.



                                                                                                                               return to top of the exercise


(4.4) Study the control flow


1. index.jsp (Code-4.31 below) under springMVCSimpleFormController->Web Pages is accessed.  The control is forwarded to login.html automatically, which will be handled by DispatcherServlet.

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
        <title>Insert title here</title>
    </head>
    <body>
        <jsp:forward page="login.html" />
    </body>
</html>
Code-3.31: index.jsp

2. The DispatchServlet selects loginBankController according to the configuration below to handle the request.

   <bean id="simpleUrlMapping"
               class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="mappings">
            <props>
                <prop key="/login.html">loginBankController</prop>
            </props>
        </property>
    </bean>
Code-4.32: Mapping of  URL to the controller

3. The value of the formView property of the loginBankController will be used as a logical view selection.  It is login in this example.

    <bean id="loginBankController"
   class="springexample.contoller.LoginBankController">
        <property name="sessionForm">
            <value>true</value>
        </property>
        <property name="commandName">
            <value>loginCommand</value>
        </property>
        <property name="commandClass">
            <value>springexample.commands.LoginCommand</value>
        </property>
       
        <property name="authenticationService">
            <ref bean="authenticationService" />
        </property>
        <property name="accountServices">
            <ref bean="accountServices" />
        </property>
        <property name="formView">
            <value>login</value>
        </property>
        <property name="successView">
            <value>accountdetail</value>
        </property>
       
    </bean>
Code-4.33: formView property

4. The actual view will be /WEB-INF/jsp/login.jsp.

    <bean id="viewResolver"
               class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="viewClass">
            <value>org.springframework.web.servlet.view.JstlView</value>
        </property>
        <property name="prefix">
            <value>/jsp/</value>
        </property>
        <property name="suffix">
            <value>.jsp</value>
        </property>
    </bean>

5. /WEB-INF/jsp/login.jsp is displayed.



6. Display the source of the /WEB-INF/jsp/login.jsp.  Note that <spring:bind ...> tag is used.

<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core"%>
<%@ taglib prefix="spring" uri="/spring"%>


<html>
    <head>
        <title>Login to Spring Example Account Banking</title>
    </head>
   
    <body>
       
        <h1>
            Please enter your userid and password. (Use "admin" & "password" for testing.)
        </h1>
       
        <p></p>
        <form method="post" action="">
            <spring:bind path="loginCommand">
                <c:forEach items="${status.errorMessage}" var="errorMessage">
                    <font color="red"> <c:out value="${errorMessage}" /> <br>
                    </font>
                </c:forEach>
            </spring:bind>
           
           
            <table width="95%" bgcolor="f8f8ff" border="0" cellspacing="0"
                   cellpadding="5">
                <tr>
                    <td alignment="right" width="20%">
                        User id:
                    </td>
                    <spring:bind path="loginCommand.userId">
                        <td width="20%">
                            <input type="text" name='<c:out value="${status.expression}"/>'
                                   value='<c:out value="${status.value}"/>'>
                        </td>
                    </spring:bind>
                    <td width="60%">
                    </td>
                </tr>
               
                <tr>
                    <td alignment="right" width="20%">
                        Password:
                    </td>
                    <spring:bind path="loginCommand.password">
                        <td width="20%">
                            <input type="password"
                                   name='<c:out value="${status.expression}"/>'
                                   value='<c:out value="${status.value}"/>'>
                        </td>
                    </spring:bind>
                    <td>
                    </td>
                    <td width="60%">
                    </td>
                </tr>
               
               
            </table>
            <br>
            <br>
            <input type="submit" alignment="center" value="login">
        </form>
        <p>
        </p>
       
       
    </body>
</html>
Code-4.34: login.jsp

7. User enters "admin" and "password" as username and password and submit the form.

8. The onSubmit() method of the LoginBankController is called when the form is submitted.  Note that the LoginCommand object represents input form fields.   Also the AcountDetail object is saved with accountdetail as a key word into the Model object.

package springexample.contoller;

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.SimpleFormController;

import springexample.commands.AccountDetail;
import springexample.commands.LoginCommand;
import springexample.services.AccountServices;
import springexample.services.AuthenticationService;

/**
 * @author naveenb
 */
public class LoginBankController extends SimpleFormController {
   
    public LoginBankController(){
       
    }
   
    protected ModelAndView onSubmit(Object command) throws Exception{
       
        LoginCommand loginCommand = (LoginCommand) command;
        authenticationService.authenticate(loginCommand);
        AccountDetail accountdetail = accountServices.getAccountSummary(loginCommand.getUserId());
        return new ModelAndView(getSuccessView(),"accountdetail",accountdetail);
    }
   
    private AuthenticationService authenticationService;
   
    private AccountServices accountServices;
   
   
    /**
     * @return Returns the accountServices.
     */
    public AccountServices getAccountServices() {
        return accountServices;
    }
    /**
     * @param accountServices The accountServices to set.
     */
    public void setAccountServices(AccountServices accountServices) {
        this.accountServices = accountServices;
    }
    /**
     * @return Returns the authenticationService.
     */
    public AuthenticationService getAuthenticationService() {
        return authenticationService;
    }
    /**
     * @param authenticationService The authenticationService to set.
     */
    public void setAuthenticationService(
            AuthenticationService authenticationService) {
        this.authenticationService = authenticationService;
    }
}

9. The the logical name of the view to display is Success view, which is accontdetail based on the configuration below.

    <bean id="loginBankController"
   class="springexample.contoller.LoginBankController">
        <property name="sessionForm">
            <value>true</value>
        </property>
        <property name="commandName">
            <value>loginCommand</value>
        </property>
        <property name="commandClass">
            <value>springexample.commands.LoginCommand</value>
        </property>
       
        <property name="authenticationService">
            <ref bean="authenticationService" />
        </property>
        <property name="accountServices">
            <ref bean="accountServices" />
        </property>
        <property name="formView">
            <value>login</value>
        </property>
        <property name="successView">
            <value>accountdetail</value>
        </property>
       
    </bean>


10. Based on the viewResolver configuration, the controller will select /WEB-INF/jsp/accountdetail.jsp as the next view page.

    <bean id="viewResolver"
               class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="viewClass">
            <value>org.springframework.web.servlet.view.JstlView</value>
        </property>
        <property name="prefix">
            <value>/jsp/</value>
        </property>
        <property name="suffix">
            <value>.jsp</value>
        </property>
    </bean>

11. /WEB-INF/jsp/accountdetail.jsp is displayed.



12. Display the source of the /WEB-INF/jsp/accountdetail.jsp. It is displaying the properties of each entry of the accountdetail map object.

<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core"%>
<%@ taglib prefix="spring" uri="/spring"%>


<html>
    <head>
        <title>Login to Spring Example Account Banking</title>
    </head>
   
    <body>
       
        <h1>
            Account Details
        </h1>
       
        <p>
        <form method="post">
        <spring:bind path="accountdetail">
            <c:forEach items="${status.errorMessage}" var="errorMessage">
                <font color="red"> <c:out value="${errorMessage}" />
                <br> </font>
            </c:forEach>
        </spring:bind>
       
       
        <table width="95%" bgcolor="f8f8ff" border="0" cellspacing="0"
               cellpadding="5">
            Following are the list of your accounts and its details.
            <c:forEach items="${accountdetail.accountsList}" var="accountsList">
                <tr>
                    <td alignment="right" width="20%">
                        Account Name:
                        <c:out value="${accountsList.accountName}" />
                    </td>
                    <td alignment="right" width="20%">
                        Account Type:
                   &nbs