Controllers

Controller Basics
  • Controller handles urls
  • Dispatcher Servlet receives the url and then forwards processing to a controller method.
  • We annotate a normal class with a controller annotation to mark it as a controller.
  • We need to make sure that this controller gets picked up by component scanning so we define a component scan inside Dispatcher Servlet context.
    • <context:component-scan base package="com.springimplant.mvc.controllers" />
    • We define the controller package inside dispatcher servlet.
  • When IOC container starts up it creates the controller as a bean and makes it available for request processing.
  • To map the controller methods that will be processing request we use the request mapping annotation
    • This annotation can be applied at the type or method level.
    • When applied at type level we do not perform actual mapping.Everything that matches particular path will be handled by the controller.
    • We can further provide refinement by providing this annotation at controller methods.
    • These methods are called as handler methods because they service the request provided by the dispatcher servlet.
  • Next we need to look at a way to share information between controller and view
    • We do this using a model
    • In our method in controller class we are supplying an argument of type Model with name model.
      • This is used to share information between view and controller
    • Model is basically a map which takes key value pairs which are needed while adding an attribute to the model.
    • These key value pairs are referred to as an attribute of Model.
  • Since we are using the MVC annotation driven tag each attribute in the model will be termed into an attribute in the request.
  • This allows us to access that attribute via jspel or jsp expression language within our view.
    • See our jsp file we are using a attribute msg which we passed in our method
  • To get the information passed inside a model we rely on service
    • In order to use a service within Spring we need to autowire the same in our controller.
    • This allows us to perform logic or persistence of data using services.
  • You can find an example service being autowired in our controller(commented for now).
URI Templates
  • We can also pass data into our request url
    • Here we have a method "test" with data test id in our Request Mapping.
    • The testid is a variable. To extract the value of this variable we use an annotation called as "@Path Variable".
    • See how we have used this annotation in our method test.
    • This value is then automatically converted by Spring to appropriate datatype.
  • There are 30 different types of arguments that we can pass into controller.
  • We can even extract a Request Parameter value and assign it to our arguments in methods.
    • We use the "@RequestParam("action")" annotation to perform the same.
    • The Request parameters are in the form of name value pairs.
    • Here in method test we are extracting the Request Parameter called as "action".
    • Again we are typecasting the same into a String.
  • We are also able to pass Http Servelet Request Object and Http Session in our methods.
  • Data binding can also be performed in a controller method using annotation @ModelAttribute
    • When a request comes into a server it contains different parameters.
    • Parameters are basically name value pairs.
    • The "Model attribute" annotation maps these parameters to the corresponding names into the Model Attribute class.
    • Here we are using an example class for model attributes.
    • Save method is handling this request we have defined an argument of type example in method and we have annotated the same with @ModelAttribute annotation.
    • Spring will look at example type which has an attribute "name" of type String.
    • It will compare the names of fields in example class with names of Request Parameters.
    • If the key matches it will take the value of Request Parameter and set it to the field name in example class.
 package com.gaurav.mvc.controllers;  
 import javax.servlet.http.HttpServletRequest;  
 import javax.servlet.http.HttpSession;  
 import org.springframework.stereotype.Controller;  
 import org.springframework.ui.Model;  
 import org.springframework.web.bind.annotation.ModelAttribute;  
 import org.springframework.web.bind.annotation.PathVariable;  
 import org.springframework.web.bind.annotation.RequestMapping;  
 import org.springframework.web.bind.annotation.RequestParam;  
 @Controller  
 public class HomeController {  
 //     private ExampleService service;  
      @RequestMapping("/home")  
      public String goHome()  
      {  
           return "home";  
      }  
      @RequestMapping("/add")  
      public String add(Model model)  
      {  
           model.addAttribute("msg","Spring Mvc");  
           return "home";  
      }  
      @RequestMapping("/test/{testId}")  
      public String test(@PathVariable("testId") Long testId,Model model)  
      {  
           model.addAttribute("msg",testId);  
           return "home";  
      }  
      @RequestMapping("/example")  
      public String test(@RequestParam("action") String action,Model model)  
      {  
           model.addAttribute("msg",action);  
           return "home";  
      }  
      @RequestMapping("/example2")  
      public String test2(HttpServletRequest request,HttpSession session)  
      {  
           return "home";  
      }  
      @RequestMapping("/save")  
      public String save(@ModelAttribute Example example,Model model)  
      {  
           model.addAttribute("msg",example.getName());  
           return "home";  
      }  
 }  
Controllers
  • Controllers are used to provide access to an application's behavior.
  • A url is serviced by Controller which interacts with service of our application.
  • Controllers also interpret user input and transform it into model.
    • The model is then shown to user as view.
    • Other logic's such as data persistence is performed within a controller.
  • As of Spring 2.5 the main approach of using controllers has been annotation driven.
  • Spring 2.5 provides annotation such as 
    • Controller Annotation
    • Request Mapping Annotation
    • Model Attribute Annotation
  • These annotations are used within a controller to determine how they are going to process a request.
  • There is no dependencies on J2EE specific classes such as servelets.
  • There are no classes that you need to extend using a controller.
  • We have a file home.jsp which includes file header.jsp
    • header.jsp includes header navigation links
    • When we click on Add Project navigation link it goes to project "project_add.jsp".
  • Lets create a new class Project Controller which is defined with "@Controller" annotation.
    • This class is now available as controller and allow us for request processing.
    • The dispatcher servlet IOC container is indicated that this class will serve as one of our controllers.
    • When dispatcher servlet will try to route a url from a request this class will be a candidate for routing if it matches url of the request.
  • We need to enable component scanning for this package in dispatcher-servlet.xml
  • This project controller will be available as a bean in IOC container and will be available for request processing.
  • We create a method addProject()
    • This method returns a String which is the name of our view i.e. "project_add".
    • We will use this method for request handling
      • We will add request Mapping annotation to our Project Controller("/project").
      • This makes the class available for request mapping for a particular path.
    • We will also provide a request mapping annotation to our method i.e("/add")
    • When we run our project and click on add it displays the form in project_add.jsp.
