I've seen this basic question asked on these forums before, but none of the answers seem to solve my particular issue. Anyway, I have a small Spring webapp, consisting of a core Spring business layer, SpringMVC, and Spring-Quartz (I am also using MyBatis, although I don't believe that's relevant). All of my Spring libraries are 3.1.3
The problem is that when I deploy my app to Tomcat 6, usually the root application context and the web application context are each being initialized twice. This is evident by looking at the logs, and is also evident by the fact that my Quartz job is firing off twice when it should be firing once (that latter point is why this is not just a theoretical problem).
I thought I had my application contexts all sorted out, but clearly there must be something that I'm missing. My general approach is this:
Below are my config files, minus all of the XML cruft:
UsMain-servlet.xml
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
</bean>
<mvc:resources mapping="/rsc/**" location="/rsc/" cache-period="31556926"/>
<mvc:annotation-driven />
<context:component-scan base-package="com.me.controllers" />
web.xml
<web-app ... version="2.5">
...
<servlet>
<servlet-name>UsMain</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>UsMain</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
</web-app>
applicationContext.xml
<import resource="classes/com/me/config/spring-biz-context.xml" />
<import resource="classes/com/me/config/spring-quartz-context.xml" />
Below are a sampling of log lines that I see twice when Tomcat starts up:
2013-11-07 05:18:27 [main] INFO org.springframework.web.context.ContextLoader - Root WebApplicationContext: initialization started
2013-11-07 05:18:27 [main] INFO org.springframework.web.context.support.XmlWebApplicationContext - Refreshing Root WebApplicationContext: startup date [Thu Nov 07 05:18:27 UTC 2013]; root of context hierarchy
2013-11-07 05:18:27 [main] INFO org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loading XML bean definitions from ServletContext resource [/WEB-INF/applicationContext.xml]
2013-11-07 05:18:35 [main] INFO org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loading XML bean definitions from ServletContext resource [/WEB-INF/classes/com/me/config/spring-biz-context.xml]
... bunch of stuff ...
2013-11-07 05:18:38 [main] INFO org.springframework.web.context.support.XmlWebApplicationContext - Refreshing WebApplicationContext for namespace 'UsMain-servlet': startup date [Thu Nov 07 05:18:38 UTC 2013]; parent: Root WebApplicationContext
2013-11-07 05:18:38 [main] INFO org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loading XML bean definitions from ServletContext resource [/WEB-INF/UsMain-servlet.xml]
The one other thing which may or may not be a red herring... if I modify my code or config files in any way and then repackage the WAR file, and then stop Tomcat, copy the WAR into webapps/, and start Tomcat, the app contexts load only once (yay!) But if I restart Tomcat after that, then this problem occurs.
EDIT
As I keep exploring this issue, the "may or may not be a red herring" thing seems to be an important factor. In fact, this may be more of a question about Tomcat than about Spring.
If I delete the deployed webapp's subdirectory from within the webapps/ directory before restarting Tomcat, then the problem does not occur. If I leave the subdirectory intact before restarting Tomcat, then the problem does occur.
In other words, I package the webapp into MyApp.war, and stick that WAR into Tomcat's webapps/ directory. When Tomcat starts, it unpacks the WAR and creates a webapps/MyApp/ subdirectory. The first time, things work fine. But if I just restart Tomcat, the problem occurs. If I delete webapps/MyApp/ and then restart Tomcat, then things are again fine.
So, in a way, the problem is solved. But ideas on what is happening would be still be very helpful. To my knowledge, this is not the way Tomcat/webapps were intended to operate.
I've been looking into this more, and it is now clear that the issue is not with Spring and its application contexts, but rather it's something that Tomcat is doing. So I will answer the question I asked with "because Tomcat is deploying the web application twice when it is restarted".
My evidence of this is that the problem never occurs if I delete my web app's deployment subdirectory from the webapps/ directory before I restart, but it always occurs if I do not delete it. Also, I added some logging to one of my "Singleton" Spring beans; when this problem occurs and the bean is created twice, each time it is loaded by a different classloader.
As to why Tomcat is doing this, I don't yet know, but that's an entirely separate question.
EDIT
Just adding that I have figured out what's up with Tomcat, just in case anyone else encounters the same issue I was having. It had to do with my attempt to deploy my WAR file as the root web application. See this URL: Apache Tomcat Configuration Reference and search for this string:
If you want to deploy a WAR file or a directory using a context path that is not related to the base file name then one of the following options must be used to prevent double-deployment:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With