My application is pretty large, containing for instance 310 jars in web-inf/lib for a total of 100Mb. Starting the server, this step below takes 13s:
Sep 16, 2014 1:05:33 PM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory C:\apache-tomcat-7.0.47\webapps\ROOT
The application relies on web-fragment and annotations to start properly.
I tried the following to skip the 13s scanning time:
modify conf/context.xml with attribute logEffectiveWebXml="true"
catalina run 2> web-complete.log
extract the web.xml
snippet from web-complete.log
, save it under webapps\ROOT\web-inf\web.xml
If I start my application, I still see 13s scanning time. metadata-complete was already set to "true" in the snipet above.
After adding the following statement to web.xml skips the 13s altogether, but this time my application cannot start anymore:
<absolute-ordering />
1) What would be the proper way to make tomcat start fast in my case ?
2) Can you explain why metadata-complete does not help on the 13s ?
3) Altough my web.xml is complete, why does not allow the app to start ?
Thanks,
You are probably assuming that Tomcat is, by default, doing something inefficient when deploying your webapp, and that if you make just the right change you can kludge around it and make your webapp start much faster. Those are not safe assumptions to make. Tomcat tends to be very efficient, even handling large webapps.
It sounds to me like your webapp is large enough where the JDK is not able to load that huge number of classes and instantiate that large number of objects in less time than 13 seconds. The time is likely spent mainly in instantiating & initializing servlets and everything that they require, which is a very large amount of work to do if your webapp has many large subsystems to initialize before serving requests. Doing all of that can certainly take tens of seconds, and during that time not much of it is spent parsing config files, even opening JARs to find and parse some.
Why your webapp fails to start with a static metadata-complete deployment descriptor, I don't know, in part because you're not saying it what specific way it's failing when it fails. But, it's likely that by setting metadata-complete to true you have bypassed a necessary part of webapp startup that your webapp depends on.
A Potential Startup Optimization
Something that you might configure specifically for your large webapp that could save Tomcat a significant amount of time looking through your webapp's files is: skipping JARs that you know Tomcat shouldn't scan for certain things such as Servlet 3 fragments and TLDs. Have a look at your Tomcat's conf/catalina.properties file.. these configurable system properties are in there:
# Additional JARs (over and above the default JARs listed above) to skip when
# scanning for Servlet 3.0 pluggability features. These features include web
# fragments, annotations, SCIs and classes that match @HandlesTypes. The list
# must be a comma separated list of JAR file names.
org.apache.catalina.startup.ContextConfig.jarsToSkip=
# Additional JARs (over and above the default JARs listed above) to skip when
# scanning for TLDs. The list must be a comma separated list of JAR file names.
org.apache.catalina.startup.TldConfig.jarsToSkip=tomcat7-websocket.jar
Add all of your JARs that should be skipped when Tomcat is searching for these, and my guess is that Tomcat's part of starting your webapp will complete sooner. How much sooner depends on the webapp.
Answering my own questions:
2) Can you explain why setting metadata-complete to true does not help to reduce the 13s ?
Metadata-complete attribute does not control directly class annotation scanning. It controls if web-fragments will be discovered, and then in-turn the classes contained in these fragments will be scanned.
Provided the same web fragments are enabled in <absolute-ordering> (or left empty), ServletContainerInitializer.onStartup(Set>, ServletContext) will receive the same set of annotated classes independently of the value of metadata-complete.
So, by itself changing the value of metadata-complete will not have an impact on exploded war deployment / class scanning. Changes will happen only if the webfragments are specified.
As a side effect, jars not part of a web fragement will not be scanned which may cause problem with annotated classes in TLDs. It is thus important that all components of the applications are web fragments to benefit from this optimization.
3) Altough my web.xml is complete, why it does not allow the app to start ?
With option logEffectiveWebXml="true" set on conf/context.xml, are only logged listeners and filters. ServletContainerInitializers (SCIs) are not specified.
If <absolute-ordering> is not set in web.xml, SCIs will be discovered as part of the web fragment scanning. If it is set empty as in my example above, all web fragments will be skipped and hence the application will not start.