Header.jsp
 <%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>  
 <nav class="navbar navbar-default">  
      <div class="container-fluid">  
           <div class="navbar-header">  
                <a class="navbar-brand" href="#">Project Management</a>  
           </div>  
           <ul class="nav navbar-nav">  
                <li><a href="#">Home</a></li>  
                <li class="dropdown">  
                     <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">Projects  
                     <span class="caret"></span>  
                     </a>  
                     <ul class="dropdown-menu" role="menu">  
                          <li><a href="<spring:url value="/project/add"/>">Add</a></li>  
                          <li><a href="#">Find</a></li>  
                     </ul>  
                </li>  
                <li class="dropdown">  
                     <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">Resources  
                               <span class="caret"></span>  
                     </a>  
                     <ul class="dropdown-menu" role="menu">  
                          <li><a href="#">Add</a></li>  
                          <li><a href="#">Find</a></li>  
                     </ul>  
                </li>  
           </ul>  
      </div>  
 </nav>  
Project Controller
 package com.gaurav.mvc.controllers;  
 import org.springframework.stereotype.Controller;  
 import org.springframework.web.bind.annotation.RequestMapping;  
 @Controller  
 @RequestMapping("/project")  
 public class ProjectController {  
      @RequestMapping("/add")  
      public String addProject()  
      {  
           return "project_add";  
      }  
 }  

Request Mapping
  • Till now we have used request mapping annotation above Project controller and methods to determine which controller and action needs to be selected on a url hit.Lets look further in this
    • We add a new function saveProject() with some Request Mapping value i.e(value="/add")
      • If we receive a request with "/project/add" the dispatcher servelet will not be able to  predict which method to invoke since both have similer parameters.
      • In such a case let us add our first parameter to RequestMapping annotation ("method=RequestMethod.GET" and "method=RequestMethod.POST") to methods addProject and saveProject respectively.
    • In the project_add.jsp file we add "action value=" parameter to form element and pass url "/project/add/" and method = "post".So this form will post to url "/project/add".
    • In menu we already have a GET request to "/project/add".
    • "addProject" and "invokeProject" will be shown in console output when we visit the form and when we submit the form.
    • Next we add another function "saveMultiProject" with same url parameters value="/add" ,method=RequestMethod.POST,params={"type=multi"})
      • Here we have a new attribute with name params this will make sure any url that comes with "type=multi" parameter invokes this method.
    • Now let us add parameters multi and special to our another function "saveSpecial".
      • @RequestMapping(value="/add",method=RequestMethod.POST,params={"type=multi","special"}) 
        • This function is invoked when we get method params as "type=multi" & special as value of another parameter.
    • We have marked console output in each of the functions so that we know when each one has been invoked.
ProjectController.java
 package com.gaurav.mvc.controllers;  
 import org.springframework.stereotype.Controller;  
 import org.springframework.web.bind.annotation.RequestMapping;  
 import org.springframework.web.bind.annotation.RequestMethod;  
 @Controller  
 @RequestMapping("/project")  
 public class ProjectController {  
      @RequestMapping(value="/add",method=RequestMethod.GET)  
      public String addProject()  
      {  
           System.out.println("Invoking addProject");  
           return "project_add";  
      }  
      @RequestMapping(value="/add",method=RequestMethod.POST)  
      public String saveProject()  
      {  
           System.out.println("Invoking saveProject");  
           return "project_add";  
      }  
      @RequestMapping(value="/add",method=RequestMethod.POST,params={"type=multi"})  
      public String saveMulti()  
      {  
           System.out.println("Invoking saveMulti");  
           return "project_add";  
      }  
      @RequestMapping(value="/add",method=RequestMethod.POST,params={"type=multi","special"})  
      public String saveSpecial()  
      {  
           System.out.println("Invoking saveSpecial");  
           return "project_add";  
      }  
 }  

project_add.jsp
 <%@ page language="java" contentType="text/html; charset=ISO-8859-1"  
   pageEncoding="ISO-8859-1"%>  
 <%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>  
 <!DOCTYPE html>  
 <html>  
 <head>  
 <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">  
 <title>Project Manager</title>  
      <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">  
      <link rel="stylesheet" href="<spring:url value="/resources/css/home.css"/>" type="text/css"/>  
      <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>  
      <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>  
 </head>  
 <body>  
      <jsp:include page="../views/fragments/header.jsp"></jsp:include>  
      <div class="container">  
           <div class="row">  
                <form action="<spring:url value="/project/add"/>" method="post" class="col-md-8 col-md-offset-2">  
                     <div class="form-group">  
                          <label for="project-name">Name</label>  
                          <input type="text" id="project-name" class="form-control" name="name"/>  
                     </div>  
                     <div class="form-group">  
                          <label for="project_type">Type</label>  
                          <select name="type" class="selectpicker">  
                               <option></option>  
                               <option value="single">Single Year</option>  
                               <option value="multi">Multi-Year</option>  
                          </select>  
                     </div>  
                     <div class="form-group">  
                          <label for="sponsor">Sponsor</label>  
                          <input id="sponsor" type="text"   
                                    class="form-control" name="sponsor"/>  
                     </div>  
                     <div class="form-group">  
                          <label for="funds">Authorized Funds</label>  
                          <input id="funds" type="text"  
                               class="form-control" name="authorized_funds"/>  
                     </div>  
                     <div class="form-group">  
                          <label for="hours">Authorized Hours</label>  
                          <input id="hours" type="text"  
                               class="form-control" name="authorized_hours"/>  
                     </div>  
                     <div class="form-group">  
                          <label for="project-name">Description</label>  
                          <textarea class="form-control" rows="3"></textarea>  
                     </div>  
                     <div class="form-group">  
                          <label for="special">Special</label>  
                          <input id="special" name="special" type="checkbox"/>  
                     </div>  
                     <button type="submit" class="btn btn-default">Submit</button>  
                </form>  
           </div>  
      </div>  
 </body>  
 </html>  

Model Basics
  • Model is used to abstract all of our data or information in the system from view.
    • Domain objects or entities are not available in jsp files or any other views.
  • Let us create a project class with attributes ("projectId","name","description","sponsor","authorizedHours","authorizedFunds","year","special","type").(see project.java file below)
  • We will display its object on our "home.jsp" page.
  • In our controllers we will collect information related to our entity or domain object and pass it into our model and then this model will be available in our view.
    • Let us pass the "object of Model" as argument in Controller method.
    • Create and initialize project object.
    • Place this object into model using "addAttribute" method.
home.jsp
 <%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>  
 <%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>    
 <!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>Project Manager</title>  
 <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">  
 <link rel="stylesheet" href="<spring:url value="/resources/css/home.css"/>" type="text/css"/>  
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>  
 <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>  
 </head>  
 <body>  
 <jsp:include page="../views/fragments/header.jsp"></jsp:include>  
 <div class="container">  
      <h2>Current Project</h2>  
      <ul class="list-group">  
           <li class="list-group-item"><label>Project Name:</label><span>${currentProject.name}</span></li>  
           <li class="list-group-item"><label>Sponsor:</label><span>${currentProject.sponser}</span></li>  
           <li class="list-group-item"><label>Description:</label><br/><span>${currentProject.description}</span></li>  
      </ul>  
      <h1>This page is called using a view resolver</h1>  
      <span>${msg}</span>  
 </div>  
 </body>  
 </html>  
