2.3. First application based on Spring MVC

Caution

This version is already obsolete. Please check the latest guideline.

Before entering into the advanced usage of Spring MVC, it is better to understand Spring MVC by actually trying handson web application development using Spring MVC. This purpose of this chapter to understand the overall picture. Note that it does not follow the recommendations given from the next chapter onwards. (for the ease of understanding).

2.3.1. Prerequisites

The description of this chapter has been verified on the following environment. (For other environments, replace the contents mentioned here appropriately)

Product Version
JDK 1.6.0_33
Spring Tool Suite (STS) 3.2.0
VMware vFabric tc Server Developer Edition 2.8
Fire Fox 21.0

Note

To connect to the internet via a proxy server, STS Proxy settings and Maven Proxy settings are required for the following operations.

Warning

“Spring Template Project” used in this chapter has been removed from Spiring Tool Suite 3.4; hence, the contents of this chapter can only be confirmed on “Spring Tool Suite 3.3” or before.

Refer to [coming soon] Create Project from Blank Project in case using Spring Tool Suite 3.4.

We plan to update the contents of this chapter in future.

2.3.2. Create a New Project

From the menu of SpringSource Tool Suite, select [File] -> [New] -> [Spring Template Project] -> [Spring MVC Project] -> [Next], and create Spring MVC project.

Note

If proxy server is being used, there is a possibility of not being able to select Spring Template Project. In order to resolve this, do the following.

  • First select [window] -> [Preferences] -> [Spring] -> [Template Projects] and remove all items except “spring-defaults”.
  • Then click Apply.
  • After this, when [File] -> [New] -> [Spring Project] is clicked, [Spring MVC Project] can be selected from Templetes.

Enter “helloworld” in [Project Name], “com.example.helloworld” in [Please specify the top-level package] and click [Finish] on the next screen.

New Spring MVC Project

Following project is generated in the Package Explorer (Internet access is required)

workspace

The generated configuration file (src/main/webapp/WEB-INF/spring/appServlet/servlet-context.xml) of Spring MVC is described briefly to understand the configuration of Spring MVC.

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:beans="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- DispatcherServlet Context: defines this servlet's request-processing
        infrastructure -->

    <!-- (1) Enables the Spring MVC @Controller programming model -->
    <annotation-driven />

    <!-- Handles HTTP GET requests for /resources/** by efficiently serving
        up static resources in the ${webappRoot}/resources directory -->
    <resources mapping="/resources/**" location="/resources/" />

    <!-- (2) Resolves views selected for rendering by @Controllers to .jsp resources
        in the /WEB-INF/views directory -->
    <beans:bean
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <beans:property name="prefix" value="/WEB-INF/views/" />
        <beans:property name="suffix" value=".jsp" />
    </beans:bean>

    <!-- (3) -->
    <context:component-scan base-package="com.example.helloworld" />
</beans:beans>
Item number Description
(1)
Default settings of Spring MVC are configured by defining <annotation-driven />. Refer to the official website Enabling the MVC Java Config or the MVC XML Namespace of Spring framework for default configuration.
(2)
Define the location of View by specifying Resolver of View.
(3)
Define the package which will be target of searching components used in Spring MVC.

Following is the com.example.helloworld.HomeController (However, it is modified to simple form for explanation).

package com.example.helloworld;

import java.util.Date;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

/**
 * Handles requests for the application home page.
 */
@Controller// (1)
public class HomeController {

    private static final Logger logger = LoggerFactory
            .getLogger(HomeController.class);

    /**
     * Simply selects the home view to render by returning its name.
     */
    @RequestMapping(value = "/", method = RequestMethod.GET) // (2)
    public String home(Model model) { // (3)
        logger.info("Welcome home!");

        Date date = new Date();
        model.addAttribute("serverTime", date);

        return "home"; // (4)
    }
}

It is explained briefly.

Item number Description
(1)
It can be read automatically by DI container if @Controller annotation is used. As stated earlier in “explanation of Spring MVC configuration files (3)”, it is the target of component-scan.
(2)
It gets executed when the HTTP method is GET and when the Resource is (or request URL) is “/”.
(3)
Set objects to be delivered to View.
(4)
Return View name. Rendering is performed by WEB-INF/views/home.jsp as per the configuration in “Explanation of Spring MVC configuration files (2)”.

