Spring 4 MVC HelloWorld Tutorial – Annotation/JavaConfig Example

Spring MVC 4 HelloWorld Annotation/JavaConfig Example, step-by-step learning Spring MVC 4 annotations, project setup, code, deploy & Run, in simple way. Let’s get started.

In the previous Spring MVC 4 Hello World tutorial-XML example, we have developed a Hello world web application using XML configuration. However, XML is not the only way to configure spring application. Alternatively, we can configure the application using Java configuration.

If you look back on previous post, you will find that there are mainly two places where we have used XML configuration. First, in spring-servlet.xml where we have defined a view-resolver for identifying the real view , and location to search for beans via component-scanning. Second, in web.xml, we have defined the front-controller configuration and the url pattern it will be looking on.

In this tutorial, we will again create a Hello world example but using Java configuration this time. We will REMOVE both of above mentioned xml files and replace these xml configurations via their java counterparts.

Following technologies stack being used:

  • Spring 4.0.6.RELEASE
  • Maven 3
  • JDK 1.6
  • Tomcat 8.0.21
  • Eclipse JUNO Service Release 2

Let’s begin.

Step 1: Create a project with required directory structure

Post Creating a maven web project with eclipse contains step-by-step instruction to create a maven project with eclipse.

Following will be the final Project structure.


Now let’s add/update the content mentioned in above project structure discussing each in detail.

Step 2: Update pom.xml with Spring and Servlet dependency

The Spring java-based configuration we are going to discuss depends on Servlet 3.0 api, so we need to include that as a dependency in pom.xml

<?xml version="1.0"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
	xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">






First thing to notice here is the maven-war-plugin declaration. As we will be completely removing web.xml, we will need to configure this plugin in order to avoid maven failure to build war package. Second change is the inclusion of JSP/Servlet/Jstl dependencies which we might be needing as we are going to use servlet api’s and jstl view in our code.In general, containers already contains these libraries, so we can set the scope as provided for them in pom.xml.

Additionally, maven-compiler-plugin has been added here to explicitly specify the jdk-version we are going to use. Do note that it also forces eclipse to respect the jdk-version being used for the project. if it is not present, and you perform mvn-update from within your eclipse, eclipse switches jdk-version back to default jdk-version [1.5] which is annoying. So do add it in your project pom as well.

Step 3: Add Controller

Add a controller class under src/main/java as shown below:


package com.websystique.springmvc.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;

public class HelloWorldController {

	@RequestMapping(method = RequestMethod.GET)
	public String sayHello(ModelMap model) {
		model.addAttribute("greeting", "Hello World from Spring 4 MVC");
		return "welcome";

	@RequestMapping(value = "/helloagain", method = RequestMethod.GET)
	public String sayHelloAgain(ModelMap model) {
		model.addAttribute("greeting", "Hello World Again, from Spring 4 MVC");
		return "welcome";


@Controller annotation on class name declares this class as spring bean and @RequestMapping annotation declares that this class is default handler for all requests of type ‘/’. First method does not have any mapping declared so, it will inherit the mapping from mapping declared on class level, acting as default handler for GET requests. Second method (due to additional mapping declaration with value attribute) will serve the request of form /helloagain. Attribute method says which type of HTTP request this method can serve. ModelMap is a Map implementation, which here acting as replacement of [request.getAttribute()/request.setAttribute()]setting values as request attribute. Note that we are returning “welcome” string form this method. This string will be suffixed and prefixed with suffix and prefix defined in view resolver(see spring-servlet.xml above) to form the real view file name.

Step 4: Add View

Create a new folder named views under WEB-INF and add in a Simple JSP page welcome.jsp (WEB-INF/views/welcome.jsp) to simply access the model value sent from controller.

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>HelloWorld page</title>
	Greeting : ${greeting}

Step 5: Add Configuration Class

Add the below mentioned class under src/main/java with specified package as shown below. This configuration class can be treated as a replacement of spring-servlet.xml as it contains all the information required for component-scanning and view resolver.


package com.websystique.springmvc.configuration;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;

@ComponentScan(basePackages = "com.websystique.springmvc")
public class HelloWorldConfiguration {
	public ViewResolver viewResolver() {
		InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();

		return viewResolver;


@Configuration indicates that this class contains one or more bean methods annotated with @Bean producing bean manageable by spring container. Above Configuration class is equivalent to following XML counterpart:

<beans xmlns="http://www.springframework.org/schema/beans"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
 	http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
 	http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">

	<context:component-scan base-package="com.websystique.springmvc" />

	<mvc:annotation-driven />
		<property name="prefix">
		<property name="suffix">


@EnableWebMvc is equivalent to mvc:annotation-driven in XML. It enables support for @Controller-annotated classes that use @RequestMapping to map incoming requests to specific method.

@ComponentScan is equivalent to context:component-scan base-package="..." providing with where to look for spring managed beans/classes.

Step 6: Add Initialization class

Add an initializer class implementing WebApplicationInitializer under src/main/java with specified package as shown below(which in this case acts as replacement of any spring configuration defined in web.xml). During Servlet 3.0 Container startup, this class will be loaded and instantiated and its onStartup method will be called by servlet container.


package com.websystique.springmvc.configuration;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;

import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;

public class HelloWorldInitializer implements WebApplicationInitializer {

	public void onStartup(ServletContext container) throws ServletException {

		AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();

		ServletRegistration.Dynamic servlet = container.addServlet("dispatcher", new DispatcherServlet(ctx));



The content above resembles the content of web.xml from previous tutorial as we are using the front-controller DispatherServler, assigning the mapping (url-pattern in xml) and instead of providing the path to spring configuration file(spring-servlet.xml) , here we are registering the Configuration Class. Overall, we are doing the same thing, just the approach is different.

UPDATE: Note that now you can write the above class even more concisely [and it’s the preferred way], by extending AbstractAnnotationConfigDispatcherServletInitializer base class, as shown below:

package com.websystique.springmvc.configuration;

import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

public class HelloWorldInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

	protected Class<?>[] getRootConfigClasses() {
		return new Class[] { HelloWorldConfiguration.class };
	protected Class<?>[] getServletConfigClasses() {
		return null;
	protected String[] getServletMappings() {
		return new String[] { "/" };


Step 7: Build and Deploy the application

One thing to keep in mind that the Spring java based configuration api’s like WebApplicationInitializer depends on Servlet 3.0 containers.So make sure you don’t have any web.xml with servlet declaration less than 3.0. For our case, we have removed web.xml file from our application.

Now build the war (either by eclipse as was mentioned in last tutorial) or via maven command line( mvn clean install). Deploy the war to a Servlet 3.0 container . Since here i am using Tomcat, i will simply put this war file into tomcat webapps folder and click on start.bat inside tomcat bin directory.

Run the application


That’s it.

Download Source Code


If you like tutorials on this site, why not take a step further and connect me on Facebook , Google Plus & Twitter as well? I would love to hear your thoughts on these articles, it will help me improve further our learning process.

If you appreciate the effort I have put in this learning site, help me improve the visibility of this site towards global audience by sharing and linking this site from within and beyond your network. You & your friends can always link my site from your site on www.websystique.com, and share the learning.

After all, we are here to learn together, aren’t we?

  • Bijith

    Hi, I deployed the code in Tomcat 8 and I also followed the steps mentioned in Setup Eclipse+Tomcat. However, when I start the server, the step: Initializing Spring FrameworkServlet ‘dispatcher’ doesn’t seem to happen. The server starts and runs without issues, but since the initialization didn’t happen, it is not able to recognize the URL pattern. I tried in Jetty server and I find the same issue there as well. I am getting 404 Not found error when I hit the URL. This is working fine for the previous code with XML though. Kindly help.

    I am using Eclipse Luna(4.4) with JDK1.8. I am using the same code as mentioned in this page.

  • Debasis


    I am using Weblogic 12.1.3 version. I am getting Error 403–Forbidden. Please help.

  • Manoj sharma

    Hi, I have tried your demo and i am getting 404 error. I have also configure tomcat+eclipse as you have mentioned.

    • websystique

      Hi, Many of the readers had the same issue and it turned out that their Eclipse+ tomcat setup was having issues.Please make sure that it is following the steps as shown in Setup Tomcat+Eclipse, specially the deployment assembly/maven dependencies step.

      • Eduardo Milpax Díaz

        False, I did the same steps as you(no xml at all) and create a war file using maven, I deploy the file to webapps tomcat folder and still got the same error

  • Mohamed Nashath

    Thank you, It’s working fine for me. Could you please explain how to do navigation from one JSP to another JSP using this example. Thank you

    • websystique

      Hi, you could create a link in one jsp with the url mapping to a controller which will eventually provide the next view[jsp].Have a look at this post.

  • Rajkumar J


    I tried this code in Tomcat 8 its working fine, but when I tried to deploy the same war in JBoss 7.1, Spring configurations (AbstractAnnotationConfigDispatcherServletInitializer and WebApplicationInitializer ) are not loading. Please help me, how to fix this issue in JBoss 7.1

  • jason

    Is the HelloWorldInitializer that extends AbstractAnnotationConfigDispatcherServletInitializer complete?

    • websystique

      Hi, Yes it is. Do you face any issue?

  • Ewald

    When I try to run the downloaded source (runnig from Netbeans on the bundled Tomcat) I get a nice stacktrace and the following message:

    ApplicationEventMulticaster not initialized – call ‘refresh’ before multicasting events via the context: WebApplicationContext for namespace ‘dispatcher-servlet’: startup date [Fri Oct 07 08:10:02 CEST 2016]; root of context hierarchy

    What’s wrong?

    • websystique

      Hi Ewald, I don’t have netbeans setup at my end.However, i did come across a StackOverFlow link which can help you.

  • mma

    Firstly i want to thank you for this tutorial, but i have this error when i run the project :


    • websystique

      Hi Mma,

      It seems to be a problem with your Eclipse+tomcat setup. Please have a look at Setup Eclipse+Tomcat, should be fine.

      • mma

        thank you, yes it was a problem in my tomcat, i installed a newest version and it was fine :)

      • Vipul Singh

        I using eclipse neon with sts plugin. and i am getting 404 error.please reply asap

      • Eduardo Milpax Díaz

        I did it both ways(eclipse + tomcat and deploying the app to tomcat webapps folder), still don’t work.

        I’m using tomcat version 9.0.0.M4

  • Pingback: JSP (expression language) not working in java based configuration spring mvc - Tech()

  • David


    Unable to create your project from zero. Sometimes not recognize dependencies, sometimes not recognize @RequestMapping, etc…

    So I decided to download your code and install using import option in Eclipse Neon.
    Everything is ok, but HelloWorldInitializer give full of errors.
    I attach several images, hoping you can tell me something.

    eclipse neon
    tomcat 8.0
    java 1.8_09
    https://uploads.disquscdn.com/images/fd2f9ef68080f1625faa94d55e263dd8382e35b44dda90b3435fc507c066c4ed.png https://uploads.disquscdn.com/images/586c3f27391d512d6b7da371300628bab2688c03352b61a389ae7cd2cc0f86dd.png

    Thanks https://uploads.disquscdn.com/images/bb5a5c47f7e956917af0db7aaa855bc6ee3f3d062b35eaf10774187361e799d9.png

    • websystique

      Hi David, Firstly update your pom.xml to include maven-compiler-plugin [as shown in post, might be missing in download] with your java version[1.6 or 7/8], then do a maven update, should be fine.

  • Amit

    Hi, Thank you for the post. I am struggling with 404 error with Java based configuration. I am using JBoss EAP 6.1 to run this application. URLs are being mapped correctly. However it still gives 404 error while accessing the page. I am using the correct URLs.



    Please don’t get confused with the name ‘Spring4XMLDemo’. It is actually Java based configuration, not xml based. XML based config is working fine for me.

    16:18:38,163 INFO [org.jboss.web] (ServerService Thread Pool — 190) JBAS018210: Register web context: /Spring4XMLDemo

    16:18:38,169 INFO [org.apache.catalina.core.ContainerBase.[jboss.web].[default-host].[/Spring4XMLDemo]] (ServerService Thread Pool — 190) Spring WebApplicationInitializers detected on classpath: [com.websystique.springmvc.configuration.HelloWorldInitializer@19618d]

    16:18:38,195 INFO [org.apache.catalina.core.ContainerBase.[jboss.web].[default-host].[/Spring4XMLDemo]] (ServerService Thread Pool — 190) Initializing Spring root WebApplicationContext

    16:18:38,195 INFO [org.springframework.web.context.ContextLoader] (ServerService Thread Pool — 190) Root WebApplicationContext: initialization started

    16:18:38,226 INFO [org.springframework.web.context.support.AnnotationConfigWebApplicationContext] (ServerService Thread Pool — 190) Refreshing Root WebApplicationContext: startup date [Mon Jul 04 16:18:38 BST 2016]; root of context hierarchy

    16:18:38,257 INFO [org.springframework.web.context.support.AnnotationConfigWebApplicationContext] (ServerService Thread Pool — 190) Registering annotated classes: [class com.websystique.springmvc.configuration.HelloWorldConfiguration]

    16:18:38,398 INFO [org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor] (ServerService Thread Pool — 190) JSR-330 ‘javax.inject.Inject’ annotation found and supported for autowiring

    16:18:38,561 INFO [org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping] (ServerService Thread Pool — 190) Mapped “{[/helloagain],methods=[GET]}” onto public java.lang.String com.websystique.springmvc.controller.HelloWorldController.sayHelloAgain(org.springframework.ui.ModelMap)

    16:18:38,561 INFO [org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping] (ServerService Thread Pool — 190) Mapped “{[/],methods=[GET]}” onto public java.lang.String com.websystique.springmvc.controller.HelloWorldController.sayHello(org.springframework.ui.ModelMap)

    16:18:38,598 INFO [org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter] (ServerService Thread Pool — 190) Looking for @ControllerAdvice: Root WebApplicationContext: startup date [Mon Jul 04 16:18:38 BST 2016]; root of context hierarchy

    16:18:38,677 INFO [org.springframework.web.context.ContextLoader] (ServerService Thread Pool — 190) Root WebApplicationContext: initialization completed in 482 ms

    16:18:38,679 INFO [org.apache.catalina.core.ContainerBase.[jboss.web].[default-host].[/Spring4XMLDemo]] (ServerService Thread Pool — 190) Initializing Spring FrameworkServlet ‘dispatcher’

    16:18:38,679 INFO [org.springframework.web.servlet.DispatcherServlet] (ServerService Thread Pool — 190) FrameworkServlet ‘dispatcher’: initialization started

    16:18:38,694 INFO [org.springframework.web.servlet.DispatcherServlet] (ServerService Thread Pool — 190) FrameworkServlet ‘dispatcher’: initialization completed in 15 ms

    16:18:38,807 INFO [org.jboss.as.server] (DeploymentScanner-threads – 1) JBAS018565: Replaced deployment “Spring4XMLDemo.war” with deployment “Spring4XMLDemo.war”

    • websystique

      Hi Amit, sorry for being late. I wonder if you are still facing the issue? I don’t have a jboss ready setup at moment [used tomcat] but if you are still stuck, let me know, will prepare the env and try myself.

      • Amit

        Hi, Thanks for the response. I have resolved the issue. I used JBoss 7.0 EAP and servlet API version 3.1.0. It resolved the issue.

  • http://www.techinfinite.tk pranish

    how to use spring boot and spring 4 together? Or spring boot also has its 4 version

  • Gautham Shetty

    getting following error after mvn clean compile

    INFO] ————————————————————————

    [ERROR] No goals have been specified for this build. You must specify a valid lifecycle phase or a goal in the format : or :[:]:. Available lifecycle phases are: validate, initialize, generate-sources, process-sources, generate-resources, process-resources, compile, process-classes, generate-test-sources, process-test-sources, generate-test-resources, process-test-resources, test-compile, process-test-classes, test, prepare-package, package, pre-integration-test, integration-test, post-integration-test, verify, install, deploy, pre-clean, clean, post-clean, pre-site, site, post-site, site-deploy. -> [Help 1]

    org.apache.maven.lifecycle.NoGoalSpecifiedException: No goals have been specified for this build. You must specify a valid lifecycle phase or a goal in the format : or :[:]:. Available lifecycle phases are: validate, initialize, generate-sources, process-sources, generate-resources, process-resources, compile, process-classes, generate-test-sources, process-test-sources, generate-test-resources, process-test-resources, test-compile, process-test-classes, test, prepare-package, package, pre-integration-test, integration-test, post-integration-test, verify, install, deploy, pre-clean, clean, post-clean, pre-site, site, post-site, site-deploy.

    at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:94)

    at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:307)

    at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:193)

    at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:106)

  • Dileep Kumar Kottakota

    Getting this error even i have latest jdk.

    “dynamic web module 3.1 requires java 1.7 or newer”

  • Anil Vighne

    Hello Sir please give example on spring cache.

  • ankit chauhan

    Hello websystique,

    I just post it to tell you how unbelievably nice this tutorial is .. :)


    • websystique

      Hi Ankit,

      Glad you liked it.

  • Nicolas R.M

    Hi, annotation vs xml configuration?

    • websystique

      Hi Nicolas,
      Both the configurations are shown here, Annotation being the preferred approach. Let me know if i misunderstood your question.

      • Nicolas R.M

        Yes, thank you, you are great! :)

  • Texan Rock

    type Status report

    message /Spring4MVCHelloWorldNoXMLDemo/

    description The requested resource is not available.

    after deploy in tomcat 8

  • Arnish Gupta


    i have a problem that it shows ${greeting} as output, but i want to print the value that declared in controller.

    • websystique

      Hi Arnish, Could you try adding in your JSP please? It should fix the issue.

      • Arnish Gupta

        Thank you, it’s working.

        • son ngo

          please fix on your original lesson. I think somebody dont know how to fix this error.

  • mdk

    Both these dependencies should have a scope of provided, otherwise they will be exported to /WEB-INF/lib and contaminate your tomcat



    should be : -



    • websystique

      Thanks MDK,

      I’ve already said about it in my post above, but it’s always better to point-it out loudly.

  • Sumit Surana

    Hi, I tried the above example as it is and even removed the web.xml file with servlet-api version being 3.1.0 and is included in my pom.xml, but the jsp expression syntax ie ${greeting} is not working and is showing “Greeting: ${greeting}” on the web page instead of “Greeting : Hello World from Spring 4 MVC”

    • websystique

      Hey Sumit, sorry for late reply.

      The attached project itself is fine. The problem you are getting seems related to the container in that your expression are not getting evaluated.
      Could you try adding following at top of your JSP and try to build and deploy again?

      Let me know the outcome.

      • sandeep

        After adding the isELIgnored it is working with “/helloagain”. But when trying with “/”, its not printing the “Hello World from Spring 4 MVC” rather printing the “Hello World”. In case of web.xml we had added the welcome-file-list but in this case there is no web.xml

        • sandeep

          After I removed the index.jsp, it started redirecting to the welcome.jsp

  • Pingback: Spring 4 MVC HelloWorld Tutorial - Full XML Example - WebSystique()

  • websystique

    Hi Pabitra, post has been updated with fix.Thanks for reporting this issue.

  • websystique

    Hi Aditya, I’ve added jstl dependency explicitly in pom.xml, and updated the zip. Thanks for reporting this issue. Seems recent version of tomcat [8.x] need explicit JSTL.