Ask a question
Monday, 14 September 2009 12:58

Agile - Spring Web MVC Framework

Rate this item
(1 vote)
Benefits of the Spring Web MVC Framework

The Spring Web MVC Framework is a robust, flexible, and well-designed framework for rapidly developing web applications using the MVC design pattern. The benefits achieved from using this Spring module are similar to those you get from the rest of the Spring Framework. Let's review a few of these. I will demonstrate some of these benefits later in this chapter.
 
·         Easier testing This is a common theme you will find across all the Spring classes. The fact that most of Spring's classes are designed as JavaBeans enables you to inject test data using the setter methods of these classes. Spring also provides mock classes to simulate Java HTTP objects (HttpServletRequest, for example), which makes unit testing of the web layer much simpler.
·         Bind directly to business objects Spring MVC does not require your business (model) classes to extend any special classes; this enables you to reuse your business objects by binding them directly to the HTML forms fields. In fact, your controller classes are the only ones that are required to extend Spring classes (or implement a Spring controller interface).
·         Clear separation of roles Spring MVC nicely separates the roles played by the various components that make up this web framework. For example, when we discuss concepts such as controllers, command objects, and validators, you will begin to see how each component plays a distinct role.
·         Adaptable controllers If your application does not require an HTML form, you can write a simpler version of a Spring controller that does need all the extra components required for form controllers. In fact, Spring provides several types of controllers, each serving a different purpose. For example, there are no-form controllers, simple form controllers, wizardlike form controllers, views with no controllers, and even prepackaged controllers that enable you to write views without your own custom controller.
·         Simple but powerful tag library Spring's tag library is small, straightforward, but powerful. For example, Spring uses the JSP expression language (EL) for arguments to the tag.
·         Web Flow This module is a subproject and is not bundled with the Spring core distribution. It is built on top of Spring MVC and adds the capability to easily write wizardlike web applications that span across several HTTP requests (an online shopping cart, for example).
·         View technologies and web frameworks Although we are using JSP as our view technology, Spring supports other view technologies as well, such as Apache Velocity (jakarta.apache.org/velocity/) and FreeMarker (freemarker.org). This is a powerful concept because switching from JSP to Velocity is a matter of configuration. Furthermore, Spring provides integration support for Apache Struts (struts.apache.org), Apache Tapestry (jakarta.apache.org/tapestry), and OpenSymphony's WebWork (opensymphony.com/webwork/).
·         Lighter-weight environment As I mentioned in the previous chapter, Spring enables you to build enterprise-ready applications using POJOs; the environment setup can be simpler and less expensive because you could develop and deploy your application using a lighter-weight servlet container.

Spring Web MVC Concepts

The world of Java has seen many MVC design pattern-based web frameworks crop up in the past few years (several are listed at the very end of this chapter). MVC was originally conceived at XEROX PARC around the 197879 time frame and was later implemented in the Smalltalk-80 class library (also at XEROX PARC). It is a relatively simple concept to grasp and provides for a clean separation of presentation and data, as I'll explain briefly here.

First, let's look at our architecture diagram established earlier in the book and shown here in Figure 7.1.
 
Figure 7.1. High-level architecture diagram for Time Expression

As you can see, all incoming HTTP requests from a web browser are handled by Controllers. A controller, as the name indicates, controls the view and model by facilitating data exchange between them. The key benefit of this approach is that the model can worry only about the data and has no knowledge of the view. The view, on the other hand, has no knowledge of the model and business logic and simply renders the data passed to it (as a web page, in our case). The MVC pattern also allows us to change the view without having to change the model.

Let's review some basic Spring MVC concepts. First, we will look at the concepts related to Java coding, and then we will look at the configuration required to make all this work.

Spring MVC Java Concepts

Figure 7.1
provided us a high-level view of the architecture for Time Expression. Now let's take a slightly more detailed and focused look at the Spring MVC components. Figure 7.2 shows an end-to-end flow for a typical screen in Time Expression. This diagram shows many of the concepts we will discuss next.
 
