Issue Details (XML | Word | Printable)

Key: SERVLET_SPEC-36
Type: Bug Bug
Status: Resolved Resolved
Resolution: Fixed
Priority: Major Major
Assignee: Shing Wai Chan
Reporter: janbartel
Votes: 0
Watchers: 0
Operations

If you were logged in you would be able to see more operations.
servlet-spec

Clarify relationship of metadata-complete and ServletContainerInitializers

Created: 29/Mar/12 12:10 AM   Updated: 14/Aug/12 12:24 AM   Resolved: 14/Aug/12 12:24 AM
Component/s: None
Affects Version/s: None
Fix Version/s: None

Time Tracking:
Not Specified

Tags:
Participants: janbartel, Mark Struberg, markt_asf, Rajiv Mordani and Shing Wai Chan


 Description  « Hide

Servlet Spec 3.0 does not make clear what relationship exists between metadata-complete setting in web.xml and the discovering and invocation of ServletContainerInitializers.

The stated purpose of ServletContainerInitializers is to allow for pluggable framework initialization, and the given example is initializing the JSP container. This implies that a setting of metadata-complete=true is irrelevant to the finding and calling of ServletContainerInitializers.

If so, even if metata-complete==true for a given webapp, then we are forced to scan every class available to the webapp in the case that a discovered ServletContainerInitializer has a @HandlesTypes annotation - if the HandlesTypes specifies an annotation, then we will scan every class for that annotation, or if HandlesTypes specifies a class, then we need to scan for that class and its descendants. This can take a significant amount of time for a webapp with a large number of jars in WEB-INF/lib.

Please clarify if this is correct, or if metatadata-complete==true means that all ServletContainerInitializers are ignored.



Shing Wai Chan added a comment - 14/Aug/12 12:24 AM

The metadata-completed is clarified as mentioned above. For ServletContainerInitializer, an instance will be created at each application startup time.

Sending eod-pluggability.fm
Sending overview.fm
Sending status.fm
Transmitting file data ...
Committed revision 41.


Mark Struberg added a comment - 01/Aug/12 07:18 AM

> If we interpret 8.2.1 as no processing for "all" annotation, then does it means that CDI annotations should not be processed.
You are mixing apples with eggs. What does the CDI annotations have to do with servlet specific annotations?

The main point here is: if you don't allow a user to disable the SCI somehow, then this might be a major pain in some situations!

In our case it IS already a major pain that SCI automatically start if there is no web.xml. Not only the vastly higher scan times, but e.g. JSF defines that a SCI must be present for automatically starting JSF. In our case this did lead to starting JSF for our resources webapp which contains no JSF at all! It just blew up on servlet-3.0 containers and we had to do crazy things to get rid of it.

I'm perfectly fine if an empty <absolute-ordering/> finally will disable SCI pickup!

Please allow me to ask for another clarification:
What is the lifecycle of the SCI? It's name "Serlvet CONTAINER Initializer" indicates that this only gets scanned 1 time when the container boots. Completely independent of any web application deployed therein.
8.2.4 "An instance of the ServletContainerInitializer is looked up via the jar services API by the container at container / application startup time"

It also defines when the onStartup method gets called, but I have not yet understood if there is 1 SCI instance per webapp and SCI-Class or if the container startup creates a singleton for the whole container and all webapps invoke the onStartup to the same instance? Is this mentioned somewhere? This has a major impact about how to write the SCIs. Please also think about having 2 webapps containing jsf-impl.jar in their WEB-INF/lib (so the same JsfSCI but in 2 different isolated classloaders) vs having the jsf-impl.jar in a container lib dir.


Shing Wai Chan added a comment - 31/Jul/12 11:42 PM

This issue is discussed in expert group and the email archive can be found in http://java.net/projects/servlet-spec/lists/users/archive with subject "About SERVLET_SPEC-36".


Shing Wai Chan added a comment - 31/Jul/12 10:15 PM

I mention MANIFEST.MF as another example of metadata.

We may like to clarify the wording of 8.2.1 to be more specific to deployment descriptor related annotations.
If we interpret 8.2.1 as no processing for "all" annotation, then does it means that CDI annotations should not be processed. Of course, this is "not" the case. (And this is also contradict the documents in web.xml schema.)

