On 13 Jan 2006, at 13:10, Cyrus Daboo wrote:
The text filter is very specific to the webapp (it does some custom indexing of the iCalendar data - not a straight text extraction as other text filters do) and it has a dependency on iCalendar libraries for parsing. Thus a whole bunch of stuff, not just the text filter, would have to be moved up to the tomcat class loader - this seems like a bad layering violation to me.

It is - but the problem is more fundamental.

Fundamentally, you've got two paths you'll end up on:

1) You keep the core outside the war classloader, and the filter in the system classloader. Because the core application is using shared classes, references to classes that aren't available in the WAR classlaoder is available to other WARs - however, they are invalid when used there. Keep it in the WAR classloader, and you risk creating a dirty environment for other WARs.

2) You move the core into the WAR with the rest of it - but now you need to ensure that your shutdown hooks are getting called by the war to shut down the environment properly. You can either use HiveMind or some other dependency injection system to perform the shutdown on registry shutdown (and call shutdown from a filter, for example) or use one of the servlet unloads to do so. But now you can't share anything between instances, and nothing's visible to other applications, some of which may be SSO.

There's no good way around this - we have the same problem in the Castor project; when the core is loaded from common, classes loaded into it become a part of the system that's visible, if someone tries hard enough, to other classloaders in other wars, and do cause layering violations.

There's a design-around, I guess, though: Ensuring that all access to the core is done through a 'context', and the context retains all of the classloaded filters, etc.; releasing that context can then release the classloader-dependent, environment-specific stuff, while preventing the layering problems. On the other hand this, by design, prevents transparent sharing of the global context, as a global context no longer exists - applications are responsible for knowing when a context is shareable based on the stuff that's loaded into it and their own use of the context.

If you won't move to 2), you have to make 1) tenable - that means that when your application shuts down, you need to find a way to basically either unregister everything you registered which was war- specific, or return the system to (either an initialized or a shutdown) state where none of those classes are loaded.

Not uncommon, no - but not easily avoidable when people violate the layering by passing class implementations in the war out to something that runs, and continues to run beyond the war's unload, in a set of other threads. Ultimately, the WAR was responsible for creating the layering violation - it's the WAR's job of doing whatever's necessary to make unload possible.

That may mean API for de-registering the stuff you've added, or it may mean forcing a shutdown of the jackrabbit container. Them's the breaks.

Reply via email to