spring web, security + web.xml + mvc dispatcher + Bean is created twice

During the servlet container lifecycle, the container first initializes the ServletContextListener, then the Filter and Servlet instances.

A Spring Web application typically loads two contexts: the root context and the dispatcher servlet context. The ContextLoaderListener class is a ServletContextListener which loads the application (or root) context. It identifies the file to load either through the context-param with the name contextConfigLocation as given in the web.xml like below

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
        /WEB-INF/mvc-dispatcher-servlet.xml
    </param-value>
</context-param>

or, by default, by looking for a file at /WEB-INF/applicationContext.xml. Since you’ve specified /WEB-INF/mvc-dispatcher-servlet.xml as the contextConfigLocation, that context will be loaded.

Once this is done, the container initializes the DispatcherServlet, which also loads a context. It identifies the file load either through an init-param element with the name contextConfigLocation as given in the web.xml below

<servlet>
    <servlet-name>dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/spring/appServlet/some-random-location.xml</param-value>
    </init-param>
</servlet>

or, by default, by looking for a file at /WEB-INF/name-of-your-servlet-servlet.xml. In other words, it takes the value of the <servlet-name> element and appends -servlet.xml to it and looks for it in WEB-INF.

Since you haven’t specified an init-param with name contextConfigLocation, the DispatcherServlet loads the context file at /WEB-INF/mvc-dispatcher-servlet.xml, since its name is mvc-dispatcher. The context loaded by the DispatcherServlet has access to the beans loaded by the ContextLoaderListener, that’s why we call that the root context (and the others children).

All this to say that both your ContextLoaderListener and your DispatcherServlet are creating their own copy of an ApplicationContext by each loading a XmlWebApplicationContext from the same file at /WEB-INF/mvc-dispatcher-servlet.xml.

Identify what beans or configuration you think should be available to the whole application and put them in the file that will be loaded by the ContextLoaderListener. Identify the beans or configuration you think should be available to the DispatcherServlet and put them in its context file.

Leave a Comment