Project.java
 package com.springimplant.mvc.data.entities;  
 import java.math.BigDecimal;  
 public class Project   
 {  
 private Long projectId;  
 private String name;  
 private String description;  
 private String sponser;  
 private BigDecimal authorizedHours;  
 private BigDecimal authorizedFunds;  
 private String year;  
 private boolean special;  
 private String type;  
 public Long getProjectId() {  
      return projectId;  
 }  
 public void setProjectId(Long projectId) {  
      this.projectId = projectId;  
 }  
 public String getName() {  
      return name;  
 }  
 public void setName(String name) {  
      this.name = name;  
 }  
 public String getDescription() {  
      return description;  
 }  
 public void setDescription(String description) {  
      this.description = description;  
 }  
 public String getSponser() {  
      return sponser;  
 }  
 public void setSponser(String sponser) {  
      this.sponser = sponser;  
 }  
 public BigDecimal getAuthorizedHours() {  
      return authorizedHours;  
 }  
 public void setAuthorizedHours(BigDecimal authorizedHours) {  
      this.authorizedHours = authorizedHours;  
 }  
 public BigDecimal getAuthorizedFunds() {  
      return authorizedFunds;  
 }  
 public void setAuthorizedFunds(BigDecimal authorizedFunds) {  
      this.authorizedFunds = authorizedFunds;  
 }  
 public String getYear() {  
      return year;  
 }  
 public void setYear(String year) {  
      this.year = year;  
 }  
 public boolean isSpecial() {  
      return special;  
 }  
 public void setSpecial(boolean special) {  
      this.special = special;  
 }  
 public String getType() {  
      return type;  
 }  
 public void setType(String type) {  
      this.type = type;  
 }  
 }  
HomeController.java
 package com.gaurav.mvc.controllers;  
 import javax.servlet.http.HttpServletRequest;  
 import javax.servlet.http.HttpSession;  
 import org.springframework.stereotype.Controller;  
 import org.springframework.ui.Model;  
 import org.springframework.web.bind.annotation.ModelAttribute;  
 import org.springframework.web.bind.annotation.PathVariable;  
 import org.springframework.web.bind.annotation.RequestMapping;  
 import org.springframework.web.bind.annotation.RequestParam;  
 import com.springimplant.mvc.data.entities.Project;  
 @Controller  
 public class HomeController {  
 //     private ExampleService service;  
      @RequestMapping("/")  
      public String goHome(Model model)  
      {  
           Project project=new Project();  
           project.setName("Java Tutorial");  
           project.setSponser("Spring Implant");  
           project.setDescription("A simple project initiated to Learn Java with Fun");  
           model.addAttribute("currentProject",project);  
           return "home";  
      }  
      @RequestMapping("/add")  
      public String add(Model model)  
      {  
           model.addAttribute("msg","Spring Mvc");  
           return "home";  
      }  
      @RequestMapping("/test/{testId}")  
      public String test(@PathVariable("testId") Long testId,Model model)  
      {  
           model.addAttribute("msg",testId);  
           return "home";  
      }  
      @RequestMapping("/example")  
      public String test(@RequestParam("action") String action,Model model)  
      {  
           model.addAttribute("msg",action);  
           return "home";  
      }  
      @RequestMapping("/example2")  
      public String test2(HttpServletRequest request,HttpSession session)  
      {  
           return "home";  
      }  
      @RequestMapping("/save")  
      public String save(@ModelAttribute Example example,Model model)  
      {  
           model.addAttribute("msg",example.getName());  
           return "home";  
      }  
 }  

Autowiring Controller Services
  • Our controller may invoke different methods on services within our application.
    • Controller may use different beans within the "rootApplicationContext"
    • For this we need to autowire our beans and services in controller so that they can be used in our application and perform business logic.
  • We will create a search service which will look up for projects.
    • We will create a page called as "projects.jsp" inside our views which will list all projects.
    • Next we will create a Project Service with name "ProjectService.java".
      • This service returns a list of projects that we have initialized inside the constructor of the service.
    • This service needs to be established as a bean in "rootApplicationContext".For this we use a bean tag give it an "id" a "class"(see updated file of  "applicationContext.xml").
  • We create a new method "find()" inside our Projects Controller file that will return view "projects".(see updated file Project Controller.java)
    • To call our service bean we use @Autowired annotation
    • Create a private field of type ProjectService.
    • Inside find method we add projectservice field to model and invoke findAll() method.
    • This will place the list of our projects under attribute name "projects".
    • projectservice is a bean included in our applicationContext.
  • In the jsp we will use jstl library and use its for each to iterate through each of our projects as follows.
           <c:forEach items="${projects}" var="project">  
                          <tr>  
                               <td>${project.name}</td><td>${project.sponser}</td><td>${project.description}</td>  
                          </tr>  
                     </c:forEach>  
ApplicationContext.xml
 <?xml version="1.0" encoding="UTF-8"?>  
 <beans xmlns="http://www.springframework.org/schema/beans"  
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
      xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">  
 <bean id="projectService" class="com.springimplant.mvc.data.services.ProjectService"/>  
 </beans>  
ProjectController.java(only code to be added given)
      @Autowired  
      private ProjectService projectService;  
      @RequestMapping(value="/find")  
      public String find(Model model)  
      {  
           model.addAttribute("projects",this.projectService.findAll());  
           return "projects";  
      }  
Projects.java
 <%@ page language="java" contentType="text/html; charset=ISO-8859-1"  
   pageEncoding="ISO-8859-1"%>  
 <%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>  
 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>  
 <!DOCTYPE html>  
 <html>  
 <head>  
 <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">  
 <title>Project Manager</title>  
      <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">  
      <link rel="stylesheet" href="<spring:url value="/resources/css/home.css"/>" type="text/css"/>  
      <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>  
      <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>  
 </head>  
 <body>  
      <jsp:include page="../views/fragments/header.jsp"></jsp:include>                 
      <div class="container">  
           <h2>Projects</h2>  
           <table class="table table-hover">  
                <tbody>  
                     <tr>  
                          <th>Name</th><th>Sponsor</th><th>Description</th>  
                     </tr>  
                     <c:forEach items="${projects}" var="project">  
                          <tr>  
                               <td>${project.name}</td><td>${project.sponser}</td><td>${project.description}</td>  
                          </tr>  
                     </c:forEach>  
                </tbody>  
           </table>  
      </div>  
 </body>  
 </html>  
