Spring Tutorial

springmvc

How can we create a new SpringMVC project using SpringSource Tool Suite?

  1. Launch SpringSource Tool Suite
  2. From the top menu, select File -> New -> Spring Project
  3. In the new project window, give name as “SpringMVCExample” and chose template as “Spring MVC Project”. If you are using this template for the first time, STS will download it from SpringSource website. If you want, you can add the project to any working set.
  4. When the template is downloaded, in next screen you need to provide the top-level package name. This package will be used as the base-package for Spring components.
  5. If your project is not compiled and you see some errors, run Maven/Update Project. Make sure to check the “Force update of Snapshots/Releases” options. Overall project looks just like any other maven based web application with some Spring configuration files.

The above steps create the Maven pom.xml file, with the necessary dependencies. However, if we need to add more dependencies later on, we can always edit this Maven pom.xml file. The artifactId will be the servlet-context for the web application, so you can change it if you want something else.

The project dependencies that we are interested in are:

  1. spring-context: Spring Core dependency. Notice the exclusion of commons logging in favor of SLF4J.
  2. spring-webmvc: Spring artifact for MVC support
  3. aspectjrt: AspectJ API reference
  4. SLF4J and Log4j: For logging purposes, Spring is very easy to configure for log4j or Java Logging API because of SLF4J integration.
  5. javax.inject – JSR330 API for dependency injection

The above steps also generate:

  1. log4j.xml file: Notice that it’s printing everything to console, we can easily add appenders to redirect logging to files.
  2. web.xml file: The ContextLoaderListener ties the ApplicationContext lifecycle to ServletContext lifecycle and automate the creation of ApplicationContext. ApplicationContext is the place for Spring beans and we can provide it’s configuration through contextConfigLocation context parameter. root-context.xml file provides the configuration details for WebApplicationContext. DispatcherServlet is the controller class for Spring MVC application and all the client requests is getting handled by this servlet. The configuration are being loaded from servlet-context.xml file.
  3. root-context.xml file: We can define shared beans here.
  4. servlet-context.xml file: annotation-driven element is used to let Controller servlet know that annotations will be used for bean configurations. resources element defines the location where we can put static files such as images, html pages etc that we don’t want to get through Spring framework. InternalResourceViewResolver is the view resolver, we can provide view pages location through prefix and suffix properties. So all our JSP pages should be in /WEB-INF/views/ directory. context:component-scan element is used to provide the base-package location for scanning Controller classes. Remember the value of top-level package given at the time of project creation, it’s the same value getting used here.

HomeController is created automatically with the home() method, although I have extended it little bit by adding loginPage() and login() methods.

package com.journaldev.spring;

import java.text.DateFormat;
import java.util.Date;
import java.util.Locale;

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

/**
 * Handles requests for the application home page.
 */
@Controller
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)
    public String home(Locale locale, Model model) {
        logger.info("Welcome home! The client locale is {}.", locale);

        Date date = new Date();
        DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);

        String formattedDate = dateFormat.format(date);

        model.addAttribute("serverTime", formattedDate );

        return "home";
    }

    @RequestMapping(value = "/login", method = RequestMethod.GET)
    public String loginPage(Locale locale, Model model) {
        return "login";
    }

    @RequestMapping(value = "/home", method = RequestMethod.POST)
    public String login(@Validated User user, Model model) {
        model.addAttribute("userName", user.getUserName());
        return "user";
    }
}

@Controller annotation is used to indicate that it’s a web controller class.

@RequestMapping is used with classes and methods to redirect client request to specific handler method. Notice that handler methods are returning String, this should be the name of view page to be used as response.

As you can see that we are having three methods returning different strings, so we need to create JSP pages with same name.

Notice that login() method will get called with HTTP method as POST, so we are expecting some form data here. So we have User model class and it’s marked for validation using @Validated annotation.

Every method contains Model as argument and we can set attributes to be later used in the JSP response pages.

Spring MVC Model Classes. Model classes are used to hold form variables, our User model bean looks like below.

package com.journaldev.spring;

public class User {
    private String userName;
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }    
}

A model is a simple java bean with variable name and it’s getter and setter methods.

View Pages. We have three JSP pages like below. home.jsp code:

<%@ 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>

Notice the use of JSP Expression Language to get the attribute values. login.jsp code:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!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=UTF-8">
<title>Login Page</title>
</head>
<body>
<form action="home" method="post">
<input type="text" name="userName"><br>
<input type="submit" value="Login">
</form>
</body>
</html>

A simple JSP page for user to provide the userName as input. Notice that form variable name is same as User class variable name. Also form action is “home” and method is “post”. It’s clear that HomeController login() method will handle this request. user.jsp code:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!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=UTF-8">
<title>User Home Page</title>
</head>
<body>
<h3>Hi ${userName}</h3>
</body>
</html>

Simple home page for user where username is displayed, notice that we are setting this attribute in the login method. Our application is ready for execution, just run it on the VMware tc Server or your choice of any other servlet container.

In Spring Web MVC, DispatcherServlet class works as the front controller. It is responsible to manage the flow of the spring mvc application. The @Controller annotation is used to mark the class as the controller in Spring 3. The @RequestMapping annotation is used to map the request url. It is applied on the method.

All the incoming request is intercepted by the DispatcherServlet that works as the front controller. The DispatcherServlet gets entry of handler mapping from the xml file and forwards the request to the controller. The controller returns an object of ModelAndView. The DispatcherServlet checks the entry of view resolver in the xml file and invokes the specified view component.

  1. Create the request page (optional)
  2. Create the controller class
  3. Provide the entry of controller in the web.xml file
  4. Define the bean in the xml file
  5. Display the message in the JSP page
  6. Load the spring core and mvc jar files
  7. Start server and deploy the project

Create the request page (optional). This is the simple jsp page containing a link. It is optional page. You may direct invoke the action class instead. index.jsp: <a href="hello.html">click</a>

Create the controller class. To create the controller class, we are using two annotations @Controller and @RequestMapping. The @Controller annotation marks this class as Controller. The @Requestmapping annotation is used to map the class with the specified name. This class returns the instance of ModelAndView controller with the mapped name, message name and message value. The message value will be displayed in the jsp page. HelloWorldController.java:

package com.javatpoint;  
import org.springframework.stereotype.Controller;  
import org.springframework.web.bind.annotation.RequestMapping;  
import org.springframework.web.servlet.ModelAndView;  
@Controller  
public class HelloWorldController {  
    @RequestMapping("/hello")  
    public ModelAndView helloWorld() {  
        String message = "HELLO SPRING MVC HOW R U";  
        return new ModelAndView("hellopage", "message", message);  
    }  
}

Provide the entry of controller in the web.xml file. web.xml:

<?xml version="1.0" encoding="UTF-8"?>  
<web-app version="2.5"   
    xmlns="http://java.sun.com/xml/ns/javaee"   
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee   
    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">  
 <servlet>  
    <servlet-name>spring</servlet-name>  
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>  
    <load-on-startup>1</load-on-startup>  
</servlet>  
<servlet-mapping>  
    <servlet-name>spring</servlet-name>  
    <url-pattern>*.html</url-pattern>  
</servlet-mapping>  
</web-app>

