Details
-
Type:
Bug
-
Status:
Resolved
-
Priority:
Major
-
Resolution: Not A Bug
-
Affects Version/s: 8.1.2
-
Fix Version/s: None
-
Component/s: Servlet
-
Labels:None
-
Environment:jetty-maven-plugin 8.1.2.v20120308, spring 3.1
-
Number of attachments :
Description
I'm testing a migration to servlet 3.0 dependencies for my application, but my startup time with the jetty-maven-plugin has tripled even after setting
metadata-complete="true"
in web.xml.
I did some digging around, and found that jetty was still scanning all of the classes on the classpath because there were implementations of ServletContainerInitializer found (via the services SPI). Two instances were found, org.springframework.web.SpringServletContainerInitializer and org.apache.jasper.runtime.TldScanner.
I found this in org.eclipse.jetty.annotations.AnnotationConfiguration:
public AnnotationParser registerServletContainerInitializerAnnotationHandlers (WebAppContext context, AnnotationParser parser, List<ServletContainerInitializer> scis) throws Exception { //TODO verify my interpretation of the spec. That is, that metadata-complete has nothing //to do with finding the ServletContainerInitializers, classes designated to be of interest to them, //or even calling them on startup. //Get all ServletContainerInitializers, and check them for HandlesTypes annotations. //For each class in the HandlesTypes value, if it IS an annotation, register a handler //that will record the classes that have that annotation. //If it is NOT an annotation, then we will interrogate the type hierarchy discovered during //parsing later on to find the applicable classes. ...
Spring has a @HandlesTypes(WebApplicationInitializer.class) annotation, which is causing jetty to scan for all types implementing WebApplicationInitializer.
I agree that the spec isn't exactly clear on this, but Tomcat is certainly working on the assumption that metadata-complete="true" means that it shouldn't bother with ServletContainerInitializers. (see http://svn.apache.org/repos/asf/tomcat/tc7.0.x/trunk/java/org/apache/catalina/startup/ContextConfig.java -> see
protected void webConfig() { if (webXml.getMajorVersion() >= 3) { // Step 1. Identify all the JARs packaged with the application. If the JARs have a web-fragment.xml it will be parsed at this point. if (!webXml.isMetadataComplete()) { // Step 2. Order the fragments. // Step 3. Look for ServletContainerInitializer implementations // Step 4. Process /WEB-INF/classes for annotations etc... } } }
This is a problem for me because there is no way to tell jetty to skip the classpath scanning (45 seconds) if I have a ServletContainerInitializer on my classpath.
Barry,
I also assumed originally that if metadata-complete=true, we wouldn't use the ServletContainerInitializers, however it turns out that the jsp engine we use in jetty (from Glassfish) uses a ServletContainerInitializer. Thus, if metadata-complete was true, the initializer would not be called, and the tag libs were not set up correctly.
I would be happy to change our implementation, but I'd need some signal from the spec committee as to what the interpretation really is, and then some means of ensuring that the jsp container would be set up correctly in the absence of the ServletContainerInitializer.
I will check with the servlet spec committee.
In the meanwhile, have you tried setting the following context attribute, which should reduce which jars in WEB-INF/lib that are scanned to only those that match the pattern?:
org.eclipse.jetty.server.webapp.WebInfIncludeJarPattern
eg
./.*foo-api-[^/]\.jar$|./.*bar-[^/]\.jar$|./.*wibble[^/]\.jar$
Jan