ProjectService.java
 package com.springimplant.mvc.data.services;  
 import java.math.BigDecimal;  
 import java.util.Arrays;  
 import java.util.LinkedList;  
 import java.util.List;  
 import com.springimplant.mvc.data.entities.Project;  
 public class ProjectService {  
      private List<Project> projects = new LinkedList<>();  
      public ProjectService(){  
           Project p1 = this.createProject("Project 1", "This is description for Project 1" );  
           Project p2 = this.createProject("Project 2", "This is overview of Project 2");  
           Project p3 = this.createProject("Project 3", "This explains Project 3");  
           this.projects.addAll(Arrays.asList(new Project[]{p1,p2,p3}));  
      }  
      public List<Project> findAll(){  
           return this.projects;  
      }  
      private Project createProject(String title, String description) {  
           Project project = new Project();  
           project.setName(title);  
           project.setAuthorizedFunds(new BigDecimal("100000"));  
           project.setAuthorizedHours(new BigDecimal("1000"));  
           project.setSponser("Spring MVC Implant");  
           project.setProjectId(1L);  
           project.setSpecial(false);  
           project.setType("multi");  
           project.setYear("2015");  
           project.setDescription(description);  
           return project;  
      }  
 }  

URI Templates
  • We can pass data back to controller via URI template.
  • A URI template inputs a variable into the URL that our dispatcher servlet will be serving request for.
  • Restful urls,Restful Api's use Restful URI Templates to get data for example "/book/{isbn}" will fetch data for a book by ISBN.
  • Taking forward our example let us create each project name on our "find" page as a hyperlink which links to a project description page.
    • We will insert a URI template within the url.
    • This URI template will have a project id which controller will use to fetch information regarding the project.
    • We will display this information in "project.jsp" file.
    • In href attribute of anchor tag we use "<spring:url value="/project/${project.projectId}" />"
    • This is called as a URI template.
  • Next we will create a method in project controller with name "findProject()"
    • This will return a string "project" to display "project.jsp".
      • "project.jsp" will be our new view which will show information related to a project.
    • We will fetch the project object from the "find" method which we have defined in our Project Service and add it to the model passed into the method of controller.
  • To this method add request mapping to value "/{projectId}" since we already have "/project" as controller request mapping.
    • This will call this method when ever we hit "/project/{projectId}"
  • To assign url template variable to our variable passed as argument in method use
    • @PathVariable("projectId") Long projectId.(see updated controller file)
  • Run the application and click on the project name on find page you will see the information of Project.
Method added to Project Controller
      @RequestMapping(value="/{projectId}")  
      public String findProject(Model model, @PathVariable("projectId") Long projectId) {  
           model.addAttribute("project",this.projectService.find(projectId));  
           return "project";  
      }  

Method added to Project Service
      public Project find(Long projectId){  
           return this.projects.stream().filter(p -> {  
                return p.getProjectId().equals(projectId);  
           }).collect(Collectors.toList()).get(0);  
      }  

Changes to projects.jsp
 <td><a href='<spring:url value="/project/${project.projectId}"/>'>${project.name}</a></td>  

project.jsp
 <%@ page language="java" contentType="text/html; charset=ISO-8859-1"  
   pageEncoding="ISO-8859-1"%>  
 <%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>  
 <!DOCTYPE html>  
 <html>  
 <head>  
 <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">  
 <title>Project Manager</title>  
      <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">  
      <link rel="stylesheet" href="<spring:url value="/resources/css/home.css"/>" type="text/css"/>  
      <link rel="stylesheet" href="<spring:url value="/resources/css/bootstrap-select.min.css"/>" type="text/css"/>  
      <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>  
      <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>  
      <script src="<spring:url value="/resources/js/bootstrap-select.min.js"/>"></script>  
 </head>  
 <body>  
      <jsp:include page="../views/fragments/header.jsp"></jsp:include>  
      <div class="container">  
           <div class="row">  
                     <div class="form-group">  
                          <label for="project-name">Name</label>  
                          <span>${project.name}</span>  
                     </div>  
                     <div class="form-group">  
                          <label for="project_type">Type</label>  
                          <span>${project.type }</span>  
                     </div>  
                     <div class="form-group">  
                          <label for="sponsor">Sponsor</label>  
                          <span>${project.sponser}</span>  
                     </div>  
                     <div class="form-group">  
                          <label for="funds">Authorized Funds</label>  
                          <span>${project.authorizedFunds}</span>  
                     </div>  
                     <div class="form-group">  
                          <label for="hours">Authorized Hours</label>  
                          <span>${project.authorizedHours}</span>  
                     </div>  
                     <div class="form-group">  
                          <label for="project-name">Description</label>  
                          <span>${project.description}</span>  
                     </div>  
                     <div class="form-group">  
                          <label for="special">Special</label>  
                          <span>${project.special == true ? 'Yes':'No'}</span>  
                     </div>  
           </div>  
      </div>  
 </body>  
 </html>  

Method Arguments
  • The controller handler methods have very flexible signatures.
    • For example in "findProject" method we are passing Model as well as ProjectId
    • In  "find" method we are passing only model.
  • The entire list of these arguments is available in Spring documentation
  • Some of the commonly used arguments are as follows.
    • HttpSession argument
      • All the session attributes can be set or get using this argument.
    • HttpServletRequest argument
      • We can get any Http request parameter using this argument.
    • @RequestParam("name") String name
      • Used to get a specified request parameter.
      • We can also typecast Request Parameters into our required type using this argument.
        • Example @RequestParam("name") Long name
Example and usage of Method Arguments in Get and Post methods
      @RequestMapping(value="/add",method=RequestMethod.GET)  
      public String addProject(HttpSession session)  
      {  
           session.setAttribute("token","12345");  
           System.out.println("Invoking addProject");  
           return "project_add";  
      }  
      @RequestMapping(value="/add",method=RequestMethod.POST)  
      public String saveProject(HttpServletRequest request,@RequestParam("name") String name,HttpSession session)  
      {  
           System.out.println(session.getAttribute("token"));  
           System.out.println(request.getParameter("name"));  
           System.out.println(name);  
           System.out.println("Invoking saveProject");  
           return "project_add";  
      }  

