Back to Thoughts On Technology Page | Back to Peter's Home Page | Back to Family Home Page

Simple Spring 4.x Example
Peter Rose - 08/11/14


Abstract
Summary
Basics

Application Development: Phase 01
Setting Up The Example Environment
web.xml
Spring xml Configuration File
The SprBeanForm.java
Developing The Application's Controller Layer
Phase 01 is Done: Ship It!

Application Development: Phase 02
Setting Up The Phase 02 Environment
Developing The Application's View Layer
Developing A Spring Annotated Controller
Phase 02 is Done: Ship It!

Application Development: Phase 03
Updating SprPageController
Updating Screen Display Code
Phase 03 is Done: Ship It!

Application Development: Phase 04
Summary
Setting Up The Phase 04 Environment
Change JSP Screens
Modified SprPageController
Browser to Controller Communication Flow
Controller Redirect on Submit
Final Thoughts


Top


Abstract
This article will provide a simple introduction to some of the very basic Spring 4 implementation features that I have found key to understanding how to use Spring.

It is written for someone who understands the basics of web application development who wants to learn Spring, but can't find a truly simple, basic map of how to do this.

I don't cover any of the supporting general technologies that one would have to know just to be interested in the main topic. I do not, however, make any assumptions about what you the reader knows about the main topic. I start talking about the topic from ground zero making no assumptions that the reader has any idea where to even start their learning.

This means that I write the same way that I develop code: write the simplest code you can, test it, and then move to the next very simple step.

Top


Summary
To my mind, the key component to understand Spring is the xml configuration file that sits in your project's WEB-INF directory (or in my case at the src root level parallel with com). For this discussion, this file is called spr-servlet.xml. It's the traffic cop that directs business logic flow from both jsp and servlet/controller class. Thus, you'll find a lot of referencing to this file as the article progresses.

I'm going to develop a really, stupidly, simple application to show how all this referencing ties together.

Development will be broken down into Phases, one small step at a time. The first phase just establishes the structural environment, directory structure, and the absolute minimal code to show Spring communication outside of the browser.

In Phase 02, I'll put together a very simple browser request to controller with simple page display to just lay out the bones of that initial Spring communication within the View-Controller layers.

Phases 03 and 04 continue to expand the example, all still using the absolute minimal Spring code. In Spring, like a lot of things, there are many ways to not only solve simple problems, but many ways to configure solutions to complex problems. I'll show you stupid simple, basic solution path. You can take that knowledge and use it to figure out all the rest.

Top


Basics
I assume this is not the first web application that you are looking at and that you understand the M-V-C object oriented model that Spring is built on in general, can set up Tomcat, use an ant file, know the difference between a servlet and a Spring controller class, have worked with Java Interfaces and abstract classes, and grasp the use of web.xml and xml configuration files. If not, then this 'simple' example won't be so simple and you may want to pass on this article.

The main components of a really simple Spring application are:

  • The .jsp File
  • web.xml
  • Spring xml Configuration File
  • Spring Controller Class
  • The View Bean

The trick in using Spring is to find those key useful elements in these components that you need to know in order to understand enough to get a jsp to display in your browser that is populated from a Spring controller class. Let's take each piece and briefly define it before getting into the tall weeds.


The .jsp File
Like any other jsp file, Spring has a tagging methodology that is used to either display data or to pass input data back to a controller class.


web.xml
The web.xml file is pretty standard stuff for web applications. They define what files are in the application as well as telling the application server what tags to look for from a browser request, and what the master Spring controller class is that needs to be called as a result of that request.


Spring xml Configuration File
Spring uses an xml configuration file that contains metadata that defines the application beans and their dependencies. This file takes the specific tag from a browser request and maps it to a specific controller class implementing the master Spring controller class.


The Spring Controller Class
These classes are servlets that implement the Spring Controller. The Spring xml configuration file directs requests to these classes. They work indirectly (and sometimes directly) with the HttpServlet api.

I might point out a concern I had when I first took a look at Spring. The controller that is used with most applications that provide forms based processing is the SimpleFormController. I went to the JavaDocs on this and was distressed to see that this object is 6 layers of abstraction down from Object whereas, for example, the DispatchAction in Struts is 2 layers down, just extending Action. I'm wondering where the modern design of flat inheritance in favor of composition by type went to? But that was under the Spring 2.x model. Spring 3.x has deprecated all extensions to controller classes. Instead, controllers are just Spring annotated pojos. More on this later, but infinitely more acceptable than bloated inheritance hierarchies.


The View Bean
These are java objects that are manipulated and transported via the Spring ModelAndView class. They are used for data transport and communication between the jsp and the Spring controller class.

Top


Application Development: Phase 01


Top


Setting Up The Example Environment
Before jumping into the code, I want to define the spr project and lay out it's directory structure so you have a simple map of where things are.


The Spring Framework
Obviously, before you do anything you have to download the Spring framework. If you understand Maven, then you'd go to: http://spring.io/projects. Because there is no single downloadable jar or zip file for Spring, you either build a Maven project that will go out and get all of these files, or you go to http://repo.spring.io/release/org/springframework/spring/, select the version that you want, and download that zip file.

Note that upgrading to jdk 1.8 requires Spring 4. Don't try to use Spring 3.x with jdk 1.8.... By the way, after pouring through literally 30 sites claiming to answer Tomcat initialization Exceptions, it was only after reading the comment by Aleksandr Dubinsky from a Stack post that I learned this stupidly simple answer. I don't belong to Stack so I have no way of contacting him, but my deep thanks to Aleksandr for bringing me back from jumping out of my ground floor study window. See last post at: http://stackoverflow.com/questions/22771826/beandefinitionstoreexception-failed-to-read-candidate-component-class.

From the Spring API documentation 17.2 JSP & JSTL: "Note that as of Spring 3.0, the minimum supported servlet version is 2.4 (JSP 2.0 and JSTL 1.1), which reduces the scope for confusion somewhat."

I'm coming into this not knowing Maven. Rather than holding my learning of Spring up by trying to figure Maven out, I downloaded the zip file, extracted all of the files into a junk directory, selected all of the api jars out of the list (like spring-beans-3.2.0.RELEASE.jar vs. spring-beans-3.2.0.RELEASE-sources.jar). I put those selected jar files into a springjars folder. I then pull those files into my IDE's library.

You'll need more than just those jars to work with, for example: commons-logging.jar. Having said that, you might not need to worry about any of this. If you want to work with plug-ins for your IDE and use Maven, then you can ignore a huge part of all of the ancillary setup work that I go through.