In this xml file, we are specifying the servlet class DispatcherServlet that acts as the front controller in Spring Web MVC. All the incoming request for the html file will be forwarded to the DispatcherServlet.

Define the bean in the xml file. This is the important configuration file where we need to specify the ViewResolver and View components. The context:component-scan element defines the base-package where DispatcherServlet will search the controller class. Here, the InternalResourceViewResolver class is used for the ViewResolver. The prefix+string returned by controller+suffix page will be invoked for the view component. This xml file should be located inside the WEB-INF directory. spring-servlet.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"  
    xmlns:p="http://www.springframework.org/schema/p"  
    xmlns:context="http://www.springframework.org/schema/context"  
    xsi:schemaLocation="http://www.springframework.org/schema/beans  
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
http://www.springframework.org/schema/context  
http://www.springframework.org/schema/context/spring-context-3.0.xsd">  
    <context:component-scan  base-package="com.javatpoint" />  
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">  
        <property name="prefix" value="/WEB-INF/jsp/" />  
        <property name="suffix" value=".jsp" />  
    </bean>  
</beans>

Display the message in the JSP page. This is the simple JSP page, displaying the message returned by the Controller. It must be located inside the WEB-INF/jsp directory for this example only. hellopage.jsp:

Message is: ${message}

We can have a lot of controller classes. HelloWorldController.java:

package com.javatpoint;  
import org.springframework.stereotype.Controller;  
import org.springframework.web.bind.annotation.RequestMapping;  
import org.springframework.web.servlet.ModelAndView;  

@Controller  
public class HelloWorldController {  
    @RequestMapping("/hello")  
    public ModelAndView helloWorld() {  
        String message = "HELLO SPRING MVC";  
        return new ModelAndView("hellopage", "message", message);  
    }    
}

WelcomeWorldController.java:

package com.javatpoint;  
import org.springframework.stereotype.Controller;  
import org.springframework.web.bind.annotation.RequestMapping;  
import org.springframework.web.servlet.ModelAndView;  

@Controller  
public class WelcomeWorldController {  
    @RequestMapping("/welcome")  
    public ModelAndView helloWorld() {  
        String message = "WELCOME SPRING MVC";  
        return new ModelAndView("welcomepage", "message", message);  
    }    
}
@Controller  
public class HelloWorldController {  

    @RequestMapping("/hello")  
    public ModelAndView helloWorld(HttpServletRequest request,HttpServletResponse res) {  
        String name=request.getParameter("name");  
        String password=request.getParameter("password");  

        if(password.equals("admin")){  
            String message = "HELLO "+name;  
            return new ModelAndView("hellopage", "message", message);  
        }  else{  
            return new ModelAndView("errorpage", "message","Sorry, username or password error");  
        }  
    }  

}

Here, we will learn how to handle a form data in spring MVC without using database. Here, we will use @Controler, @RequestMapping and @ModelAttribute annotations. To display the input form, we are going to use <form:form> tag of spring framework. Let's see a simple example to store form data in a model object and display data of a list.

package com.javatpoint.beans;  
public class Emp {  
private int id;  
private String name;  
private float salary;  
private String designation;  

public Emp() {}  

public Emp(int id, String name, float salary, String designation) {  
    super();  
    this.id = id;  
    this.name = name;  
    this.salary = salary;  
    this.designation = designation;  
}  

public int getId() {  
    return id;  
}  
public void setId(int id) {  
    this.id = id;  
}  
public String getName() {  
    return name;  
}  
public void setName(String name) {  
    this.name = name;  
}  
public float getSalary() {  
    return salary;  
}  
public void setSalary(float salary) {  
    this.salary = salary;  
}  
public String getDesignation() {  
    return designation;  
}  
public void setDesignation(String designation) {  
    this.designation = designation;  
}  

}
package com.javatpoint.controllers;  

import java.util.ArrayList;  
import java.util.List;  
import org.springframework.stereotype.Controller;  
import org.springframework.web.bind.annotation.ModelAttribute;  
import org.springframework.web.bind.annotation.RequestMapping;  
import org.springframework.web.bind.annotation.RequestMethod;  
import org.springframework.web.servlet.ModelAndView;  
import com.javatpoint.beans.Emp;  
@Controller  
public class EmpController {  

    @RequestMapping("/empform")  
    public ModelAndView showform(){  
         //command is a reserved request attribute name, now use <form> tag to show object data  
        return new ModelAndView("empform","command",new Emp());  
    }  
    @RequestMapping(value="/save",method = RequestMethod.POST)  
    public ModelAndView save(@ModelAttribute("emp") Emp emp){  
        //write code to save emp object  
        //here, we are displaying emp object to prove emp has data  
        System.out.println(emp.getName()+" "+emp.getSalary()+" "+emp.getDesignation());  

        //return new ModelAndView("empform","command",emp);//will display object data  
        return new ModelAndView("redirect:/viewemp");//will redirect to viewemp request mapping  
    }  

    @RequestMapping("/viewemp")  
    public ModelAndView viewemp(){  
        //write the code to get all employees from DAO  
        //here, we are writing manual code of list for easy understanding  
        List<Emp> list=new ArrayList<Emp>();  
        list.add(new Emp(1,"rahul",35000f,"S.Engineer"));  
        list.add(new Emp(2,"aditya",25000f,"IT Manager"));  
        list.add(new Emp(3,"sachin",55000f,"Care Taker"));  

        return new ModelAndView("viewemp","list",list);  
    }  
}

empform.jsp:

<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%>    
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>    

       <form:form method="post" action="save">    
        <table >    
         <tr>    
          <td>Name : </td>   
          <td><form:input path="name"  /></td>  
         </tr>    
         <tr>    
          <td>Salary :</td>    
          <td><form:input path="salary" /></td>  
         </tr>   
         <tr>    
          <td>Designation :</td>    
          <td><form:input path="designation" /></td>  
         </tr>   
         <tr>    
          <td colspan="2"><input type="submit" value="Save" /></td>    
         </tr>    
        </table>    
       </form:form>

viewemp.jsp:

<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%>    
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>    
<table border="2" width="70%" cellpadding="2">  
  <tr><th>Id</th><th>Name</th><th>Salary</th><th>Designation</th></tr>  
   <c:forEach var="emp" items="${list}">   
     <tr>  
       <td>${emp.id}</td>  
       <td>${emp.name}</td>  
       <td>${emp.salary}</td>  
       <td>${emp.designation}</td>  
     </tr>  
   </c:forEach>  
</table>

CRUD (Create, Read, Update and Delete) application is the most important application for creating any project. It provides an idea to develop a large project. In spring MVC, we can develop a simple CRUD application. Here, we are using JdbcTemplate for database interaction.

EmpDao.java:

package com.javatpoint.dao;  
import java.sql.ResultSet;  
import java.sql.SQLException;  
import java.util.List;  
import org.springframework.jdbc.core.BeanPropertyRowMapper;  
import org.springframework.jdbc.core.JdbcTemplate;  
import org.springframework.jdbc.core.RowMapper;  
import com.javatpoint.beans.Emp;  

public class EmpDao {  
JdbcTemplate template;  

public void setTemplate(JdbcTemplate template) {  
    this.template = template;  
}  
public int save(Emp p){  
    String sql="insert into Emp99(name,salary,designation)   
          values('"+p.getName()+"',"+p.getSalary()+",'"+p.getDesignation()+"')";  
    return template.update(sql);  
}  
public int update(Emp p){  
    String sql="update Emp99 set name='"+p.getName()+"', salary="+p.getSalary()+",   
          designation='"+p.getDesignation()+"' where id="+p.getId()+"";  
    return template.update(sql);  
}  
public int delete(int id){  
    String sql="delete from Emp99 where id="+id+"";  
    return template.update(sql);  
}  
public Emp getEmpById(int id){  
    String sql="select * from Emp99 where id=?";  
    return template.queryForObject(sql, new Object[]{id},new BeanPropertyRowMapper<Emp>(Emp.class));  
}  
public List<Emp> getEmployees(){  
    return template.query("select * from Emp99",new RowMapper<Emp>(){  
        public Emp mapRow(ResultSet rs, int row) throws SQLException {  
            Emp e=new Emp();  
            e.setId(rs.getInt(1));  
            e.setName(rs.getString(2));  
            e.setSalary(rs.getFloat(3));  
            e.setDesignation(rs.getString(4));  
            return e;  
        }  
    });  
}  
}

EmpController.java:

@Controller  
public class EmpController {  
    @Autowired  
    EmpDao dao;//will inject dao from xml file  

    /*It displays a form to input data, here "command" is a reserved request attribute 
     *which is used to display object data into form 
     */  
    @RequestMapping("/empform")  
    public ModelAndView showform(){  
        return new ModelAndView("empform","command",new Emp());  
    }  
    /*It saves object into database. The @ModelAttribute puts request data 
     *  into model object. You need to mention RequestMethod.POST method  
     *  because default request is GET*/  
    @RequestMapping(value="/save",method = RequestMethod.POST)  
    public ModelAndView save(@ModelAttribute("emp") Emp emp){  
        dao.save(emp);  
        return new ModelAndView("redirect:/viewemp");//will redirect to viewemp request mapping  
    }  
    /* It provides list of employees in model object */  
    @RequestMapping("/viewemp")  
    public ModelAndView viewemp(){  
        List<Emp> list=dao.getEmployees();  
        return new ModelAndView("viewemp","list",list);  
    }  
    /* It displays object data into form for the given id.  
     * The @PathVariable puts URL data into variable.*/  
    @RequestMapping(value="/editemp/{id}")  
    public ModelAndView edit(@PathVariable int id){  
        Emp emp=dao.getEmpById(id);  
        return new ModelAndView("empeditform","command",emp);  
    }  
    /* It updates model object. */  
    @RequestMapping(value="/editsave",method = RequestMethod.POST)  
    public ModelAndView editsave(@ModelAttribute("emp") Emp emp){  
        dao.update(emp);  
        return new ModelAndView("redirect:/viewemp");  
    }  
    /* It deletes record for the given id in URL and redirects to /viewemp */  
    @RequestMapping(value="/deleteemp/{id}",method = RequestMethod.GET)  
    public ModelAndView delete(@PathVariable int id){  
        dao.delete(id);  
        return new ModelAndView("redirect:/viewemp");  
    }  
}

spring-servlet.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"    
    xmlns:p="http://www.springframework.org/schema/p"    
    xmlns:context="http://www.springframework.org/schema/context"    
    xsi:schemaLocation="http://www.springframework.org/schema/beans    
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd    
http://www.springframework.org/schema/context    
http://www.springframework.org/schema/context/spring-context-3.0.xsd">    

<context:component-scan base-package="com.javatpoint.controllers"></context:component-scan>  

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

<bean id="ds" class="org.springframework.jdbc.datasource.DriverManagerDataSource">  
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"></property>  
<property name="url" value="jdbc:oracle:thin:@localhost:1521:xe"></property>  
<property name="username" value="system"></property>  
<property name="password" value="oracle"></property>  
</bean>  

<bean id="jt" class="org.springframework.jdbc.core.JdbcTemplate">  
<property name="dataSource" ref="ds"></property>  
</bean>  

<bean id="dao" class="com.javatpoint.dao.EmpDao">  
<property name="template" ref="jt"></property>  
</bean>  
</beans>

empform.jsp:

<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%>    
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>    

        <h1>Add New Employee</h1>  
       <form:form method="post" action="save">    
        <table >    
         <tr>    
          <td>Name : </td>   
          <td><form:input path="name"  /></td>  
         </tr>    
         <tr>    
          <td>Salary :</td>    
          <td><form:input path="salary" /></td>  
         </tr>   
         <tr>    
          <td>Designation :</td>    
          <td><form:input path="designation" /></td>  
         </tr>   
         <tr>    
          <td> </td>    
          <td><input type="submit" value="Save" /></td>    
         </tr>    
        </table>    
       </form:form>

empeditform.jsp. Here "/SpringMVCCRUDSimple" is the project name, change this if you have different project name. For live application, you can provide full URL.

<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%>    
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>    

        <h1>Edit Employee</h1>  
       <form:form method="POST" action="/SpringMVCCRUDSimple/editsave">    
        <table >    
        <tr>  
        <td></td>    
         <td><form:hidden  path="id" /></td>  
         </tr>   
         <tr>    
          <td>Name : </td>   
          <td><form:input path="name"  /></td>  
         </tr>    
         <tr>    
          <td>Salary :</td>    
          <td><form:input path="salary" /></td>  
         </tr>   
         <tr>    
          <td>Designation :</td>    
          <td><form:input path="designation" /></td>  
         </tr>   

         <tr>    
          <td> </td>    
          <td><input type="submit" value="Edit Save" /></td>    
         </tr>    
        </table>    
       </form:form>

viewemp.jsp:

<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%>    
   <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>    

<h1>Employees List</h1>  
<table border="2" width="70%" cellpadding="2">  
<tr><th>Id</th><th>Name</th><th>Salary</th><th>Designation</th><th>Edit</th><th>Delete</th></tr>  
   <c:forEach var="emp" items="${list}">   
   <tr>  
   <td>${emp.id}</td>  
   <td>${emp.name}</td>  
   <td>${emp.salary}</td>  
   <td>${emp.designation}</td>  
   <td><a href="editemp/${emp.id}">Edit</a></td>  
   <td><a href="deleteemp/${emp.id}">Delete</a></td>  
   </tr>  
   </c:forEach>  
   </table>  
   <br/>  
   <a href="empform">Add New Employee</a>

Pagination. Pagination is used to display large number of records in different parts. In such case, we display 10, 20 or 50 records in one page. For remaining records, we provide links.

public class EmpDao {  
JdbcTemplate template;  

public void setTemplate(JdbcTemplate template) {  
    this.template = template;  
}  

public List<Emp> getEmployeesByPage(int pageid,int total){  
    String sql="select * from Emp limit "+(pageid-1)+","+total;  
    return template.query(sql,new RowMapper<Emp>(){  
        public Emp mapRow(ResultSet rs, int row) throws SQLException {  
            Emp e=new Emp();  
            e.setId(rs.getInt(1));  
            e.setName(rs.getString(2));  
            e.setSalary(rs.getFloat(3));  
            return e;  
        }  
    });  
}  
}
@Controller  
public class EmpController {  
    @Autowired  
    EmpDao dao;  

