Why does Spring MVC need at least two contexts? - java

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.

Related

What is the purpose of having multiple spring "application context"

Per the Spring Documentation, application context is:
Central interface to provide configuration for an application. This is read-only while the application is running, but maybe reloaded if the implementation supports this.
In some applications, there are multiple application contexts. What's the purpose and benefit of having multiple application contexts? I want to understand the logic behind it. Why would one do it?
P.S: In spring doc use is written. I want to know the pros of having multiple application contexts and the rationale behind it.
The root context is the parent of every dispatcher servlet context/child context. Beans defined in root context are visible to each dispatcher servlet context/child context but not vice-versa.
Typically, root context is used to define all cross-cutting beans such as security, transactions, and other configurational beans, while the dispatcher context or child context contains those beans that are specifically related to MVC.
We create multiple dispatcher servlets when we need multiple sets of MVC configuration. For e.g. we may have a REST API alongside a traditional MVC application or an unsecured and a secure section of a website.
Cannot comment so putting the answer:-
Java Spring multiple ApplicationContext
Hope this answer your question
It is useful to implement a layered architecture (model objects, data access, services, web services, mvc app etc).
As M.Deinum said it is good to have one root context that loads the others and helps keeping them separated.
Here is the official doc for the architecture of Spring Framework applications: https://docs.spring.io/spring/docs/3.0.x/spring-framework-reference/html/overview.html

Convert traditional projects to spring boot, without changing applicationContext.xml, dispatcher-servlet.xml & tomcat's context.xml

The background & requirements are:
there are a lot of old projects which have an applicationContext.xml and one or more dispatcher[-XXX]-servlet.xml. We hope those projects can still works while using spring boot(we developed a deployment tools to deploy spring boot applications, but the old projects are still deployed manually). But, #SpringBootApplication can't build the contexts as they were. And rewriting them into codes one by one costs too much, I think.
In those project, we use an extended RequestMappingHandlerMapping, so we can't use the native MVC.
the context.xml of tomcat, which contains jndi definitions, is maintained by OPs. We have to load it just like tomcat does.
i can't find where to set welcome file, which were set in web.xml
I currently using:
#Configuration
#ImportResource({"classpath:/applicationContext.xml", "classpath:/dispatcher-servlet.xml"})
Those simple projects without using jndi can startup.
But as my understanding, in this case, the applicationContext and dispatcher-servlet are in the same level(dispatcher-servlet should the child of applicationContext, isn't it?). So, i can't even ensure this one works properly.
We did a similar thing about a year ago and your setup was more or less the same as ours and importing those XML files did the trick; the only thing we had to do was to ensure our application class was in a different package hierarchy in order to avoid conflicting/duplicate bean definitions due to its inherent #ComponentScan.
And having dispatcher servlet and application context in the same context won't cause any issues - yes, dispatcher servlet's context is usually defined as a separate context and is a child of the more broad applicationContext but what most people fail to grasp is that that separation only matters if your application wants to have more than one dispatcher servlet, which is rarely the case any more, if it ever was.
In case of multiple dispatcher servlets it was a must to enable them to have different WebMVC configurations, and applicationContext was there to allow you to share common beans and configuration between your servlet contexts so that you don't have to do the same work twice.

Have two servlet contexts in one Spring Boot application context under Jetty

Imagine I have one Spring Boot instance, pretty boring, one ApplicationContext, starter-jetty. By default, it does one ServletContext on /, puts a DispatcherServlet on / too. Every servlet and filter then placed under this context.
Now, I want to have one servlet context with contextPath=/api with a few servlets and another servlet context under /internal with a different set of servlets. They have to share ApplicationContext and most beans. And yes, it has to be plain old servlets & filters, not just two WebMvc instances.
How do I configure that? The most crucial question is how to make two ServletContext's for Jetty to consume. Just class names are enough, links to examples are encouraged. Hints on how to painlessly configure the distribution of Servlet's and Filter's between servlet contexts are appreciated too.

bidirectional dependency between web applicaton context and service context

I have 2 spring contexts: "webapplication" context and a "core" context. The context "core" is initialized at server startup and attached to a Singleton class that holds the context. The "webapplication" context is initialized when the webapplication is started.
I want to inject bean dependencies from beans in one context to the other (bidirectional access). The webapplication beans are to be "session" scoped beans.
I'm testing this proof of concept with: webapp bean --> (that depends on) core bean --> (that depends on another) webapp bean.
At the webapplication context initialization i could inject "core" beans to the "webapplication" beans (a BeanFactory that acceses the singleton do the magic), but can't figure out how to do the inverse; because the Spring ThreadLocal that holds the WebApplicationContext is not yet initialized.
The question is. Is it what i'm trying to do possible? If the answer is "yes", how would you do that?
Thank's in advance.
EDIT:
I'd realized i'm doing something wrong. The fact is that i'm trying to inject in the service layer a dependency to a session bean, at the wrong time; that is, at the web initialization time when i have no current user session.
This looks to me like an architectural issue, not a technical (and certainly not Spring) one. Your separation between core context and web context is very good. The former handles business processes while the latter is responsible for representation, maybe some API.
The dependency from web (representation, access) to core is understandable and required - after all you are building an interface over business routines. This is how spring-mvc works by default, creating separate child (web) application context of core context.
I can hardly imagine a use case for inverted dependency. Why is your business logic depending on web layer? What if you try to migrate your application one that to a different representation technique (desktop, mobile)? Can you justify the reason for this inverted dependency? What do you mean by session bean?
Bidirectional dependencies, as well as static singletons holding a class-loader wide reference to application context should indicate that something is wrong with the design.

how to get WebApplicationContext outside current servlet context?

There are two WARs deployed in Tomcat (or other server), foo1.war and foo2.war.
All spring beans are defined in foo1.war, but is it possible to get these spring beans in the servlet that deployed in foo2.war?
I cannot just use WebApplicationContextUtils to get the WebApplicationContext, right? They are different WAR.
thanks
Technically, you can get the WebApplicationContext of the other app, if you expose the servlet context and call servletContext.getContext("/otherapp").getAttribute(..), but that's ugly.
You can have instances of the same bean definitions if you simply move the common definitions to a common.xml and include it in both projects.
If you need to communicate some data betweent the two apps, use another mechanism: web services (soap, rest), messaging (jmx).
Adding to #Bozho answer: you can also share instance data (e.g. singletons), when the two WARs are deployed in a single EAR. You should be able to expose the appContexts as statically visible fields in a class provided by EAR and thus visible to both WARs.

Categories

Resources