tomcat-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Nick Williams <nicho...@nicholaswilliams.net>
Subject Re: Making sure I understand application startup order correctly
Date Sat, 01 Jun 2013 15:59:30 GMT

On May 31, 2013, at 5:06 AM, Mark Thomas wrote:

> On 30/05/2013 23:42, Nick Williams wrote:
> 
>> I still have some uncertainties with a couple:
>> 
>> #2: 8.2.4 says of ServletContainerInitializers: "the order in which
>> these services are discovered MUST follow the application’s class
>> loading delegation model."
> 
> That is poor specification language. Discovery != invocation although I
> suspect that is what is meant.
> 
>> So, SCI /classes/ in the application
>> should be discovered before SCI classes in the container /if/ "parent
>> last" class loading is used (it is by default in Tomcat), and SCI
>> classes in the container should be discovered before SCI classes in
>> the application /if/ "parent first" class loading is used (it is by
>> default in WebSphere, for example). If they get reordered from the
>> order they're discovered in before they're fired, I'm not sure why
>> Tomcat is doing that. You say that Tomcat, specifically, respects the
>> fragment order (even though the spec doesn't say you must do so), but
>> SCIs provided by the container don't belong to fragments and thus
>> can't have a fragment order, so that ordering scheme only works for
>> SCIs provided by the application. So if Tomcat is ordering them
>> differently from the order they're discovered in, how is it
>> determining that order?
> 
> Tomcat first scans for JARs and fragments. Dummy fragments are created
> for any discovered JAR that doesn't have one. The JarScanner will always
> scan WEB-INF/lib before it scans the container regardless of the setting
> of delegate on the Context. That is one possible bug.
> 
> Tomcat then orders the fragments it has discovered. This includes
> fragments from container JARs. There is another potential bug here as
> fragments in container JARs should be ignored.
> 
> Tomcat then looks in the ordered fragments for SCIs. A possible bug here
> is that SCIs from the container should always be processed and currently
> they could be ignored based on ordering.
> 
> It appears to be possible for a container JAR with an SCI that should
> always be used to be excluded from a webapp. A third possible bug.
> 
> The counter point is that, as per the spec, it should be impossible to
> disable any container provided SCI on a per application basis.
> 
>> #6: 8.2.3(1) says "The order for listeners, servlets, filters if
>> relevant must be specified in either the web-fragment.xml or the
>> web.xml." 8.2.2(1)(b) says "The web.xml and WEB-INF/classes MUST be
>> processed before any of the web-fragments listed in the
>> absolute-ordering element." 8.2.2(2)(b) says "The web.xml and
>> WEB-INF/classes MUST be processed before any of the web-fragments
>> listed in the ordering element." So, I know for sure that <filters>
>> in web.xml and web-fragment.xml come before
>> programmatically-registered filters (this was part of my mistake
>> before). What I'm still uncertain on is: - If there are /no/
>> <filters> in web.xml or web-fragment.xml and filters are /only/
>> registered programmatically, is their order unspecified, or are they
>> in the order addFilter is called?
> 
> Again, look for isMatchAfter in the registration interface.
> 
>> - What comes first: @WebFilters or
>> programmatically-registered filters?
> 
> @WebFilters since annotations are merged into the associated web.xml.
> 
>> Or is this unspecified? - If
>> there are <filters> and programmatically-registered filters, will the
>> <filters> be placed on the chain in the order they are declared and
>> /then/ the programmatic filters placed on the chain in the order they
>> are declared, or is this unspecified?
> 
> isMatchAfter

Okay. I understand now. Here's one of the consequences of inability to order SCI is the spec
(thankfully Tomcat supports it, but that's not portable):

I have two filters: a LoggingFilter (/*) and an AuthenticationFilter (each URL pattern that
needs securing). The LoggingFilter sets up information about the current request (UUID, username,
etc.) in the Log4j context map, and it must come before the AuthenticationFilter, which makes
sure the user is logged in. That filter must, then, come before any other filters.

I add the filters in an SCI using isMatchAfter=false. Thankfully, Tomcat supports SCI ordering,
so putting this in my deployment descriptor ensures that the WebSocket filter gets added after
my filters:

    <absolute-ordering>
        <name>spring_web</name>
        <others />
    </absolute-ordering>

And, indeed, that worked. However, it's not guaranteed to work on all containers.

Off-topic, I should point out that I believe this is also a potential flaw in the Tomcat WebSocket
filter registration. It is also mapped isMatchAfter=false. So, if someone were to add similar
logging/auth filters to their deployment descriptor, they would only ever match AFTER the
WebSocket filter, which I can't imagine would ever be desired. IMO, the WebSocket filter registration
needs to be isMatchAfter=true. This would ensure that logging/auth filters in the deployment
descriptor matched first, and also eliminate my need to have an <absolute-ordering>.

Nick

> 
>> My overriding concern is ordering something "before anything else."
>> Based on reading the various specs, reading the link Pid sent me, and
>> your answers, I've concluded the following, which I pray someone can
>> tell me is wrong, because if I'm right it seems like a backwards
>> movement in the spec:
>> 
>> - In Servlet 2.5, there was a way to execute something "before
>> anything else" on application startup. You could define a
>> ServletContextListener as the /very first listener/ in the deployment
>> descriptor (web.xml), and its contextInitialized method would always
>> be invoked before the initialize methods on any other listeners,
>> servlets, or filters. - As of Servlet 3.0 and the introduction of
>> ServletContainerInitializers, there is no longer a way to guarantee
>> that something can be executed "before anything else." A) Any
>> ServletContainerInitializers' onStartup methods will always be called
>> before ServletContextListeners' contextInitialized methods, so you
>> can't rely on the ServletContextListener to come first anymore. B)
>> You can't create your own ServletContainerInitializer and make it run
>> before any others because the order of ServletContainerInitializers
>> is unspecified.
>> 
>> C) You can disable all web fragments with
>> <absolute-ordering /> and that will stop those SCIs from firing but
>> you still can't stop the container SCIs from firing so, again,
>> there's no way to *make* something run first anymore.
>> 
>> I hope I'm wrong about this... 
> 
> In Tomcat you can define an absolute order and the SCIs from the JARs
> will be triggered in that order followed by the container SCIs. This
> seems logical but can't find any spec language that requires this.
> 
> Without Tomcat's additional control over SCI ordering and irrespective
> of the potential bugs identified above I think you are correct.
> 
> Mark
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
> For additional commands, e-mail: users-help@tomcat.apache.org
> 


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Mime
View raw message