Mastering Spring MVC

Enjoy Spring-based Web development with the Spring MVC module

1 2 3 4 Page 4
Page 4 of 4
<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.

Listing 10. 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.

Internationalization support

The third parameter passed to the ValidationUtils methods is a key into a properties file from which Spring can look up the value to display as the error message. This is for internationalization, which is beyond the scope of this article. Just know that Spring supports internationalization, and this is one example of where it does so.

Listing 11 shows the source code for the post.jsp file.

Listing 11. 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:

  • The <form:form> tag's additional commandNameparameter should match up to your SimpleFormController's setCommandName() parameter.
  • 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.

In conclusion

In a few easy lessons, you've built a fully functioning Spring MVC application from scratch. You started by using a simple controller to construct a model and pass it to a JSP file for presentation. Then you added a command controller and a form controller for form validation.

Spring MVC is a highly capable framework and a powerful extension to the Spring Framework. It provides several ways to map request URIs to controllers, defines several controller base classes to suit your business needs, and gives you multiple options for mapping view names to views. If you are building Spring applications, Spring MVC certainly should be at the top of your short list of Web frameworks.

Steven Haines is the founder and CEO of GeekCap, Inc., which provides technical e-learning solutions for software developers. Previously he was the Java EE Domain Expert at Quest Software, defining software used to monitor the performance of various Java EE application servers. He is the author of Pro Java EE 5 Performance Management and Optimization, Java 2 Primer Plus, and Java 2 From Scratch. He is the Java host on InformIT.com and a Java Community Editor on InfoQ.com. Steven has taught Java at the University of California, Irvine, and Learning Tree University.

Learn more about this topic

More from JavaWorld

1 2 3 4 Page 4
Page 4 of 4