Also, in our case, we have the annotation, @HandlesTypes. And if we do not process @HandlesTypes (when metadata-complete=true) and still look up the META-INF/services, in this case, ServletContainerInitializer, then the ServletContainerInitializer will not be working properly.

As I mentioned before, we would have a clarification on 8.2.4. And we would like to be more specific about the deployment descriptor related annotations.


Mark Struberg added a comment - 31/Jul/12 09:24 PM

I'm not sure what your point with the manifest is?

> The included jars, hence excluded jars, specify in <absolute-ordering> is independent of the value of metadata-complete.

8.2.1: "... As before, if the metadata-complete element is set to true in the web.xml descriptor, annotations in the class files and web-fragments bundled in jars will not be processed."

or a bit paraphrased: "... if the metadata-complete element is set to true ... web-fragments bundled in jars will not be processed.".

Which I read as: No annotations, no web-fragments, which mean jars of web-fragments not listed in the web.xml are excluded from processing if metadata-complete="true". Is this interpretation correct? Yes/No?

And now please combine this with the rules specified in 8.2.2:
"Excluded jars are not scanned for annotated servlets, filters or listeners. However, if a servlet, filter or listener from an excluded jar is listed in web.xml or a non-excluded web-fragment.xml, then it's annotations will apply unless otherwise excluded by metadata-complete. ServletContextListeners discovered in TLD files of excluded jars are not able to configure filters and servlets using the programmatic APIs. Any attempt to do so will result in an IllegalStateException. If a discovered ServletContainerInitializer is loaded from an excluded jar, it will be ignored. Excluded jars are not scanned for classes to be handled by any ServletContainerInitializer."

I just mentioned 8.2.4, because it does not mention any exclusions to the general rules defined in 8.2.1.


Shing Wai Chan added a comment - 31/Jul/12 08:40 PM

Besides web.xml, there are other metadata in a web application.
Prior to Servlet 3.0, a classpath can be specified in MANIFEST.MF.
In Servlet 3.0, web-fragment.xml can be specified in a given jar.

I see ServletContainerInitializer in 8.2.2 and 8.2.4, but not in 8.2.1.
The included jars, hence excluded jars, specify in <absolute-ordering> is independent of the value of metadata-complete.
In 8.2.2, it describes the behaviors of excluded jars.
In 8.2.4, it is not related to deployment descriptor metadata.

ServletContainerInitializer is a service provider specified in META-INF/services.
And it can be resided in a jar outside a web application.

And in general, the ServletContainerInitializer is for framework like jsp, jsf, etc.
Jsp and Jsf should not be turned off when metadata-complete=true (cf. section 8.3 of Servlet 3.0 spec).


Mark Struberg added a comment - 31/Jul/12 05:33 PM - edited

Yes Shing, I understood your argument. But please allow me to disagree with the underlying subsumption: as the ServletContainerInitializer is a 'metadata pickup mechanism' (it's defined in the servlet spec and used to initialize webapps), and the web.xml is the configuration for all stuff handled by the servlet spec, it imo certainly qualifies as 'servlet metadata' so to speak.

Of course there is no 1:1 analogon between the ServletContainerInitializer and a web.xml tag, but it is kind of a 'bracelet' around various of them.

Please look at servlet-3.0 8.2.4, 8.2.1 and a few other paragraphs. In all those the ServletContainerInitializer is mentioned on exactly the same level as all other servlet-spec 'metadata'. I can see no reason for not applying the same rules defined to the other parts of the spec.

One of my argumentation chain is the following (there are actually quite a few arguments, for paragraphs see above):

1.) a jar is a web fragment. explicit or implicit
2.) if metadata-complete="true" is set in WEB-INF/beans.xml only the web-fragments in <absolute-ordering> count. If there is no <absolute-ordering> then there is no web-fragment enabled.
3.) 8.2.2: "If a discovered ServletContainerInitializer is loaded from an excluded jar, it will be ignored. Excluded jars are not scanned for classes to be handled by any ServletContainerInitializer."

With which of the points don't you agree?


Shing Wai Chan added a comment - 31/Jul/12 04:38 PM

Mark, according to document for web.xml schema mentioned above, metadata-complete is "only" related to "annotations that specify deployment information". It is "not" for "any" annotation. This is not specific to servlet spec. Java EE spec, for instance ejb-jar_3_1.xsd, also defines the metadata-complete this way.