    @RequestMapping(value="/viewemp/{pageid}")  
    public ModelAndView edit(@PathVariable int pageid){  
        int total=5;  
        if(pageid==1){}  
        else{  
            pageid=(pageid-1)*total+1;  
        }  
        List<Emp> list=dao.getEmployeesByPage(pageid,total);  

        return new ModelAndView("viewemp","list",list);  
    }  
}

Spring MVC File Upload. Add commons-io and fileupload.jar files. Add entry of CommonsMultipartResolver in spring-servlet.xml.

<bean id="multipartResolver" 
  class="org.springframework.web.multipart.commons.CommonsMultipartResolver"/>

Create form to submit file. Method name must be "post" and enctype "multiple/form-data":

<form action="savefile" method="post" enctype="multipart/form-data">  
  Select File: <input type="file" name="file"/>  
  <input type="submit" value="Upload File"/>  
</form>

Use CommonsMultipartFile class in Controller:

@RequestMapping(value="/savefile",method=RequestMethod.POST)  
public ModelAndView upload(@RequestParam CommonsMultipartFile file,HttpSession session){  
        String path=session.getServletContext().getRealPath("/");  
        String filename=file.getOriginalFilename();  

        System.out.println(path+" "+filename);  
        try{  
        byte barr[]=file.getBytes();  

        BufferedOutputStream bout=new BufferedOutputStream(  
                 new FileOutputStream(path+"/"+filename));  
        bout.write(barr);  
        bout.flush();  
        bout.close();  

        }catch(Exception e){System.out.println(e);}  
        return new ModelAndView("upload-success","filename",path+"/"+filename);  
    }

Display image in JSP:

<h1>Upload Success</h1>  
<img src="${filename}"/>
@Controller  
public class HelloController {  
    private static final String UPLOAD_DIRECTORY ="/images";  

    @RequestMapping("uploadform")  
    public ModelAndView uploadForm(){  
        return new ModelAndView("uploadform");    
    }  

    @RequestMapping(value="savefile",method=RequestMethod.POST)  
    public ModelAndView saveimage( @RequestParam CommonsMultipartFile file,  
           HttpSession session) throws Exception{  

    ServletContext context = session.getServletContext();  
    String path = context.getRealPath(UPLOAD_DIRECTORY);  
    String filename = file.getOriginalFilename();  

    System.out.println(path+" "+filename);        

    byte[] bytes = file.getBytes();  
    BufferedOutputStream stream =new BufferedOutputStream(new FileOutputStream(  
         new File(path + File.separator + filename)));  
    stream.write(bytes);  
    stream.flush();  
    stream.close();  

    return new ModelAndView("uploadform","filesuccess","File successfully saved!");  
    }  
}

Advantage of Tiles support in Spring MVC:

  1. Reusability: We can reuse a single component in multiple pages like header and footer components.
  2. Centralized control: We can control the layout of the page by a single template page only.
  3. Easy to change the layout: By the help of single template page, we can change the layout of the page anytime. So your website can easily adapt new technologies such as bootstrap, jquery etc.
@Controller  
public class HelloWorldController {  
    @RequestMapping("/hello")  
    public ModelAndView helloWorld() {  
        String message = "Hello World, Spring MVC @ Javatpoint";  
        return new ModelAndView("hello", "message", message);  
    }  
}
@Controller  
@SessionAttributes  
public class ContactController {  
    @RequestMapping(value = "/addContact", method = RequestMethod.POST)  
    public String addContact(@ModelAttribute("contact") Contact contact, BindingResult result) {  
        //write the code here to add contact  
        return "redirect:contact.html";  
    }  

    @RequestMapping("/contact")  
    public ModelAndView showContacts() {  
        return new ModelAndView("contact", "command", new Contact());  
    }  
}

spring-servlet.xml file. This is the important configuration file where we need to specify the ViewResolver and View components. The context:component-scan element defines the base-package where DispatcherServlet will search the controller class. Here, the UrlBasedViewResolver class is used for the ViewResolver. The prefix+string returned by controller+suffix page will be invoked for the view component. This xml file should be located inside the WEB-INF directory.

 <beans xmlns="http://www.springframework.org/schema/beans"  
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
    xmlns:p="http://www.springframework.org/schema/p"  
    xmlns:context="http://www.springframework.org/schema/context"  
    xsi:schemaLocation="http://www.springframework.org/schema/beans  
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
        http://www.springframework.org/schema/context  
        http://www.springframework.org/schema/context/spring-context-3.0.xsd">  

    <context:component-scan  
        base-package="com.javatpoint.controller" />  

    <bean id="viewResolver"  
        class="org.springframework.web.servlet.view.UrlBasedViewResolver">  
        <property name="viewClass">  
            <value>  
                org.springframework.web.servlet.view.tiles2.TilesView  
            </value>  
        </property>  
    </bean>  
    <bean id="tilesConfigurer"  
        class="org.springframework.web.servlet.view.tiles2.TilesConfigurer">  
        <property name="definitions">  
            <list>  
                <value>/WEB-INF/tiles.xml</value>  
            </list>  
        </property>  
    </bean>  
</beans>

tiles.xml:

<?xml version="1.0" encoding="UTF-8" ?>  
<!DOCTYPE tiles-definitions PUBLIC  
       "-//Apache Software Foundation//DTD Tiles Configuration 2.0//EN"  
       "http://tiles.apache.org/dtds/tiles-config_2_0.dtd">  
<tiles-definitions>  
    <definition name="base.definition"  
        template="/WEB-INF/jsp/layout.jsp">  
        <put-attribute name="title" value="" />  
        <put-attribute name="header" value="/WEB-INF/jsp/header.jsp" />  
        <put-attribute name="menu" value="/WEB-INF/jsp/menu.jsp" />  
        <put-attribute name="body" value="" />  
        <put-attribute name="footer" value="/WEB-INF/jsp/footer.jsp" />  
    </definition>  

    <definition name="contact" extends="base.definition">  
        <put-attribute name="title" value="Contact Manager" />  
        <put-attribute name="body" value="/WEB-INF/jsp/contact.jsp" />  
    </definition>  

    <definition name="hello" extends="base.definition">  
        <put-attribute name="title" value="Hello Spring MVC" />  
        <put-attribute name="body" value="/WEB-INF/jsp/hello.jsp" />  
    </definition>  

</tiles-definitions>

hello.jsp:

<html>  
<head>  
    <title>Spring MVC Example</title>  
</head>  
<body>  
<h1>Welcome to Spring MVC</h1>  
    <p>Message is: ${message}</p>  
</body>  
</html>

contact.jsp:

<%@taglib uri="http://www.springframework.org/tags/form" prefix="form"%>  
<html>  
<head>  
    <title>Spring Tiles Contact Form</title>  
</head>  
<body>  
<h2>Contact Manager</h2>  
<form:form method="post" action="addContact.html">  

    <table>  
    <tr>  
        <td><form:label path="firstname">First Name</form:label></td>  
        <td><form:input path="firstname" /></td>   
    </tr>  
    <tr>  
        <td><form:label path="lastname">Last Name</form:label></td>  
        <td><form:input path="lastname" /></td>  
    </tr>  
    <tr>  
        <td><form:label path="lastname">Email</form:label></td>  
        <td><form:input path="email" /></td>  
    </tr>  
    <tr>  
        <td><form:label path="lastname">Telephone</form:label></td>  
        <td><form:input path="telephone" /></td>  
    </tr>  
    <tr>  
        <td colspan="2">  
            <input type="submit" value="Add Contact"/>  
        </td>  
    </tr>  