Data Binding
  • Data Binding simplifies how we handle form processing.
  • Data in a class properties is bound to the "name" attribute in fields of a form.
  • The parameters from an HTML form are sent over in a request.
  • The request comes to the controller side and is processed by the server handler method.
  • In our case it will hit the "saveproject" method with request type as post.
    • We will pull out each of the parameter values from the request and create a project object.
    • Using data binding we can map the entire request object to the corresponding class object(Project class in this case)
    • We pass an attribute called as project of type Project Class in the method.
      • Before this attribute add "@ModelAttribute" annotation.
    • Spring will match each attribute in request to the properties in Project Class.
    • It assigns the value from the request to the field with corresponding name in Project Class.
    • We have added Console output to "setName" method.
    • Added a toString() method to the Project Class.
    • Corrected/Added the "name" values in jsp in the HTML form so that they match Project properties so that we can print the updated object.
    • When we now print "Project" object in saveProject() we find that values are mapped. 
      @RequestMapping(value="/add",method=RequestMethod.POST)  
      public String saveProject(@ModelAttribute Project project,HttpServletRequest request,@RequestParam("name") String name,HttpSession session)  
      {  
           System.out.println(session.getAttribute("token"));  
           System.out.println(request.getParameter("name"));  
           System.out.println(name);  
           System.out.println(project);  
           System.out.println("Invoking saveProject");  
           return "project_add";  
      }  

Advanced Concepts
  • Advanced concepts in controllers include following
    • More complex data bindings.  
      • Includes mapping to Collection objects and Composite Objects.
    • Present additional methods using annotations for storing model attributes.
      • Model attribute annotation to store attributes on model.
        • This is alternative way to store objects in our model
      • One context allows data binding and other allows storing objects within the model.
    • Discover how to store session attributes.
      • Used to persist data in each request.
    • Learn how to work with the request and response bodies.
      • Response body is used to directly output message via controllers without involving jsp pages.
      • Request body allows data coming in from a page to be mapped directly to one of our controller handler methods arguments.
      • Helps to make manipulations on request object.
Data Binding Composite Objects
  • Let us create a Sponsor class to represent details of a sponsor. 
  • Let us change the property sponsor in our project controller to an object of class Sponsor type.
    • Generate new Getter and Setter methods for this property.
    • Next we change our project_add.jsp file and add form tags to it replacing the current HTML tags. 
    • We have form tags for all the types except the sponsor type which is an object of Sponsor class.
    • We will be adding details of the Sponsor i.e. the Sponsor Name,email,phone as defined in Sponsor class along with the Project.
      • We have added 3 new input fields for this which are "Sponsor Name","Sponsor Email","Sponsor Phone" replacing the original Sponsor field.
      • Now we need to convert these to Form Tag Library Fields.
      • The main issue we will face is for the path property.
        • We will define the path of these fields as "sponsor.name","sponsor.email","sponsor.phone" as shown in file.
        • This accesses the project object's sponsor field's name,email and phone field respectively.
        • This will automatically add Sponsor data to the respective object.
        • In actual these values are represented as "project.sponsor.name","project.sponsor.email","project.sponsor.phone". But since we already have form's model attribute property as "project" we define path from "sponsor" only.
  • The changes made to the files are as follows
Sponsor.java
 package com.springimplant.mvc.data.entities;  
 public class Sponsor {  
      private String name;  
      private String phone;  
      private String email;  
      public Sponsor() {  
      }  
      public Sponsor(String name, String phone, String email) {  
           super();  
           this.name = name;  
           this.phone = phone;  
           this.email = email;  
      }  
      public String getName() {  
           return name;  
      }  
      public void setName(String name) {  
           this.name = name;  
      }  
      public String getPhone() {  
           return phone;  
      }  
      public void setPhone(String phone) {  
           this.phone = phone;  
      }  
      public String getEmail() {  
           return email;  
      }  
      @Override  
      public String toString() {  
           return "Sponsor [name=" + name + ", phone=" + phone + ", email=" + email + "]";  
      }  
      public void setEmail(String email) {  
           this.email = email;  
      }  
 }  

Project.java
 package com.springimplant.mvc.data.entities;  
 import java.math.BigDecimal;  
 public class Project {  
      private Long projectId;  
      private String name;   
      private String description;   
      private Sponsor sponsor;   
      private BigDecimal authorizedHours;   
      private BigDecimal authorizedFunds;   
      private String year;   
      private boolean special;   
      private String type;   
      public Long getProjectId() {   
       return projectId;   
      }   
      public void setProjectId(Long projectId) {   
         this.projectId = projectId;   
       }   
       public String getName() {   
         return name;   
       }   
       public void setName(String name) {  
            System.out.println("Field Name Binded to object");  
         this.name = name;   
       }   
       public String getDescription() {   
         return description;   
       }   
       public void setDescription(String description) {   
         this.description = description;   
       }   
       public Sponsor getSponsor() {   
         return sponsor;   
       }   
       public void setSponsor(Sponsor sponsor) {   
         this.sponsor = sponsor;   
       }   
       public BigDecimal getAuthorizedHours() {  
         return authorizedHours;   
       }   
       public void setAuthorizedHours(BigDecimal authorizedHours) {   
         this.authorizedHours = authorizedHours;   
       }   
       public BigDecimal getAuthorizedFunds() {   
         return authorizedFunds;   
       }   
       public void setAuthorizedFunds(BigDecimal authorizedFunds) {   
         this.authorizedFunds = authorizedFunds;   
       }   
       public String getYear() {   
         return year;   
       }   
       public void setYear(String year) {   
         this.year = year;   
       }   
       public boolean isSpecial() {   
         return special;   
       }   
       public void setSpecial(boolean special) {  
         this.special = special;  
       }   
       public String getType() {   
         return type;  
       }   
       public void setType(String type) {   
         this.type = type;  
       }  
      @Override  
      public String toString() {  
           return "Project [projectId=" + projectId + ", name=" + name + ", description=" + description + ", sponser="  
                     + sponsor + ", authorizedHours=" + authorizedHours + ", authorizedFunds=" + authorizedFunds + ", year="  
                     + year + ", special=" + special + ", type=" + type + "]";  
      }   
 }  
