Does anybody know how Spring is actually bootstraps?
Which instances created and by whom?
I really want to know who creates instances of WebApplicationContext and ContextLoader. Is it work of Tomcat?
Servlet context listener (web.xml) approach
A web application WAR is being deployed by user.
Servlet container (Tomcat) reads web.xml.
Servlet context listener ContextLoaderListener is being instantiated (if defined as <listener> inside the web.xml) by servlet container.
ContextLoaderListener creates new WebApplicationContext with application context XML configuration.
Your ROOT context beans are registered and instantiated by BeanFactory inside the application context.
DispatcherServlet is being instantiated by servlet container.
DispatcherServlet creates its own WebApplicationContext (WEB-INF/{servletName}-servlet.xml by default) with the ROOT context as its parent.
Your servlet beans are registered and instantiated by BeanFactory inside the application context.
DispatcherServlet registers some default beans in case you did not provide them yourself.
Servlet container initializer (non web.xml) approach
This one is possible with Servlet 3 features.
A web application WAR is being deployed by user.
Servlet container searches for classes implementing ServletContainerInitializer via Java's ServiceLoader.
Spring's SpringServletContainerInitializer is found and instantiated by servlet container.
Spring's initializer reads web application's class-path and searches for WebApplicationInitializer implementations.
Your WebApplicationInitializer is found (btw. check its JavaDoc!!!) and instantiated by SpringServletContainerInitializer.
Your WebApplicationInitializer creates new ROOT WebApplicationContext with XML or #Configuration based configuration.
Your WebApplicationInitializer creates new servlet WebApplicationContext with XML or #Configuration based configuration.
Your WebApplicationInitializer creates and registers new DispatcherServlet with the context from previous step.
Servlet container finishes the web application initialization and instantiates components which were registered by their class in previous steps (none in my example).
Java based approach is much more flexible. You can leave the context creation to DispatcherServlet or even the whole instantiation of DispatcherServlet itself to servlet container (just register servlet DispatcherServlet.class instead of its instance).
See http://docs.spring.io/spring/docs/4.0.x/spring-framework-reference/htmlsingle/#context-create.
The principle is to declare a ServletContextListener in the standard webapp descriptor (web.xml). Such a listener is indeed instantiated by the container and is called when the application is initialized and when it's destroyed.
Spring provides such a ServletContextListener: ContextLoaderListener which, as its name indicates, loads a Spring context when the webapp is initialized.
Related
I am struggling with Architecture level of Spring web application, Below I am making my pointers. Please help regarding the below:
Context Level Programing: Servlet Context and Root Application Webapplication context and Web Application context.
I don't know which bean needs to mention on which level.
What is the Hierarchy level of Context in Spring Web Application. which comes upper or lower.
Which context is under which context.
My Understanding is Servlet Context is the object of Servlet Container(tomcat container), and Servlet container is responsible to manage all the servlet, where all servlet lives.
All Bean dependecies Lives in Application container, and root web application context is the object of Application Container.
Every servlet have its own web application context, i don't know what is this, is it same as Servlet context.
4. And Relation between them?
Please describe it with help of diagram like this, (It will be really appreciable)
This is just example to understand which loads first and what is inside what.
Please check this reference diagram
Think of context as a component's execution environment.
A servlet container (Web server), hosts web applications and on startup it creates one ServletContext for each of these applications. So each web app lives in a servlet context which provides to it information about its environment (container). This is Java Servlet API. Tomcat is an implementation of this API.
Now, Spring is one of the frameworks we can use to create web apps. When we deploy our web app in the container, it (container) will create a ServletContext and this is where our app will live in.
Each Spring application has a root context (ApplicationContext) and in it one or more child contexts can exist. WebApplicationContext extends ApplicationContext. There can be many WebApplicationContexts, children of the root context of an application. The WebApplicationContext (which adds a method, getServletContext() ) is able to work with the ServletContext in which it lives.
So in a spring based web app deployed in a container:
container --contains 1..n--> ServletContext --contains 1--> ApplicationContext --contains 1..n--> WebApplicationContext
I'm developing an application which is run both on Spring Boot (with no web.xml) and on WebSphere (with web.xml). There is a controller which needs to have DispatcherServlet injected into it. While it works on spring boot environment this fails on WebSphere - no bean of type DispatcherServlet can be found.
Down in web.xml i use the parent context (Context Loader Listener) with middle-tier and several dispatchers having their separate contexts. One of them contains such controller (among others).
Why it's not working? My first assumption is that Spring Boot first creates and registers the DispatcherServlet and then scans for controllers while when running with web.xml it happens in reversed order so Controllers are instantiated before DispatcherServlet is accessible from the context.
How can I tackle this problem?
You can not inject DispatcherServlet directly because it is not registered in Spring Context (XmlWebApplicationContext for example).
But you can extend DispatcherServlet, store link to itself to static field (in constuctor invocation). And you this link anywhere in your code.
Other way - if you create DispatcherServlet "manually" - you can register your DispatcherServlet as bean in application-context.xml.
In Spring MVC, there are two contexts. One is the application context or global context which is booted up by ContextLoaderListener. It takes all the configuration files mentioned in contextConfigLocation parameter.
Now if you are using Spring MVC as well, then Dispatcher servlet is required, which boots up another container which is also known as web application container. This container takes the global container as a parent.
When integrating struts1 with spring, there is only one context. Why does spring mvc need two? Is it possible to use only one context when using spring mvc?
thanks!
Having a root web application context plus a child servlet context is just an option. If you know that your application won't have a second servlet, it's arguably simpler to have one single Spring context for the whole web application.
You can achieve that setup by simply removing the ContextLoaderListener (and the accompanying contextConfigLocation context-param) from your web.xml and moving all bean definitions into the xml defining the servlet context ([servlet-name]-servlet.xml).
This is possible, because the FrameworkServlet (super-class of DispatcherServlet) doesn't care if there is a root application context when creating the servlet context. It just relays the root context as the parent if available. See related code here.
Imagine you had two separate Dispatchers, each serving a different purpose, and each having its own dependencies. You would configure those independently using separate contexts.
If there is any shared configuration, this can go in the 'global' context.
I don't think it's possible to have only one context using DispatcherServlet, as it creates its own context and links it to the parent context (via the FrameworkServlet superclass).
FrameworkServlet.createWebApplicationContext
Check this answer About multiple containers in spring framework
Yes ,you can have one context only.
For code reuse it would be better to isolate services in Application Context rather then WebApplicationContext.but this not compulsion.you can keep only webApplicationcontext only.
is there any difference between servlet and filter lifecycle?.
No, both a servlet and a filter:
are instantiated (once) when the context starts
the init(..) method is called
they handle each request - first it passes through all filters and then reaches the servlet
when the context is destroyed (i.e. when your container stops, or your application is undeployed from the manager console), the destroy(..) method is called
So far I was also wondering the differences. I created a web project to observe life-cycle of them. It can be check-outed at
http://dntuan-java-workspace.googlecode.com/svn/trunk/simple-web
Once it is deployed on tomcat, you can observe logs from the console to see that filters are initialized before context is started. Whereas servlet is only initialized when a request is made (e.g. http://localhost:8080/simple-web/servlet/life.jsp)
More information from JSR-000315 JavaTM Servlet 3.0:
2.3.1 Loading and Instantiation
The servlet container is responsible for loading and instantiating
servlets. The loading and instantiation can occur when the container
is started, or delayed until the container determines the servlet is
needed to service a request.
6.2.1 Filter Lifecycle
After deployment of the Web application, and before a request causes
the container to access a Web resource, the container must locate the
list of filters that must be applied to the Web resource as described
below. The container must ensure that it has instantiated a filter of
the appropriate class for each filter in the list, and called its
init(FilterConfig config)method.
I have a portlet application. It is configured using Spring framework IoC container. I am using org.springframework.web.context.ContextLoaderListener to load my context.
I have an application context at root level (applicationContext.xml) and a portlet specific context (MyPortlet-portlet.xml).
I have a portlet of type org.springframework.web.portlet.DispatcherPortlet which is wired up to a Controller. In the Controller I want to access one of the beans (e.g. bean with id "myBean") I have defined in my portlet specific context. I have tried
MyBean mybean = (MyBean)PortletApplicationContextUtils.getWebApplicationContext(
getPortletContext()).getBean("myBean")
However only the beans in my application context are available here - none of my beans in my portlet specific context are available.
Is there a way to access the beans in my portlet specific context?
Thanks
Firstly, can't you just wire in the bean to your controller in the normal way, rather than retrieving it programmatically?
Failing that, you should realise that getWebApplicationContext() gets a reference to the root webapp context, not the servlet app context:
Find the root WebApplicationContext
for this portlet application, which is
typically loaded via
ContextLoaderListener or
ContextLoaderServlet.
If your controller needs a handle on its own context, then it should implement ApplicationContextAware or BeanFactoryAware, or it can use #Autowired ApplicationContext if you want to use autowiring.