I recently ran into a situation where I wanted to log details about what Jetty's class loader was doing for one of our web apps. There is a hook in WebAppContext to provide your own WebAppClassLoader implementation, which was just what I needed, so I proceeded to write LoggingWebAppClassLoader (source below). The trouble was: where do I actually get a chance to insert my custom implementation?
It's easy enough to do this if you're embedding Jetty in your app:
// Scala code val context = new WebAppContext() val lwacl = new LoggingWebAppClassLoader(context) context.setClassLoader(lwacl) ...
Unfortunately we're not embedding, but just deploying a .war to an existing Jetty server. I messed around with this at length, and eventually asked on StackOverflow. The answer there got me on the right path, though I had a few other issues along the way.
Here's how I got it working:
- Changed my deployment technique to Jetty's context deployer ($JETTY_HOME/contexts) instead of just copying .war files into $JETTY_HOME/webapps.
- Wrote myapp.xml (see below) to define the context. It's in here that you can configure Jetty to use the custom WebAppClassLoader.
- Copied the jar file containing my LoggingWebAppClassLoader class into $JETTY_HOME/lib so the class is available to the context deployer.
Of course it seems pretty straight-forward now that I've figured it out :) The biggest issue was that I didn't know much about deploying via Jetty contexts. They seem to have a lot of advantages over the vanilla war deployer in that you can easily tweak any Jetty internals at deploy time. Downside is "programming" in XML...
myapp.xml (Jetty context):<Configure id="mycontext" class="org.mortbay.jetty.webapp.WebAppContext"> <Set name="contextPath">/</Set> <Set name="war">/foo/myapp.war</Set> <Set name="classLoader"> <New class="fully.qualified.name.LoggingWebAppClassLoader"> <Arg><Ref id="mycontext"/></Arg> </New> </Set> </Configure>LoggingWebAppClassLoader.java:
import java.io.IOException; import org.mortbay.jetty.webapp.WebAppContext; import org.mortbay.jetty.webapp.WebAppClassLoader; public class LoggingWebAppClassLoader extends WebAppClassLoader { public LoggingWebAppClassLoader(ClassLoader parent, WebAppContext context) throws IOException { super(parent, context); } public LoggingWebAppClassLoader(WebAppContext context) throws IOException { super(context); } private void log(String s) { System.out.println(s); } @Override public void addClassPath(String classPath) throws IOException { log(String.format("addClassPath: %s", classPath)); super.addClassPath(classPath); } @Override public Class loadClass(String name) throws ClassNotFoundException { log(String.format("loadClass: %s", name)); return super.loadClass(name); } }
No comments:
New comments are not allowed.