project_add.jsp
 <%@ page language="java" contentType="text/html; charset=ISO-8859-1"  
   pageEncoding="ISO-8859-1"%>  
 <%@ taglib uri="http://www.springframework.org/tags" prefix="spring" %>  
 <%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %>  
 <!DOCTYPE html>  
 <html>  
 <head>  
 <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">  
 <title>Project Manager</title>  
      <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">  
      <link rel="stylesheet" href="<spring:url value="/resources/css/home.css"/>" type="text/css"/>  
      <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>  
      <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>  
 </head>  
 <body>  
      <jsp:include page="../views/fragments/header.jsp"></jsp:include>  
      <div class="container">  
           <div class="row">  
                <spring:url value="/project/add" var="formUrl" htmlEscape="true"/>  
                <form:form method="POST" action="${formUrl}" modelAttribute="project">  
                     <div class="form-group">  
                          <label for="project-name">Name</label>  
                          <form:input path="name" id="project-name" cssClass="form-control"/>  
                     </div>  
                     <div class="form-group">  
                          <label for="project_type">Type</label>  
                          <form:select path="type" cssClass="selectpicker" items="${types}"></form:select>  
                     </div>  
                     <div class="form-group">  
                          <label for="sponsor-name">Sponsor Name</label>  
                          <form:input id="sponsor-name" path="sponsor.name" cssClass="form-control"/>  
                     </div>  
                     <div class="form-group">  
                          <label for="sponsor-phone">Sponsor Phone</label>  
                          <form:input id="sponsor-phone" path="sponsor.phone" cssClass="form-control"/>  
                     </div>  
                     <div class="form-group">  
                          <label for="sponsor-email">Sponsor Email</label>  
                          <form:input id="sponsor-email" path="sponsor.email" cssClass="form-control"/>  
                     </div>  
                     <div class="form-group">  
                          <label for="funds">Authorized Funds</label>  
                          <form:input path="authorizedFunds" id="funds" cssClass="form-control"/>  
                     </div>  
                     <div class="form-group">  
                          <label for="hours">Authorized Hours</label>  
                          <form:input path="authorizedHours" id="hours" cssClass="form-control"/>  
                     </div>  
                     <div class="form-group">  
                          <label for="project-name">Description</label>  
                          <form:textarea path="description" id="description" cssClass="form-control" rows="3"/>  
                     </div>  
                     <div class="form-group">  
                          <label for="special">Special</label>  
                          <form:checkbox path="special" id="special" />  
                     </div>  
                     <button type="submit" class="btn btn-default">Submit</button>  
                </form:form>  
           </div>  
      </div>  
 </body>  
 </html>  

Data Binding Lists
  • Let's add field of type List<String> to Project class called as pointsOfContact in Project Entity.
    • Add setters and getters for this field.
    • Update the toString() method.
  • Now Let us add a form input field for this in project_add.jsp
    • We will add 3 such fields and label them as POC,POC2,POC3.
  • Next set the path property of these fields as  "pointsOfContact[0]", "pointsOfContact[2]", "pointsOfContact[2]" respectively.
  • This points to the list pointsOfContact and binds them to the first Item,second Item and Third Item in the list.
  • The changed files are shown below
Project.java
      private List<String> pointsOfContact;  
      public List<String> getPointsOfContact() {  
           return pointsOfContact;  
      }  
      public void setPointsOfContact(List<String> pointsOfContact) {  
           this.pointsOfContact = pointsOfContact;  
      }  
      @Override  
      public String toString() {  
           return "Project [projectId=" + projectId + ", name=" + name + ", description=" + description + ", sponsor="  
                     + sponsor + ", authorizedHours=" + authorizedHours + ", authorizedFunds=" + authorizedFunds + ", year="  
                     + year + ", special=" + special + ", type=" + type + ", pointsOfContact=" + pointsOfContact + "]";  
      }   
project_add.jsp
           <div class="form-group">  
                          <label for="poc">POC</label>  
                          <form:input id="poc" path="pointsOfContact[0]" cssClass="form-control"/>  
                     </div>  
                     <div class="form-group">  
                          <label for="poc2">POC 2</label>  
                          <form:input id="poc2" path="pointsOfContact[1]" cssClass="form-control"/>  
                     </div>  
                     <div class="form-group">  
                          <label for="poc3">POC 3</label>  
                          <form:input id="poc3" path="pointsOfContact[2]" cssClass="form-control"/>  
                     </div>  

Model Attributes
  • Model attribute annotation has two contexts
    • When we annotate a method argument.
      • We retrieve this argument from Model
        • We check if there is a class of type Resource available to be provided as argument of this method.
      • If we can't find class in Model we will create a new class using default constructor and we will check Request Object or Request Params passed in and map fields by name  on fields of Resource Object.
      • This is called as Data Binding
    • The other context is to annotate method of controller
      • Makes sure returned object is placed in model as an attribute.
      • For example in below annotation the returned object from method will be placed in model under "checkOptions" attribute
        • @ModelAttribute("checkOptions")
      • We can prepopulate radio buttons and check boxes using these attributes. 
      • We can also prepopulate form's "modelAttribute" using this.
    • Command/Hidden objects in form used to backup data.
Changes made to Resource Controller
      @RequestMapping("/add")  
      public String add(Model model)  
      {   
           return "resource_add";  
      }  
      @ModelAttribute("resource")  
      public Resource getResource()  
      {  
           return new Resource();  
      }  
      @ModelAttribute("checkOptions")  
      public List<String> getChecks()  
      {  
           return new LinkedList<>(Arrays.asList(new String[]{"Lead Time","Special Rate","Requires Approval"}));  
      }  
      @ModelAttribute("radioOptions")  
      public List<String> getRadios()  
      {  
           return new LinkedList<>(Arrays.asList(new String[]{"Hours","Piece","Tons"}));  
      }  
      @ModelAttribute("itemOptions")  
      public List<String> getItems()  
      {  
           return new LinkedList<>(Arrays.asList(new String[]{"Lead Time","Special Rate","Requires Approval"}));  
      }  

Session Attributes
  • Used to store model attributes between requests.
  • We need to have persistent data between different requests.
  • We store this information using a session attribute using in a servelet api.
  • We use session attribute annotation to achieve this functionality.
  • We store our Model variables into the Session.
  • We have added another review page before final submission of data to check this.
    • So our Add Page will post to review page which will in turn post to Save Page
  • The syntax for session attribute annotation is as follows.
    • @SessionAttribute("resource")
  • Session Attribute is persistent only to a controller so we cannot use it to persist objects between controllers.
