Categories: springmvc

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 going.

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

 <modelVersion>4.0.0</modelVersion>
 <groupId>com.websystique.springmvc</groupId>
 <artifactId>Spring4MVCHelloWorldNoXMLDemo</artifactId>
 <packaging>war</packaging>
 <version>1.0.0</version>
 <name>Spring4MVCHelloWorldNoXMLDemo</name>

 <properties>
  <springframework.version>4.0.6.RELEASE</springframework.version>
 </properties>

 <dependencies>
  <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-webmvc</artifactId>
   <version>${springframework.version}</version>
  </dependency>

  <dependency>
   <groupId>javax.servlet</groupId>
   <artifactId>javax.servlet-api</artifactId>
   <version>3.1.0</version>
  </dependency>
  <dependency>
   <groupId>javax.servlet.jsp</groupId>
   <artifactId>javax.servlet.jsp-api</artifactId>
   <version>2.3.1</version>
  </dependency>
  <dependency>
   <groupId>javax.servlet</groupId>
   <artifactId>jstl</artifactId>
   <version>1.2</version>
  </dependency>
 </dependencies>

 <build>
  <pluginManagement>
   <plugins>
    <plugin>
     <groupId>org.apache.maven.plugins</groupId>
     <artifactId>maven-compiler-plugin</artifactId>
     <version>3.2</version>
     <configuration>
      <source>1.6</source>
      <target>1.6</target>
     </configuration>
    </plugin>
    <plugin>
     <groupId>org.apache.maven.plugins</groupId>
     <artifactId>maven-war-plugin</artifactId>
     <version>2.4</version>
     <configuration>
      <warSourceDirectory>src/main/webapp</warSourceDirectory>
      <warName>Spring4MVCHelloWorldNoXMLDemo</warName>
      <failOnMissingWebXml>false</failOnMissingWebXml>
     </configuration>
    </plugin>
   </plugins>
  </pluginManagement>
  <finalName>Spring4MVCHelloWorldNoXMLDemo</finalName>
 </build>
</project>

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:

com.websystique.springmvc.controller.HelloWorldController

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;

@Controller
@RequestMapping("/")
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"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>HelloWorld page</title>
</head>
<body>
 Greeting : ${greeting}
</body>
</html>

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.

com.websystique.springmvc.configuration.HelloWorldConfiguration

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;

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "com.websystique.springmvc")
public class HelloWorldConfiguration {
 @Bean
 public ViewResolver viewResolver() {
  InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
  viewResolver.setViewClass(JstlView.class);
  viewResolver.setPrefix("/WEB-INF/views/");
  viewResolver.setSuffix(".jsp");

  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"
 xmlns:context="http://www.springframework.org/schema/context"
 xmlns:mvc="http://www.springframework.org/schema/mvc"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 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 />
 
 <bean
  class="org.springframework.web.servlet.view.InternalResourceViewResolver">
  <property name="prefix">
   <value>/WEB-INF/views/</value>
  </property>
  <property name="suffix">
   <value>.jsp</value>
  </property>
 </bean>

</beans>

@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.

com.websystique.springmvc.configuration.HelloWorldInitializer

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();
  ctx.register(HelloWorldConfiguration.class);
  ctx.setServletContext(container);

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

  servlet.setLoadOnStartup(1);
  servlet.addMapping("/");
 }

}

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 {

 @Override
 protected Class<?>[] getRootConfigClasses() {
  return new Class[] { HelloWorldConfiguration.class };
 }
 
 @Override
 protected Class<?>[] getServletConfigClasses() {
  return null;
 }
 
 @Override
 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


References

View Comments

    • Maybe you have the old JSP (1.2)
      And it needs inclusion EL..

      add it in your JSP file

  • Hi, I need to add listeners and filters using AbstractAnnotationConfigDispatcherServletInitializer but I can't find a way to do that. See my Initializer class (addFilters(), addListeners()) which is using WebApplicationInitializer interface:

    -- imports --
    public class ApplicationInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext container) throws ServletException {
    // Registers the application configuration with the root context
    AnnotationConfigWebApplicationContext appContext = new AnnotationConfigWebApplicationContext();
    appContext.setDisplayName("EXP Planning Tool");
    appContext.register(ApplicationConfig.class);

    // Manage the lifecycle of the root application context
    setRootApplicationContext(container, appContext);

    // Configure Dispatcher Servlet
    setDispatcherServletContext(container, appContext);

    // Configure Filters
    addFilters(container);

    // Configure Listeners
    addListeners(container);
    }

    private void setRootApplicationContext(ServletContext container, AnnotationConfigWebApplicationContext appContext) {
    container.addListener(new ContextLoaderListener(appContext));
    }

    private void setDispatcherServletContext(ServletContext container, AnnotationConfigWebApplicationContext appContext) {
    ServletRegistration.Dynamic dispatcher = container.addServlet("dispatcher", new DispatcherServlet(appContext));
    dispatcher.setLoadOnStartup(1);
    dispatcher.addMapping("/");

    }

    private void addListeners(ServletContext container) {
    container.addListener(new SessionListener());
    }

    private void addFilters(ServletContext container) {
    container.addFilter("CROSSOriginFilter", CrossOriginFilter.class).addMappingForUrlPatterns(null, false, "/*");
    // container.addFilter("EPTAuthFilter", EPTAuthFilter.class).addMappingForUrlPatterns(null, false, "*.do");
    }
    }

    Can you give me a AbstractAnnotationConfigDispatcherServletInitializer equavalent code for my above code?

  • 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.

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

    • 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.

      • 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

  • 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

    • 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.

  • Hi,

    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

  • Hello,
    Is the HelloWorldInitializer that extends AbstractAnnotationConfigDispatcherServletInitializer complete?

Share
Published by

Recent Posts

Spring Boot + AngularJS + Spring Data + JPA CRUD App Example

In this post we will be developing a full-blown CRUD application using Spring Boot, AngularJS, Spring Data, JPA/Hibernate and MySQL,…

7 years ago

Spring Boot Rest API Example

Spring Boot complements Spring REST support by providing default dependencies/converters out of the box. Writing RESTful services in Spring Boot…

7 years ago

Spring Boot WAR deployment example

Being able to start the application as standalone jar is great, but sometimes it might not be possible to run…

7 years ago

Spring Boot Introduction + hello world example

Spring framework has taken the software development industry by storm. Dependency Injection, rock solid MVC framework, Transaction management, messaging support,…

7 years ago

Secure Spring REST API using OAuth2

Let's secure our Spring REST API using OAuth2 this time, a simple guide showing what is required to secure a…

8 years ago

AngularJS+Spring Security using Basic Authentication

This post shows how an AngularJS application can consume a REST API which is secured with Basic authentication using Spring…

8 years ago