Figure 7.2. End-to-end flow for Enter Hours screen using Spring and Hibernate.
Controller

Spring provides many types of controllers. This can be both good and bad. The good thing is that you have a variety of controllers to choose from, but that also happens to be the bad part because it can be a bit confusing at first about which one to use.

The best way to decide which controller type to use probably is by knowing what type of functionality you need. For example, do your screens contain a form? Do you need wizardlike functionality? Do you just want to redirect to a JSP page and have no controller at all? These are the types of questions you will need to ask yourself to help you narrow down the choices.

Figure 7.3
shows a class diagram of some of the more interesting controllers that are part of Spring MVC. Table 7.1 provides brief descriptions on the interface and classes shown in Figure 7.3. (Note:The descriptions provided in this table are taken directly out of the Spring Framework Javadocs.) I tend to use SimpleFormController, UrlFilenameViewController, and AbstractController most often. We will see examples of these later in this chapter.

 
Figure 7.3. Class diagram showing a partial list of Spring controllers.




Description-of-Various-Spring-Controllers
 
Model and View
Many of the methods in the Controller related subclasses return a org.springframework.web.servlet.ModelAndView object. This object holds the model (as a java.util.Map object) and view name and makes it possible to return both in one return value from a method. We will see examples of this later in this chapter when we build two of the screens for Time Expression.
Command (Form Backing) Object

Spring uses the notion of a command object, which essentially is a JavaBean style class that gets populated with the data from an HTML form's fields. This same object is also passed to our validators (discussed next) for data validation, and if the validations pass, it is passed to the onSubmit method (in controller related classes) for processing of valid data. Given that this command object is a simple JavaBean-style class, we can use our business objects directly for data binding instead of writing special classes just for data binding. I will demonstrate this benefit later in this chapter.
Validator

A Spring validator is an optional class that can be invoked for validating form data for a given command (form) controller. This validator class is a concrete class that implements the org.springframework.validation.Validator interface. One of the two methods required by this interface is the validate method, which is passed a command object, as mentioned previously, and an Errors object, which can be used to return errors. I will demonstrate an example of a Validator class later in this chapter. Another notable validation class is org.springframework.validation.ValidationUtils, which provides convenient methods for rejecting empty fields.
Spring Tag Library (spring:bind)

The spring bind tag library is simple yet powerful. It is typically used in JSP files via the tag, which essentially binds HTML form fields to the command object. Furthermore, it provides access to special variables within JSP, such as ${status.value}, ${status.expression}, and ${status.errorMessages}, which we will look at later in the chapter.

Spring MVC Configuration Concepts

In this section, we will review some core concepts related to configuring the Spring Web MVC Framework.
DispatcherServlet

DispatcherServlet
(part of the org.springframework.web.servlet package) is the entry point to the world of Spring Web MVC, as depicted in Figure 7.2. It essentially dispatches requests to the controllers. If you have worked with Java web applications before, you will not be surprised to find out that this class is configured in the web.xml file, as shown in the following excerpt from the complete web.xml for Time Expression:
org.springframework.web.servlet.DispatcherServlet
 
We will discuss DispatcherServlet in detail later in this chapter.
Handler Mappings

You can map handlers for incoming HTTP requests in the Spring application context file. These handlers are typically controllers that are mapped to partial or complete URLs of incoming requests. The handler mappings can also contain optional interceptors, which are invoked before and after the handler. This is a powerful concept. I will demonstrate an example of this later in this chapter when we use such a web interceptor for authentication and close our Hibernate session for the given HTTP request.

The following code excerpt taken from our complete timex-servlet.xml file shows how a handler can be mapped to a partial URL:
    class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
    
        
            signInController
            signOutController
        
    


View Resolvers
Spring uses the notion of view resolvers, which resolve view names to the actual views (enterhours to enterhours.jsp, for example). We will use Spring's InternalResourceViewResolver class to resolve our view names. (This is covered in the next section.)