ResourceController.java
 package com.springimplant.mvc.controllers;  
 import java.util.Arrays;  
 import java.util.LinkedList;  
 import java.util.List;  
 import org.springframework.stereotype.Controller;  
 import org.springframework.ui.Model;  
 import org.springframework.web.bind.annotation.ModelAttribute;  
 import org.springframework.web.bind.annotation.RequestMapping;  
 import org.springframework.web.bind.annotation.SessionAttributes;  
 import com.springimplant.mvc.data.entities.Resource;  
 @Controller  
 @RequestMapping("/resource")  
 @SessionAttributes("resource")  
 public class ResourceController {  
      @RequestMapping("/review")  
      public String review(@ModelAttribute Resource resource)  
      {  
           System.out.println("Invoking Review() method");  
           return "resource_review";  
      }  
      @RequestMapping("/add")  
      public String add(Model model)  
      {  
           System.out.println("Invoking add() method");  
           return "resource_add";  
      }  
      @RequestMapping("/save")  
      public String save(@ModelAttribute Resource resource,Model model) throws ClassNotFoundException  
      {  
           System.out.println("Invoking save() method");  
           System.out.println(resource);  
           return "redirect:/resource/add";  
      }  
      @ModelAttribute("resource")  
      public Resource getResource()  
      {  
           System.out.println("Adding a new Resource to the model");  
           return new Resource();  
      }  
      @ModelAttribute("checkOptions")  
      public List<String> getChecks()  
      {  
           System.out.println("Adding CheckOptions");  
           return new LinkedList<>(Arrays.asList(new String[]{"Lead Time","Special Rate","Requires Approval"}));  
      }  
      @ModelAttribute("radioOptions")  
      public List<String> getRadios()  
      {  
           return new LinkedList<>(Arrays.asList(new String[]{"Hours","Piece","Tons"}));  
      }  
      @ModelAttribute("itemOptions")  
      public List<String> getItems()  
      {  
           return new LinkedList<>(Arrays.asList(new String[]{"Lead Time","Special Rate","Requires Approval"}));  
      }  
 }  
resource_review.jsp
 <%@ page language="java" contentType="text/html; charset=ISO-8859-1"  
      pageEncoding="ISO-8859-1"%>  
 <%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>  
 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>  
 <!DOCTYPE html>  
 <html>  
 <head>  
 <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">  
 <title>Project Manager</title>  
 <link rel="stylesheet"  
      href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">  
 <link rel="stylesheet"  
      href="<spring:url value="/resources/css/home.css"/>" type="text/css" />  
 <link rel="stylesheet"  
      href="<spring:url value="/resources/css/bootstrap-select.min.css"/>"  
      type="text/css" />  
 <script  
      src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>  
 <script  
      src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>  
 <script  
      src="<spring:url value="/resources/js/bootstrap-select.min.js"/>"></script>  
 </head>  
 <body>  
      <jsp:include page="../views/fragments/header.jsp"></jsp:include>  
      <div class="container">  
           <div class="row">  
                <h2>Please review the resource for accuracy</h2>  
                <div class="form-group">  
                     <label for="project-name">Name</label> <span>${resource.name}</span>  
                </div>  
                <div class="form-group">  
                     <label for="project_type">Type</label> <span>${resource.type }</span>  
                </div>  
                <div class="form-group">  
                     <label>Cost</label> <span>${resource.cost}</span>  
                </div>  
                <div class="form-group">  
                     <label>Unit Of Measure</label> <span>${resource.unitOfMeasure}</span>  
                </div>  
                <div class="form-group">  
                     <label>Indicators</label>  
                     <c:forEach var="indicator" items="${resource.indicators}">  
                          <span>${indicator}</span>  
                     </c:forEach>  
                </div>  
                <a href="<spring:url value="/resource/add"/>" class="btn btn-default">Edit</a>  
                <a href="<spring:url value="/resource/save"/>"  
                     class="btn btn-default">Save</a>  
           </div>  
      </div>  
 </body>  
 </html>  
resource_add.jsp
 <%@ page language="java" contentType="text/html; charset=ISO-8859-1"  
      pageEncoding="ISO-8859-1"%>  
 <%@ taglib uri="http://www.springframework.org/tags" prefix="spring" %>  
 <%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %>  
 <!DOCTYPE html>  
 <html>  
 <head>  
 <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">  
 <title>Project Manager</title>  
 <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">  
 <link rel="stylesheet" href="<spring:url value="/resources/css/bootstrap-select.min.css"/>" type="text/css" />  
 <link rel="stylesheet" href="<spring:url value="/resources/css/global.css"/>" type="text/css" />  
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>  
 <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>  
 <script src="<spring:url value="/resources/js/bootstrap-select.min.js"/>"></script>  
 </head>  
 <body>  
      <jsp:include page="../views/fragments/header.jsp"></jsp:include>  
      <div class="container">  
           <div class="row">  
                <h1>Resource</h1>  
           </div>  
           <spring:url value="/resource/review" var="formUrl" htmlEscape="true"/>  
           <form:form action="${formUrl}" method="POST" modelAttribute="resource">  
                <div class="row">  
                     <div class="form-group">  
                          <label for="resource-name">Name</label>   
                          <form:input path="name" cssClass="form-control" id="resource-name" />  
                     </div>  
                     <div class="form-group">  
                          <label for="resource-type">Type</label>   
                          <form:select path="type" items="${itemOptions}" cssClass="form-control"></form:select>  
                     </div>  
                     <div class="form-group">  
                          <label for="cost">Cost</label>   
                          <form:input path="cost" cssClass="form-control" id="cost" />  
                     </div>  
                     <div class="form-group">  
                          <label for="unit">Unit of Measure</label>   
                          <form:radiobuttons path="unitOfMeasure" items="${radioOptions}"/>  
                     </div>  
                     <div class="form-group">  
                          <label for="indicators">Indicators</label>   
                          <form:checkboxes id="indicators" path="indicators" items="${checkOptions}"/>  
                     </div>  
                     <div class="form-group">  
                          <label for="notes">Notes</label>  
                          <form:textarea id="notes" path="notes" cssClass="form-control" rows="3"/>  
                     </div>  
                     <button type="submit" class="btn btn-default">Submit</button>  
                </div>  
           </form:form>  
      </div>  
 </body>  
 </html>  

Session Status
  • The session status interface can be injected in our controller Handler Methods.
  • Once injected we can invoke different methods of this interface to remove session attributes so that they are unavailable for request Processing.
  • Just Pass an argument of type SessionStatus in controller handler method to use this interface
  • An example scenario of using this interface is when data is persisted in database we may need to clear the session.
Changes to ResourceController
      @RequestMapping("/save")  
      public String save(@ModelAttribute Resource resource,SessionStatus status) throws ClassNotFoundException  
      {  
           System.out.println("Invoking save() method");  
           System.out.println(resource);  
           status.setComplete();  
           return "redirect:/resource/add";  
      }  

