43

Seems like the slow Tomcat 7 startup problem can be resolved with "metadata-complete" set to "true" in the web.xml, like so:

<?xml version="1.0" encoding="UTF-8"?>
<web-app metadata-complete="true" id="WebApp_ID" version="3.0"...

The problem is that Tomcat scans for annotations at startup, and this significantly slows it down. My time is cut down from 25 secs to 5 secs. (More info here: Tomcat and Servlet 3.0 Web Configuration)

However, I have some annotations in my code, like:

@ManagedBean
@RequestScoped
@Override
...

I am confused - will my code work after I have set metadata-complete="true"? Do I have to remove annotations and move everything into web.xml?

skaffman
  • 398,947
  • 96
  • 818
  • 769
Danijel
  • 8,198
  • 18
  • 69
  • 133

2 Answers2

74

The slow startup is caused because every single class file in every single JAR file in /WEB-INF/lib is also scanned for Servlet 3.0 specific annotations. You apparently have a lot of (large) JAR files in /WEB-INF/lib.

The metadata-complete="true" indicates that the JAR files in /WEB-INF/lib doesn't need to be scanned for Servlet 3.0 specific annotations, but the webapp's own classes will still be scanned.

Note that you listed there two JSF annotations and one Java SE annotation, not any Servlet 3.0 annotations. The Servlet 3.0 annotations are listed in the javax.servlet.annotation package. JSF will only scan for annotations when the JAR file contains a JSF 2.0 compatible /META-INF/faces-config.xml file. It won't immediately scan every single class in every JAR file. The Java SE @Override annotation is not a runtime annotation, but a compile-time aid only.

See also:

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • 2
    Thanks a lot – had missed the part that only JAR files are not scanned for annotations (till now thought that `metadata-complete="true"` affects web application's classes, too). – NSPKUWCExi2pr8wVoGNk Nov 18 '12 at 18:51
  • This just reduced my startup by 50%, from ~110 to ~55. Why is it false by default? Are there any collateral effects I might be overlooking? @Danijel How did this work out for you? – theblang Apr 09 '13 at 16:05
  • @mattblang: JSF artifacts in (custom) tag/component libraries won't be auto-registered anymore. You'd need to explicitly register them yourselves where applicable. – BalusC Apr 09 '13 at 16:06
  • @mattblang For me? This answer by BalusC saved me! I don't remember any more, but speed improvement was drastic. – Danijel Apr 10 '13 at 10:23
  • @BalusC Our application has a large number of JAR files included. How can I know which ones need to be explicitly registered, if any? – theblang Apr 10 '13 at 15:18
  • @mattblang: sorry, please read "Servlet artifacts" instead of "JSF artfacts" in the previous comment. I didn't carefully read back the old answer and mixed up them. As to the question, well, that are those classes having `@WebListener`, `@WebFilter` and `@WebServlet` annotations. – BalusC Apr 10 '13 at 15:22
  • @BalusC So to really know what I might need to explicitly register, I would need to inspect every single JAR file (or its doc)? – theblang Apr 10 '13 at 16:09
  • @mattblang: basically, yes. I've found WinRAR helpful to search for strings in multiple JARs. You could then just search for string "@Web" in those JARs. – BalusC Apr 10 '13 at 16:11
  • @BalusC Thank you once again for providing your knowledge. – Edward J Beckett Jan 11 '14 at 02:03
  • @BalusC - What does the servlet container do by scanning jar files for annotations and web-fragment.xml's? If the application still works after adding metadata-complete=true, does it mean this tag just result in lazy class loading and initialization? – Andy Dufresne Feb 11 '14 at 06:49
  • @BalusC In my case (I am using Tomcat 7), `metadata-complete="true"` turns off annotations scanning both in `/WEB-INF/lib` and `/WEB-INF/classes`. In particular it turns off scanning `@Resource` annotations on registered listeners, filters and servlets. – Pavel S. Sep 03 '15 at 11:00
15

Here is what Java Servlet 3.0 / 3.1 Specification has to say:

The web application deployment descriptor contains a metadata-complete attribute on the web-app element. The metadata-complete attribute defines whether the web.xml descriptor is complete, or whether other sources of metadata used by the deployment process should be considered. Metadata may come from the web.xml file, web-fragment.xml files, annotations on class files in WEB-INF/classes, and annotations on classes in jar files in the WEB-INF/lib directory. If metadata-complete is set to "true", the deployment tool only examines the web.xml file and must ignore annotations such as @WebServlet, @WebFilter, and @WebListener present in the class files of the application, and must also ignore any web-fragment.xml descriptor packaged in a jar file in WEB-INF/lib. If the metadata-complete attribute is not specified or is set to "false", the deployment tool must examine the class files and web-fragment.xml files for metadata,as previously specified.

This being said and to answer your question: Yes, in order to optimise the start up time of Tomcat you need to use metadata-complete="true" and put every Servlet or Filter or Listener in your deployment descriptor.

sleske
  • 81,358
  • 34
  • 189
  • 227
Ivan Hristov
  • 3,046
  • 2
  • 25
  • 23