Spring Setup for Time Expression
Now that I have provided you some fundamental concepts for Spring MVC, let's begin setting it up for development of Time Expression screens.
We need a couple of components to get Spring up and running for us. Figure 7.1 showed the Time Expression high-level architecture we established early in this book. As you can see, we need a servlet container that Spring can run within for our web application. So let's start with the installation of a Servlet container first, and then we will download and install the Spring Framework.
Installing a Servlet Container (Apache Tomcat)
I have chosen to use Apache Tomcat (http://tomcat.apache.org/) as the Servlet container for the Time Expression application. However, you can use any other product you want; this can be a servlet-container-only product, such as Tomcat, or a full-blown application server, such as JBoss Application Server, BEA WebLogic, or IBM Websphere.
Note
If you have been following along the examples in this book, you will recall the timex/local.properties file used by our Ant build.xml file (both files are provided in this book's code zip file). Note the deploy.dir property in the timex/local.properties file; this can be adjusted to point to your servlet container's deployment directory. For example, in my case, the deploy.dir property is set up as shown here:
deploy.dir=/apache-tomcat-5.5.15/webapps
 
 
Now we can run the ant deploy from a command line using our build.xml file.
By running this ant command, a fresh new timex.war web archive file will be built and deployed to the specified directory (in deploy.dir).
Hot Deploying WAR Files and HTTP Mock Style Testing
In 2001, I wrote an article titled "How Many Times Do You Restart Your Server During Development?" (http://www.javaworld.com/javaworld/jw-04-2001/jw-0406-soapbox.html). Although various servlet containers or application servers handle reloading of applications differently, restarting the server every time you make a change to your application can become a waste of time. Much of this has to do with the way Java's class loading works, but it still doesn't make it any less frustrating.
If your server doesn't (hot) redeploy your war files successfully, you could consider tweaking your style of coding and testing. One good alternative (discussed in this chapter) is to use Spring's mock classes to simulate a HTTP request and use JUnit to unit test the code instead of relying completely on the web application server for your testing.
Incidentally, I recently came across an option for Apache Tomcat that will enable to us to avoid restarts when deploying our application. This can be activated by setting the following attributes in the conf/context.xml file found under the Tomcat install directory, .
Alternatively, we could use the Tomcat Ant deploy tasks; however, I wanted to keep our build.xml generic for most web servers. Nevertheless, documentation on these tasks can be found at the tomcat.apache.org website.

Installing the Spring Framework
By now, you should have a thorough understanding of what Spring can do for you. Next, it is time to download Spring, install it, and begin using it!
The Spring Framework can be downloaded from http://springframework.org. We will now follow the instructions provided on the website to download and install it.
The following are one-time setup steps we will need to follow to get Spring set up for our environment. From here, you might add external jars for added Spring functionality as needed to the timex/lib/ directory. (In Chapter 10, "Beyond the Basics," we will add OpenSymphony's quartz.jar file to our directory.)
  • Spring Copy spring.jar to the timex/lib/ directory of Time Expression, based on the directory structure we established in Chapter 3, "XP and AMDD-Based Architecture and Design Modeling," and shown here in Figure 7.4.
Directory Structure of Time Expression

 
   JSTL We also need to obtain JavaServer Pages Standard Tag Library (JSTL), which is part of the Jakarta taglibs project and can be downloaded from http://jakarta.apache.org/taglibs/. After downloading this package, copy the jstl.jar and standard.jar files to the timex/lib/ directory. JSTL helps eliminate (or at least significantly reduces) the amount of embedded scriptlet code in our JSP files. For example, JSTL provides tags for iterations/loops (, for example), conditional tags (, for example), formatting tags (fmt:formatDate, for example), and several other tags. You will see examples of many of these tags in this chapter.

Running Our SpringTest

Incidentally, the three files we discussed in the previous chapter can now be created in the following paths, and we could run ant springtest (from our timex/ top-level directory) to test that we can use Spring in our code. The complete code for these files can be found in this book's code zip file:
 
·         src/conf/springtest-applicationcontext.xml
·         src/java/com/visualpatterns/timex/test/SpringTest.java
·         src/java/com/visualpatterns/timex/test/SpringTestMessage.java

Configuring Spring MVC

Now that we have the servlet container and Spring software installed, we need to configure Spring MVC so that we can begin developing and deploying the Time Expression sample application.
Configure DispatcherServlet inweb.xml

The very first thing we need to do is to have all incoming HTTP requests (that match a certain pattern) forwarded to Spring MVC, by Tomcat.

The following excerpt from our web.xml file demonstrates how we can configure all requests ending with an .htm extension to be processed by the Spring's org.springframework.web.servlet.DispatcherServlet class:
    timex
    
        org.springframework.web.servlet.DispatcherServlet
    
    1
 
    timex
    *.htm
 
 
Later on we will see how requests with a .jsp extension are handled by Spring's DispatcherServlet.

Note
Our Spring application context file, timex-servlet.xml, will automatically be searched for and loaded by Spring for us.

This file is stored under timex/src/conf but automatically copied to the timex/build/timex/WEB-INF/ directory by our Ant build.xml file when the build, dist, or deploy targets are used.


 
Create Spring's Application Context XML File (timex-servlet.xml)

Now we need to create our application context XML file, timex-servlet.xml. We will review various parts of this file throughout the remainder of this chapter. You will see how this file quickly becomes an essential part of working with Spring MVC.

The following excerpt from timex-servlet.xml shows how we configure a Spring view resolver to resolve logical view names to the physical view (JSP) file:
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    
        org.springframework.web.servlet.view.JstlView
        
    
        /WEB-INF/jsp/
    
    
        .jsp
    
 
 
Note
By storing our JSP files in the build/timex/WEB-INF/jsp/ directory, we are essentially hiding these files so they cannot be accessed directly from a web browser using their actual filenames (that is, only views ending with .htm are mapped to these files). To access .jsp files directly, they must be placed a couple of levels up, under build/timex/, the same location where our welcome file, index.jsp, will reside.

Hiding files is a security precautionary measure. Appendix D, "Securing Web Applications," provides additional security guidelines.

Developing Time Expression User Interfaces with Spring

Now that we have Tomcat and Spring installed and set up, we can go through the steps required to develop our sample screens. Let's look at two Time Expression screens we will develop in this chapterone a nonform screen and the other an HTML form screen.

Timesheet List Screen

Figure 7.5
shows the Timesheet List screen, which is a nonform screen (that is, it contains no input fields a user can fill in because it is a display-only screen). From the perspective of coding a controller, this is the most basic screen that you can develop using Spring MVC; we will review the code behind this shortly.
 
Figure 7.5. Time Expression's Timesheet List web page (view name: timesheetlist).

Enter Hours Screen

Figure 7.6
shows the Enter Hours screen, a form screen (that is, it contains input fields a user can fill in). This is a little more complicated than the Timesheet List screen because we will have to bind the HTML form fields to our Java code, perform validations on the data entered, display errors, and so on.
 
Figure 7.6. Time Expression's Enter Hours web page (view name: enterhours).

Java Files

By now we have enough information to come up with filenames for our Java classes and JSP (view) filenames. Table 7.2 shows a map of the view, controller, and collaborator (model) classes required to complete the two screens shown in Figures 7.5 and 7.6. You might recall that we designed this map in Chapter 3 (see Table 3.5).

 
Table 7.2. Sample Application Flow Map

Note that the collaborator classes mentioned here were already developed in Chapter 5, "Using Hibernate for Persistent Objects," so we need to develop the view and controller classes now.
Figure 7.7 shows a rudimentary class diagram on how the controller and model related classes fit together.
 
Figure 7.7. Class diagram showing relationship between Time Expression model and controller classes

If you have developed web applications in Java before, you might question the placement of .jsp files under the same directory structure as my Java classes (that is, java/com/visualpatterns/timex/); this is purely a personal preference because I like to see my MVC files grouped together under the same parent directory.

Let's look at how to develop the Timesheet List and Enter Hours screens, step-by-step. We will later look at how to develop the Sign In screen because it is a special case because of the authentication (sign in) required.

Timesheet List Screen: A No-Form Controller Example

Developing a no-form controller in Spring is a relatively straightforward process. Let's look at the steps involved to do this.

Step-by-Step Configuration

The following are Spring-related items we need to configure in timex-servlet.xml, our Spring application context file.
Map Handler

The first thing we need to do is to map the incoming request URL to an actual controller, which will handle the request. The following excerpt from the timex-servlet.xml file shows how we can map the timesheetlist.htm URL to an internal bean reference named timesheetListController (discussed next) with the help of Spring's SimpleUrlHandlerMapping class:
    class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
    
        
            
        
    
    
        
            
                timesheetListController
            
 
Also, notice the interceptors property; by configuring this, we can intercept HTTP requests, for example, to implement authentication (interceptors are discussed in detail later in this chapter).
Define Controller and Associated Class

The next step is to define the controller class referenced by the map handler. The following excerpt from the timex-servlet.xml file demonstrates how this is done:
    class="com.visualpatterns.timex.controller.TimesheetListController">
    
        
    
    
        
    
 
    
        timesheetlist
    
 
 
Notice the ref attributes. As you might guess, these are references to other beans defined in our application context, as shown in this XML excerpt:
    class="com.visualpatterns.timex.model.TimesheetManager"/>
    class="com.visualpatterns.timex.util.ApplicationSecurityManager" />
 
We already developed the TimesheetManager class in Chapter 5; we will develop the ApplicationSecurityManager class later in this chapter.
This is all we need to configure for the Timesheet List screen. Now we need to write the controller and view code, referenced here. Let's look at that next.

Step-by-Step Coding

The Timesheet List screen is a relatively simple screen and will be developed using the most basic type of Spring controller because it contains no form fields; therefore, it will not require things such as Command and Validator classes. Basically, if we look at this from an MVC design pattern perspective, the files for this screen will include the following:
 
·         Model TimesheetManager.java and Timesheet.java
·         View timesheetlist.jsp
·         Controller TimesheetController.java

We already developed the model files in the previous chapter, so all we need to develop here are the controller and view files. Let's dissect and review parts of our complete code.

Let's begin by writing the unit test code for our controller class.
Writing Our Test First with Mock Objects

The next few code excerpts from our TimesheetListControllerTest.java file show how we can unit test controller classes. We will create this in the timex/src/java/com/visualpatterns/timex/controller directory.
We start by creating an instance of the org.springframework.mock.web. MockHttpServletRequest class to simulate a real HTTP request. This class not only provides the benefit of being able to unit test our code but also reduces the need to deploy the application and potentially restart the servlet container (Tomcat, for example) each time we want to test something.
mockHttpServletRequest = new MockHttpServletRequest("GET",
"/timesheetlist.htm");
 
Next, we will create some test dependency objects and inject them, as Spring will do for us at runtime:
Employee employee = new Employee();
employee.setEmployeeId(EMPLOYEE_ID);
applicationSecurityManager.setEmployee(mockHttpServletRequest,
        employee);
 
// inject objects that Spring normally would
timesheetListController = new TimesheetListController();
timesheetListController.setTimesheetManager(timesheetManager);
timesheetListController
        .setApplicationSecurityManager(applicationSecurityManager);
 
In our test code, we instantiated our own TimesheetManager class for the sake of simplicity. However in real-world applications, you might want to use Spring's FileSystemXmlApplicationContext or ClassPathXmlApplicationContext classes to instantiate your classes. This way, you not only get an instance of a class but also have its dependent objects loaded and injected by Spring.
Now we can complete our test by checking the java.util.List we just retrieved; our test ensures that list is not empty and also that it contains Timesheet objects for the employee we requested the records for:
ModelAndView modelAndView = timesheetListController.handleRequest(
        mockHttpServletRequest, null);
 
assertNotNull(modelAndView);
assertNotNull(modelAndView.getModel());
 
List timesheets = (List) modelAndView.getModel().get(
        TimesheetListController.MAP_KEY);
assertNotNull(timesheets);
 
Timesheet timesheet;
for (int i = 0; i < timesheets.size(); i++)
{
     timesheet = (Timesheet) timesheets.get(i);
     assertEquals(EMPLOYEE_ID, timesheet.getEmployeeId());
     System.out.println(timesheet.getTimesheetId() + " passed!");
}
 
That's about it for our unit test class; now let's review the actual TimesheetListController class.

Writing Unit Test and Actual Code in the Same Sitting

This book's code zip file shows the complete code for our TimesheetListControllerTest.java class, which is the JUnit test case for TimesheetController.java. As I've preached previously in this book, development of a unit test and the actual code works best when it is done in the same sitting. For example, I wrote the TimesheetListControllerTest.java and TimesheetListController.java in the same sitting; that is, I coded a little, compiled and tested a little, and then repeated these steps until my controller class provided all the functionality I needed. The obvious benefit of this approach was that my code was unit tested by the time I was done!

Furthermore, our controller class will now contain only the code we neednothing more, nothing less.

Another notable benefit worth mentioning is that at times I find myself getting programmer's block (similar to writer's block). But starting out with the unit test code helps me get going. Note that what I have mentioned here is a personal style of working, but hopefully you will find value in it and give the test-first approach a try (if you don't already do so).
 
One thing I do want to stress is that like everything else, you need to find the right balance. Although I believe in the test-first approach, there are times when it isn't feasible for me to write a unit test code that becomes more complicated than the actual code or is cumbersome to write. After all, you are writing Java code to test other Java code, which raises an obvious questiondo we also test the test code? Of course, I'm kidding here, but my point is to find the right balance and in most cases, unit tests work out pretty well.

Last, unit testing works best if you write small methods that can be unit tested relatively easily.


 
Controller Code

Now it is time to review the code behind our controller class for the Timesheet List screen, TimesheetListController.java. We will create this in the timex/src/java/com/visualpatterns/timex/controller directory.

For starters, notice that we are implementing the org.springframework.web.servlet.mvc.Controller interface; this is perhaps the most basic type of controller you can develop using Spring.
public class TimesheetListController implements Controller
The next interesting thing to note is the handleRequest method; this is the only method we must implement to satisfy the requirements of the Controller interface.
public ModelAndView handleRequest(HttpServletRequest request,
                                 HttpServletResponse response)
 
The handleRequest method returns a ModelAndView object, which contains the view name and the model data (a java.util.List, in our case). The view name is resolved by JstlView, which we defined in the timex-servlet.xml file we saw earlier in this chapter.
return new ModelAndView(VIEW_NAME,
                        MAP_KEY,
                        timesheetManager.getTimesheets(employeeId));
 
There are a few more variations to how you can construct the ModelAndView class, as shown in the following list (see the Spring Framework API Javadocs for details):
·         ModelAndView()
·         ModelAndView(String viewName)
·         ModelAndView(String viewName, Map model)
·         ModelAndView(String viewName, String modelName, Object modelObject)
·         ModelAndView(View view)
·         ModelAndView(View view, Map model)
·         ModelAndView(View view, String modelName, Object modelObject)
View/JSP Code

We already prototyped the screens in Chapter 2, "The Sample Application: An Online Timesheet System," so we now need to add some code to the related view (.jsp) files. This book's code zip file contains the before file, timesheetlist.html (prototyped, static HTML), and the after file, timesheetlist.jsp (dynamic/JSP), versions of this file.

Let's review our timesheetlist.jsp a bit closer. For starters, we will create this in the timex/src/java/com/visualpatterns/timex/view directory. Now let's look at some JSP code.
The following excerpt from our timesheetlist.jsp file shows the dynamic code used for populating the HTML table on the Timesheet List screen; this is done in a loop using JSTLs forEach tag. Within each loop, we are generating the HTML table's rows and columns (and also formatting the hours) using the JSTL core library.
    
        
            href='enterhours.htm?eid=
Last modified on Wednesday, 23 September 2009 21:11
Vicky

Vicky

E-mail: This e-mail address is being protected from spambots. You need JavaScript enabled to view it