The object set in Model is set in HttpServletRequest. The value passed from Controller can be output by mentioning ${serverTime} in home.jsp as shown below. ( However, as described below, it is necessary to perform HTML escaping since there is possibility of ${XXX} becoming a target of XSS )

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page session="false" %>
<html>
<head>
	<title>Home</title>
</head>
<body>
<h1>
	Hello world!  
</h1>

<P>  The time on the server is ${serverTime}. </P>
</body>
</html>

2.3.3. Run on Server

Right click “helloworld” project in STS, and start helloworld project by executing “Run As” -> “Run On Server” -> “localhost” -> “VMware vFabric tc Server Developer Edition v2.8” -> “Finish”. Enter “http://localhost:8080/helloworld/” in browser to display the following screen.

Hello World

2.3.4. Create an Echo Application

Lets go ahead and reate a simple application. It is a typical eco application in which message will be displayed if name is entered in the text field as given below.

Form of Echo Application
Output of Echo Application

2.3.4.1. Creating a form object

First create a form object to accept the value of text field. Create EchoForm class in com.example.helloworld.echo package. It is a simple JavaBean that has only 1 property.

package com.example.helloworld.echo;

import java.io.Serializable;

public class EchoForm implements Serializable {
    private static final long serialVersionUID = 2557725707095364445L;

    private String name;

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

2.3.4.2. Create a Controller

Next, create the Controller class. create the EchoController class in “com.example.helloworld.echo” package.

package com.example.helloworld.echo;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("echo")
public class EchoController {

    @ModelAttribute // (1)
    public EchoForm setUpEchoForm() {
        EchoForm form = new EchoForm();
        return form;
    }

    @RequestMapping // (2)
    public String index(Model model) {
        return "echo/index"; // (4)
    }

    @RequestMapping("hello") // (5)
    public String hello(EchoForm form, Model model) {// (3)
        model.addAttribute("name", form.getName()); // (6)
        return "echo/hello";
    }
}
Item number Description
(1)
Add @ModelAttribute annotation to the method. Return value of such a method is automatically added to the Model.
Attribute name can be specified in @ModelAttribute, but the class name with the first letter in lower case is the default attribute name.
In this case it will be echoForm. This attribute name must match with the value of modelAttribute of form:form tag.
(2)
When nothing is specified in value attribute of @RequestMapping annotation at the method level, it is mapped to @RequestMapping added at class level.
In this case, index method is called, if <contextPath>/echo is accessed. When nothing is set in method attribute, mapping is done for any HTTP method.
(3)
EchoForm object added to the model in (1) is passed as argument.
(4)
Since echo/index is returned as View name, WEB-INF/views/echo/index.jsp is rendered by ViewResolver.
(5)
Since hello is specified in @RequestMapping annotation at method level, if <contextPath>/echo/hello is accessed, hello method is called.
(6)
name entered in form is passed as it is to the View.

2.3.4.3. Create JSP Files

Finally create JSP of input screen and output screen. Each file path must match with View name as follows.

  • Input Screen src/main/webapp/WEB-INF/views/echo/index.jsp
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://www.springframework.org/tags" prefix="spring"%>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<!DOCTYPE html>
<html>
<head>
<title>Echo Application</title>
</head>
<body>
  <!-- (1) -->
  <form:form modelAttribute="echoForm" action="${pageContext.request.contextPath}/echo/hello">
    <form:label path="name">Input Your Name:</form:label>
    <form:input path="name" />
    <input type="submit" />
  </form:form>
</body>
</html>
Item number Description
(1)
HTML form is constructed by using tag library. Specify the name of form object created by Controller in modelAttribute.
Refer herefor tag library.

The generated HTML is as follows

<body>