I want to understand everything, so I use a separate build file from the IDE. In that build file, I deploy my war into a separate instance of Tomcat on my server, by-passing the IDE. I do this so that I simulate a build and deploy to production external of an IDE so I have the control over the release and not some IDE. In addition, there are some shops that don't use frameworks, but rather raw JSP coding with, Oh! No! Servlets! So, you just better understand the guts of all this!

To get my initial environment setup, I also got the following jars and put them into my classpath:

  • commons-logging.jar (compilelib)
  • servlet-api.jar (compilelib)
  • com.springsource.net.sf.cglib-x.x.x.jar (for example: from http://grepcode.com/snapshot/repository.springsource.com with the following appended to url: /net.sourceforge.cglib/com.springsource.net.sf.cglib/2.2.0 to be placed into the springjars lib folder)

I don't run a web app from within my IDE. I use that to develop code that I then run an external xml build file against. This creates and deploys a war file into a separate instance of tomcat, again, external to the IDE.

Pardon me for digressing into a rant here, but a good software engineer knows how to build things, not just put stuff together out of black box. How are you ever going to successfully debug a problem that comes up if you can't determine if it's a structural issue or a programmatic issue?

I'm not stupid, but I feel stupid sometimes reading endless articles on the web by engineers who claim to teach this stuff, and yet make so many assumptions about what the reader actually knows. It literally took me 2 full days just to find out where these framework jars came from and how to build a 'simple' controller and a 'simple' bean.

I can't tell you how many 'simple' Spring examples use dependency injection of beans with 6 properties instead of showing how a bean is populated through the framework mechanics itself and then showing the injection schema. Looking at this stuff is like trying to learn Spanish out of a dictionary.

Trying to figure just the configuration of the framework and the construction of just a few of the required artifacts took me 4 full days fooling around reading this type of stuff on the web. I had to basically take pieces from several sites, combine them together, and correct invalid references in some of the files. I spent half a day just unscrambling silly, but indecipherable console and tommycat errors- all 'fatal', of course.


The spr Example Application Directory Structure
The name of my application is spr - short for Spring. Clever, hu? All it's going to do when complete is go to a welcome.jsp screen from a browser request, and display an input box into which a user can enter a quote. Submitting that quote sends a message to the controller to display who posted that quote onto the quotes.jsp page. A link on quotes.jsp will direct back to welcome.jsp. Pretty simple, but it will cover a lot of how to get going in Spring.


The Basic spr Directory Structure
The spr project's directory structure will exist under: c:/[some path]/

Project Directory Structure:


c:/[some path]/SpringLearning
   sprPhase01
      dev
         src
            spr-servlet.xml
            com
               pmr
                  spr
                     beans
                     controller
                        SpringBeans
                           SprBeanForm.java
                        SprPageController.java
         war
            web
               META-INF
               WEB-INF
                  classes
                     resources
                  jsp
                  lib
                  web.xml
   sprPhase02

Thus, when I create the project in the IDE, I'll name it by phase, i.e. SprPhase01, SprPhase02, etc. The IDE will thus put its folders and build directories under SprPhase01, for example. This is so I can just zip up the dev directory and dump it out anywhere and rebuild the project in the new environment. In this way, I don't bind my code to an IDE and can have multiple phases open to work with at the same time.

Top


web.xml
The web.xml file is pretty standard stuff for web applications. They define what files are in the application as well as telling the application server what tags to look for from a browser request, and what the master Spring controller class is that needs to be called as a result of that request.

When a browser request is made with the intent of displaying the welcome.jsp, it is the web.xml which directs the browser request to the correct Spring controller servlet. Here's a bare-bones skeleton of the web.xml that we'll build off of:

File: /war/spr/WEB-INF/web.xml:


<?xml version="1.0" encoding="UTF-8"?>

<web-app id="WebApp_ID" version="3.0"
  xmlns="http://java.sun.com/xml/ns/j2ee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
  http://java.sun.com/xml/ns/j2ee/web-app_3_0.xsd">

  <display-name>
      Spring 4.x Example Application Phase01
  </display-name>

</web-app>

If you're an experienced web developer then you know this is a useless implementation of web.xml. It's supposed to be at this point in my discussion. I'm not going to be using browser calls into the controller until Phase 02 development, so this file will never be called. It's here as a placeholder to show location only.

Top


Spring xml configuration file
Spring uses an xml configuration file containing metadata that defines the application beans and their dependencies. This file takes the specific tag from a browser request and maps it to a specific controller class implementing the master Spring controller class.

This config file, that I'll call spr-servlet.xml, is the core of Spring. You can put it anywhere in your classpath, usually at the root level of your project's WEB-INF directory. To make my life simple by not having to remember to configure a whole bunch of stuff if I move the project to another machine, I just put this file at the src level, parallel to com. Again, I'm going to refer to this file for this example as spr-servlet.xml.

Whereas web.xml defines the components of your web application, spr-servlet.xml controls how the information flows through your application (similar to how in Struts, for example, the struts-config.xml file functions). The spr-servlet.xml is the traffic cop of the application.

The spr-servlet.xml file is really the focal point of understanding Spring. Hitting a link on a .jsp or doing a forward reference from a Spring controller class triggers commands in spr-servlet.xml that redirect application flow. I'm going to address both of these, but before that you need to understand how information gets from the jsp to the controller class.

The spr-servlet.xml enables you to communicate with the Spring framework. It should be placed in your WEB-INF directory, and a really basic version for our non-browser based Phase 01 implementation is as simple as the following:

File: /war/spr/WEB-INF/spr-servlet.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"
   xmlns:p="http://www.springframework.org/schema/p"
   xmlns:context="http://www.springframework.org/schema/context"
   xsi:schemaLocation="
     http://www.springframework.org/schema/beans
     http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">

  <bean class="com.pmr.spr.controller.SpringBeans.SprBeanForm" id="mySprBean">
    <property name="postedBy" value="Property postedBy from spr-servlet.xml"/>
    <property name="message" value="Property message from spr-servlet.xml"/>
  </bean>

</beans>

The bean class tag is an xml definition of a java bean, SprBeanForm.java, that will be used as a DTO object to communicate information between the screen and the controller. So.... we sorta need to create this bean along with the controller that will reference and use it.

Top


The SprBeanForm.java
I defined an SprBeanForm.java structure in the spr-servlet.xml file. Obviously, I'm referring to the concrete SprBeanForm object in the controller, so I'll have to create an SprBeanForm.java class, or I'll get a compiler error. Here's the SprBeanForm.java class:

File: /src/com/pmr/spr/controller/SpringBeans/SprBeanForm:


package com.pmr.spr.controller.SpringBeans;

/**
 * SpringBean to connect jsp with controller
 *
 * @author zzrose
 */
public class SprBeanForm {
  private static final long serialVersionUID = 1L;
  private String postedBy = "bean Supreme Cosmic Cloud Force";
  private String message = "bean Bite my shorts!";

  public SprBeanForm() {
    System.out.println("Hark! SprBean instantiated!");
  }

  public String getMessage() {
    return message;
  }

  public void setMessage(String message) {
    this.message = message;
  }

  public String getPostedBy() {
    return postedBy;
  }

  public void setPostedBy(String postedBy) {
    this.postedBy = postedBy;
  }
}

Really simple. And note the print statement in the constructor. This will tell me where in the run process I am in case there's an error - which there was and this helped me debug the issue quickly. When things do work, you'll see exactly when this bean gets instantiated when the controller is run - and we'll be running that from the command line before we ever get to hooking a browser request into any of this.

Of most importance in Spring at this point is that SprBeanForm.java is just a pojo; nothing designating it as having anything to do with Spring. However, this does not mean that it won't later. Or, what happens when you change to a framework that does require beans that extend some framework base bean?

Keep all beans that transport data between the browser and controller separate from application beans. This may mean that you have to duplicate the bean to pass down into your business layer, but that's fine. All you need to do is employ the commons BeanUtils in the following manner:

import org.apache.commons.beanutils.BeanUtils;

UserBean newObject = new UserBean();
BeanUtils.copyProperties(oldObject, newObject);

What makes Spring aware of the SprBeanForm is its definition in spr-servlet.xml:


  <bean class="com.pmr.spr.controller.SpringBeans.SprBeanForm" id="mySprBean">
    <property name="postedBy" value="Property postedBy from spr-servlet.xml"/>
    <property name="message" value="Property message from spr-servlet.xml"/>
  </bean>

A few things to note from this. First is the id tag that identifies this bean to Spring as 'mySprBean'. Note that in the SprPageController, this SprBeanForm is extracted from the context via 'mySprBean'. Next, is that I've populated values for the SprBeanForm properties in both the spr-servlet.xml and in the bean itself. This is because when you run the program, you'll see exactly what Spring is doing with this bean, and when.

Finally, in this version the bean has its properties set to values. This is only if you know exactly what you want that bean to display on the screen on its initialization. When we run Phase 01 output, you'll see this xml set message vs one that we hard code into the bean itself; the xml file overrides the bean values. Be sure to note that in Phase 02 development, this bean definition will be simply 'sprBeanForm' vs 'mySprBean' which was done to show you that you can use any id to reference the object:

<bean class="com.pmr.spr.controller.SpringBeans.SprBeanForm" id="sprBeanForm"/>

Because Spring talks to and uses this bean, it's not really a Java Bean bean.... It belongs to the Spring Framework, not the application. It's part of the Spring controller and view structure, and is thus put into a sub folder, SpringBeans, of the controller directory, i.e. /spr/controller/SpringBeans/SprBean.java.

You may have wondered about that when you saw the directory structure layout that I presented earlier. This is why it's the way it is. This type of structure thus easily isolates the view and controller components from the rest of the application. You have to keep framework oriented components localized to the view layer of the application. If you allow the SprBean to migrate into the business layer section and it contains Spring annotations, what are you going to do when your project leader tells you to re-cast the app from Spring into Struts, or WebWork with Velocity Templates?

Top


Developing The Application's Controller Layer
The Spring controller classes are servlets that, under the sheets and not overtly, implement the Spring Controller. The Spring xml configuration file spr-servlet.xml directs requests to these classes. They work indirectly (and sometimes directly) with the HttpServlet api.

File: /src/com/pmr/spr/controller/SprPageController:


package com.pmr.spr.controller;

import com.pmr.spr.beans.SprBeanForm;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * Spring 4.x annotated controller vs implementing Controller or extending
 * older deprecated classes.
 *
 * @author Peter Rose
 */
public class SprPageController {

  public static void main(String[] args) {
    ApplicationContext context =
        new ClassPathXmlApplicationContext("spr-servlet.xml");
    SprBeanForm bean = (SprBeanForm) context.getBean("mySprBean");

    System.out.println("");
    System.out.println("----------------------------------------------");
    System.out.println("Message is: " + bean.getMessage());
    System.out.println("----------------------------------------------");
    System.out.println("");
  }
}

Notice that SprPageConroller doesn't extend or implement a Spring ancestor core class. We're not ready to fully bring Spring into the picture just yet.

As in any web application, you can get stuff out of the context. Thus, the controller, in this version, needs to use the context to get an instance of the SprBeanForm.java.

Top


Phase 01 is Done: Ship it!
A former Web Development Manager that I worked for a long, long time ago in a far away galaxy, (yes, Mark, this is you...) used to yell out, "SHIP IT!!!" when code was ready to deploy into the main test server. We'd all scramble around and make it happen, in a chaotic sort of way. But "Ship it!" meant just that: get it off your dev environment and onto the server. Now! Not tomorrow. Not when your deadline has past. Not in 10 minutes, or when you feel like it.... N-O-W!

Okay, let's ship it! Since the controller SprPageController has a main() method, just run it from your IDE. If you don't see something similar to the following output, or you get compiler errors, or Exceptions thrown out at you, then just keep chipping away at it until you get valid output. Do not continue until you get the output because you'll get hopelessly lost in the following discussions if you do.



Jul 12, 2014 2:59:19 PM org.springframework.context.support.AbstractApplicationContext prepareRefresh

INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@21b8d17c: startup date [Sat Jul 12 14:59:19 EDT 2014]; root of context hierarchy

Jul 12, 2014 2:59:19 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions

INFO: Loading XML bean definitions from class path resource [spr-servlet.xml]

Jul 12, 2014 2:59:19 PM org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons

Hark! SprBeanForm instantiated!

INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@2acf57e3: defining beans [mySprBean]; root of factory hierarchy

----------------------------------------------
Message is: Property message from spr-servlet.xml
----------------------------------------------

BUILD SUCCESSFUL (total time: 0 seconds)



Note that the message is from the spr-servlet.xml and not the hard-coded message that we put into the SprBean

Now, in the controller, right after the line where we get the SprBeanForm out of the context, we could add this line of code:

bean.setMessage("piss off.....");

When the controller is run, then the message in the console will be: "Message is: piss off....."

This is the end of Phase 01 development. There's no point in trying to do anything more complicated than this with Spring until you get the code to compile and run in your IDE. I spent 5 days trying to figure out how to get to just this point.

Trust me when I say this: Do not copy my code. Use it as a template and type everything in yourself. Make sure you understand what every piece of this means, and does before you go on to looking at the Phase 02 development.

Top


Application Development: Phase 02


Top


Setting Up The Phase 02 Environment
In Phase 02 I'm going to build a jsp page, welcome.jsp, and add some code to my controller, SprPageController.java, to recognize a browser request to display that welcome.jsp page. The welcome.jsp will display a drop down list of quotes sent from the server, i.e. controller. There will be a link under the quote to take you to quotes.jsp that will display the person who posted that quote. That's it. Just keeping it really, really simple.

In Phase 03, I'll populate a list of quotes for the welcome.jsp, show how to select one of those quotes, submit its id to the controller, which will call a business object, and return the author of that quote to the welcome.jsp page. I'm doing the same thing in Phase 02, but all of the display info is hard coded into the controller.


Create the a New sprPhase02 Directory Structure
In your windows explorer, create a new directory called sprPhase02 and put it under the directory SpringLearning, i.e. [path]/SpringLearning/SprPhase02. And then copy the following directories from sprPhase01 into sprPhase02: ant, archives, bin, compilelib, config, and dev.

"Whoah!" you're probably screaming right now if you're either an experienced developer or just out of school with your B.S. CS. "What's wrong with you? Why are you duplicating all of that? Why aren't you using a version control manager like CVS, SVN, LibreSource, PVCS, etc.? You just set version points and you can then easily rollback to whatever version you want at anytime. Why are you making this so difficult?"

I admit that my way is very pedestrian. I don't do this commercially; I use version control. Having said that, for this article I just don't want to make any assumptions about what the reader knows or can do. Why paralyze someone by using GIT version control in my discussion if they don't even know what version control software is or does, let alone how to use it?

I purposefully duplicate the code from one phase to the next and then add onto it as I go. I have all phases open as active projects in my IDE. Look, learning a new technology is difficult enough without having to get into configuring version control software, which, by the way, in 30 years of business applications software development I've never had to do. I'm a 'user' of technology; not an administrator of it. It's all really just plumbing to me. But, I digress once again....


Edit Files to Change sprPhase01 References to sprPhase02
Go through every file, including the spr-servlet.xml and web.xml, and change any reference to sprPhase01 to sprPhase02. You don't have to change a thing in anything in src because all files reference com.pmr.spr, or whatever your structure is that you set up for yourself.


Create a new SprPhase02 Project In IDE
Next, create a new SprPhase02 project in your IDE, and map in all library jar files from compilelib and springjars as you did for the SprPhase01 project. In addition, download and install jstl-1.2.jar (or whatever version is compatible with current times) into your compilelib directory.

Please be aware that you cannot have the build directory or the IDE work directory (ex. nbproject from the NetBeans IDE), or have manifest files or build.xml files from SprPhase01 project in your SprPhase02 directory hierarchy, or your IDE will simply puke at you.


Take a Breath, and Run It!
Now.... just let it all sit for a few seconds and marinate in the cosmic forces of the IDE while you take a few deep breaths. Put a smile on, and then run the SprPageController.java from the IDE as you did before.

Verify that you get the same output. If you don't, delete the project from your IDE, and start over. Do not make code changes, add jars, or anything else. All you should need to do is change the sprPhase01 path references in a couple of files to sprPhase02.

Top


Developing The Application's View Layer
Phase 02 implements a browser request to display the welcome.jsp. That page will display a greeting:

Current Picture


Clicking the link on the welcome.jsp greeting screen will display another page, quotes.jsp. This screen will display a quote.

Current Picture


Clicking the link on quotes.jsp will take the user back to welcome.jsp where the greeting message is replaced by one showing who said the quote.

Current Picture

Let's build these two new pages, which will be put into WEB-INF/jsp.


Creating Application Web Page welcome.jsp
Ultimately, the web.xml file will direct traffic to the following simple jsp page, welcome.jsp, under the /war/web/WEB-INF/jsp directory, i.e. /war/web/WEB-INF/jsp/welcome.jsp.

File: /war/web/WEB-INF/jsp/welcome.jsp:


<%@ page language="java" contentType="text/html;
      charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<%@taglib prefix="c"
      uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
      "http://www.w3.org/TR/html4/loose.dtd">

<html>
<head>
  <title>
      Simple Spring 4.x MVC Example Application Welcome Page
  </title>
</head>
<body>
  <table width="500" border="1">
    <tr>
      <td colspan="6"> </td>
    </tr>
    <tr>
        <th colspan="6" style="text-align:center">
            Simple Spring 4.x MVC Example Application Welcome Page
        </th>
    </tr>
    <tr>
      <td colspan="6"> </td>
    </tr>
    <tr>
      <td>
          <blockquote><blockquote><blockquote>
            <p/>${message}<br/>
            <a href="quotes.html" >Click here</a> to see a quote...
          </blockquote></blockquote></blockquote>
      </td>
    </tr>

    <tr>
      <td colspan="6"> </td>
    </tr>
  </table>
</body>
</html>

Obviously, there's some additional standard page tag gibberish at the top, but the only thing interesting here is the Spring tag: ${message}. You may note from this, that this tag is not going to display a list of quotes, but rather just one quote.

And that's fine. If you can't get the controller to send one little String value back to the page, you're only going to get your roids in a real uproar trying to get it to send anything more complicated back. Let's just keep it really simple and build this out one little step at a time.

Keep in mind as we go on here the href to 'quotes.html'. This is going to be received by the controller method with a '/quotes' annotation in its @RequestMapping tag, which we'll soon see as:

@RequestMapping(value="/quotes", method=RequestMethod.GET)


Creating Application Web Page quotes.jsp
This file will also be placed under the /war/web/WEB-INF/jsp directory, i.e. /war/web/WEB-INF/jsp/quotes.jsp.

File: /war/web/WEB-INF/jsp/quotes.jsp:


<%@ page language="java" contentType="text/html;
      charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<%@taglib prefix="c"
      uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
      "http://www.w3.org/TR/html4/loose.dtd">

<html>
<head>
<title>Simple Spring 4.x MVC Example Application Quotes Page</title>
</head>
<body>
    <br>
    <center>
    <div style="text-align:center;width:700px;height:300px;">
        <h2>
        Simple Spring 4.x MVC Example Application Quotes Page<br/><br/>
        <fieldset style="border-color:blue;color:green;">
          <legend style="color:green;">
            Here's a quote for you!
          </legend>
          <div style="font-face:Verdana;text-size:50px;color:red;">
            <p/>"${message}"<br/>
          </div>
        </fieldset><br/>
        <a href="postedby.html">Click here</a> to see who posted this quote.
        </h2>
        <p/>Brought to you by <i>Bob!</i>
    </div>
    </center>
</body>
</html>

Not much clever going on here. Again, note that ${message} will bring back who posted the quote that was displayed on the welcome.jsp. Simple....


Update web.xml
Once the pages are built, it'll be easy to see why we have to change our simple web.xml. It will be changed to recognize specific types of browser requests, and forward those requests to the Spring DispatcherServlet. Those references are all done in web.xml. Here's an updated version of web.xml. Note that it's like any other web.xml file other than the inclusion of some Spring framework references.

File: /war/spr/WEB-INF/web.xml:


<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="3.0"
  xmlns="http://java.sun.com/xml/ns/j2ee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
  http://java.sun.com/xml/ns/j2ee/web-app_3_0.xsd">

  <display-name>Spring 3.x Example Application Phase02</display-name>
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>

  <servlet>
    <servlet-name>spr</servlet-name>
    <servlet-class>
        org.springframework.web.servlet.DispatcherServlet
    </servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>

  <servlet-mapping>
   <servlet-name>spr</servlet-name>
   <url-pattern>*.html</url-pattern>
  </servlet-mapping>

  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>WEB-INF/spr-servlet.xml</param-value>
  </context-param>

  <listener>
   <listener-class>
      org.springframework.web.context.ContextLoaderListener
    </listener-class>
  </listener>

  <listener>
    <listener-class>
      org.springframework.web.context.request.RequestContextListener
    </listener-class>
  </listener>

</web-app>

The spr value in the servlet-mapping tag relates up to the servlet tag and says any requests coming into the system with *.html should be directed to the Spring DispatcherServlet - which is loaded when you boot Tomcat.

This is why all of the href links on the .jsp screens are of form name.html.

Remember, web.xml is a standard artifact for any web application. It only defines what objects are used, not how they are used. The 'how' is what our spr-servlet.xml file does. So, let's take a look at how that needs to be changed.


Update spr-servlet.xml
Remember our spr-servlet.xml file? It was pretty simple. But this time, we're going to build some additional functionality into it so that it tells Spring where all of our controller objects are, and define a new Spring object referenced by Spring with id="viewResolver".

Because we're now switching from a console run app to a browser based app, move spr-servlet.xml from it's current location in src, if you had placed it there as I did, into your WEB-INF folder along with web.xml.

File: /war/spr/WEB-INF/spr-servlet.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"
   xmlns:p="http://www.springframework.org/schema/p"
   xmlns:context="http://www.springframework.org/schema/context"
   xsi:schemaLocation="
     http://www.springframework.org/schema/beans
     http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">

  <context:component-scan base-package = "com.pmr.spr.controller" />

  <bean id="viewResolver"
    class="org.springframework.web.servlet.view.UrlBasedViewResolver">
    <property name="viewClass"
        value="org.springframework.web.servlet.view.JstlView" />
    <property name="prefix" value="/WEB-INF/jsp/" />
    <property name="suffix" value=".jsp" />
  </bean>

  <bean class="com.pmr.spr.controller.SpringBeans.SprBeanForm" id="mySprBean">
    <property name="postedBy" value="Property postedBy from spr-servlet.xml"/>
    <property name="message" value="Property message from spr-servlet.xml"/>
  </bean>

</beans>

Of primary importance to note here is that the name of this xml file, spr-servlet, is determined by the value of the servlet-name element from 'web.xml', with '-servlet' appended to it. Thus, because the servlet-name tag in web.xml is 'spr', then our file must, in order to be recognized by Spring, be named: 'spr-servlet.xml'. If the web.xml servlet-name element was 'bobrocks', then the Spring configuration file name would have to be 'bobrocks-servlet.xml'. This is the standard naming convention used with Spring's Web MVC framework.

I've added a 'context:component-scan' tag to the spr-servlet.xml file. This tells Spring where it can find all of the application's controller objects. This is part of the Object Oriented process called IoC, or Inversion of Control, and in particular: Dependency Injection, both of which are huge parts of the Spring Framework.

The Spring UrlBasedViewResolver class, referenced by mandated Spring id of 'viewResolver' is a Spring process: "...that allows for direct resolution of symbolic view names to URLs, without explicit mapping definition." Helpful, hu? Just put it in there and you'll see how it all goes together when we update our SprPageController.java.

Top


Developing A Spring Annotated Controller
After setting up the web environment, I'm going to change the SprPageController.java to respond to a browser request to display that welcome.jsp page.

However you normally set up your environment to run a web server, do that now. I run my own build script from a DOS window batch file. This script deploys a .war file into my external instance of Tomcat. But that's just me. You can just run Tomcat from IDE plugins if that's easier for you. Doesn't matter; just set your environment up and get tommycat running....

File: /com/pmr/controller/SprPageController:


package com.pmr.spr.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

/**
 * Spring 4.x annotated controller vs implementing Controller or extending
 * older deprecated classes.
 * <p/>
 * @author Peter Rose@RequestMapping("/welcome")

 */
@Controller
public class SprPageController {


  @RequestMapping(value="/welcome", method=RequestMethod.GET)
  public String showWelcomePage(ModelMap model) {
    System.out.println("Entering SprPageController.showWelcomePage");
    String message = "Hark! This is Bob!";
    model.addAttribute("message", message);
    return "welcome";
  }


  @RequestMapping(value="/quotes", method=RequestMethod.GET)
  public String showQuote(ModelMap model) {
    System.out.println("Entering SprPageController.showQuote");
    String message = "Does anybody know what time it is?";
    model.addAttribute("message", message);
    return "quotes";
  }


  @RequestMapping(value="/postedby", method=RequestMethod.GET)
  public String showPostedBy(ModelMap model) {
    System.out.println("Entering SprPageController.showPostedBy");
    String message = "Hummm.... I think Bob said this?";
    model.addAttribute("message", message);
    return "welcome";
  }

}

The @Controller annotation identifies a particular class that it serves the role of a controller. Spring doesn't require you to extend any controller base class, implement an interface, or reference the Servlet API. However, you can still use Servlet-specific features, which we've seen using the context, for example.

The RequestMapping annotation has different forms of parameterization. For our example, the first responds to a request from something like we built in our welcome.jsp of '/quotes.html'. The controller looks for this tag in the RequestMappings for it's methods, and executes the code it finds.

You can specify whether to accept specific types of HttpRequest in the method=RequestMethod.XXX parameter. So that we can see what these parameters are, I'll use GET. However, in a production application, you'd probably want to use POST.

Spring injects a ModelMap object into the method. Under the sheets, ModelMap is just a container for a HashMap for storing name-value pairs into the HttpRequest, HttpSession, etc. depending on what scope you assign to these objects. The name must always be a String and the value must be an object. It's this ModelMap that is being referenced on the .jsp page via the ${message}, or ${postedBy} fields on the page. If the value is an object, obviously you'll have to reference the individual properties from within the tag the way you would use any accessor construct. More on that later; let's just display a String for now!

Top


Phase 02 is Done: Ship it!
Okay, fire up tommycat, and run the following url:

http://localhost:8080/sprPhase02/welcome.html

Because of the way our project is structured, sprPhase02 is considered the root level. If we weren't building this out in phases, then our root level would just be spr and make a lot more sense.

In addition, the rather cumbersome, and annoying method to get the welcome.jsp page to come up by needing to directly reference it via /welcome.html is a little pedestrian in a commercial app. I'll leave it as an exercise for you to create a mapping that will bring up welcome.jsp via just the following:

http://localhost:8080/spr
[hint: you'll have to change web.xml...]

Spring is very fussy about all of the dependencies and references it uses. You may very well experience the joy of watching literally hundreds of error and exception messages plug up your tommycat console. It is laborious to decipher this stuff. It took me, for example, 3 hours to figure out one simple change to spr-servlet.xml that I needed to do. Good luck!

Here's the Phase 02 output for 2 requests for posted by:

Entering SprPageController.showWelcomePage
Entering SprPageController.showQuote
Entering SprPageController.showPostedBy
Entering SprPageController.showQuote
Entering SprPageController.showPostedBy

When you're successful getting all 3 views from the 2 .jsp screens to come up, you're ready to move on to Phase 03 development.

Top


Application Development: Phase 03


Top


Updating SprPageController
In Phase 03 I want to show how to move away from using the ModelMap as the transport mechanism. There are times when you could opt to use this. But most web applications require communication involving individual objects or Lists of objects. To show this, all you need to do is change the controller method signatures, and make a small change on each .jsp screen.

File: /com.pmr.controller.SprPageController:


package com.pmr.spr.controller;

import com.pmr.spr.controller.SpringBeans.SprBeanForm;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

/**
 * SprPhase03
 * <p/>
 * Spring 4.x annotated controller vs implementing Controller or extending
 * older deprecated classes.
 * <p/>
 * @author Peter Rose@RequestMapping("/welcome")

 */
@Controller
public class SprPageController {

  @RequestMapping(value="/welcome", method=RequestMethod.GET)
  public SprBeanForm showWelcomePage(@ModelAttribute SprBeanForm bean) {
    System.out.println("Entering SprPageController.showWelcomePage");
    String message = "Hark! This is Bob calling from Phase03!";
    System.out.println("  --current bean property value: " + bean.getMessage());
    bean.setMessage(message);
    System.out.println("  --outgoing bean message property value: ");
    System.out.println("    ** " + bean.getMessage());
    return bean;
  }

  @RequestMapping(value="/quotes", method=RequestMethod.GET)
  public String showQuote(@ModelAttribute SprBeanForm bean) {
    System.out.println("Entering SprPageController.showQuote");
    String message = "New message for quotes.html using SprBean";
    System.out.println("  --current bean property value: " + bean.getMessage());
    bean.setMessage(message);
    System.out.println("  --outgoing bean message property value: ");
    System.out.println("    ** " + bean.getMessage());
    return "quotes";
  }

  @RequestMapping(value="/postedby", method=RequestMethod.GET)
  public String showPostedBy(@ModelAttribute SprBeanForm bean) {
    System.out.println("Entering SprPageController.showPostedBy");
    String message = "New message for welcome.html from postedby using SprBean";
    System.out.println("  --current bean property value: " + bean.getMessage());
    bean.setMessage(message);
    System.out.println("  --outgoing bean message property value: ");
    System.out.println("    ** " + bean.getMessage());
    return "welcome";
  }
}

That may be a little cluttered with all of the print statements, so here's the raw getPostedBy() method body:


  @RequestMapping(value="/postedby", method=RequestMethod.GET)
  public String showPostedBy(@ModelAttribute SprBeanForm bean) {
    String message = "New message for welcome.html from postedby using SprBean";
    bean.setMessage(message);
    return "welcome";
  }

The method still returns a String because these are controller methods that tell DispatcherServlet which page to display next. In this case, we want to display the message (who posted the quote) back onto the welcome.jsp page.

Note, however the '@ModelAttribute SprBeanForm bean' parameter. When you see the output, you'll note that every time this method (or any other method with this type of signature) is called, it creates a new instance of the referenced bean, in this case an SprBeanForm.

And where does it get the information to do this? Right, from the spr-servlet.xml file. Well, not exactly. In Phase 01 when we pulled this bean from the ApplicationContex, we got the spr-servlet.xml pre-set value for message of: "Property message from spr-servlet.xml". This time, however, you'll see that the message property set in the bean for this phase, "bean Bite my shorts!", will be displayed.

Why is that? Because this time Spring uses the xml file as a reference template for the bean, using that to instantiate the actual SprBeanForm.java itself.

What happens next in the controller method is that the SprBeanForm bean is populated with the value of the message. By object reference, Java assigns this new value to the message property, and sends that bean off to welcome.jsp for display.

This is really useful, but it is totally against good Object Oriented object communication. The problem here is that you never want a method to change an object by reference unless you take the extra step of returning that object to the caller.

Why the unneeded return? Just for clarity of what the method is supposed to be doing. It is very confusing to see a void method return signature and discover that one of the object parameters that you are passing in gets changed by reference. This is what drives experienced engineers crazy. Sure, it's elegant. But I could really give a shit about elegant when I'm trying to figure out what the application flow is when I'm six levels of abstraction and control down and find out that some fool has done a reference change somewhere along the call stack. But I digress....

Just to demonstrate, however, a little different approach to how method parameters can be used to facilitate a different business use, see this code example from what I think came from the Spring sample pet store application:


   @RequestMapping(value="/owners/{ownerId}", method=RequestMethod.GET)
   public String findOwner(@PathVariable String ownerId, Model model) {
     Owner owner = ownerService.findOwner(ownerId);
     model.addAttribute("owner", owner);
     return "displayOwner";
   }



Top


Updating Screen Display Code
Currently, both welcome.jsp and quotes.jsp display the message value as:

${message}

But, changing the bean by reference in the controller means that it is the SprBeanForm that is now in the HttpRequest, and not just a String with 'message'. Remember, in Phase 02 you were dealing with the ModelMap, a name-value HashMap construct with the name tag of "message" equal to the message set in the controller as the return. Now, we've got a bean with it's reference defined in spr-servlet.xml as "sprBeanForm.xml". And so, all we have to do now is to change on both of the screens how we reference the value we want to:

${sprBeanForm.message}

Pretty painless, hu?

Top


Phase 03 is Done: Ship it!
Okay, fire up tommycat, and run the following url:

http://localhost:8080/sprPhase02/welcome.html

Here is the output you should see.

Hark! SprBeanForm instantiated!
Entering SprPageController.showWelcomePage
    --current bean property value: bean Bite my shorts!
    --outgoing bean message property value:
        ** Hark! This is Bob calling from Phase03!
Hark! SprBeanForm instantiated!
Entering SprPageController.showQuote
    --current bean property value: bean Bite my shorts!
    --outgoing bean message property value:
        ** New message for quotes.html using SprBean
Hark! SprBeanForm instantiated!
Entering SprPageController.showPostedBy
    --current bean property value: bean Bite my shorts!
    --outgoing bean message property value:
        ** New message for welcome.html from postedby using SprBean

Carefully go through the call stack, examining what's going on so that you're comfortable with the overall approach that this type of Spring methodology provides.

Top


Application Development: Phase 04


Top


Summary Phase 04
Phase 04 will change the current basic html screens into Spring aware forms.

The problem domain of the application will change in Phase04. Before, when going to the quotes.jsp screen, a quote would be displayed. Selecting the link would take you back to welcome.jsp and display who said the quote. In Phase 04, we're going to flip things around.

The welcome.jsp will now contain an input field where the user will enter a quote. Upon first coming to the screen, the SprBeanForm.java will display its pre filled in values onto the welcome.jsp for both the message and postedBy properties.

Current Picture

The user will type into the message input box some text and then submit the form. The server will reply back on the quotes.jsp with what that entered text was, and who posted that quote.

Current Picture

This demonstrates a better life cycle for a web application's view layer. We'll be needing business objects and a data layer, and that's all to come in ensuing phases. The sole intent of Phase 04 is to show how to use the Spring framework's form processing for a simple browser to controller communication.

Top


Setting Up The Example Environment
As before in Phase 02 and Phase 03, create an sprPhase04 subdirectory under SpringLearning, and copy all of the relevant Phase 03 directory structure.

Make necessary edits in your config files, and be sure everything compiles in your IDE. If you're using an external Tomcat instance, do your build and fire it up.

Make sure you can run the Phase03 code now in the new Phase 04 environment with path url:

http://localhost:8080/sprPhase04/welcome.html.

Top


Change JSP Screens
To use the tags from this library, add the following directive to the top of your JSP page:
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>

where form is the tag name prefix you want to use for the tags from this library.


welcome.jsp


<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
    "http://www.w3.org/TR/html4/loose.dtd">
<%@ page language="java" contentType="text/html;
    pcharset=ISO-8859-1" ageEncoding="ISO-8859-1"%>
<%@ taglib prefix="form"
    uri="http://www.springframework.org/tags/form" %>
<%@ taglib prefix="c"
    uri="http://java.sun.com/jsp/jstl/core"%>

<head>
  <title>Simple Spring 4.x MVC Example Application Welcome Page</title>
</head>
<body>
<form:form action="postedby.html"
      commandName="sprBeanForm" method="GET">
  <table width="600" border="4" style="border-color:blue;">
    <tr>
      <td> </td>
    </tr>
    <tr>
      <th style="text-align:center">
          Simple Spring 4.x MVC Example Application Welcome Page
      </th>
    </tr>
    <tr>
      <td> </td>
    </tr>
    <tr>
      <td>
        <blockquote><blockquote><blockquote>
          Gimmie a quote: <form:input path="message" type="text"
              value="${sprBeanForm.message}" size="50" /><br/>
          <input type="submit" value="Click here to see who said this..." />
          <br/><br/>
          Posted by: ${sprBeanForm.postedBy}
        </blockquote></blockquote></blockquote>
      </td>
    </tr>

    <tr>
      <td> </td>
    </tr>
  </table>
</form:form>
</body>
</html>

When the welcome.jsp is displayed, this is what you should see printed out to the Tomcat log:

Entering SprPageController.showWelcomePage
    --message value: bean Bite my shorts!
    --postedBy value: bean Supreme Cosmic Cloud Force
    --outgoing message value: bean Bite my shorts!


quotes.jsp


<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
    "http://www.w3.org/TR/html4/loose.dtd">
<%@ page language="java" contentType="text/html;
    pcharset=ISO-8859-1" ageEncoding="ISO-8859-1"%>
<%@ taglib prefix="form"
    uri="http://www.springframework.org/tags/form" %>
<%@ taglib prefix="c"
    uri="http://java.sun.com/jsp/jstl/core"%>

<html>
<head>
<title>Simple Spring 4.x MVC Example Application Quotes Page</title>
</head>
<body>
<form:form commandName="sprBeanForm" method="GET">
    <br>
    <center>
    <div style="text-align:center;width:700px;height:300px;">
        <h2>
        Simple Spring 4.x MVC Example Application Quotes Page<br/><br/>
        <fieldset style="border-color:blue;color:green;">
          <legend style="color:green;">
            Here's what you wanted!
          </legend>
          <div style="font-face:Verdana;text-size:50px;color:red;">
            <p/>You sent the quote: "${sprBeanForm.message}"<br/>
            and this is who said it: ${sprBeanForm.postedBy}!!!
            <form:input path="message" type="hidden"/>
            <form:input path="postedBy" type="hidden"/>
          </div>
        </fieldset><br/>
        Click <a href="welcome.html">here</a> to input another quote.
        <br/><br/>
        </h2>
        <p/>Brought to you by <i>Bob!</i>
    </div>
    </center>
</form:form>
</body>
</html>

When the quotes.jsp is displayed, this is what you should see printed out to the Tomcat log:

Entering SprPageController.showPostedBy
    --message value: This is the text I entered on welcome.jsp
    --postedBy value: bean Supreme Cosmic Cloud Force
    --outgoing message value: This is the text I entered on welcome.jsp
    --outgoing postedBy value: That's a stupid quote!

Top


Modified SprPageController
After you take a look at the re-written controller, I'll discuss in detail the flow between this and the two pages.


SprPageController.java


package com.pmr.spr.controller;

import com.pmr.spr.controller.SpringBeans.SprBeanForm;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

/**
 * SprPhase04
 * <p/>
 * Spring 4.x annotated controller vs implementing Controller or extending
 * older deprecated classes.
 * <p/>
 * @author Peter Rose
 */
@Controller
public class SprPageController {

  @RequestMapping(value="/welcome", method = RequestMethod.GET)
  public String showWelcomePage(@ModelAttribute SprBeanForm bean) {
    System.out.println("Entering SprPageController.showWelcomePage");
    System.out.println("  --message value: " + bean.getMessage());
    System.out.println("  --postedBy value: " + bean.getPostedBy());
    String message2 = bean.getMessage();
    bean.setMessage(message2);
    System.out.println("  --outgoing message value: " + bean.getMessage());
    return "welcome";
  }

  @RequestMapping(value="/postedby", method = RequestMethod.GET)
  public String showPostedBy(@ModelAttribute SprBeanForm bean) {
    System.out.println("Entering SprPageController.showPostedBy");
    System.out.println("  --message value: " + bean.getMessage());
    System.out.println("  --postedBy value: " + bean.getPostedBy());
    String message = bean.getMessage();
    bean.setMessage(message);
    bean.setPostedBy("That's a stupid quote!");
    System.out.println("  --outgoing message value: " + bean.getMessage());
    System.out.println("  --outgoing postedBy value: " + bean.getPostedBy());
    return "quotes";
  }
}



Top


Browser to Controller Communication Flow


URL action from browser
When the user enters the url http://localhost:8080/sprPhase04/welcome.html into the browser and submits, the root sprPhase04 is recognized in the web.xml which routes the request to the designated extended DispatcherServlet we created, SprPageController.java with the token 'welcome.html'.

The 'welcome.html' token is parsed by the DispatcherServlet to match the annotated reference in the controller:

@RequestMapping(value="/welcome", method = RequestMethod.GET)


Spring controller annotation
The @RequestMapping annotation in the controller calls the SprPageController's showWelcomePage() method. We verify that this happens from the printout to the Tomcat log of:

Entering SprPageController.showWelcomePage
    --message value: bean Bite my shorts!
    --postedBy value: bean Supreme Cosmic Cloud Force
    --outgoing message value: bean Bite my shorts!

And this is what you see displayed on welcome.jsp. The fact that both message and postedBy properties display the hard coded values in the SprBeanForm.java is important to note. If you don't want those values to display, then you just change them with setters in this method - which is what we're going to do when we submit welcome.jsp.

Top


Controller Redirect on Submit
When the user enters some text into the input field on welcome.jsp and submits, note how the page handles this through a button action:
    <form:form action="postedby.html"      commandName="sprBeanForm" method="GET">

The form's 'action' parameter is mimicking our original URL format, i.e.

    http://localhost:8080/sprPhase04/welcome.html

in it's value of 'postedby.html'. This token will be parsed the same way that the 'welcome.html' in the URL was done. It will thus be redirected through the controller's annotation of:

    @RequestMapping(value="/postedby", method=RequestMethod.GET)

to the method being annotated:

    public String showPostedBy(@ModelAttribute SprBeanForm bean) {

Again, I feel I should point out that the welcome.jsp form's method=GET reference must, must match that in the controller. If they don't, then the controller won't find the method to call. Just to be clear, if the form has a method=GET and the control's annotation has method = RequestMethod.POST, it won't be found. Buyer beware....

Top


Conclusion Phase 04
At this point in the development of the spr application, I've hopefully been able to get you though the base mechanics of how Spring enables communication between the browser and controller layers of a multi-tier enterprise web application.

The controllers should be kept this simple, and only delegating further business solution to the business object layer. For example, SprPageController.showPostedBy(), instead of making the assignment

    bean.setPostedBy("That's a stupid quote!");
I'd instead instantiate a business object, and let it return the postedBy property for the bean:
    SprQuoteFinderBO bo = new SprQuoteFinderBO();
    String message = bean.getMessage();
    String whoPostedQuote = bo.findPostedBy(message);
    bean.setPostedBy(whoPostedQuote);


Top


Final Thoughts
You should now be in a position to go to the Spring documentation and see all of the other return types from Spring annotated controller methods can have, what constructs are available for method parameters, and how to scope the objects that you are using.

A word of caution: Spring is a very complex framework with many, many different APIs, and just a slew of different ways that you can do things. When you start reading about all this stuff, you'll see how powerful the Spring framework and container are.

My advice is: don't do it; forget about it all. Well, most of it, anyway, because there are some really powerful features for writing web services and implementing different patterns that you'll need in a commercial development environment. But, don't try to learn them now until you have a need to get into a particular area.

Look, all of this stuff is front end development, without all the fancy UI issues. It's just communication between the browser and a controller. That's it. In the old days, we just used raw .jsp tags and some jstl, and passed stuff back and forth on the basic request and response servlet objects. In fact, we just used a plain old servlet for the controller.

Sure, we had lots of typing to pull the name-value pairs from the submit request url, stuff them into a bean, and then do the same unscrambling back on the .jsp for display. And yes, that was all prone to a lot more errors which a framework removes.

But again, the long and the short of all this front end stuff is pretty simple: you take some user input on the screen, have that info transmitted to a controller where you can pull it off, and then pass it down into your business layer for processing. When you get some results back, you pass those back to the screen.

I've brought you to the point of seeing how Spring works at a very basic level. If this is as far as you go with Spring, you've got pretty much all the tools you need to write a simple web application. When you need to do something a little more complex, just figure it out, and move on! And have fun!

peter


Back to Thoughts On Technology Page | Back to Peter's Home Page | Back to Family Home Page