Why Dispatcherservlet Creates Another Application Context

Why DispatcherServlet creates another application context?

To answer your first question, the DispatcherServlet creates a context because that's how it allows itself to be configured, and if you have multiple DispatcherServlets in one app, they'd each need to be configured separately. Therefore each one gets its own context, and each of those contexts is separate from the "root" context, where all of your real, "working" beans should live so they can be shared between the other contexts. There have been a number of questions over the last couple of weeks that were spawned by confusion over this very issue. You might gain a better understanding of how things work by checking out the answers:

Spring XML file configuration hierarchy help/explanation

Declaring Spring Bean in Parent Context vs Child Context

Spring-MVC: What are a "context" and "namespace"?

Spring: Why root application context and servlet application context are created by different parties?

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.

Spring context is loaded twice when Spring DispatcherServlet is used from within MeteorServlet of Atmosphere

It is because you have both a org.springframework.web.context.ContextLoaderListener and a org.springframework.web.servlet.DispatcherServlet defined within your web.xml, processing the same spring-context.xml

org.springframework.web.context.ContextLoaderListener will be invoked when you first deploy your web application and will create a single Spring ApplicationContext using /WEB-INF/spring-context.xml and /WEB-INF/security/spring-security.xml.

Next, the Servlets for your webapp will be created, one of which appears to delegate to a Spring Dispatcher servlet. This will create a new ApplicationContext using only /WEB-INF/spring-context.xml.

This is why you see your ApplicationContext being created twice. To prevent it, use either the DispatcherServlet or the ContextLoaderListener to create your ApplicationContext. Given your need to integrate with another framework, I suspect the easiest option might be to use the DispatcherServlet.

How exactly are the root context and the dispatcher servlet context into a Spring MVC web application?

Root Context

The root-context in a Spring application is the ApplicationContext that is loaded by the ContextLoaderListener. This context should have globally available resources like services, repositories, infrastructure beans (DataSource, EntityManagerFactorys etc.) etc.

The ContextLoaderListener registers this context in the ServletContext under the name org.springframework.web.context.WebApplicationContext.ROOT.

If you load an ApplicationContext yourself and register it with the name above in the ServletContext that will then qualify as the root-context.

Child Context

The child-context in a Spring application is the ApplicationContext that is loaded by a DispatcherServlet (or for instance a MessageDispatcherServlet in a Spring-WS application). This context should only contain beans relevant to that context, for Spring MVC that would be ViewResolvers, HandlerMappings etc.

The servlet registers this context in the ServletContext under the name org.springframework.web.servlet.FrameworkServlet.CONTEXT.<servlet-name>.

Root <-Child Relation

Only child contexts have access to the parent context, because you could have multiple child contexts. For instance in an Spring MVC combined with Spring WS application. The parent-context is detect by the children by finding it in the ServletContext with the well known name.

If the root context would have access to the child which one would it use to wire beans? Next to that if that would be the case you would also get surprising results when AOP is involved. AOP defined in the child context would suddenly influence beans configured in the root context.

Multiple application context, multiple dispatcher servlets?

Can you have multiple dispatcher servlets in a single web application ?

Of course, quoting the official documentation (bold is actually there as well!)

A web application can define any number of DispatcherServlets. Each servlet will operate in its own namespace, loading its own application context with mappings, handlers, etc. Only the root application context as loaded by ContextLoaderListener, if any, will be shared.


How?

Just declare several servlets with different names but using org.springframework.web.servlet.DispatcherServlet class. Also make sure yourServletName-servlet.xml file is available.


What is a situation we might need this in ?

DispatcherServlet is very flexible. Not only Spring MVC uses it, but also Spring WS, Spring support for hessian, etc.


Also, can there only be a single application context in the entire web application ?

Answered already, also in the quoted documentation: one application context per DispatcherServlet + one main web application context.


How can we define multiple application contexts ?

See above, just create multiple DispatcherServlets.


Can a dispatcher servlet exist in a non-spring application ?

DispatcherServlet is a Spring context (Spring application) on its own, thus: no. On the hand DispatcherServlet can be declared in an application not having parent (main) application context, thus: yes.

dispatcher-servlet.xml and application-context.xml

  1. Because people don't want one humongous application-context.xml, they split them up by application layer.

  2. No, it's just a Spring application context file.

  3. They do the same thing.

  4. That's not what it's for, it's for defining what your spring-managed objects get injected with.

Two DispatcherServlets share same ApplicationContext

You have to define a root web application context:

<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/root-context.xml</param-value>
</context-param>

<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

The wiring of the servlet context to the root context is done by default by Spring.

Sharing the same Spring context between main ServletContainer and a DispatcherServlet

Solution:

because of mixing

  <context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
my.config.class.MyConfig
</param-value>
</context-param>

and

<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:/WEB-INF/admin-servlet.xml</param-value>
</init-param>

Spring was creating both an AnnotationConfigWebApplicationContext and an XmlWebApplicationContext which it is apparently not able to merge. By converting my admin-servlet.xml to an equivalent WebMvcConfigurerAdapter implementation, only 1 AnnotationConfigWebApplicationContext is created.



Related Topics



Leave a reply



Submit