13

As I understand, a Spring based web application is initialized as below:

Step 1: Servlet container (e.g. Tomcat) locates the implementation of ServletContainerInitializer, which is SpringServletContainerInitializer.

Step 2: SpringServletContainerInitializer creates DispatcherServlet and ContextLoaderListener

Step 3: DispatcherServlet creates servlet application context. And ContextLoaderListener creates root application context.

Step 1 is defined by Servlet 3.0 spec. Step 2, 3 are totally defined by Spring.

I can see the rational of putting web beans in servlet context and non-web beans in root context. But why do we have to create these 2 contexts in different places, i.e. DispatcherServlet and ContextLoaderListener?

If all we want is just to prepare everything necessary, why not just create both contexts in ContextLoaderListener since it can be seen as the main() method of the whole web application. I think that's more logic and current approach only complicates things up.

ADD 1

Based on @Shailendra's reply, I draw this:

enter image description here

My understanding is, Spring introduced the application context concepts and store them in the Servlet Context. Servlet Context is a concept introduced by java servlet technolgoy.

I guess the DispatcherServlet implementation should have a member variable to hold the key to its servlet application context in the servlet context. So it can access it's own context. Maybe the key is the servlet name.

And the root application context should have a well-known key so everyone can access it.

ADD 2

The well-known key for root application context is this:

(in org.springframework.web.context.WebApplicationContext)

String ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE = WebApplicationContext.class.getName() + ".ROOT";

ADD 3

The DispatcherServlet does have a reference to its WebApplicationContext. It inherits the following memeber from FrameworkServlet:

/** WebApplicationContext for this servlet */
private WebApplicationContext webApplicationContext;

And

public FrameworkServlet(WebApplicationContext webApplicationContext) {
    this.webApplicationContext = webApplicationContext;
}
smwikipedia
  • 52,824
  • 76
  • 267
  • 432
  • What do you refer to with `non-web` beans? If your application is running in a servlet container the only context should be the servlet one, AFAIK. Spring also lets you create as many context as you want, but this only will make things more complicated. – Xtreme Biker Oct 16 '15 at 06:16
  • @XtremeBiker by `non-web` beans, I mean those for back-end operations. – smwikipedia Oct 16 '15 at 06:56
  • 1
    Each `DispatcherServlet` creates its own context, you can have multiple `DispatcherServlet`s how should the `ContextLoaderListener` know how many servlets there are and how to configure the context for those. It is not the task / responsibility of each of them. Also it isn't required to have a `ContextLoaderListener` you can do perfectly without it, so how would you bootstrap your application then? Also the different `ApplicationContext` instances are all stored in the `ServletContext` under well known names, as that is also how the `DispatcherServlet` detects the (optional) root context. – M. Deinum Oct 16 '15 at 08:34
  • @M.Deinum I think as a web application designer, he should know how many DispatcherServlets there are. And what each of them needs. So designer can take the job to create necessary contexts. So for now, I think *current* approach is just one approach taken by Spring *accidentally*. It may not be *the* only possible/best option. – smwikipedia Oct 16 '15 at 13:49
  • It still is not the responsibility of the `ContextLoaderListener` to load the child contexts. Also there are more types of servlets constructing an `ApplicationContext` like the `MessageDispatcherServlet` for Spring WebServices. – M. Deinum Oct 16 '15 at 16:47
  • @M.Deinum I think your point is *to let the context consumer create its own context*. I can agree with that. Please correct me if I misinterpret your idea. – smwikipedia Oct 17 '15 at 02:17
  • It isn't the consumer it is the owner of the context. The `DispatcherServlet` owns the `ApplicationContext` it constructs. The `ContextLoaderLIstener` doesn't care wether it is the single context or if there are other means that a child context is created (you could also create your own servlet or class that bootstraps a context). – M. Deinum Oct 17 '15 at 10:08

1 Answers1

6

But why do we have to create these 2 contexts in different places, i.e. DispatcherServlet and ContextLoaderListener

Because the two contexts are supposed to be different but yet have a hierarchical relation in order to be able to override. Typically the context loaded using ContextLoaderListener is "root" context which belongs to the whole application while the one initialized using DispatcherServlet is actually specific to that servlet. Technically you can have multiple servlets in an application and so multiple such contexts each specific for respective servlet but having same root context. For more details see another of my answer here.

Community
  • 1
  • 1
Shailendra
  • 6,814
  • 2
  • 21
  • 32