Mark Struberg added a comment - 31/Jul/12 08:39 AM

PS: for servlet-3.1 you should pick up the discussion initiated in the EE-7 umbrella spec about a generic scan.xml which tries to cover the scanning aspects for all the EE parts.


Mark Struberg added a comment - 31/Jul/12 08:37 AM

The quote you just posted is another argument for NOT scanning if metadata-complete="true".

Shing, just to make the clear point: CURRENTLY the servlet-3.0 spec DEFINES CLEARLY that metadata-complete="true" DISABLES ANY class scanning!

There are a dozen paragraphs which underline this point of view in the spec + in the JavaDocs + even in the schema for web.xml. And there seems to be NONE which says the opposite.

There is just NOTHING to clarify as the wording is absolutely clear. You could just clarify things which are not or not defined at all or not sufficiently clear defined!

As it seems to stand now (unless someone posts the paragraph which defines the opposite), the Servlet-3.0 specification clearly defines that metadata-complete="true" disables any class-scanning and ServletContainerInitializers wont get picked up neither.

Let's look at this from another side: what are you trying to achieve? What is the reason (use-cases) why you like to have it automatically enabled, even if a user says he doesn't like to get any stuff?


Shing Wai Chan added a comment - 31/Jul/12 07:39 AM

The following is from schema of web.xml:
"The metadata-complete attribute defines whether this deployment descriptor and other related deployment descriptors for this module (e.g., web service descriptors) are complete, or whether the class files available to this module and packaged with this application should be examined for annotations that specify deployment information.
If metadata-complete is set to "true", the deployment tool must ignore any annotations that specify deployment information, which might be present in the class files of the application."

So, the metadata-complete is related to annotations that specify deployment descriptor information. But there is no deployment descriptor for @HandlesTypes in this case.
(CDI is another example that the annotations specifying information not in deployment descriptor.)

While sending my previous comments, I have sent an email to Servlet 3.1 EG about adding a clarification ("independent of metadata-complete") in 8.2.4 as follows:
"In addition to the ServletContainerInitializer we also have an annotation - HandlesTypes. The annotation will be applied on the implementation of ServletContainerInitializer, independent of metadata-complete, to express interest in classes that are either annotated with the classes specified in the value or if a class extends / implements one of those classes anywhere in the classes super types."


Mark Struberg added a comment - 31/Jul/12 05:30 AM

Shing, don't get me wrong. The question is not whether you think it should not be scanned by the servlet engine but whether it's written down in the spec. I just found a few paragraphs which all seem to express that absolutely no annotation scanning is done if metadata-complete="true" is set. And there are even a few paragraphs which define this explicitly for ServletContainerInitializer!

Thus I'll ask again: please point me to the paragraphs in the spec which underlines your interpretation. I just could not find it, but I only quickly read through it so I might have overlooked it.

There are 3 possible situations now:

a.) Your 'interpretation' is expressed in a paragraph of the servlet-3.0 spec PDF (or JavaDocs). And this wording is clear that the other paragraphs do not count. Well, then servlet containers must scan of course!

b.) The spec wording is ambiguous and the still to be found paragraph and the few paragraphs I pointed to (expressing the opposite) are expressing contrary facts. In that case you should clarify this in the next spec. Until then any servlet container would be free to implement it as they like.

c.) There is no such paragraph which explicitly expresses that annotations must get scanned even if metadata-complete="true". In that case only this spec wording counts. If you would like to change this behaviour then I suggest you read through the guidelines of how to cope with incompatible changes in Java specs. You are e.g. only allowed to change this in a full release and not in a MR.

I've perfectly understood that the ServletContainerInitializer uses the java.util.ServiceProvider and not web.xml, but please read 8.2.2:
"If a discovered ServletContainerInitializer is loaded from an excluded jar, it will be ignored. Excluded jars are not scanned for classes to be handled by any ServletContainerInitializer."

There is NO room for any other interpretation imo! At least if there is not yet another paragraph which expresses any contrary behaviour.
The problem with java.util.ServiceLoader is that you can easily enable it, but there is NO way to disable it!

