11

BackGround

After reading from 1 2 3 4 5 6 Links I reached the following conclusion-

As Spring mvc designed over standered servlets,and facilitate same functionality of servlet context and application context.In spring there is two type of context ApplicationContext and WebApplicationContext-

ApplicationContext initialise by ContextLoaderListener,single instanse per application. WebApplicationContext loaded by per DispatcherServlet.

We can understand above like this ApplicationContext extends by WebApplicationContext so what ever stuff associated with ApplicationContext at the end this is part of WebApplicationContext.

Doubts

  1. ApplicationContextAware offers which context object.

    public class SomeThing implements ApplicationContextAware {
        @Override
        public void setApplicationContext(ApplicationContext ctx) throws BeanException {
            //this context object is `ApplicationContext` or `WebApplicationContext`?
        }
    }
    
  2. context and container seems synonyms to most of us,I want to give an example.Let say we have two dispatcher servlet one for rest and other for mvc.

    First Dispatcher-

    public class RestInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
        @Override
        protected String[] getServletMappings() {
            return new String[] { "/rest/*" };
        }
    }
    

    Second Dispatcher-

    public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
        @Override
        protected String[] getServletMappings() {
            return new String[] {
                "/mvc/*"
            };
        }
    }
    

    than here there is two instance of WebApplicationContext,those common part is loaded by ContextLoaderListner as define in rootContext.

    I am not sure, but there must not be 2 IocContainer in a single SpringApplication.

  3. BeanFactory ie SpringIocContainer is,where all the bean object lives,what ever objects we associates with WebApplicationContext is part of Spring container,how does this container initialised by WebApplicationContext?I want to want to know how does they both associated with each other?

    And whenever we did ctx.getBean()- this returns object from spring container,how does this communication between context and container happens?

There is a similar answer that denies the both are same,it says

Spring comes with several container implementations,Both load bean definitions, wire beans together, and dispense beans upon request,but an ApplicationContext offers much more.

So my point is why Both load bean definitions, wire beans together,this is kind of rework?

One more thing even though web-app is spring driven or not, there must be a context which standard servlet provides and used in Http communication......

Spring follows this or spring handles this in some other manner.And in spring context means a just IOC container, of which some part is loaded by DispacherServlet and some part is loaded by ContextLoaderListner and can facilitate much more such as I18N,access to static resource etc..

TheCurious
  • 593
  • 1
  • 4
  • 29
  • 1
    A `WebApplicationContext` is an `ApplicationContext`. Both the `ContextLoaderLIstener` and `DispatcherServlet` load an instance of `WebApplicationContext` (which actually is an interface). There is only an `ApplicationContext` regardless of the fact if it is web or non web related. The `ApplicationContext` IS the container. – M. Deinum Feb 17 '17 at 07:39
  • 2
    @M.Deinum As you pointed there is a single `context` per application,there is lots of whitepapers those explained existence of both,some of them mentioned in question itself.Moreover if you initialize your context by `DispatcherServlet` only ie no `ContextLoaderListner` ans call spring security `` this will throw `IllegalStateException: No ApplicationContext found:` –  Feb 17 '17 at 09:05
  • 1
    No I nowhere pointed to that there is a single context... But spring only has the notion of an `ApplicationContext`.. Which can be of type `WebApplicationContext`. There can be 1 or 100. What I hinted at that both the `ContextLoaderListener` and `DispatcherServlet` load a `WebApplicationContext`. The `ContextLoaderLIstener` loads a context generally called the root context, which is also what filters can access. You can also make it that (if you have one `DispatcherServlet` to expose that one as the root context (and that is generally what people forget leading to the issue you point at)). – M. Deinum Feb 17 '17 at 10:33
  • 1
    @M.Deinum I cant understand how a IOC container be a `context`.IOC container is springs memory management design and more.. which takes care of instantiation of beans.even though application is spring driven or not there must be a `context` that standered servlet facilitate.What I thinks,`context` access bean object from `IocContainer` or vice versa. – TheCurious Feb 17 '17 at 10:53
  • No it isn't. You are confusing servlet context with a spring context / container / application context. Spring has no ties (basically) to the servlet context, heck you could even use Spring in a standalone application. Hence from the spring pov the `ApplicationContext` is the IOC Container is the context. – M. Deinum Feb 17 '17 at 10:58
  • I never compare servlet tech specific context with spring context,my concern was with `Standered Servlet Context` which is the core `HTTP`,now you again saying container is context,my doubt is `rootContext` or 'webaplicationContext'.Also what `WebApplicationContextUtils.getWebApplicationContext(myServlet.getServletContext())` achieves? – TheCurious Feb 17 '17 at 11:24
  • check out if this link helps with your question http://stackoverflow.com/questions/41550796/spring-where-does-autowired-look-for-beans/41552579#41552579 – mlg Feb 21 '17 at 16:56

2 Answers2

1

For Your Doubt 1

In an spring application there is a single instance of context Which is WebAplicationCntext per DispatcherServlet.Which can be refer by a super Interface ApplicationContext-

