How to bootstrap a Spring Web MVC application programmatically
- Details
- Written by Nam Ha Minh
- Last Updated on 20 June 2019   |   Print Email
Boostrap a Spring MVC application using XML-based approach:
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> <display-name>SpringWebMVCApp</display-name> <servlet> <servlet-name>SpringController</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/applicationContext.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>SpringController</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>Since Servlet 3.0+, the above registration for Spring’s dispatcher servlet can be done programmatically (code-based), thanks to the Servlet 3.0’s new feature called shared libraries/runtimes pluggability which scans jar files bundled in the WEB-INF\lib directory for implementations of the ServletContainerInitializer interface and invokes its onStartup() method which contains initialization/bootstrapping code, during servlet container/web application startup. In respond to this new feature, Spring 3.1+ provides its own implementation by the SpringServletContainerInitializer class which is bundled in configured in the spring-web-VERSION.jar file.The SpringServletContainerInitializer class is bootstrapped automatically by any Servlet 3.0-compliant container (e.g. Apache Tomcat 7), and it will look for an implementation of the WebApplicationInitializer interface and invoke its onStartup() method. Following is an example of a WebApplicationInitializer’s implementation that does the same thing as the XML-based approach above:
Bootstrap a Spring MVC application using code-based approach:
import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletRegistration; import org.springframework.web.WebApplicationInitializer; import org.springframework.web.context.support.XmlWebApplicationContext; import org.springframework.web.servlet.DispatcherServlet; public class SpringWebAppInitializer implements WebApplicationInitializer { @Override public void onStartup(ServletContext container) throws ServletException { XmlWebApplicationContext appContext = new XmlWebApplicationContext(); appContext.setConfigLocation("/WEB-INF/applicationContext.xml"); ServletRegistration.Dynamic dispatcher = container.addServlet( "SpringDispatcher", new DispatcherServlet(appContext)); dispatcher.setLoadOnStartup(1); dispatcher.addMapping("/"); } }However, as we can see, the Spring’s application context configuration still remains XML-based:
appContext.setConfigLocation("/WEB-INF/applicationContext.xml");We may configure the applicationContext.xml file as follows:
XML-based application context configuration:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="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"> <bean name="/" class="net.codejava.spring.HomeController" /> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/" /> <property name="suffix" value=".jsp" /> </bean> </beans>So to replace this XML by a code-based approach, we can create a configuration class using Spring’s @Configuration and @Bean annotations and register this configuration class by the AnnotationConfigWebApplicationContext class.
Code-based application context configuration:
package net.codejava.spring; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.mvc.Controller; import org.springframework.web.servlet.view.InternalResourceViewResolver; @Configuration public class ApplicationContextConfig { @Bean(name = "viewResolver") public InternalResourceViewResolver getViewResolver() { InternalResourceViewResolver viewResolver = new InternalResourceViewResolver(); viewResolver.setPrefix("/"); viewResolver.setSuffix(".jsp"); return viewResolver; } @Bean(name = "/") public Controller getHomeController() { return new HomeController(); } }This configuration defines two beans, one for a typical Spring MVC’s view resolver and one for a controller. Code of the HomeController class is as follows:
package net.codejava.spring; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.Controller; public class HomeController implements Controller { @Override public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { return new ModelAndView("home"); } }The handleRequest() method of this controller class simply returns a logical view name “home” which is mapped to the following home.jsp page:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!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=UTF-8"> <title>Spring MVC Bootstrap</title> </head> <body> <div align="center"> <h1>Welcome to Spring MVC Bootstrap demo!</h1> <h3>100% code-based approach, no XML at all!</h3> </div> </body> </html>And register this configuration file using the AnnotationConfigWebApplicationContext class as follows:
AnnotationConfigWebApplicationContext appContext = new AnnotationConfigWebApplicationContext(); appContext.register(ApplicationContextConfig.class);Then we have our SpringWebAppInitializer class finalized as follows:
100% code-based approach:
package net.codejava.spring; 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 SpringWebAppInitializer implements WebApplicationInitializer { @Override public void onStartup(ServletContext container) throws ServletException { AnnotationConfigWebApplicationContext appContext = new AnnotationConfigWebApplicationContext(); appContext.register(ApplicationContextConfig.class); ServletRegistration.Dynamic dispatcher = container.addServlet( "SpringDispatcher", new DispatcherServlet(appContext)); dispatcher.setLoadOnStartup(1); dispatcher.addMapping("/"); } }If we build this application in Eclipse IDE, we would have the following project structure:Package and deploy this application on a Servlet 3.0-compliant server (Apache Tomcat) and access it in browser by the following URL:
http://localhost:8080/SpringMVCBootstrap
Output:As we can see, this simple Spring Web MVC application is running perfectly! Thanks to the code-based approach, we don’t have to write any XML code at all! One big benefit of this approach is that we can package our application’s bootstrap code in a jar file and put it under WEB-INF\lib directory and the servlet container will automatically detect and initialize it.Download the sample application (Eclipse project) to test this out yourself.Related Spring Tutorials:
- How to enable Spring MVC in web.xml
- Understand the core of Spring framework
- Understand Spring MVC
- Understand Spring AOP
- Spring MVC beginner tutorial with Spring Tool Suite
Comments
I am getting the following :
HTTP Status 404 - /SpringMVCBootstrap/
type Status report
message /SpringMVCBootstrap/
description The requested resource (/SpringMVCBootstrap/) is not available.
Maybe the application failed to start. What did you see in the server's error log file?
while i am running this code it showing runtime exception.
EXCEPTION
java.lang.IllegalStateException: BeanFactory not initialized or already closed - call 'refresh' before accessing beans via the ApplicationContext
at org.springframework.context.support.AbstractRefreshableApplicationContext.getBeanFactory(AbstractRefreshableApplicationContext.java:170)
I think problem in SpringWebAppInitializer class