Understanding contexts in Spring MVC - spring

I am new to spring and I am creating a simple web application. I have been reading about contexts in Spring MVC.
I am using STS plugin for eclipse. I created a
Spring MVC project using the plugin.
Now I have three xml documents in the project, web.xml, root-context.xml and servlet-context.xml. These were created by STS for me.
In web.xml, dispatcher servlet is pointed towards servlet-context.xml and I understand the dispatcher servlets job is to create a web application context which knows how to resolve views and is a place for controller beans to exist.
Is my understanding correct? If so, what other job is accomplished by this context?
Now, there is a file called root-context.xml which has a component scan on my projects default package. My understanding is this context needs to have global beans which many servlets might use. Is my understanding correct? What else does this do? What kind of context is created using this file?
Now, I am further along in the project and I have several *-context.xml files (dao-context.xml, security-context.xml etc) which are loaded using contextLoaderListner (in web.xml). Is this a good idea? Or should everything go into servlet-context.xml? I think it's a good idea to have different contexts as it provides separation of concern. Comments? Also, what kind of context is created from these *-context.xml files? What is the proper folder location for these files?
Web.xml is for the servlet container like tomcat etc and all other xml files in the project are for the spring container. Is that correct? All these files are separated to provide separation of concern?
How many application contexts and web application contexts exists in the current scenario?
Why would anyone need more than one dispatcher servlet?
Why would anyone need more than one application context?
Thoughts? Comments? Corrections? Best practices?

The whole idea behind this design is to handle different architectural layers in a typical web application and provide for inheritance / override mechanism for beans across contexts. Each type of context in Spring is related to different architectural layer for e.g, web layer, service layer etc.
A Spring based web application can have multiple dispatcher servlet configured (although in majority of cases its a single servlet - but dispatcher serlvet is a servlet nonetheless and there could be multiple configured in web.xml). These can be configured to handle different url patterns. So obviously each is a different servlet and hence can have different Spring web Application context. Each of these can contain different configurations for Spring web layer like controllers,interceptors,view resolvers,locale resolvers etc. as these typically belong to the web layer of an application. All these configurations and beans are private to each dispatcher servlet so they are not visible to each other. Hence having a seperate spring web application context makes sense to enable this privacy. However there are other beans which are designed to be shared hence belong to a root context. So all the shareable things belong to the root context and it can be considered global for this web application.
Each dispatcher servlet inherits all the beans defined in the root context. However the important point to note is that the shared beans can be overridden by respective dispatcher servlet specific beans. So in web applications root context can be viewed as something which is inherited but can be overridden.

Well spring does not force you to have xml files in that way, you can very well work everything using only one xml file that would be servlet-context.xml and using only dispatcher servlet. Generally there are different files in order to define your service beans or dao beans, so this basically depends on your application design, for eg if you are using spring security you might want to add one more xml file something like security-context.xml like as I said it depends on design. You can actually eliminate context loader listener completely and still manage to do everything using dispatcher servlet.
Your question is too broad in scope, since you are new to spring may be you should get more details about spring containers and decide what suits your requirement.
I generally have my servlet-context.xml in WEB-INF and other configuration like service-context.xml in classpath, again this is no strict rule just how it suits me.

Related

Spring Application Architecture Design

