Mastering Spring MVC

Enjoy Spring-based Web development with the Spring MVC module

Model-View-Controller Web frameworks for Java are plentiful, and most of them integrate with Spring, but the tightest integration can be found in Spring's own MVC module. Get started with Spring MVC in this introductory article by Steven Haines, who begins with a history of the Model-View-Controller paradigm in Java Web development. He then introduces the Spring Framework and explains how it leverages the concepts of Spring, including dependency injection. Finally, Steven guides you through a programming tutorial that demonstrates the core features of Spring MVC in an easy-to-follow, hands-on format. Level: Beginner

In the ongoing evolution of Java EE technologies, the Spring Framework has emerged as a top choice for the middle, or business tier of enterprise application development. Spring's lightweight paradigm for developing enterprise applications has won it a large following that today rivals that of the standard Java EE platform. As a result, most MVC (Model-View-Controller) Web frameworks integrate with Spring, including Spring's in-house module, Spring MVC. If you're developing Spring applications for the Web, familiarity with Spring MVC will help you step up your game while also leveraging all the familiar benefits of the Spring Framework.

To provide a context for understanding Spring MVC, I'll start with a brief history of Java Web applications, followed by an overview of the Spring Framework and its business value. I'll then introduce Spring MVC and walk you through a development project: a mini content-management system (CMS) that demonstrates how to build and deploy a Spring MVC application. You can download the source code any time.

Java Web applications: A brief history

This brief history begins with Java's entry into Web application development: the Servlet API, introduced in 1997. Before then, developing dynamic Web applications with disparate APIs and programming models proved to be challenging. (I'll resist the urge to recap the old days of CGI, the futile battle between Netscape Server plug-ins and ISAPI plug-ins, and all the homegrown APIs.) The Servlet API provided a standard on which vendors could build Web containers and developers could implement a simple programming model for constructing Web pages.

With servlets, dynamically constructing HTML documents became easy. But because the documents were constructed inside Java source code, maintenance was challenging. For example, changing a font or moving a piece of content within a page required you to update the HTML inside the servlet code and then recompile and redeploy it to the container.

Sun resolved this issue in 1999 by introducing JavaServer Pages (JSP). 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?

The solution was to separate programmatic responsibilities into the technologies best suited for them. 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:

  • The model represents your data or the objects with which your application is interacting.
  • The view is a visualization of your model.
  • 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.

Spring: An overview

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.

Introducing Spring MVC

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:

  • One or more controllers that invoke business logic and create a ModelAndView object
  • A visualization component such as a JSP
  • 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:

  • Redirect to static views
  • Provide basic servlet-like functionality
  • Process commands
  • Process shared actions
  • Handle forms
  • 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.

Listing 1 shows the source code for the homepage controller. This simple controller accepts no request parameters and returns a ModelAndView object that contains a list of news articles.

Listing 1. HomePageController.java

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 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:

  • "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).
  • "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.
  • 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>
1 2 3 4 Page
Recommended
Join the discussion
Be the first to comment on this article. Our Commenting Policies
See more