Difference between dispatcher-servlet and spring-servlet - spring

As the title says what is the difference between dispatcher-servlet.xml and spring-servlet.xml They seem very similar in terms of structure. When should one be used over the other ?

Here's an explanation from spring forums
Basically it's just the name. Dispather is autoloading context called [servletname]-servlet.xml so in this case there's a servlet called 'spring' and another called 'dispatcher'.
You name your servlets in web.xml.
For example if you had:
<servlet>
<servlet-name>babubiba</servlet-name>
<servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
in your web.xml then DispatcherServlet would try to load babubiba-servlet.xml by default.
If you can change context name by adding contextConfigLocation init-param to your servlet config.

Related

Understanding spring dispatcher servlet initialization

Here is how spring documentation recomends to initialize dispatcherServlet:
<web-app>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/root-context.xml</param-value>
</context-param>
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value></param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>
My question is about providing an empty param-value inside the init-param tag. Despite defining that param as context-param we still provide the empty value. Therefore contextConfigLocation should be null when passes to servlet's init() method. What's wrong, correct me please.
In Spring Web Applications, there are two types of container, each of which is configured and initialized differently.
Application Context
Web Application Context
Application context is inialised by config file's that you specified in as context-params and picked up by ContextLoaderListener. This is purely i would consider as business logic related beans.
Web application context is child of application context which may or may not be present. Each DispatcherServlet will have associated WebApplicationContext and which takes spring beans from your init-params to create context.
Whatever beans are available in the ApplicationContext can be referred to from each WebApplicationContext.
Reason why we have two different bean configurations is to keep a clear separation between middle-tier services such as business logic components and data access classes (that are typically defined in the ApplicationContext) and web- related components such as controllers and view resolvers (that are defined in the WebApplicationContext per Dispatcher Servlet).

Location of groovy based bean definition configuration in a Spring MVC application

I have seen that Spring 4 has a feature to define / having a groovy file for bean definitions instead of an XML file. I already have a Spring MVC application with mvc-dispatcher-servlet.xml for my bean definitions. But I want to go with Groovy based bean definition for my Spring MVC application. But, I am not sure where to place the groovy file and where do I need to refer it/ configure it to Load the bean definitions properly. Can somebody help or provide refrence?
use the GroovyWebApplicationContext ,
Web.xml
<servlet>
<servlet-name>mvc-dispatcher</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<param-name>contextClass</param-name>
<param-value>
org.springframework.web.context.support.GroovyWebApplicationContext
</param-value>
</init-param>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:/spring/dispatcherServlet.groovy</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
this is not a full example, but it is a good start

Double (Scheduler) bean initialization