Environment :
Spring 4
Hibernate 4
MySQL
Spring MVC REST
Issue :
I am writing a simple REST based application for CRUD operations.
The architecture/components is below :
I have below design issues :
1. In Spring Application , the best practice is to have two separate contexts -
i) applicationContext : initialised through ContextLoaderListener (for servives abd daoLayerClasses)
ii) webApplicationContext : initialised through Dispather servlet (for Controllers/view Resolvers)
2. However I haven't seen any sample Spring REST based application using BOTH THE CONTEXTS above. Only Dispatcher servlet appraoch is used.
3. So , will creating two separate contexts for REST based application as shown in above architecture be an overkill and unnecessary ?
Or It is better to create two contexts separating SPRING REST layer in WebApplicationContext (#RestController) and ApplicationContext containing
(#Services,#Repository)
I think it is totally unnecessary to create separate contexts for your Controllers and Service/Repository classes unless you were thinking of having multiple Dispatchers or something like that. Generally you should keep it simple and have as few contexts as possible.
The answers to this question will be subjective, but as mentioned in other threads and in the Spring MVC docs two contexts are typical, but not the only way to do it.
I think the main reason is to separate them is when you have UI and APIs. They may depend on the same backend services, but probably shouldn't have co-mingled beans.

How do I get one common instance of ApplicationContext using Spring in Java

I know that Spring is most useful for dependency injection. But what I don't understand is how do I have one common "ApplicationContext ac=....." for the whole project, lets say I have a WebApplication and it has multiple number of packages but all of them still in one project , so how do I make the ApplicationContext instantiate only once. I had read somewhere that in Spring objects are initialized only once something as singleton beans but what I dont understand is that how is it different than Singleton design pattern, there is one question on this in SO but I couldn't quite clearly understand the answer as I am a newbie to Spring trying to learn by myself. Any help would really be appreciated. Sorry if the Q is too long. Hope I was able to explain my doubt clearly.
Spring veans are by default Singleton, although it is possible to configure them as prototype which means that a new bean will be created upon each request. In practice, singleton means one instance per context and are their lifecycle is managed by Spring nwhich also provides hooks into the various stages. Spring does not manage prototype beans once they have been created.
It is common in a SpringMVC application to have more than one context (one for the business services, the other for the web controllers). You would only need to create an ApplicationContext when building a standalone application. SpringMVC applications use the ContextLoaderListener to create the necessary contexts.

Share spring container between test application and embedded tomcat

We are using cucumber-jvm to write an integration test layer in our application. One of the challenges we are finding is managing the database between the tests and the web application.
A typical scenario is that we want to persist some entities in a Given step of a scenario, then perform some actions on the user interface that may, in turn, persoist more entities. At the end, we want to clean the database. Because the cucumber-jvm tests are in one jvm and the web application is running in another jvm we cannot share a transaction (at least in a way of which I am aware) so the database must be cleaned manually.
My initial thought was to use an Embedded Tomcat server running off of an embedded in-memory database (HSQLDB) in the same JVM as the cucumber-jvm test. This way we might be able to share a single spring container, and by extension a single transaction, from which all objects could be retrieved.
During my initial tests it looks like Spring gets loaded and configured twice: once when the test starts and the cucumber.xml is read, and a second time when the embedded tomcat starts and the web application reads its applicationContext.xml. These appear to be in two completely separate containers because if I try to resolve an object in one container that is specified in the other container then it doesn't resolve. If I duplicate my configuration then I get errors about duplicate beans with the same id.
Is there a way that I can tell Spring to use the same container for both my test application and the embedded tomcat?
I'm using Spring 3.2.2.GA and Embedded Tomcat 7.0.39 (latest versions of both libraries).
Am I crazy? Do I need to provide more technical details? Apologies if I use some incorrect terminology.
Thanks
p.s. If my problem seems familiar to you and you can suggest an alternative solution to the one I am trying, please let me know!
Jeff,
It is normal that spring is loaded twice. There are two places where two spring contexts are created:
In the servlet container listener org.springframework.web.context.ContextLoaderListener that is configured in web.xml. This one reads its configuration from the file set by the context-param contextConfigLocation.
In the implementation of ObjectFactory provided by cucumber-spring plugin cucumber.runtime.java.spring.SpringFactory. This one reads its configuration from cucumber.xml.
The two spring contexts are totally different and their instances are kept in two different places. As a servlet context attribute for the former and kept by the JavaBackend for the latter.
When starting the embedded tomcat, it is possible to get access to the servlet context and thus set ourself the spring context used bt tomcat with the one from cucumber. But, spring has a special class called WebApplicationContext for context used in a servlet container. The cucumber SpringFactory on other hand creates its context through ClassPathXmlApplicationContext. So unless there is a way to specify the type of application context from the xml config, we will have to provide an ObjectFactory that shoots a WebApplicationContext.
What we can do is to have two web.xml. One for the normal and one for the test. For the test, we use our version of the ContexLoader listener.

A heavily customized Spring Web application and the dispatcher servlet

We have a web application that uses spring, struts and camel right now and there is a lot of customization we have done to allow us to know when beans are added to the context.
So, we have gotten to a point where we would like to remove struts from the application, because we are only using it to handle actions and we figure we could either use spring or camel to do the same thing. So I was able to get it to work with camel/velocity, but we didn't like how we really couldn't use the request object directly in the jsp (afaik, you have to put everything in the header of the Exchange and in the jsp you would do ${header.someReqVariableName}).
So we wanted to go the spring route, but since we load the context.xml directly, we have a provider that extends ContextSingletonBeanFactoryLocator and we pass the xml file name as a param, we haven't been able to figure out how to get the DispatcherServlet to work without giving it another configuration xml.
Is there a way to either:
Have camel use jsp for processing a jsp (and have all the usage of jsp tags)?
or
Have spring to see that a context has already been loaded and use that instead of having another new one?
or
Something better I have thought up?
You can use camel-jetty to expose HTTP endpoints, but I wouldn't use it for any complex web app development (JPS, etc). I'd use use Spring MVC (or similar) and use Camel for any complex routing/messaging requirements...
Here is another way, you can use the producer template to send the request to the camel context if you can get the reference of the camel context from the spring.

Is it bad practice for a spring-based jar project to provide a bean configuration file?

If you have a library containing Spring beans that need to be wired together before an application can use them, does it make sense to include any sort of bean configuration file in the JAR (such as the /META-INF directory)? The idea is to give the application the option of importing this into its master Spring context configuration.
There may be more than one way to wire these beans, so I could provide a bean configuration file for each of the standard ways in which you'd typically wire them together.
Or, do I force the application to wire these up explicitly?
If it helps, the specifics of my problem involve a library I created to encapsulate our product's persistence layer. It contains Service, DAO and model beans. The DAO implementations currently use Hibernate (this probably won't change). Some of the DAO implementations need different kinds of Strategy beans injected into them (database encryption logic), depending on the type of database we are deploying on (MySQL vs SQL Server, etc). So we have potentially a few different configuration scenarios. I could also provide datasource bean configurations, relying on property substitution at the app level to inject all the particulars needed by the datasource.
Thanks for your input!
In this case, it's a good idea to provide some beans files, either as examples for documentation purposes, or as fully-fledged files ready for including into a wider context.
If your beans' wiring can get complex, then you shouldn't really leave it entirely up to the library client to figure it out.
This is more of a documentation and education task, really.

Resources