public class SomeThing implements ApplicationContextAware{
@Override
public void setApplicationContext(ApplicationContext ctx) throws BeanException{
//this context object is `WebApplicationContext` which is refer by `ApplicationContext`.
 }
}

In spring , context means a just IOC container, of which some part is loaded by DispacherServlet and some part is loaded by ContextLoaderListner and can facilitate much more such as I18N,access to static resource etc

Your above understanding is almost correct.In Spring All the WebApplicationContext object shares some common reference which is rootContext.

This answer desn't include answer of doubt2, doubt3 ,and why all context perform same task.

0

Basically, in a spring MVC application the spring contexts are registered in the servlet context of the web application. You can do that in the web.xml file setting the spring ContextLoaderListener or with java configuration. In the comments I pointed out this link where it explains how this is done via java configuration classes:

spring: where does `@autowired` look for beans?

There you can see how the 'connection' is done. Then, you asked in the comments what this achieves:

WebApplicationContextUtils.getWebApplicationContext(myServle‌​t.getServletContext(‌​))

If you check the code of that class you can see it gets the WebApplicationContext from the attributes of the ServletContext. These attributes are set in the initialization of the web application. If you notice, in the ContextLoader class (parent of ContextLoaderListener), in the initWebApplicationContext method it sets these attributes to the servlet context:

/**
     * Initialize Spring's web application context for the given servlet context,
     * using the application context provided at construction time, or creating a new one
     * according to the "{@link #CONTEXT_CLASS_PARAM contextClass}" and
     * "{@link #CONFIG_LOCATION_PARAM contextConfigLocation}" context-params.
     * @param servletContext current servlet context
     * @return the new WebApplicationContext
     * @see #ContextLoader(WebApplicationContext)
     * @see #CONTEXT_CLASS_PARAM
     * @see #CONFIG_LOCATION_PARAM
     */
    public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {
        if (servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE) != null) {
            throw new IllegalStateException(
                    "Cannot initialize context because there is already a root application context present - " +
                    "check whether you have multiple ContextLoader* definitions in your web.xml!");
        }

        Log logger = LogFactory.getLog(ContextLoader.class);
        servletContext.log("Initializing Spring root WebApplicationContext");
        if (logger.isInfoEnabled()) {
            logger.info("Root WebApplicationContext: initialization started");
        }
        long startTime = System.currentTimeMillis();

        try {
            // Store context in local instance variable, to guarantee that
            // it is available on ServletContext shutdown.
            if (this.context == null) {
                this.context = createWebApplicationContext(servletContext);
            }
            if (this.context instanceof ConfigurableWebApplicationContext) {
                ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) this.context;
                if (!cwac.isActive()) {
                    // The context has not yet been refreshed -> provide services such as
                    // setting the parent context, setting the application context id, etc
                    if (cwac.getParent() == null) {
                        // The context instance was injected without an explicit parent ->
                        // determine parent for root web application context, if any.
                        ApplicationContext parent = loadParentContext(servletContext);
                        cwac.setParent(parent);
                    }
                    configureAndRefreshWebApplicationContext(cwac, servletContext);
                }
            }
            servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);

            ClassLoader ccl = Thread.currentThread().getContextClassLoader();
            if (ccl == ContextLoader.class.getClassLoader()) {
                currentContext = this.context;
            }
            else if (ccl != null) {
                currentContextPerThread.put(ccl, this.context);
            }

            if (logger.isDebugEnabled()) {
                logger.debug("Published root WebApplicationContext as ServletContext attribute with name [" +
                        WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE + "]");
            }
            if (logger.isInfoEnabled()) {
                long elapsedTime = System.currentTimeMillis() - startTime;
                logger.info("Root WebApplicationContext: initialization completed in " + elapsedTime + " ms");
            }

            return this.context;
        }
        catch (RuntimeException ex) {
            logger.error("Context initialization failed", ex);
            servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, ex);
            throw ex;
        }
        catch (Error err) {
            logger.error("Context initialization failed", err);
            servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, err);
            throw err;
        }
    }

That is done in this line:

servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);

As you can see, it is stored in the same place where you are trying to get it with the WebApplicationContextUtils.getWebApplicationContext(myServle‌​t.getServletContext(‌​)) :

/**
     * Find the root {@code WebApplicationContext} for this web app, typically
     * loaded via {@link org.springframework.web.context.ContextLoaderListener}.
     * <p>Will rethrow an exception that happened on root context startup,
     * to differentiate between a failed context startup and no context at all.
     * @param sc ServletContext to find the web application context for
     * @return the root WebApplicationContext for this web app, or {@code null} if none
     * @see org.springframework.web.context.WebApplicationContext#ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE
     */
    public static WebApplicationContext getWebApplicationContext(ServletContext sc) {
        return getWebApplicationContext(sc, WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
    }

So as you can see all the answers to your doubts are in the code that spring executes during the startup of the web application.

Hope I answered your question.

Community
  • 1
  • 1
mlg
  • 5,248
  • 1
  • 14
  • 17