  <form id="echoForm" action="/helloworld/echo/hello" method="post">
    <label for="name">Input Your Name:</label>
    <input id="name" name="name" type="text" value=""/>
    <input type="submit" />
  </form>
</body>
</html>
  • Output Screen src/main/webapp/WEB-INF/views/echo/hello.jsp
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://www.springframework.org/tags" prefix="spring"%>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<!DOCTYPE html>
<html>
<head>
<title>Echo Application</title>
</head>
<body>
  <p>
    Hello <c:out value="${name}" />!
  </p>
</body>
</html>

Output name passed from Controller. Take countermeasures for XSS using c:out tag.


Note

Countermeasure for XSS are taken using c:out standard tag here. However, f:h() function that can be used easily is provided in common library. Refer to XSS Countermeasures for details.

Implementation of Eco application is completed here. Start the server, access the link http://localhost:8080/helloworld/echo to access the application.


2.3.4.4. Implement Input Validation

Input validation is not performed in this application till this point. In Spring MVC, Bean Validation (JSR-303) and annotation based input validation can be easily implemented. For example input validation of name is performed in Eco Application.

Following dependency is added to pom.xml for using Bean Validation.

        <!-- Bean Validation (JSR-303) -->
        <dependency>
            <artifactId>hibernate-validator</artifactId>
            <groupId>org.hibernate</groupId>
            <version>4.3.1.Final</version>
        </dependency>

In EchoForm, add @NotNull annotation and @Size annotation to name property as follows (can be added to getter method).

package com.example.helloworld.echo;

import java.io.Serializable;

import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

public class EchoForm implements Serializable {
    private static final long serialVersionUID = 2557725707095364446L;

    @NotNull // (1)
    @Size(min = 1, max = 5) // (2)
    private String name;

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}
Item number Description
(1)
By adding @NotNull annotation, whether name parameter exists in HTTP request is checked.
(2)
By adding @Size(min=1, max=5) annotation, whether the size of name is more than or equal to 1 and less than or equal to 5 is checked.

In EchoController class, add @Valid annotation as shown below and also use of hasErrors method.

package com.example.helloworld.echo;

import javax.validation.Valid;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("echo")
public class EchoController {

    @ModelAttribute
    public EchoForm setUpEchoForm() {
        EchoForm form = new EchoForm();
        return form;
    }

    @RequestMapping
    public String index(Model model) {
        return "echo/index";
    }

    @RequestMapping("hello")
    public String hello(@Valid EchoForm form, BindingResult result, Model model) { // (1)
        if (result.hasErrors()) { // (2)
            return "echo/index";
        }
        model.addAttribute("name", form.getName());
        return "echo/hello";
    }
}
Item number Description
(1)
In Controller, add @Valid annotation to the argument on which validation needs to be executed. Also add BindingResult object to arguments.
Input validation is automatically performed using Bean Validation and the result is stored in BindingResult object.
(2)
It can be checked whether there is error by using hasErrors method.
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://www.springframework.org/tags" prefix="spring"%>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<!DOCTYPE html>
<html>
<head>
<title>Echo Application</title>
</head>
<body>
  <form:form modelAttribute="echoForm" action="${action}">
    <form:label path="name">Input Your Name:</form:label>
    <form:input path="name" />
    <form:errors path="name" cssStyle="color:red" /><!-- (1) -->
    <input type="submit" />
  </form:form>
</body>
</html>
Item number Description
(1)
Add form:errors tag for displaying error message when an error occurs on input screen.
Implementation of input validation is completed.
Error message is displayed in the following conditions:
  • When an empty name is sent
  • Size is more than 5 characters.
Validation Error (name is empty)
Validation Error (name's size is over 5)

The generated HTML is as follows

<body>

  <form id="echoForm" action="/helloworld/echo/hello" method="post">
    <label for="name">Input Your Name:</label>
    <input id="name" name="name" type="text" value=""/>
    <span id="name.errors" style="color:red">size must be between 1 and 5</span>
    <input type="submit" />
  </form>
</body>
</html>

2.3.4.5. Summary

The following are the learnings from this chapter.

  1. Setting up configuration file of Spring MVC (simplified level)
  2. How to do Screen Transition (simplified level)
  3. Way to pass values between screens.
  4. Simple input validation

If above points are still not understood, it is recommended to read this chapter again and start again from building the environment. This will imporve the understanding of above concepts.