I have 2 contexts in my application, one is "spring" (Web+MVC), second is "rpc" (just RPC service). Both of them inherits configs from the "spring" directory (there are 4 files: app-config.xml, infrastructure-config.xml, integration-config.xml and security-config.xml).
The app-config.xml contains initialization of the Quartz Scheduler.
So, if I starts my application, there are two Quartz Scheduler threads and all scheduled services are invoked twice. Is that because I inheriting settings from app-confix.xml into both contexts ?
I thought that beans deffined in parent config are initialized only once and shared between context which inheriting that parent config.
Thanks for any advice :).
Example from my web.xml.
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring/*-config.xml
</param-value>
</context-param>
<servlet>
<servlet-name>rpc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>rpc</servlet-name>
<url-pattern>/rpc/*</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/web/*</url-pattern>
</servlet-mapping>
In your configuration two independent contexts are getting created. Just the fact that they use the same files doesn't cause spring to create a common parent context.
What you need to do is setup a contextLoaderListener in the web.xml - give it the common config file and then exclude it from the servlets config. The Listener will create the root context and bind it to the servlet context - both the servlets will then link to that as the parent context.

How do you share Spring beans between different Spring contexts?

We have an application which uses Spring BlazeDS integration. So far we have just been using Spring and Flex, and it is working fine. We now have a requirement to add some Spring MVC controllers as well. The Spring BlazeDS documentation states that the way to do this is to declare two sperate contexts in the web.xml, as follows:
<servlet>
<servlet-name>flex</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>flex</servlet-name>
<url-pattern>/messagebroker/*</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>spring-mvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring-mvc</servlet-name>
<url-pattern>/spring/*</url-pattern>
</servlet-mapping>
Here is my question: There are Spring beans which are required to be used within both contexts - the spring-mvc one and the flex one. How can one do this - how can one declare a bean (either in xml or by component scanning) in one context and allow it to be shared with beans declared in the other context?
Thanks !
Create a parent context by using ContextLoaderListener. The DispatcherServlet contexts will automatically become children of that context.
Create your shared beans in the parent context and refer to them in beans in the child contexts.
If you are using <component-scan> make sure you don't accidentally scan classes into multiple contexts. See my answer here.
Add this to your web.xml:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/YOUR_APP_CONTEXT.xml</param-value>
</context-param>
Both beans defined via scanning and direct definitions will be available for your BlazeDS and SpringMVC endpoints.

spring 3 mvc multiple application context instances

here is my web.xml:
<?xml version="1.0" encoding="UTF-8"?><web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<!-- Enables clean URLs with JSP views e.g. /welcome instead of /app/welcome -->
<filter>
<filter-name>UrlRewriteFilter</filter-name>
<filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>UrlRewriteFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring/*.xml
</param-value>
</context-param>
<!-- Handles all requests into the application -->
<servlet>
<servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring/*.xml
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- Maps all /app requests to the DispatcherServlet for handling -->
<servlet-mapping>
<servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
Why there are two instances of application context created?
When I add a scheduled method with #Scheduled it is invoked twice, because of those two application contexts.
You are loading twice times the same spring config files. Of course you have two separate application contexts. At first I would rename the servlet name for the DispatcherServerlet to "spring3mvc". The servlet definition should look like this:
<servlet>
<servlet-name>spring3Mvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
If you have it in this way, you should have a spring config file "spring3Mvc-servlet.xml" in your "WEB-INF" directory. Spring will find this file automatically because of the right naming convention. In this file you should just have the beans who are important for springMVC. It could look like this:
<context:component-scan base-package="org.company.gui.controller"/>
<bean id="jspViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".view.jsp"/>
</bean>
This should fix your problem.
I noticed that you have
<load-on-startup>1</load-on-startup>
in the following block
<servlet>
<servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring/*.xml
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
try removing that... it worked for me
Do you have any other spring filters or jsp pages in your web.xml not shown in your code snippet?
I ask, to answer your question, because I believe this quote from Spring documentation could explain what might be happening...
"In the web MVC framework, each
DispatcherServlet has its own
WebApplicationContext, which inherits
all the beans already defined in the
root WebApplicationContext. These
inherited beans defined can be
overridden in the servlet-specific
scope, and new scope-specific beans
can be defined local to a given
servlet instance."
If you answered "yes" to my web.xml question, then my guess is that Spring instantiates a root WebApplicationContext when a spring filter is created (via ContextLoaderListener). So, this would happen BEFORE...
Then, when the DispatcherServlet is created, the "contextConfigLocation" refers to the same files (that is, the same bean names), so a new WebApplicationContext gets overridden bean names local to that servlet!
I wonder, even if you answered "no", whether this might still happen anyway. Since you set "contextConfigLocation" (used by the ContextLoaderListener) and "override" it in DispatcherServlet configuration; I assume Spring is not checking whether those configurations are using the same file set.
You can run these scenarios through a debugger and put breakpoints on WebApplicationContext methods to find out for sure.
Workaround:
To solve the problem, either:
1) make sure your 2 contextConfigLocations don't overlap in files they use
Or:
2) break out the Scheduling bean in its own xml file and make sure it's referred to by only one of the 2 contextConfigLocations

Resources