</table>    

</form:form>  
</body>  
</html>

header.jsp:

<h2>Header</h2>  
<hr/>

footer.jsp:

<hr/>  
<p>Copyright  2010-2014 javatpoint.com.</p>

menu.jsp:

<p>Menu 1</p>  
<p>Menu 2</p>

layout.jsp:

<%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles"%>  
<!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=UTF-8">  
<title><tiles:insertAttribute name="title" ignore="true" /></title>  
</head>  
<body>  
        <div><tiles:insertAttribute name="header" /></div>  
        <div style="float:left;padding:10px;width:15%;"><tiles:insertAttribute name="menu" /></div>  
        <div style="float:left;padding:10px;width:80%;border-left:1px solid pink;">  
        <tiles:insertAttribute name="body" /></div>  
        <div style="clear:both"><tiles:insertAttribute name="footer" /></div>  
</body>  
</html>

Rather than implementing presentation code inside servlets, JSPs lets you build HTML-like documents that interweave snippets of Java code to support dynamic content. At runtime, JSPs are translated to servlet source code, compiled, and then deployed to a Web container dynamically. If you change any part of the JSP, the container detects the change, recompiles the page, and redeploys it. This architecture was called page-driven or Model 1.

In page-driven applications, each page not only contains the business logic required to generate the dynamic content, but also the control logic to determine application flow. Control logic became difficult to maintain because there was no central location or design paradigm to help you understand how a user passed from one page to the next. And as business requirements evolved to include features like authentication and authorization, page code became convoluted with additional logic that usually had to be duplicated across pages, even if it was irrelevant to the page being constructed. On a site with 1,000 pages, all with authorization mechanisms, who wants to update all 1,000 pages when those authorization mechanisms change?

Servlets are great for writing Java code, acting as a central point for managing application flow and invoking business methods, but horrible at presentation; JSPs are great at presentation but are a horrible place to embed all of your business logic. Thus was born the Model 2 architecture, which adheres to the MVC Smalltalk design pattern:

  1. The model represents your data or the objects with which your application is interacting.
  2. The view is a visualization of your model.
  3. The controller manages application flow and makes calls into business objects.

In Java systems, the model is typically a loose JavaBean, or Plain Old Java Object (POJO) that has getters and setters to manipulate its contents. It can be a very simple object or a very complicated one with dozens of subobjects, but it's just an object nonetheless.

The view is usually a JSP page, but countless other technologies and templating languages can be used, such as FreeMarker, Velocity, XML/XSLT, JasperReports, and so on. After the business logic is complete and the model has been generated, the controller passes the model to the view to be presented to the user.

The controller is typically implemented by a servlet that calls into business services to perform some action. The controller usually hosts additional logic such as authentication and authorization: it controls which actions a user can execute. For example, you might not allow a user who hasn't first logged in to post a message to a message board. If the controller notices that the user is trying to access the "post" page, it redirects the user to a login page first.

In a Spring MVC architecture, you implement controllers that make calls into Spring service beans to perform business actions and then send a model object to one of your views for presentation. But I'm getting a bit ahead of myself. First we'll do a quick high-level review of Spring.

During the early days of Enterprise JavaBeans (EJB), developers led by Rod Johnson created the Spring Framework as a lightweight alternative to Java EE's complexity. Spring is many things — entire books have been written about it — but one of the key benefits that it pioneered is dependency injection (DI). DI is a design pattern, coined by Martin Fowler, that separates an application's dependencies (and dependency configuration) from the code that uses those dependencies. Spring implements DI by allowing you to "wire" together an application from beans, using either an XML configuration file or annotations. For example, if your application needs to access a database, you can configure your database connection pool in a Spring configuration file and tell Spring to "inject" a DataSource from that pool into your data-access object (DAO) bean; then you can inject that DAO into a service bean. The point is that your application should focus on solving its business problems rather than on the overhead required to construct resources and objects. Spring creates your objects for you and makes them available at runtime.

Another important point to understand about DI is how your objects are written. Consider a service bean that accesses a DAO object for data persistence:

public class MyService {
   private MyDao dao;
   public void setMyDao( MyDao dao ) {
      this.dao = dao;
   }
   public Widget businessMethod() {
      return dao.doBusinessThing();
   }
}

In traditional applications you would probably create a DAO factory object that, through a configuration file, creates the appropriate instance of the DAO on your behalf. In this example, Spring creates the correct MyDao instance (as you define it in the configuration file), creates the MyService object, and invokes the setMyDao() method to inject the DAO into the service. You write your application assuming that the DAO object is valid and is the correct implementation. Your service bean should not be concerned with creating the DAO object, but rather with invoking the correct method on the DAO object to accomplish the business objective.

The core business value in adopting Spring is the separation between code and configuration, which leads to a more manageable application.

The aptly named Spring MVC is a full MVC implementation that follows the patterns and paradigms that Spring is known for, including DI. Spring provides a front controller servlet named DispatcherServlet. To build an application, you construct the following components:

  1. One or more controllers that invoke business logic and create a ModelAndView object
  2. A visualization component such as a JSP
  3. XML or annotation configuration to wire the components together

Spring provides various controllers for you to use as base classes for creating your own controllers, depending on your needs. Among them are ones that:

  1. Redirect to static views
  2. Provide basic servlet-like functionality
  3. Process commands
  4. Process shared actions
  5. Handle forms
  6. Provide wizard-like functionality to process multipage forms

The rest of this article will be a hands-on introduction to Spring MVC, by way of a programming exercise. Together, we'll build a CMS that presents a list of articles, allows users to read articles, and allows users to post new articles. It's simple, but it demonstrates how to use a basic controller that accepts no parameters, a command controller that accepts the identifier of an article to display, and a form controller that processes an article submission.

package com.geekcap.geeknews.web;

import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractController;
import com.geekcap.geeknews.core.GeekNewsService;
import com.geekcap.geeknews.core.NewsArticle;

/**
 * The HomePageController is responsible for building the model of data to display
 * on the home page, which at this point contains a list of article overviews.
 * 
 * @author shaines
 *
 */
public class HomePageController extends AbstractController {
   /**
    * Provides access to GeekNews business methods
    */
   private GeekNewsService service;

   /**
    * Responsible for translating a web request into a ModelAndView object for presentation
    */
   @Override
   protected ModelAndView handleRequestInternal(HttpServletRequest req, HttpServletResponse res) throws Exception {

      // Use the service to load the articles
      List<NewsArticle> articles = service.getArticleOverviews();

      // Send the articles to the "home" view
      return new ModelAndView( "home", "articles", articles );
   }

   /**
    * Injected by Spring
    * @param service
    */
   public void setGeekNewsService( GeekNewsService service ) {
      this.service = service;
   }
}

The above controller accepts no request parameters and returns a ModelAndView object that contains a list of news articles.

