Handling Forms with Spring 3 MVC

This article is a part of a series of articles written about Spring 3. The previous article of this series is available here. I recommend you read - or at least browse quickly - the previous article before reading further.

In this article we take another baby step towards Spring MVC. [Aside: A pdf by the originator of the term MVC.] Building from the previous article, let's add code necessary to add "Contacts" to the application. First thing, we will need to add some UI component to initiate the process. For simplicity's sake let it be a simple link.

File: /springwebapp001/src/main/webapp/index.jsp
[...]
<a href="contacts/addNew.html"> Add new contact.</a><br/>  
[...]
As you would notice, we have pointed this link to "contacts/addNew.html". This means that we need something - a controller and / or a method that is looking for this request. Let us create a controller that will field all requests starting with "contacts".

File: src/main/java/org/academy/ui/spring3/controllers/ContactCtlr.java
package org.academy.ui.spring3.controllers;                   
                                                              
import org.academy.ui.spring3.forms.ContactFrm;               
import org.slf4j.Logger;                                      
import org.slf4j.LoggerFactory;                               
import org.springframework.stereotype.Controller;             
import org.springframework.validation.BindingResult;          
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;          
                                                              
@Controller                                                   
@RequestMapping(value = "/contacts")                          
public class ContactCtlr {                                    
 private final static Logger logger = LoggerFactory        
   .getLogger(ContactCtlr.class);                    
[...]
}
Spring also has to know that it has to scan for a particular package for controllers.

File: /springwebapp001/src/main/webapp/WEB-INF/spring-servlet.xml
[...]
<context:component-scan base-package="org.academy.ui.spring3.controllers" />   
[...]
Having set this we will need a method in the ContactCtlr to field GET requests for /addNew.html. [Aside: What is the difference between GET and POST request? Read here.]

File: src/main/java/org/academy/ui/spring3/controllers/ContactCtlr.java
[...]
private final String addNewView = "Contacts/AddNew";          
                                                              
@RequestMapping(value = "/addNew", method = RequestMethod.GET)
public String addNewContact() {                               
 logger.debug("Display form to add a new contact.");       
 return addNewView;                                        
}                                                             
[...]
Here we have simply directed the control to "Contacts/AddNew" which boils down to /springwebapp001/src/main/webapp/WEB-INF/views/Contacts/AddNew.jsp.

<%@taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<html>
<head>
<title>Add New Contact</title>
</head>
<body>
<form:form method="post" commandName="contact" action="addNew.html">
<table>
<tr>
<td colspan="2">Add a new contact.</td>
</tr>
<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="email">Email</form:label></td>
<td><form:input path="email" /></td>
</tr>
<tr>
<td><form:label path="telephone">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>
This form will need to be backed by a java pojo which will hold all the form elements mentioned in the jsp.

File: /springwebapp001/src/main/java/org/academy/ui/spring3/forms/ContactFrm.java
package org.academy.ui.spring3.forms;

public class ContactFrm {
 private String firstname; 
 private String lastname; 
 private String email; 
 private String telephone;
 
 public String getFirstname() {
  return firstname;
 }
 public void setFirstname(String firstname) {
  this.firstname = firstname;
 }
 public String getLastname() {
  return lastname;
 }
 public void setLastname(String lastname) {
  this.lastname = lastname;
 }
 public String getEmail() {
  return email;
 }
 public void setEmail(String email) {
  this.email = email;
 }
 public String getTelephone() {
  return telephone;
 }
 public void setTelephone(String telephone) {
  this.telephone = telephone;
 }

}
From the AddNew.jsp you can see the form expects someone to handle a call to "addNew.html". As before, lets get back to the controller and add a method that handles a POST request to "addNew.html". Please note that this is a POST request as opposed to the GET request which we have handled before.

File: /springwebapp001/src/main/java/org/academy/ui/spring3/controllers/ContactCtlr.java
[...]
@RequestMapping(value = "/addNew", method = RequestMethod.POST)         
public ModelAndView addNewContact(                                      
  @ModelAttribute("contact") ContactFrm contactFrm,               
  BindingResult result) {                                         
 logger.debug("Adding a new contact. {}", contactFrm.getFirstname());
 // Some code to work on the data received from the user.                                                                     
 return new ModelAndView(addNewView, "contact", new ContactFrm());   
}
[...]
Lo and behold, if you compile and run this app in any servlet container i.e. Tomcat, you will get a link, that will lead to a Form, that will allow you to put in data, that will transport that data to a java controller at server end, and come back to the form for more. Those of the audience who have designed and developed web applications before MVC frameworks came into being will have moist eyes for sure. Even if you have worked with the early frameworks for MVC, Struts to name the most successful one, will rue the hours spend in getting the three components (M,V and C) together, that now we can get done in under 10 minutes. Software development has definitely come a long way.

In the next section we will add unit testing and logging to this application. Happy coding.

Want to read more?

Here is the link to earlier article in this series.
Hello World with Spring 3 MVC


And, of course these are highly recommended
Struts - The only other MVC framework that I can recommend
Difference between GET and POST
The origin of the term MVC

If you want to get in touch, you can look me up at Linkedin or Google + .

No comments: