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:
Let’s begin.
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.
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.
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.
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>
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.
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[] { "/" }; } }
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.
References
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 improve further our learning process.
In this post we will be developing a full-blown CRUD application using Spring Boot, AngularJS, Spring Data, JPA/Hibernate and MySQL,…
Spring Boot complements Spring REST support by providing default dependencies/converters out of the box. Writing RESTful services in Spring Boot…
Being able to start the application as standalone jar is great, but sometimes it might not be possible to run…
Spring framework has taken the software development industry by storm. Dependency Injection, rock solid MVC framework, Transaction management, messaging support,…
Let's secure our Spring REST API using OAuth2 this time, a simple guide showing what is required to secure a…
This post shows how an AngularJS application can consume a REST API which is secured with Basic authentication using Spring…
View Comments
https://uploads.disquscdn.com/images/892a63b0d7fc027f3fab7d762bfa8512ed1abda6a8a4f466ed0bb8da43818c9b.png
What went wrong in my code ? I am unable to get original text which I mapped to ModelMap.
Maybe you have the old JSP (1.2)
And it needs inclusion EL..
add it in your JSP file
Please check below link for simple spring mvc example without any xml configuration
https://codedeal.wixsite.com/codedeal/single-post/Spring-MVC-Basic-Example-Without-Any-XML-Configuration
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?
This example will do not work, due to a java api servlet issue with version 3.0.
Review my source code fixed:
Regards!
https://github.com/anibalgomezprojects/springmvc4java
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 am using Weblogic 12.1.3 version. I am getting Error 403--Forbidden. Please help.
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?
Hi, Yes it is. Do you face any issue?