The HomePageController extends Spring's AbstractController, which provides simple servlet-like functionality. It implements a single method — handleRequestInternal() — which accepts HttpServletRequest and HttpServletResponse objects, just as a servlet's service() method would. You could read parameters from the HttpServletRequest, but later I'll show you an easier alternative. The purpose of the AbstractController is to invoke business functionality and to generate a ModelAndView object from it.

In MVC vernacular, the model and view are separate entities, so you might wonder why a ModelAndView object seemingly pairs the two. In Spring MVC, the ModelAndView object is a container that hosts the model and provides insight to Spring's view resolver about how to locate the view. In the HomePageController, the ModelAndView is created with three parameters:

  1. "home": The message that is sent to the view resolver to tell it to show the page identified by home (which I'll explain below).
  2. "articles": An identifier for the model. When the view receives the model, it will be able to access it in the request through the "articles" key.
  3. articles: The model itself.

The business logic, in this case, is delegated to the GeekNewsService, which Spring injects after it creates the HomePageController (shown below). With the HomePageController built and a service bean that can be used to access back-end data, let's review the configuration of a Spring MVC application to observe how a request arrives at the Web container and then makes its way to the controller.

The primary entry point for a Spring application is the DispatcherServlet, so this first step is to create a DispatcherServlet in the web.xml file:

<servlet>
  <servlet-name>geeknews</servlet-name>
  <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  <load-on-startup>1</load-on-startup>
</servlet>

Next, that DispatcherServlet needs to be mapped to a URI pattern. You can choose any pattern that you want, but most Spring applications map requests to pages ending in .htm. Add the following to your web.xml file:

<servlet-mapping>
  <servlet-name>geeknews</servlet-name>
  <url-pattern>*.htm</url-pattern>
</servlet-mapping>

In this case, all requests that end in .htm will be sent to the geeknews DispatcherServlet. By default, Spring looks for your Spring beans in a file whose name starts with the servlet name followed by -servlet.xml. So we need to create a geeknews-servlet.xml file that contains the HomePageController, our URL mapping strategy (to map URLs to controllers), and our view resolver, and place it in the WEB-INF directory. Listing 2 shows the contents of the geeknews-servlet.xml file.

geeknews-servlet.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"
    xmlns:p="http://www.springframework.org/schema/p"        
       xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
       http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
    http://www.springframework.org/schema/context 
       http://www.springframework.org/schema/context/spring-context-2.5.xsd">

   <bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
     <property name="mappings">
          <props>
              <prop key="/home.htm">homePageController</prop>
           </props>
          </property>
    </bean>

   <bean id="homePageController" class="com.geekcap.geeknews.web.HomePageController">
      <property name="geekNewsService" ref="geekNewsService" />
   </bean>

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

The geeknews-servlet.xml file defines the HomePageController with the name homePageController. It injects the geekNewsService bean (as a reference, which means this is not a String value, but rather a reference to another bean) into its geekNewsService attribute. The geekNewsService bean is created in the geeknews-service.xml file (discussed below). In addition to defining the homePageController, the geeknews-servlet.xml file defines the urlMapping bean and the viewResolver bean.

The urlMapping bean is responsible for translating a URL pattern to a controller. There are several URL mappers:

  1. BeanNameUrlHandlerMapping: Maps a URL to a bean based on the name of the controller's bean, as defined in the bean's XML definition.
  2. SimpleUrlHandlerMapping: Maps a URL to a bean based on a list of properties. (In Listing 2, the SimpleUrlHandlerMapping class is used to map /home.htm to the bean with the ID of homePageController.)
  3. ControllerClassNameHandlerMapping: Maps a URL to a bean based on the bean's class name. For example, HomePageController would be mapped to /homePage*, such as /home.htm.
  4. ControllerBeanNameHandlerMapping: Similar to the BeanNameUrlHandlerMapping mapper, but does not expect bean names to follow the URL convention. Also supports Controller annotations.
  5. CommonsPathMapHandlerMapping: Maps URLs to a controller based on Jakarta Commons Attributes metadata.
  6. DefaultAnnotationHandlerMapping: Maps URLs to a controller for methods that implement the RequestMapping annotation.

The view resolver is responsible for translating the view name in the ModelAndView into a component, such as a JSP, that renders the view. The several available view resolvers are mostly based on the type of view they are forwarding to. View resolvers exist for FreeMarker, Jasper Reports, Velocity, XML, XSLT, and of course JSPs via URL paths. Listing 2 defines the InternalResourceViewResolver, which prefixes the view name with / and suffixes it with .jsp. Thus when the HomePageController returns the view name home, it is resolved to /home.jsp.

Putting it all together:

  1. The DispatcherServlet handles all requests that end in .htm, so it handles /home.htm.
  2. The SimpleUrlHandlerMapping maps /home.htm to the HomePageController.
  3. The HomePageController loads a list of articles from the GeekNewsService and returns those articles in a ModelAndView object whose destination is home.
  4. The InternalResourceViewResolver prefixes home with / and suffixes it with .jsp, which means that it is forwarded to /home.jsp for presentation.

web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app 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 web-app_2_4.xsd"
   version="2.4">

  <display-name>SpringMVC</display-name>

  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
        /WEB-INF/geeknews-services.xml
        /WEB-INF/geeknews-dao.xml
    </param-value>
  </context-param>

  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>

  <servlet>
    <servlet-name>geeknews</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>

  <servlet-mapping>
    <servlet-name>geeknews</servlet-name>
    <url-pattern>*.htm</url-pattern>
  </servlet-mapping>

  <taglib>
    <taglib-uri>http://java.sun.com/jstl/core</taglib-uri>
    <taglib-location>/WEB-INF/tld/c.tld</taglib-location>
  </taglib>

  <taglib>
    <taglib-uri>http://java.sun.com/jstl/fmt</taglib-uri>
    <taglib-location>/WEB-INF/tld/fmt.tld</taglib-location>
  </taglib>

  <welcome-file-list>
   <welcome-file>index.html</welcome-file>
  </welcome-file-list>

</web-app>

The DispatcherServlet automatically loads the geeknews-servlet.xml file, but when you build Spring applications it's a good practice to divide bean XML files into their logical components. In Listing 3, the contextConfigLocation context parameter defines two additional Spring XML files that should be loaded: geeknews-services.xml and geeknews-dao.xml. The ContextLoaderListener class is responsible for loading resources and reads the contextConfigLocation parameter to determine which configuration files to load. Finally, the web.xml file imports two components of the Java Standard Tag Library (JSTL) that will be used in the JSP file.

home.jsp:

<?xml version="1.0" encoding="UTF-8" ?>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" import="com.geekcap.geeknews.core.*,java.util.List"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
   <head>
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
      <title>Geek News</title>
      <link type="text/css" rel="stylesheet" href="css/geeknews.css" />
   </head>

<body>

<%@ include file="header.jsp" %>

<div id="mainContent">

<p><a href="post.htm">Post</a></p>

<c:forEach items="${articles}" var="article">

<div class="article">
<p><a href="article.htm?id=<c:out value="${article.id}"/>"><c:out value="${article.title}" /></a> 
   by <span class="articleAuthor"><c:out value="${article.author}" /></span>
   on <span class="articleDate"><fmt:formatDate value="${article.date}" type="both" /></span>
</p>

<p class="articleSummary"><c:out value="${article.summary}" /></p>
</div>

</c:forEach>

</div>

<%@ include file="footer.jsp" %>

</body>
</html>

The details of the HTML and CSS presentation are unimportant for this discussion; what's important is that the request object has an articles variable in it. The following snippet demonstrates how the JSTL core library is used to iterate over all articles and display an article's author, title, publication date, and summary:

<c:forEach items="${articles}" var="article">

<p><a href="article.htm?id=<c:out value="${article.id}"/>">
       <c:out value="${article.title}" /></a> 

   by <c:out value="${article.author}" />
   on <fmt:formatDate value="${article.date}" type="both" />
</p>

<p class="articleSummary"><c:out value="${article.summary}" /></p>

</c:forEach>

Figure 1 shows a screenshot of the Geek News homepage. The header consists of the words GEEK NEWS, hyperlinked to the home page. The body consists of a Post link, which brings up a form (which you'll implement later) for posting new articles, and then one section for each article that includes the title, author, publication date, and summary, followed by a horizontal line (implemented as a CSS bottom border on the article <div>). A footer (not shown) has copyright information (for "Fictitious Company," so don't worry, the code is yours to keep).

The header and footer are imported in the home.jsp page through the JSP include directive. They are both JSPs themselves. In their current state, they could be simple HTML documents, but in the future you might want to add a login link to the header or administration links to the footer.

Adding more controllers. The HomePageController that you've finished building is essential for the mini-CMS application, but it's only a start. The full application also needs a controller that responds to request parameters, and one for submitting content. Next you'll build the LoadArticleController, which responds to a single request parameter; after that, you'll implement the form controller for article submissions.

Command controllers. The LoadArticleController accepts a single request parameter — id — and uses the GeekNewsService to load the contents of the article that has that identifier. Looking back at the HomePageController, you could simply obtain the id parameter from the request object as you would do in a servlet:

String id = ( String )request.getAttribute( "id" );

But Spring provides a more elegant controller that obtains that parameter (and any others you need) from the request, in the form of a command object. Listing 5 shows a command object that wraps the id attribute.

ArticleCommand.java:

package com.geekcap.geeknews.web.command;

public class ArticleCommand {
    private String id;
    public ArticleCommand() {
    }
    public ArticleCommand(String id) {
        this.id = id;
    }
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
}

ArticleCommand is a simple POJO with a single parameter: id. When the POJO is paired with the appropriate controller type, Spring examines the request and tries to populate each field in the POJO. For a single parameter this might seem like overkill, but if you had 10 parameters of varying types, you would otherwise need to extract them manually as Strings and convert them to the appropriate types. You might as well take advantage of Spring's capability to do this for you.

public class LoadArticleController extends AbstractCommandController {

    /**
     * Provides access to GeekNews business methods
     */
    private GeekNewsService service;

    public LoadArticleController() {
        setCommandName( "article" );
        setCommandClass( ArticleCommand.class );
    }

    @Override
    protected ModelAndView handle(HttpServletRequest req, HttpServletResponse res, Object command, BindException errors ) throws Exception {

        // Load our article command
        ArticleCommand articleCommand = ( ArticleCommand )command;

        // Load the article from the GeekNewsService
        NewsArticle article = service.getArticle( articleCommand.getId() );

        // Build and return our ModelAndView
        return new ModelAndView( "article", "article", article );
    }

    /**
     * Injected by Spring
     * @param service
     */
    public void setGeekNewsService( GeekNewsService service ) {
        this.service = service;
    }
}

LoadArticleController extends Spring's AbstractCommandController. In two steps, you configure AbstractCommandController to auto-populate the command POJO of your choice:

  1. In the constructor, call setCommandClass() and pass it the command's Class object. The additional call to setCommandName() makes the command object available to the view, in the model, under the specified name.
  2. Implement the handle() method. The handle() method includes a command object that can be cast to your command class.

Now, the GeekNewsService can be invoked to find the article with the specified identifier by calling the command's getId() method.

The LoadArticleController is defined in the Spring XML configuration file in much the same way as the homePageController: define the bean with the injected GeekNewsService and add it to the urlMapping:

<bean id="loadArticleController" class="com.geekcap.geeknews.web.LoadArticleController">
    <property name="geekNewsService" ref="geekNewsService" />
</bean>

<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
    <property name="mappings">
        <props>
                <prop key="/home.htm">homePageController</prop>
                <prop key="/article.htm">loadArticleController</prop>
            </props>
    </property>
</bean>

The LoadArticleController returns a NewsArticle object in the model, which is redirected to the "article" page. Recall that the view resolver prefixes article with / and suffixes it with .jsp, so the view page can be found at /article.jsp. The article.jsp page — shown in Listing 7 — is similar to the home.jsp page, except that it shows only one article and displays its content rather than its summary.

article.jsp:

<?xml version="1.0" encoding="UTF-8" ?>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" import="com.geekcap.geeknews.core.*,java.util.List"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title>Article: <c:out value="${article.title}" /></title>
    <link type="text/css" rel="stylesheet" href="css/geeknews.css" />
</head>

<body>

<%@ include file="header.jsp" %>

<div id="mainContent">

<p><a href="home.htm">Home</a></p>

<div id="articleContentHeading">

<h2><c:out value="${article.title}" /></h2>
<p>By <span class="articleAuthor"><c:out value="${article.author}" /></span>
   on <span class="articleDate"><fmt:formatDate value="${article.date}" type="both" /></span>
</p>

</div>

<div id="articleContent">
<c:out value="${article.content}" escapeXml="false" />
</div>

</div>

<%@ include file="footer.jsp" %>

</body>
</html>

Now you'll build the PostArticleFormController, which handles a form posting, complete with simple form validation. Figure 3 shows a screen shot of the Geek News article-submission page.

The submission page prompts the user for an article title, author, submission date, summary, and content (with HTML markup). It is backed by a NewsArticle object, which is a POJO that wraps these parameters, shown in Listing 8.

NewsArticle.java:

package com.geekcap.geeknews.core;

import java.util.Date;

public class NewsArticle implements Comparable {

    private String id;
    private String title;
    private String author;
    private String summary;
    private String content;
    private Date date;

    public NewsArticle() {

    }

    public NewsArticle(String title, String author, Date date, String summary, String content ) {

        this.title = title;
        this.author = author;
        this.summary = summary;
        this.content = content;
        this.date = date;
    }

    public NewsArticle(String id, String title, String author, Date date, String summary, String content) {

        this.id = id;
        this.title = title;
        this.author = author;
        this.date = date;
        this.summary = summary;
        this.content = content;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public Date getDate() {
        return date;
    }

    public void setDate(Date date) {
        this.date = date;
    }

    public String getSummary() {
        return summary;
    }

    public void setSummary(String summary) {
        this.summary = summary;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    /**
     * Sorts article by descending dates
     */
    public int compareTo(Object o) {

        // Comparing the other date to ours should order descending 
        int result = ( ( NewsArticle )o ).getDate().compareTo( date );
        if( result == 0 ) {
            // Ensure that we don't lose any articles that have the same date
            return 1;
        }
        return result;
    }
}

The NewsArticle class is a straightforward POJO. The only thing unusual about it is that it is Comparable and implements the compareTo() method. This enables articles to be sorted by their date, from most recent to least recent.

PostArticleFormController.java:

package com.geekcap.geeknews.web;

import java.text.SimpleDateFormat;
import java.util.Date;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.validation.BindException;
import org.springframework.web.bind.ServletRequestDataBinder;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.SimpleFormController;

import com.geekcap.geeknews.core.GeekNewsService;
import com.geekcap.geeknews.core.NewsArticle;

public class PostArticleFormController extends SimpleFormController {

    /**
     * Provides access to GeekNews business methods
     */
    private GeekNewsService service;

    public PostArticleFormController() {
        setCommandClass( NewsArticle.class );
        setCommandName( "newsArticle" );
    }

    protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) throws Exception {
        SimpleDateFormat format = new SimpleDateFormat("MM/dd/yyyy hh:mm aa");
        binder.registerCustomEditor(Date.class, new CustomDateEditor(format, true));
    }

    protected ModelAndView onSubmit(Object command, BindException bindException) throws Exception {

        NewsArticle article = ( NewsArticle )command;

        service.addArticle( article );

        return new ModelAndView( getSuccessView() );
    }

    /**
     * Injected by Spring
     * @param service
     */
    public void setGeekNewsService( GeekNewsService service ) {
        this.service = service;
    }
}

The PostArticleFormController extends Spring's SimpleFormController and registers the NewsArticle as its command class, which in turn will be the container for its form data. The SimpleFormController class behaves differently depending on whether the Web request sent to it is a GET or a POST. If the request is a GET, it redirects the request to the form to be completed. If the request is a POST, the form object (NewsArticle in this example) is optionally validated and then passed as the command object to the onSubmit() method. In the PostArticleFormController, the onSubmit() method, knowing that its article is valid, simply invokes the GeekNewsService's addArticle() method to add the article to the CMS repository and then returns a ModelAndView object that references the getSuccessView() view.

The SimpleFormController defines two views: the form view and the success view. Users who have not successfully completed the form are redirected to the form view, otherwise, on successful submission, they are redirected to the success view. The form and success views are defined in the XML bean definition:

<bean id="postArticleFormController" class="com.geekcap.geeknews.web.PostArticleFormController">
    <property name="formView" value="post" />
    <property name="successView" value="postSuccess" />
    <property name="geekNewsService" ref="geekNewsService" />
    <property name="validator">
        <bean class="com.geekcap.geeknews.web.validator.NewsArticleValidator" />
    </property>
</bean>

Understanding how the view resolver works, you can probably already determine that the form view resolves to /post.jsp and the success view resolves to /postSuccess.jsp. The GeekNewsService is injected as usual, but there is a new property: validator. The validator defines a class that's responsible for validating the command object (NewsArticle in this example.) Listing 10 shows NewsArticleValidator's source code.

NewsArticleValidator.java:

package com.geekcap.geeknews.web.validator;

import org.springframework.validation.Errors;
import org.springframework.validation.ValidationUtils;
import org.springframework.validation.Validator;

import com.geekcap.geeknews.core.NewsArticle;

public class NewsArticleValidator implements Validator {

    @Override
    public boolean supports( Class clazz ) {
        return clazz.equals( NewsArticle.class );
    }

    @Override
    public void validate( Object command, Errors errors ) {

        NewsArticle article = ( NewsArticle )command;

        // Validate required fields
        ValidationUtils.rejectIfEmptyOrWhitespace( errors, "title", "article.missingTitle", "A title must be specified" );
        ValidationUtils.rejectIfEmptyOrWhitespace( errors, "author", "article.missingAuthor", "An author must be specified" );
        ValidationUtils.rejectIfEmptyOrWhitespace( errors, "summary", "article.missingSummary", "A summary must be specified" );
        ValidationUtils.rejectIfEmptyOrWhitespace( errors, "content", "article.missingContent", "Content must be specified" );

    }
}

Validators must report the classes that they validate through the supports() method. The NewsArticleValidator compares the class passed to it with the NewsArticle class. If the classes are the same, then it returns true, meaning that Spring can safely invoke validate() on this validator, passing it a NewsArticle.

The NewsArticleValidator performs only simple validation checking to see if the title, author, summary, and contents have values in them. You might want to extend this validation to look for invalid characters in the title, validate that the author currently exists in the system, validate that the date is valid and after "now," and so forth. This is your entry point to do so. The validator makes use of Spring's ValidationUtils class, which provides a handful of helper methods to check whether or not fields are populated. Spring also supports the Jakarta Commons Validator library's more-robust validation capabilities. The important thing to note about this example is that the errors object is updated with an error condition if a problem occurs. This tells the SimpleFormController to redirect the user back to the form, with error messages.

post.jsp:

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

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" import="com.geekcap.geeknews.core.*,java.util.List"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title>Post a New Article</title>
    <link type="text/css" rel="stylesheet" href="css/geeknews.css" />
</head>

<body>

<%@ include file="header.jsp" %>

<div id="articleForm">

<p><a href="home.htm">Home</a></p>

<p id="articleFormInstructions">Enter the information for an article posting and press "Post"</p>

<form:form action="post.htm" method="POST" commandName="newsArticle" >

<table>
    <tr>
        <th rowspan="2">Title:</th>
        <td><form:input path="title" size="60" /></td>
    </tr>
    <tr>
        <td><form:errors path="title" cssClass="validationError"/></td>
    </tr>
    <tr>
        <th rowspan="2">Author:</th>
        <td><form:input path="author" size="60" /></td>
    </tr>
    <tr>
        <td><form:errors path="author" cssClass="validationError"/></td>
    </tr>
    <tr>
        <th rowspan="2">Date:</th>
        <td><form:input path="date" size="60" /></td>
    </tr>
    <tr>
        <td><form:errors path="date" cssClass="validationError"/></td>
    </tr>
    <tr>
        <th rowspan="2">Summary:</th>
        <td><form:textarea path="summary" rows="3" cols="90"></form:textarea></td>
    </tr>
    <tr>
        <td><form:errors path="summary" cssClass="validationError"/></td>
    </tr>
    <tr>
        <th rowspan="2">Content:</th>
        <td><form:textarea path="content" rows="20" cols="90"></form:textarea></td>
    </tr>
    <tr>
        <td><form:errors path="content" cssClass="validationError"/></td>
    </tr>
    <tr>
        <th></th>
        <td><input type="submit" value="Post" /></td>
    </tr>
</table>
</form:form>
</div>
<%@ include file="footer.jsp" %>
</body>
</html>

The important observation to make about post.jsp is that it uses Spring form tags as opposed to HTML form tags. It begins by importing the Spring form tag library:

<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>

Then it's possible to preface normal form tags with form:. For example, the <form> tag is substituted with <form:form>. These tags also include some additional parameters:

  1. The <form:form> tag's additional commandNameparameter should match up to your SimpleFormController's setCommandName() parameter.
  2. The <form:input> and <form:textarea> tags have a path parameter instead of a name parameter. The path parameter is used during form validation to repopulate the value of a tag if the form needs to be redisplayed. If you look at the generated HTML, you can see that it is translated to name.

There's also a new element: <form:error>. If an error occurs during form validation, the error tag for the specified path is populated with the error message defined by the form validator. In the post.jsp page, the errors are presented in new table rows that follow the field, but you are free to put them anywhere, such as at the top of the form. Use the strategy that fits best into your user interface design.

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License