And for the CDI class scanning. Of course a CDI container will scan for annotations, but only if a beans.xml is found for that jar - otherwise it won't. It happens that I'm one of the guys writing the CDI spec...


Shing Wai Chan added a comment - 30/Jul/12 10:23 PM

The metadata-complete=true means the completeness of data specified in deployment descriptor.
But it does not mean the annotation will be ignored in the given application.
For instance, CDI annotations will still be scanned and processed.

The ServletContainerInitializer is a service provider specified in META-INF/services, not by annotation. In a ServletContainerInitializer, there may be a @HandlesTypes, which does not have corresponding metadata in deployment descriptor. Since a ServletContainerInitializer and @HandlesTypes are worked together, it should be interpreted whenever a ServletContainerInitializer is loaded.


Mark Struberg added a comment - 30/Jul/12 08:31 AM

Shing, Rajiv could you please point me to the spec paragraph where it's written down that ServletContainerInitializer class scanning must be done regardless of metadata-complete="true"?

Because Section 8.2.1 seems to contradict your statement:

8.2.1: "As before, if the metadata-complete element is set to true in the web.xml descriptor, annotations in the class files and web-fragments bundled in jars will not be processed."
There is no exclusion or "unless stated otherwise" ...

There is a more detailed statement for ServletContainerInitializers in 8.2.2:
"If a discovered ServletContainerInitializer is loaded from an excluded jar, it will be ignored. Excluded jars are not scanned for classes to be handled by any ServletContainerInitializer."

The whole 8.2.4 section also doesn't define any exception.
And section 8.4 "Processing annotations and fragments" seems to underline my interpretation.

To me as uneducated servlet spec reader (though an educated EG member) I read it in summary that ServletContainerInitializers shall get ignored if metatadata-complete="true" is set in WEB-INF/web.xml.

Again: maybe I just didn't search good enough and there is a clear definition in the spec that it should get processed - if so, then please point me to it - thanks!

If not: the rules of the JCP define that once a spec is final then ONLY the released JavaDocs and the spec wording counts - not any 'intent' anymore...

I also do not really understand the goal of this interpretation.
If I set metatdata-complete="true" then I fnnnnn dare don't like any 'implicit' mechanisms. Each EE container brings a ServletContainerInitializer for JSF, JAX-RS, JAX-WS, and tons of others. But what if I like to build something completely different? Some Tapestry or even jruby app? Then I get all the crap activated which is not needed in my case?

I'm also not sure if an empty <absolute-ordering/> would work, as web-fragments are only jars in WEB-INF/lib but ServletContainerInitializer clearly also targets other shared container classpaths as well.


markt_asf added a comment - 28/Jul/12 12:37 AM

<quote>
So, excluded jars in absolute-ordering independent of metadata-complete=true will not be scanned for ServletContainerInitializers.
</quote>

works for me since it provides a way to disable scanning for SCIs.


Shing Wai Chan added a comment - 27/Jul/12 10:39 PM

From p.67 of Servlet 3.0 spec, we have
"The <absolute-ordering> element may contain zero or one <others /> element. The required action for this element is described below. If the <absolute-ordering> element does not contain an <others/> element, any web-fragment not specifically mentioned within <name /> elements MUST be ignored. ... If a discovered ServletContainerInitializer is loaded from an excluded jar, it will be ignored. Excluded jars are not scanned for classes to be handled by any ServletContainerInitializer."

So, excluded jars in absolute-ordering independent of metadata-complete=true will not be scanned for ServletContainerInitializers.


Rajiv Mordani added a comment - 26/Jul/12 10:04 PM

If metadata-complet is true - then the web-fragments (not only the ordering) are ignored. Howerver the jars in WEB-INF/lib will still be processed for ServletContainerInitializers. Ordering does not apply to ServletContainerInitializers.


markt_asf added a comment - 22/Jun/12 08:04 AM

There is one further additional clarification required.

If metadata-complete=true, that implies that any fragment ordering specified is ignored.

However, if the main web.xml specifies an absolute ordering when metadata-complete=true, are all JARs in WEB-INF/lib processed for ServletContainerInitializers or are JARs excluded from the ordering still excluded from the processing for ServletContainerInitializers?


Shing Wai Chan added a comment - 18/May/12 05:38 PM

The metadata-complete and invocation of ServletContainerInitializers are independent.