Response Body
  • Allows us to write a response from our controller handler methods directly to the client.
  • Anything returned from controller will be directly written to the response body.
    • It won't be placed in model and we will not use jsp to render our view.
  • Used to handle data for java-script requests.
  • The value returned from handler method is used as HTTP response directly.
  • We can return json, xml response directly using this.
  • Also used in scenario where we need to change a snippet of information on the same page.
    • For Example to check weather a user name exists on signup page and show message and proceed accordingly.
  • For a given below method handler if an ajax request is made or is directly called we will get response in ajax request as returned by method itself.
Changes to ResourceController
      @RequestMapping("/request")  
      @ResponseBody  
      public String request(@ModelAttribute Resource resource)  
      {  
           //Send an Email for Request  
           //Format this into an json array to be handled in js  
           return "The request has been sent for Approval";  
      }  

Request Body Annotation
  • Allows us to take the http request body and map it to controller method parameters on one of our Controller Handler methods.
  • We do this by annotating the method parameter with @RequestBody
  • Spring uses Http Message converters to make this possible
  • Helps to bind json/xml response to an object and parse it out.
    • Spring provides an HTTP message converter that can convert json to an object.
    • So if we have Resource as type of our @RequestBody argument and we have a json String sent in it will automatically map it to the argument.
  • Spring can find a message converter for type resource or for json and then it is able to databind or desearilize json String to the Resource type automatically.
  • Since in the below method we are sending String(serialized form of Form) from ajax call we are binding it to argument of type String.
Changes to Resource Controller
      @RequestMapping(value="/request",method=RequestMethod.POST)  
      @ResponseBody  
      public String request(@RequestBody String resource)  
      {  
           //Send an Email for Request  
           //Format this into an json array to be handled in js  
           System.out.println(resource);  
           return "The request has been sent for Approval";  
      }  

Redirect Request
  • Reposting of a form can be easily done if user is not redirected.
  • In Spring we have a built in functionality to redirect which allows us to stop a form from being reposted.
  • We return a string url with "redirect:" as prefix
    • For example after add here we are redirecting to "/project/find" by returning a string "redirect:/project/find"
      @RequestMapping(value="/add",method=RequestMethod.POST)  
      public String saveProject(@Valid @ModelAttribute Project project,Errors errors,HttpServletRequest request,@RequestParam("name") String name,HttpSession session,Model model)  
      {  
           if(errors.hasErrors())  
           {  
                System.out.println("The Project is not Validated");  
                return "project_add";  
           }  
           else  
           {  
                System.out.println("The Project is Validated");  
           }  
           System.out.println(session.getAttribute("token"));  
           System.out.println(request.getParameter("name"));  
           System.out.println(name);  
           System.out.println(project);  
           model.addAttribute("project",project);  
           System.out.println("Invoking saveProject");  
           return "redirect:/project/find";  
      }  

RedirectAttributes Interface
  • It is always useful to send some data to the next url to which we are redirecting too.
    • for example after saving an entity we may need to display that entity using that id in such a case we will send id of new entity to the redirected method that displays that entity.
  • To accomplish this Spring provides us with RedirectAttribute interface.
    • This can be added as an object to our controller handler methods as an argument.
    • Next we can add attributes to this object key value pairs in String which are then appended to the request and act as basically a request parameter.
  • We then need to handle the parameters in the method to which it is redirected too.
RedirectAttribute sent via Controller method
      @RequestMapping(value="/add",method=RequestMethod.POST)  
      public String saveProject(@Valid @ModelAttribute Project project,Errors errors,HttpServletRequest request,@RequestParam("name") String name,HttpSession session,Model model,RedirectAttributes attributes)  
      {  
           if(errors.hasErrors())  
           {  
                System.out.println("The Project is not Validated");  
                return "project_add";  
           }  
           else  
           {  
                System.out.println("The Project is Validated");  
           }  
           System.out.println(session.getAttribute("token"));  
           System.out.println(request.getParameter("name"));  
           System.out.println(name);  
           System.out.println(project);  
           project.setProjectId(55L);  
           this.projectService.save(project);  
           attributes.addAttribute("projectId", project.getProjectId().toString());  
           model.addAttribute("project",project);  
           System.out.println("Invoking saveProject");  
           return "redirect:/";  
      }  
Request Parameters handled in redirected method
      @RequestMapping(value="/", params="projectId")  
      public String goProjectHome(Model model,@RequestParam("projectId") Long projectId)  
      {  
           model.addAttribute("currentProject",this.service.find(projectId));  
           return "home";  
      }  

Flash Attributes

  • Used to handle the Post-Redirect-Get pattern
  • In this attributes are not sent as request parameters but instead stored in a session.
  • On the redirected method we fetch this using @ModelAttribute.
  • We can pass entire objects to the redirected method.
  • We add the attributes using the addFlashAttribute method which is defined in RedirectAttributes interface.
  • Once the attribute is used it is automatically deleted from session that is why we call it as a Flash attribute.
In the Requested Method
      @RequestMapping(value="/add",method=RequestMethod.POST,params={"type=Multi Year"})  
      public String saveMulti(@Valid @ModelAttribute Project project,Errors errors,@RequestParam("name") String name,HttpSession session,HttpServletRequest request,RedirectAttributes attributes)  
      {  
           System.out.println("Invoking saveMulti");  
           if(errors.hasErrors())  
           {  
                System.out.println("The Project is not Validated");  
                return "project_add";  
           }  
           else  
           {  
                System.out.println("The Project is Validated");  
           }  
           System.out.println(session.getAttribute("token"));  
           System.out.println(request.getParameter("name"));  
           System.out.println(name);  
           System.out.println(project);  
           project.setProjectId(66L);  
           this.projectService.save(project);  
           attributes.addFlashAttribute("project",project);  
           return "redirect:/showproject";  
      }  
In the Redirected Method 
      @RequestMapping(value="/showproject")  
      public String goHome(Model model,@ModelAttribute("project") Project project)  
      {  
           model.addAttribute("currentProject",project);  
           return "project";  
      }  

REST Controller

  • A REST controller returns the Response Body directly.
  • If its a String it returns a String if an object is returned it is converted into JSON/XML format as specified in content type.
  • We annotate the controller with @RestController annotation.
  • This controller will return REST response from all its methods.

No comments:

Post a Comment

Spring Boot

What is circular/cyclic dependency in spring boot? When two services are interdependent on each other, that is to start one service, we requ...