Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

As of Servlet 3.0, there is no way to create code guaranteed to run first before anything else #79

Open
glassfishrobot opened this issue Aug 31, 2013 · 7 comments
Assignees

Comments

@glassfishrobot
Copy link

In Servlet 2.5 and earlier, if you needed code that you could guarantee would always run first, you implemented ServletContextListener, put your important code in the initialization method, and defined it as the very first listener in your deployment descriptor web.xml. This was critically important for many tasks, such as logging initialization. Logging initialization typically must happen before anything else, or else it could be initialized incorrectly.

Servlet 3.0 added the awesome and useful concept of the ServletContainerInitializer, but this introduced a critical problem. There is no longer any way to create code guaranteed to run before anything else. First, a ServletContainerInitializer will always run before any ServletContextListener is initialized, so you can't rely on a ServletContextListener to run your critical startup code. I thought that a ServletContainerInitializer would run in the order of its web-fragment (either in web-fragment.xml or in web.xml), but I was wrong. The spec makes no such guarantee. Initializers are guaranteed nothing more than a random execution order. Because of this, it is impossible to guarantee that critical startup code will always run first.

Some containers appear to abide by the web-fragment order any. For example, Tomcat, TomEE, and JBoss definitely order initializers according to their web-fragment order (this is confirmed in code), while WebLogic and WebSphere appear to order them the same way (they are closed source, so this can't be completely confirmed, but the behavior is consistent). However, GlassFish, Jetty, and Resin order initializers in the order they are returned from the ClassLoader.

The execution of an ServletContainerInitializer should be ordered according to its web-fragment order. Alternatively a separate ordering mechanism could be specified, but this would seem to be unnecessary and burdensome. Furthermore, I think the committee should encourage (though obviously it cannot require) existing 3.0 and 3.1 implementations to apply this change retroactively, since it doesn't change the API.

Failing to require a predictable and controllable order for initializers is a serious oversight in the spec and represents a regression from 2.5, where it was possible to write code guaranteed to always run first.

@glassfishrobot
Copy link
Author

@glassfishrobot Commented
Reported by beamerblvd

@glassfishrobot
Copy link
Author

@glassfishrobot Commented
markt_asf said:
There are some further complicating factors here:
1. Ordering of container provided SCIs vs application provided SCIs
2. Ordering when the container and the application both provide an implementation of an SCI
2a. The application provided implementation may be disabled via ordering
2b. Delegation order determines which implementation (container or application) takes precedence when loading.

I suggest the following approach.

1. Container provided SCIs are always executed first in a container determined order.
a. If an application provides an alternative implementation then that is used at this point
regardless of exclusion via ordering
2. Application provided SCIs are executed in fragment order

@glassfishrobot
Copy link
Author

@glassfishrobot Commented
dokovski said:
In relation to 1a:
Does this mean that if an app has bundled web library that uses the SCI mechanism this library takes precedence over platform supplied ones? There is a recommendation in Java EE specification EE 8.2.3 Library Conflicts:
In particular:"Note that if the library is also a required component of the Java EE platform version on which the application is being deployed, the platform version may (and typically will) take precedence."

@glassfishrobot
Copy link
Author

@glassfishrobot Commented
markt_asf said:
Re 1a it actually depends on the configured delegation order (see Servlet 3.0/3.1 section 8.2 final paragraph). The point I was trying to make is if the container defines an SCI then it is loaded with the other SCIs even if it is loaded from the application. For this to happen:

  • the application would have to ship an SCI implementation that the container also defined
  • the container / application would have to configured with an application first class loading delegation order.

The aim is that all container specified SCIs are loaded first even if the implementations of some of them are provided by the application because the application ships with an alternative implementation.

@glassfishrobot
Copy link
Author

@glassfishrobot Commented
This issue was imported from java.net JIRA SERVLET_SPEC-79

@glassfishrobot
Copy link
Author

@arjantijms Commented
Why don't we "just" introduce some kind of explicit ordering for this, i.e. take advantage of the @Priority annotation?

@glassfishrobot
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants