Green Beans: Getting Started with Spring MVC |
|

Spring MVC, a part of the core Spring Framework, is a mature and capable action-response style web framework, with a wide range of capabilities and options aimed at handling a variety of UI-focused and non-UI-focused web tier use cases. All this can potentially be overwhelming to the Spring MVC neophyte. I think it's useful for this audience to show just how little work there is to get a bare Spring MVC application up and running (i.e. consider my example something akin to the world's simplest Spring MVC application), and that's what I'll spend the rest of this article demonstrating.
I'm assuming you are familiar with Java, Spring (basic dependency injection concepts), and the basic Servlet programming model, but do not know Spring MVC. After reading this blog entry, readers may continue learning about Spring MVC by looking at Keith Donald's Spring MVC 3 Showcase, or the variety of other online and print resources available that cover Spring and Spring MVC.
A note on dependencies and build systems: this article does not assume that you are using a particular build system, e.g. Maven, Gradle or Ant. A fairly minimal sample Maven POM file is includes as an example at the end of the article.
Spring MVC includes most of the same basic concepts as other so-called web MVC frameworks. Incoming requests enter the framework via a Front Controller. In the case of Spring MVC, this is an actual Java Servlet called DispatcherServlet. Think of DispatcherServlet as the gatekeeper. It doesn't perform any real web or business logic, but rather delegates to POJOs called Controllers where the real work is done (either in whole or via the back-end). When the work has been done, it's the responsibility of Views to produce the output in the proper format (whether that's a JSP page, Velocity template, or JSON response). Strategies are used to decide which Controller (and which method(s) inside that Controller) handles the request, and which View renders the response. The Spring container is used to wire together all these pieces. It all looks something like this:
Bootstrapping the DispatcherServlet and Spring Container
As mentioned, all incoming requests flow through a DispatcherServlet. Like any other Servlet in a Java EE application, we tell the Java EE container to load this Servlet at web app startup time via an in the web app's WEB-INF/web.xml. The DispatcherServlet is also responsible for loading a Spring ApplicationContext that is used to perform wiring and dependency injection of managed component. On this basis, we specify some init parameters to the Servlet which configure the Application Context. Let's look at the config in web.xml:
WEB-INF/web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <!-- Processes application requests --> <servlet> <servlet-name>appServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>appServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
A number of things are being done here:
- We register the DispatcherServlet as as a Servlet called
appServlet - We map this Servlet to handle incoming requests (relative to the app path) starting with "/"
- We use the
ContextConfigLocationinit parameter to customize the location for the base configuration XML file for the Spring Application Context that is loaded by the DispatcherServlet, instead of relying on the default location of <servletname>-context.xml).
Wait, What if Somebody Doesn't Want to Configure Spring via XML?
The default type of Application Context loaded by the DispatcheServlet expects to load at least on XML file with Spring bean definitions. As you'll see, we'll also enable Spring to load Java-based config, alongside the XML.
Everybody will have their own (sometimes very strong) opinion in this area, but while I generally prefer-Java based configuration, I do believe that smaller amounts of XML config for certain areas can sometimes still make more sense, for one of a number of reasons (e.g. ability to change config without recompilation, conciseness of XML namespaces, toolability, etc.). On this basis, this app will use the hybrid approach, supporting both Java and XML.
Rest assured that if you prefer a pure-Java approach, with no Spring XML at all, it's pretty trivial to achieve, by setting one init param in web.xml to override the default Application Context type and use a variant called AnnotationConfigWebApplicationContext instead.
The Controller
Now let's create a minimal controller:
package xyz.sample.baremvc;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* Handles requests for the application home page.
*/
@Controller
public class HomeController {
@RequestMapping(value = "/")
public String home() {
System.out.println("HomeController: Passing through...");
return "WEB-INF/views/home.jsp";
}
}
Let's walk through the key aspects of this class:
- The class has been annotated with the
@Controllerannotation, indicating that this is a Spring MVC Controller capable of handling web requests. Because@Controlleris a specialization of Spring's@ComponentStereotype annotation, the class will automatically be detected by the Spring container as part of the container's component scanning process, creating a bean definition and allowing instances to be dependency injected like any other Spring-managed component. - The
homemethod has been annotated with a@RequestMappingannotation, specifying that this method should handle web requests to the path "/", i.e. the home path for the application. - The
homemethod simply logs a message to system out, and then returnsWEB-INF/views/home.jsp, indicating the view which should handle the response, in this case a JSP page. (If hardcoding the entire view path including WEB-INF prefix, and the fact that it's a JSP, seems wrong to you, you are right. We'll deal with this later)
Now, we need to create the view. This JSP page will simply print a greeting.
WEB-INF/views/home.jsp
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <%@ page session="false" %> <html> <head> <title>Home</title> </head> <body> <h1>Hello world!</h1> </body> </html>
Finally, as previously mentioned, we need to create a minimal Spring Application Context definition file.
WEB-INF/spring/appServlet/servlet-context.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:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
<!-- Scans within the base package of the application for @Components to configure as beans -->
<!-- @Controller, @Service, @Configuration, etc. -->
<context:component-scan base-package="xyz.sample.baremvc" />
<!-- Enables the Spring MVC @Controller programming model -->
<mvc:annotation-driven />
</beans>
Let's examine the contents of this file:
- You'll note that a few different Spring XML namespaces are being used: context, mvc, and the default beans
- The <context:component-scan> declaration ensures the Spring container does component scanning, so that any code annotated with
@Componentsubtypes such as@Controlleris automatically discovered. You'll note that for efficiency, we limit (toxyz.sample.baremvcin this case) what part of the package space Spring should scan in the classpath - The <mvc:annotation-driven> declaration sets up Spring MVC's support for routing requests to @Controllers, as well as how some things like conversion, formatting and validation are handled (with some sensible defaults based on what (libraries) is present in your classpath, and the ability to override if needed)
The web app is now ready to run. Assuming the Servlet container (tc Server in my case) is set to listen on localhost:8080, starting the application and then hitting the URL http://localhost:8080/baremvc via our browser results in a display of the expected greeting:

As trivial as it is, running this application involves all the major pieces of a working Spring MVC application. Let's walk through the major sequences and component interactions:
- When the web app starts up, the DispatcherServlet is loaded and initialized because of the entry in
web.xml. - The DispatcherServlet loads an annotation-based Application Context, which has been configured to scan for annotated components via a regular expression specifying the base package(s).
- Annotated components such as the HomeController are detected by the container.
- The HTTP request to
http://localhost:8080/baremvchits the servlet engine and is routed to our (baremvc) webapp. - The implicit "/" path at the end of the URL matches the regex that has been registered for the DispatcherServlet, and the request is routed to it
- The DispatcherServlet needs to decide what to do with the request. It uses a strategy called a
HandlerAdapterto decide where to route the request. The specific HandlerAdapter type (or types, since they can be chained) to be used can be customized, but by default, an annotation-based strategy is used, which routes requests appropriately to specific methods in classes annotated as@Controller, based on matching criteria in@RequestMappingannotations found in those classes. In this case, the regex on the home method is matched, and it's called to handle the request. - The home method does its work, in this case just printing something to system out. It then returns a string that's a hint (in this case, a very explicit one,
WEB-INF/views/home.jsp) to help chose the View to render the response. - The DispatcherServlet again relies on a strategy, called a
ViewResolverto decide which View is responsible for rendering the response. This can be configured as needed for the application (in a simple or chained fashion), but by default, anInternalResourceViewResolveris used. This is a very simple view resolver that produces aJstlViewwhich simply delegates to the Servlet engine's internalRequestDispatcherto render, and is thus suitable for use with JSP pages or HTML pages. - The Servlet engine renders the response via the specified JSP
Taking It to the Next Level
At this point, we've got an app which certainly qualifies as the world's simplest Spring MVC application, but frankly, doesn't really meet the spirit of that description. Let's evolve things to another level.
As previously mentioned, it's not appropriate to hard-code a path to a view template into a controller, as our controller curretly does. A looser, more logical coupling between controllers and views, with controllers focused on executing some web or business logic, and generally agnostic to specific details like view paths or JSP vs. some other templating technology, is an example of separation of concerns. This allows much greater reuse of both controllers and views, and easier evolution of each in isolation from the other, with possibly different people working on each type of code.
Essentially, the controller code ideally needs to be something like this variant, where a purely logical view name (whether simple or composite) is returned:
//...
@Controller
public class HomeController {
@RequestMapping(value = "/")
public String home() {
System.out.println("HomeController: Passing through...");
return "home";
}
}
Spring MVC's ViewResolver Strategy is actually the mechanism meant to be used to achieve this looser coupling between the controller and the view. As already mentioned, in the absence of the application configuring a specific ViewResolver, Spring MVC sets up a default minimally configured InternalResourceViewResolver, a very simple view resolver that produces a JstlView. There are potentially other view resolvers we could use, but to get a better level of decoupling, all we actually need to do is set up our own instance of InternalResourceViewResolver with slightly tweaked configuration. InternalResourceViewResolver employs a very simple strategy; it simply takes the view name returned by the controller, and prepends it with an optional prefix (empty by default), and appends it with an optional suffix (empty by default), then feeds that resultant path to a JstlView it creates. The JstlView then delegates to the Servlet engine's RequestDispatcher to do the real work, i.e. rendering the template. Therefore, to allow the controller to return logical view names like home instead of specific view template paths like WEB-INF/views/home.jsp, we simply need to configure this view resolver with the prefix WEB-INF/views and the suffix .jsp, so that it prepends and appends these, respectively, to the logical name returned by the controller.
One easy way to configure the view resolver instance is to introduce the use of Spring's Java-based container configuration, with the resolver as a bean definition:
package xyz.sample.baremvc;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
@Configuration
public class AppConfig {
// Resolve logical view names to .jsp resources in the /WEB-INF/views directory
@Bean
ViewResolver viewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("WEB-INF/views/");
resolver.setSuffix(".jsp");
return resolver;
}
}
We are already doing component scanning, therefore since @Cofiguration is itself an @Component, this new configuration definition with the (resolver) bean inside it is automatically picked up by the Spring container. Then Spring MVC scans all beans and finds the resolver.
This is a fine approach, but some people may instead prefer to configure the resolver as a bean in the XML definition file, e.g.
<!-- Resolve logical view names to .jsp resources in the /WEB-INF/views directory --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/views/" /> <property name="suffix" value=".jsp" /> </bean>
It's hard to make a case for this object that one particular approach is much better than the other, so it's really a matter of personal preference in this case (and we can actually see one of the strengths of Spring, its flexible nature).
Handling User Input
Almost any web app needs to take some input from a client, do something with it, and return or render the result. There are a myriad ways to get input into a Spring MVC application, and a myriad ways to render the result, but let's at least show one variant. In this simple example, we're going to modify our HomeController to add a new handler method which takes two string inputs, compares them, and return the result.
package xyz.sample.baremvc;
import java.util.Comparator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
/**
* Handles requests for the application home page.
*/
@Controller
public class HomeController {
@Autowired
Comparator<String> comparator;
@RequestMapping(value = "/")
public String home() {
System.out.println("HomeController: Passing through...");
return "home";
}
@RequestMapping(value = "/compare", method = RequestMethod.GET)
public String compare(@RequestParam("input1") String input1,
@RequestParam("input2") String input2, Model model) {
int result = comparator.compare(input1, input2);
String inEnglish = (result < 0) ? "less than" : (result > 0 ? "greater than" : "equal to");
String output = "According to our Comparator, '" + input1 + "' is " + inEnglish + "'" + input2 + "'";
model.addAttribute("output", output);
return "compareResult";
}
}
Key elements in the new code:
- We're using another
@RequestMappingannotation to make requests ending in with the path/compareto the new compare method - We are expecting the caller to pass us the two String input parameters as part of the GET request, so we grab them via the
@RequestParamannotation. Note that we are relying on the default handling for this annotation, which assumes that these params are required. The client will receive an HTTP 400 error if they are missing. Note also that this is just one way of passing in parameters to a Spring MVC application. For example, it's easy to grab parameters that are embedded as part of the request URL path itself, for a more REST-style approach - We use our Comparator instance to compare the two strings
- We stuff the comparison result into the Model object under the key
result, so that it can be accessed by the View. Think of a Model as a glorified hashmap, in simplest terms.
While we could have modified our exisitng view to also be used to display the comparison results, we are instead using a new view template:
WEB-INF/views/compareResult.jsp
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page session="false" %>
<html>
<head>
<title>Result</title>
</head>
<body>
<h1><c:out value="${output}"></c:out></h1>
</body>
</html>
Finally, we need to supply the controller with a Comparator instance to use. We have annotated the comparator field in the controller with Spring's @Autowired annotation (which will be detected automatically after the controler is detected) and instructs the Spring container to inject a Comparator into that field. Therefore, we need to ensure the container has one available. For this purpose, a minimal Comparator implementation has been created, which simply does a case insensitive comparison. For simplicity's sake, this class has itself been annotated with Spring's @Service Stereotype annotation, a type of @Component and thus will automatically be detected by the Spring container as part of the container's component scanning process, and injected into the controller.
package xyz.sample.baremvc;
import java.util.Comparator;
import org.springframework.stereotype.Service;
@Service
public class CaseInsensitiveComparator implements Comparator<String> {
public int compare(String s1, String s2) {
assert s1 != null && s2 != null;
return String.CASE_INSENSITIVE_ORDER.compare(s1, s2);
}
}
Note that we could just as easily have declared an instance of this in the container via a Java based @Bean definition in an @Configuration class, or an XML based bean definition, and certainly those variants might be preferred in many cases for the greater level of control they offer.
We can now start the application and access it with a URL such as
http://localhost:8080/baremvc/compare?input1=Donkey&input2=dog
to exercise the new code:
Next Steps
I've really only scratched the surface of what Spring MVC can do, but hopefully this blog post has given you an idea as to how easy it is to get going with Spring MVC, and how some of the core concepts in the framework tie together. It may also be appropriate at this point to mention that in the interest of making it easier to understand the core concepts, there are a few (hopefully very obvious) areas in my sample that are not handled the way they would be in a larger or production application, as an example, the hard-coding of messages inside Java code, or some of the package organization.
Now I'd like to encourage you to learn more about and experiment with Spring MVC's full featureset and comprehensive capabilities in areas such mapping of requests to controllers and methods, data binding and validation, locale and theme support, and general ability to be customized to handle pretty much all web tier use cases that fit the action response model.
One valuable resource for you in this learning process is Keith Donald's Spring MVC 3 Showcase, which includes working code showing most of the capabilities of Spring MVC, that you can easily load into SpringSource Tool Suite (STS) or another Eclipse environment and experiment with. As an aside, if you are not familiar with STS, I should mention that it's a great tool for experimenting with the Spring set of technologies, because of its great support for Spring and features like the out of the box project templates. In this short video recording, I show how to get going with a new Spring MVC application via an STS template.
Appendix – Dependencies
The code above should work regardless of which build system you use (these days, I generally prefer Gradle or Maven). Here is a relatively minimal sample Maven POM file to build the above project, which may be used as a base, or to gain an understanding of what dependencies are needed. It's actually not quite as minimal as it could be, since I've explicitly switched out commons-logging for SLF4J, and added some optional repositories and Maven plugins. The only non-obvious item may be the need for CGLIB, which is an optional dependency needed by Spring when @Configuration is used.
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>xyz.sample</groupId>
<artifactId>baremvc</artifactId>
<name>Sprring MVC sample project</name>
<packaging>war</packaging>
<version>1.0.0-BUILD-SNAPSHOT</version>
<properties>
<java-version>1.6</java-version>
<org.springframework-version>3.0.6.RELEASE</org.springframework-version>
<org.slf4j-version>1.6.1</org.slf4j-version>
</properties>
<dependencies>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${org.springframework-version}</version>
<exclusions>
<!-- Exclude Commons Logging in favor of SLF4j -->
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<!-- CGLIB, only required and used for @Configuration usage -->
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib-nodep</artifactId>
<version>2.2</version>
</dependency>
<!-- Logging -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${org.slf4j-version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>${org.slf4j-version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${org.slf4j-version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.16</version>
<scope>runtime</scope>
</dependency>
<!-- @Inject -->
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
<!-- Servlet -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- Test -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.7</version>
<scope>test</scope>
</dependency>
</dependencies>
<repositories>
<repository>
<id>org.springframework.maven.release</id>
<name>Spring Maven Release Repository</name>
<url>http://maven.springframework.org/release</url>
<releases><enabled>true</enabled></releases>
<snapshots><enabled>false</enabled></snapshots>
</repository>
<!-- For testing against latest Spring snapshots -->
<repository>
<id>org.springframework.maven.snapshot</id>
<name>Spring Maven Snapshot Repository</name>
<url>http://maven.springframework.org/snapshot</url>
<releases><enabled>false</enabled></releases>
<snapshots><enabled>true</enabled></snapshots>
</repository>
<!-- For developing against latest Spring milestones -->
<repository>
<id>org.springframework.maven.milestone</id>
<name>Spring Maven Milestone Repository</name>
<url>http://maven.springframework.org/milestone</url>
<snapshots><enabled>false</enabled></snapshots>
</repository>
</repositories>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${java-version}</source>
<target>${java-version}</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<warName>baremvc</warName>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>tomcat-maven-plugin</artifactId>
<version>1.1</version>
</plugin>
</plugins>
</build>
</project>
Similar Posts
- Maven PAR Plugin 1.0.0.M1
- First Eclipse Gemini Blueprint Milestone Ships
- Obtaining Spring 3 Artifacts with Maven
- Migrating to Spring 3.1 and Hibernate 4.1
- Logging Dependencies in Spring







Kent Rancourt says:
Added on January 4th, 2011 at 1:21 pmExcellent article, Colin; a very gentle intro. Old hat for me, but I'll be sharing this resource with others here who are not entirely comfortable with Spring MVC yet.
Slide Buddy says:
Added on January 4th, 2011 at 9:03 pmQuite a wonderful instructional post! I'm still learning the ropes in coding and reading up on various templates and html/texts that your site is definitely helping me understand it so much easier than most sites.
Mark says:
Added on January 4th, 2011 at 10:03 pmGood one. This is great for beginners
Next time if someone asks, I could just easily point them here.
Kelvin says:
Added on January 5th, 2011 at 5:36 amExcellent article. Will definitely look further into Spring MVC and see what it can do!
Sam K. says:
Added on January 5th, 2011 at 7:04 amThis, I think, is the most comprehensive tutorial about SPring MVC I have found online, so far. Thanks again.
Carlos Ortiz says:
Added on January 5th, 2011 at 8:45 amThis is very interesting reading, for novice, for advanced users, for everyone who wish to use Spring Web MVC concepts.
I would like to see more articles in Green Beans, but I don't know where to find other resources for the series. I mean, how to find all the article in the Green Beans series.
Thank you
zqudlyba says:
Added on January 6th, 2011 at 1:27 amOne of the crucial points on whether a web framework would be embraced or be ignored the community is **not** whether the framework is an engineering marvel, but more to do with the availability of working samples **accompanied** by detailed explanation (rather than having working samples alone or reference docs alone).
The problem with spring-mvc documentation is that most of it is reference docs only, not working samples with detailed explanation.
I welcome this "Green Beans" series, and it will certainly boost the uptake of spring-mvc within the wider java developer community.
Kumar says:
Added on January 6th, 2011 at 1:42 amA Very Good Article, Thanks for Sharing….
Oleksiy says:
Added on January 6th, 2011 at 5:44 pmGreat and very easy to grasp intro. Simple enough, yet condense and solid. Huge thanks!
I've used it as a basis for my post on creating archetypes in Maven. It's in Russian, sorry, but just in case you're interested, the sources are freely available at Google Code: http://flaveur.googlecode.com/svn/trunk/m2/baremvc/)
afitzgerald (blog author) says:
Added on January 7th, 2011 at 7:59 pm@Carlos Ortiz
We have added a Green Beans tag for the posts in the series, so you should be able to keep track of them easily with this URL:
http://blog.springsource.com/category/green-beans/
I hope that helps.
Adam FitzGerald
SpringSource
Carlos Adolfo Ortiz Q says:
Added on January 8th, 2011 at 12:57 amHey Adam, good to know that you have created and posted to the Green Beans and created the category. Now it must be a permanent link in the community site so everyone know there it is.
Rajeev says:
Added on January 11th, 2011 at 8:49 amI tried the baremvc app downloading the sources from http://flaveur.googlecode.com/svn/trunk/m2/baremvc/
For some reason I get a 404 when I access the app's root http://localhost:8080/baremvc/
Server side I see:
No mapping found for HTTP request with URI [/baremvc/] in DispatcherServlet with name 'dispatcherServlet'
I couldn't figure what I am missing. I thought this was a simple enough app that would get me started.
I only reorganized sources into a maven project structure that I am familiar (with the same dependencies from your pom.xml) and generated a war.
Only significant changes to sources being the package name in the .java files
and in applicationContext.xml
Oleksiy says:
Added on January 11th, 2011 at 10:48 am@Rajeev,
Thanks for trying, and sorry, I should have described how to use it
That's not an ready-to-go application, that's maven archetype, that helps you create projects from scratch.
To use it you need to issue from project root the command: mvn install
After it's done, you can generate the application with
</mvn archetype:create \
-DarchetypeGroupId=org.example \
-DarchetypeArtifactId=baremvc \
-DarchetypeVersion=1.0 \
-DgroupId=org.example \
-DartifactId=baremvcapp
After that you can go to baremvcapp folder and run tomcat with mvn tomcat:run and try it at http://localhost:8080/baremvcapp/
I've added this instructions to README to avoid further confusion.
I'm eventually extending this template, maybe will submit it to repository soon.
Rajeev says:
Added on January 12th, 2011 at 12:20 amHi @Oleksiy, Thanks a lot,
I shall follow the instructions and try it out & get back with the result.
Rajeev says:
Added on January 12th, 2011 at 1:32 amHi @Oleksiy, Thank you very much, Its working. Your application is a good minimal starting point for spring MVC.
A small glitch though, (I guess this is because it is a work in progress):
It was complaining about a missing header.jsp,
mvn archetype:create command had not copied header.jsp, footer.jsp & contents in static folder.
Commenting out the following lines in web.xml got it running
/WEB-INF/views/header.jsp
/WEB-INF/views/footer.jsp
Thanks
Oleksiy says:
Added on January 12th, 2011 at 10:29 amHi @Rajeev
I've tested it just now and it works, just make sure you use the latest instructions from README. You should not use archetype:create anymore with Maven, apparently that goal was deprecated some time ago, so everyone should transition to using archetype:generate.
Sadly Maven doesn't provide any means to stop using archetype:create, so now when you use it say with my baremvc project, you'll get errors as a result and no clue why that happended.
SEO services says:
Added on January 27th, 2011 at 6:29 amAnother great writeup on MVC with proper code bro, keep them coming, nice job!!..
Alex says:
Added on January 28th, 2011 at 11:20 pmA good article indeed. Finally I was able to understand many things about Spring MVC. On the other side the article has revealed once again how many unnecessary things are involved into Spring MVC. What for beans? What for context? What for all those annotations? Too many instances created. And still – no component model as such.
For "Hello World" ideal framework should require hardly more than plain HTML requires for "Hello World". Compare to HybridJava.
Jeff.Chen says:
Added on February 11th, 2011 at 6:54 amvery good solution!
i will use this instead struts2
Hayao says:
Added on February 14th, 2011 at 4:47 amIf you want to use @Configuration class instead of XML, you have to add in the project lib CGLIB.jar (http://cglib.sourceforge.net/) and asm.jar (http://forge.ow2.org/projects/asm/)
Ivan says:
Added on February 15th, 2011 at 8:36 amHi, I'am not familiar with maven and have no time at this moment to go for it so, can somebody make a working .war (including sources) file I can simply deploy in tomcat container?
Thanks a lot
Ken says:
Added on February 15th, 2011 at 12:14 pmThank you for the tutorial! I am also having an issue that I hope is relatively simple. I'm still at the first portion of the tutorial (HomeController is returning the path to the jsp file, rather than just "home").
I build and run Tomcat. In the log as the webapp is initializing I see "INFO: Root mapping to handler 'homeController'", so that looks good, but then when I go to http://localhost:8080/baremvc" I get a 404 error.
For kicks, I tried changing HomeController such that the annotation reads: @Controller(value="/test"). After that, I tried going to http://localhost:8080/baremvc/test, and I get the expected Hello World JSP display.
Any thoughts as to why I cannot map to the root? I'm using 3.0.5RELEASE.
Thank you!
Manish Kumar says:
Added on March 23rd, 2011 at 12:59 amQuite a wonderful instructional post! I'm still learning about how do coding and reading up on various templates about spring that your site is definitely helping me understand it so much easier than most sites.
Gonzalo Diethelm says:
Added on May 19th, 2011 at 7:57 pmHi Colin,
In your very first sentence, you say "handling a variety of UI-focused and non-UI-focused web tier use cases". I am looking for some information on using all the wonderful RESTful annotations in Spring MVC to implement (non-UI) REST services. I am thinking of something like this:
1. Using Apache Camel to provide a listening endpoint, such as http://foo/cars.
2. Any hits on that URL (or anything below it, such as /cars/13) should be forwarded to a single Java bean.
3. This Java bean should use all the Spring MVC annotations so that the proper method is selected (including looking at the HTTP verb), parameters are taken from the URL / headers / body, logic is executed and something is returned.
4. I would hope to use Spring's abilities to automagically convert from/to XML/Jason.
Can you comment on this use case and how to approach it? Is Spring MVC the proper piece of Spring I should be looking at?
Thanks in advance and best regards.
Colin Sampaleanu (blog author) says:
Added on May 20th, 2011 at 2:27 pmHi Gonzalo,
In general, Spring MVC has excellent support for implementing applications that support REST style services. This blog post didn't get into that at all since it was supposed to be a gentle intro to Spring MVC just focusing on the core concepts, but the REST support does build up on the same mechanisms.
I don't necessarily get how you want to use Apache Camel, but in general, you should be able to implement pretty flexible REST style services with Spring MVC. For some examples, I would take a look at:
The Spring MVC showcase by Keith Donald (already mentioned in this blog post): http://blog.springsource.com/2010/07/22/spring-mvc-3-showcase/
The Greenhouse sample app from Keith's group. This actually does a bunch of stuff, but does use the REST support in Spring MVC along the way: http://www.springsource.org/greenhouse
Costin Leau's RetwisJ sample app does use the REST support in Spring MVC: http://static.springsource.org/spring-data/data-keyvalue/examples/retwisj/current/
Also, you might want to look at the "wsdoc" automatic REST documentation generation tool that Patrick Linkskey blogged about recently: http://blog.versly.com/post/5656429209/wsdoc-web-service-documentation-generation
Finally, if you're considering Apache Camel as an integration tool, I would suggest you look at Spring Integration as well, for this purpose, as it offers an approach and set of capabilities that you may (or may not) prefer: http://www.springsource.org/spring-integration
Regards,
Colin
Gonzalo Diethelm says:
Added on May 20th, 2011 at 4:03 pmHi Colin, thanks for your complete answer. I have simplified a little bit my architecture and I am now simply using Spring MVC, running on Jetty (which is incredibly fast) to expose my REST services. If / when the time comes to add different types of interface for the services (such as JMS), I will look into Apache Camel and/or Spring Integration.
Perhaps you can give me a hint on something else: my REST services are now in the shape of a web app (WAR) deployed on Jetty. I would like to experiment with running them atop OSGi, so I would have an OSGi container (such as Felix), Jetty on top of that and my REST service(s) on top of Jetty. Does this seem reasonable to you? Could you point me to an example or tutorial about the best way to do this kind of deployment? I should declare before hand that am a total regarding OSGi…
If this is too off-topic, my apologies in advance. Thanks again and best regards.
Eduardo Vargas Alvarado says:
Added on May 21st, 2011 at 6:33 pmHello,
I developed first part of barmvc project.
I used NetBeans 6.9.1 and Spring 3.1
The name of the project: barmvc
NetBeans creates "index.jsp" by default. It must be deleted. If you don't delete it, "index.jsp" is viewed instead of "home.jsp"
Thanks for the article!
Nimo says:
Added on May 22nd, 2011 at 4:57 amGreat stuff! Thanks a lot for that.
A little typo in the section "Handling User Input" – you say "We stuff the comparison result into the Model object under the key result" – but it is really under the key 'output'.
Enrico says:
Added on June 12th, 2011 at 2:19 pmHi,
I've followed this step by step and added all necessary jars, but i'm getting a 404 from tomcat 6.0,
I have double checked the code looking for typos but nothing, everything looks fine with the code…..
Do you have an advise?
Edgar Deleon says:
Added on June 20th, 2011 at 1:36 pmThis is great! I just started learning Spring MVC and STS and this tutorial has helped a lot.
Thanks.
jony says:
Added on June 30th, 2011 at 3:07 amIt's great , we'll useed , can you show we more and more about it . thanks !
shin0bi69 says:
Added on July 4th, 2011 at 9:58 amIn the file "home.jsp" I get the following error in eclipse:
>> Can not find the tag library descriptor for "http://java.sun.com/jsp/jstl/core"
Can someone help ?
quasarz says:
Added on July 6th, 2011 at 11:52 amI see somebody have problem with controller mapping to root path. When go to root path it will get 404 error. That caused by run your webapp on tomcat server 7.0.X (my tomcat server version is 7.0.4).
I don't know what happen but if run wabapp on tomcat server 6.0.X it will work completely(root path will catch by your controller).
Sorry for my bad english.
quasarz says:
Added on July 6th, 2011 at 12:27 pmI see some people have problem with controller does not work with root path (error 404 on root path). This problem caused run your webapp on tomcat 7.0.X. it will disappear if you run your webapp on tomcat server 6.0.X.
Sorry for my bad english.
Barry says:
Added on July 14th, 2011 at 3:39 pmThis article was great as far as it went, but just stopped slightly short of what I'm looking for!
I wanted to add Spring MVC to an existing project, but if I change my servlet mapping to:
SpringDispatcherServlet
/smvc
I can seem to invoke the home method of the HomeController, but not the compare method. (I tried lots of different URLs).
If I change my servet mapping to:
SpringDispatcherServlet
/smvc/*
Then I do manage to invoke the compare method of the HomeController, but the forwarding results in this error:
16:32:56,480 DEBUG [JstlView] – Forwarding to resource [WEB-INF/views/compareResult.jsp] in InternalResourceView 'compareResult'
16:32:56,480 DEBUG [DispatcherServlet] – DispatcherServlet with name 'SpringDispatcherServlet' processing GET request for [/smvc/WEB-INF/views/compareResult.jsp]
16:32:56,480 WARN [PageNotFound] – No mapping found for HTTP request with URI [/smvc/WEB-INF/views/compareResult.jsp] in DispatcherServlet with name 'SpringDispatcherServlet'
If anyone could help me resolve this, I'd be really grateful!
Josh Long (blog author) says:
Added on July 15th, 2011 at 11:33 am@Barry, which server are you using? To get a baseline that achieves, more or less, the same functionality as outlined in this wonderful blog post, consider downloading the free SpringSource Tool Suite (http://www.springsource.com/developer/sts) and then going to File > New > Spring Template Project, and then choose the MVC template. Deploy this on to the pre-packaged, pre-bundled tcServer instance that's in the "Servers" panel at the bottom. This will work and it should be easy to then modify it to work as described in this blog.
Michael Morett says:
Added on July 16th, 2011 at 10:19 pmshin0bi69,
You might wanna try including the JSTL libs via Maven.
javax.servlet
jstl
1.2
Michael Morett says:
Added on July 16th, 2011 at 10:23 pmWell, the editor butchered that syntax up. Let's try that again in a roundabout way.
dependency
groupId javax.servlet /groupId
artifactId jstl /artifactId
version 1.2 /version
/dependency
Mahipal says:
Added on August 10th, 2011 at 4:05 amGreat article. Gave much information in simple manner.
Guy Heatley says:
Added on August 24th, 2011 at 4:25 amThis tutorial was useful for seeing the moving parts involved in assembling a MVC web app with Spring.
Am I the only one who considers it odd that in a "Hello World" type app, it is required that you import non-springsource 3rd party jar files i.e CGLib and ASM to get it to work, and this is not mentioned directly in the article itself?!
I'm not particularly familiar with Maven, though. Maybe if I had created a Maven project it would have worked this out for itself, perhaps?
Guy Heatley says:
Added on August 24th, 2011 at 6:11 amNot to mention the jslt jars to get references to the <@ taglib %> to work in Tomcat 6
Marcos Egatz says:
Added on September 9th, 2011 at 1:10 pmI've just read a couple of posts here and I've found the answer was to have both libraries (CGLIB.jar (http://cglib.sourceforge.net/) and asm.jar ) added to the project. Exactly as Hayao said here on February 14th, 2011 at 4:47 am .
Colin Sampaleanu (blog author) says:
Added on September 13th, 2011 at 10:07 amAs a number of people have mentioned, Spring has an optional dependency on cglib, a byte code manipulation library. This is needed for some functionality such as the @Configuration support mentioned in this article. cglib itself has a dependency on ASM, although there is a version of cglib available with ASM already embedded in the jar.
I've updated the article to show a sample Maven POM at the end which may be used to compile all the sample code.
Krunal Shah says:
Added on September 27th, 2011 at 11:39 pmI am completely new to Spring and thus Spring MVC. I have been asked to redevelop some of our application in Java based web technology and I am considering Spring MVC and try to do a simple Hello World application and I succeeded from RoseIndia website. But I am trying to the simple one which explained in here in first part and I get following error:
javax.servlet.ServletException: Servlet.init() for servlet appServlet threw exception
org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:462)
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:851)
com.springsource.insight.collection.tcserver.request.HttpRequestOperationCollectionValve.traceNextValve(HttpRequestOperationCollectionValve.java:112)
com.springsource.insight.collection.tcserver.request.HttpRequestOperationCollectionValve.invoke(HttpRequestOperationCollectionValve.java:94)
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:405)
org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:278)
org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:515)
org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:300)
java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
java.lang.Thread.run(Unknown Source)
I have created a Dynamic Web Project in SpringSource Tool Suite and just copied exactly what has been given in code. Do I have to do anything else to run this or this is not a start up point for me? If this is not a start up point for me than please kindly point me where should I start?
Thanks,
Krunal
Krunal Shah says:
Added on September 27th, 2011 at 11:45 pmJust want to add here that If I run in Tomcat server then it would run okay. But the above error I get with tc server only
SY says:
Added on September 28th, 2011 at 4:07 amI got the 404 error too.
When I access http://localhost:8080/baremvc/, the error is:
No mapping found for HTTP request with URI [/baremvc/] in DispatcherServlet with name 'appServlet'.
At tomcat 6 and tomcat 7 also got this error. Anyone figure out what's the problem?
SY says:
Added on September 28th, 2011 at 9:19 pmI found that the 404 error may because of the eclipse Tomcat config problem. I deploy the war file to tomcat, there's no problem. This error only happens in eclipse…
Lance E Sloan says:
Added on October 4th, 2011 at 12:33 pmNice article, Mr. Sampaleanu. Very clear and lots of explanations, too. I like the addition of comments in your XML files. You're my favorite Green Beans author now.
Lance E Sloan says:
Added on October 6th, 2011 at 10:34 am@Colin Sampaleanu: Great article. You explain things well and I appreciate the comments in the code as well. You're my favorite Green Beans author.
I experienced one problem with the application, though. In CaseInsensitiveComparator, I had to replace the import of org.springframework.stereotype.Component with an import of org.springframework.stereotype.Service. Eclipse advised me to make the change and it worked. Being new to Spring (and Java web apps in general) I don't understand why the change was necessary. Yet.
Borovikov Yaroslav says:
Added on October 11th, 2011 at 3:14 amHello, thank you for this good introduction to the Spring MVC. But I have found a small mistake:
- now: "instead of relying on the default location of -context.xml"
- must be: "instead of relying on the default location of -servlet.xml"
Ryan says:
Added on October 12th, 2011 at 1:27 pmGood article except that it over-emphasizes using annotations for all config. I alwalys use an xml file to configure my spring context for my web services so the high level diagram is all in one place without depending on tools to show me a bean graph. I think the same would be useful for a web site.
Tomek says:
Added on October 23rd, 2011 at 4:36 pmSorry,
I spent many hours at this project end it doesn't work. I rectified what I can but still have error in deployment. Could someone add link to working war file, please.
harshit says:
Added on November 2nd, 2011 at 3:53 pmother useful link with annotations i wrote Spring 3 mvc annotations
Paul Grenyer says:
Added on November 29th, 2011 at 4:12 amTomcat 7.0/Jetty 6.1.23
I tried this last night and I'm having problems getting it to work once deployed. With both a deployed Tomcat 7 and an embedded Jetty 6.1.23 I get the same problem. The URL:
http://localhost:8890/ModelViewController/
Gives a 404 with the message:
Problem accessing /ModelViewController/WEB-INF/views/home.html. Reason: NOT_FOUND
The log messages are:
HomeController: Passing through…
29-Nov-2011 09:09:07.607 WARN [ ] PageNotFound – No mapping found for HTTP request with URI [/ModelViewController/WEB-INF/views/home.html] in DispatcherServlet with name 'ModelViewController'
So the controller is being accessed and the view path resolved, but the container appears unable to serve it for some reason. I did wonder if it might be the web.xml configuration, but it's the same as the example:
ModelViewController
org.springframework.web.servlet.DispatcherServlet
contextConfigLocation
/WEB-INF/spring/appServlet/servlet-context.xml
1
ModelViewController
/
An Eclipse project including dependencies is here: http://paulgrenyer.net/dnld/ModelViewController.zip
Can anyone help me with this, please?
Selva Kumar says:
Added on January 9th, 2012 at 7:18 amVery good introduction for who is new babies in Spring. Can you simply the articled step by step means, from request send to output comes.Step 1 : Request Send 2. X file loades , 3. X file called here like this,
jeff says:
Added on February 18th, 2012 at 1:21 pmis this project source downloadable ? where?
Thanks in advance.
Venkat Palakolanu says:
Added on March 9th, 2012 at 5:16 amThis is really helped me lot, Thank you .
John says:
Added on March 9th, 2012 at 12:25 pmThanks for the article. It really helped me put some the annotation-driven Spring pieces together.
There seems to be one missing piece for me… If I have a controller method like processSubmit(), where HTTP Parameters will be bound to available setters in the data object (let's say FormDataObject), is there a way to explicitly supply that FormDataObject object as a Spring bean?
For example, I might want to configure a FormDataObject object in a Spring XML file (so I can inject values into some members via XML where those members won’t be populated from HTTP parameters). Can that be done?
Rituraj says:
Added on February 5th, 2013 at 3:09 amNice & Insightful post in SringMVC.
libofeng says:
Added on February 22nd, 2013 at 1:47 amit seems sth is missing in pom.xml.
I think we should add this dependency:
org.springframework
spring-web
${org.springframework-version}
Marcos Egatz says:
Added on February 22nd, 2013 at 5:02 amlibofeng,
spring-webmvc depends on spring-web, so maven should resolve it automatically. Look at the following places for further reference:
http://stackoverflow.com/questions/13533700/maven-dependency-spring-web-vs-spring-webmvc
http://mvnrepository.com/artifact/org.springframework/spring-webmvc/3.0.6.RELEASE
libofeng says:
Added on February 22nd, 2013 at 8:40 am@Marcos Egatz
Thanks for pointing out this.
I failed to run this demo webapp because it was missing the annotation of "@RequestMapping".
Now I understand that it may be caused by some problem in my enviroment(may be the network problem).
Thanks
This is a very good article for beginner.
Phil Hope says:
Added on May 7th, 2013 at 3:26 amWirklich gut. Danke dafür!