Close

Spring MVC - Application Scoped Bean Example

[Updated: Apr 18, 2018, Created: Apr 18, 2018]

A single instance of 'application' scoped bean lives within a ServletContext instance. That means it can be used between multiple servlet based applications running in the same ServletContext, e.g. two Spring's ApplicationContexts can use the same 'application' scoped bean.

The default 'singleton' bean lives only within a single ApplicationContext, whereas, an 'application' bean lives within ServletContext i.e. across multiple ApplicationContexts.

Spring stores 'application' scoped bean as a regular ServletContext attribute.

Example

In this example we will create two web based ApplicationContexts running under same ServletContext.

WebApplicationInitializer

We are going to create two DispatcherServlets with different bean configurations and different mappings:

public class MyWebInitializer implements WebApplicationInitializer {

  @Override
  public void onStartup(ServletContext servletContext) throws ServletException {
      registerSpringContext(servletContext, MyWebConfig.class, "dispatcher1", "/app1/*");
      registerSpringContext(servletContext, MyWebConfig2.class, "dispatcher2", "/app2/*");
  }

  private void registerSpringContext(ServletContext servletContext, Class<?> configClass,
                                     String servletName, String mapping) {
      AnnotationConfigWebApplicationContext ctx =
              new AnnotationConfigWebApplicationContext();
      ctx.register(configClass);
      ctx.setServletContext(servletContext);

      ServletRegistration.Dynamic servlet =
              servletContext.addServlet(servletName, new DispatcherServlet(ctx));
      servlet.setLoadOnStartup(1);
      servlet.addMapping(mapping);
  }
}

App1

@EnableWebMvc
@Configuration
public class MyWebConfig {

  @Bean
  public MyController myController() {
      return new MyController();
  }

  @Bean
  @Scope(value = WebApplicationContext.SCOPE_APPLICATION)
  public AppLevelPreference pref() {
      return new AppLevelPreference();
  }

  @Bean
  public ViewResolver viewResolver() {
      InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
      viewResolver.setPrefix("/WEB-INF/views/");
      viewResolver.setSuffix(".jsp");
      return viewResolver;
  }
}
@Controller
public class MyController {
  @Autowired
  private AppLevelPreference appLevelPreference;

  @GetMapping("/**")
  public String appHandler(Model model, HttpServletRequest req) {
      model.addAttribute("pref", appLevelPreference);
      model.addAttribute("uri", req.getRequestURI());
      model.addAttribute("msg", "response from app1");
      return "app-page";
  }

  @PostMapping("/**")
  public String appPostHandler(String fontSize, String background, HttpServletRequest req) {
      appLevelPreference.setBackground(background);
      appLevelPreference.setFontSize(fontSize);
      System.out.println(req.getRequestURI());
      return "redirect:" + req.getRequestURI();//redirect to GET
  }
}

App2

@EnableWebMvc
@Configuration
public class MyWebConfig2 {

  @Bean
  public MyController2 myController2() {
      return new MyController2();
  }

  @Bean
  @Scope(value = WebApplicationContext.SCOPE_APPLICATION)
  public AppLevelPreference pref() {
      return new AppLevelPreference();
  }

  @Bean
  public ViewResolver viewResolver() {
      InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
      viewResolver.setPrefix("/WEB-INF/views/");
      viewResolver.setSuffix(".jsp");
      return viewResolver;
  }
}
@Controller
public class MyController2 {
  @Autowired
  private AppLevelPreference appLevelPreference;

  @GetMapping("/**")
  public String appHandler(Model model, HttpServletRequest req) {
      model.addAttribute("pref", appLevelPreference);
      model.addAttribute("uri", req.getRequestURI());
      model.addAttribute("msg", "response from app2");
      return "app-page";
  }

  @PostMapping("/**")
  public String appPostHandler(String fontSize, String background, HttpServletRequest req) {
      appLevelPreference.setBackground(background);
      appLevelPreference.setFontSize(fontSize);
      System.out.println(req.getRequestURI());
      return "redirect:" + req.getRequestURI();//redirect to GET
  }
}

The application scoped bean

public class AppLevelPreference implements Serializable {
  private String background = "#fff";
  private String fontSize = "14px";
  //getters/setters
    .............
}

Note that both config classes MyWebConfig and MyWebConfig2 are using the same name for our application scoped bean (by naming same method name pref()), otherwise two different instances will be stored with two different ServletContext attribute names.

JSP page

src/main/webapp/WEB-INF/views/app-page.jsp

<html>
<body style="background:${pref.background};font-size:${pref.fontSize}">
<h3>App</h3>
<form action="" method="post" >
Background <input type="text" name="background" value="${pref.background}"/>
Font size <input type="text" name="fontSize" value="${pref.fontSize}"/>
               <input type="submit" value="Submit" />
<p>App content .... at ${uri}</p>
<p>${msg}</p>
</body>
</html>

Output

To try examples, run embedded tomcat (configured in pom.xml of example project below):

mvn tomcat7:run-war

Accessing http://localhost:8080/app1/

Now change the background value and submit the form:

Now access the other spring application at /app2/ :

Note that if you change the 'application' scope to the default 'singleton' scope in both config classes, then different AppLevelPreference instances will be used for each contexts.

Example Project

Dependencies and Technologies Used:

  • spring-webmvc 5.0.5.RELEASE: Spring Web MVC.
  • javax.servlet-api 3.0.1 Java Servlet API
  • JDK 1.8
  • Maven 3.3.9

Spring Application Scope Example Select All Download
  • application-scope-example
    • src
      • main
        • java
          • com
            • logicbig
              • example
                • app1
                • app2
        • webapp
          • WEB-INF
            • views

See Also