Skip to Content.
Sympa Menu

mace-opensaml-users - Re: [OpenSAML] loading additional configuration with XMLConfigurator

Subject: OpenSAML user discussion

List archive

Re: [OpenSAML] loading additional configuration with XMLConfigurator


Chronological Thread 
  • From: Brent Putman <>
  • To:
  • Subject: Re: [OpenSAML] loading additional configuration with XMLConfigurator
  • Date: Tue, 01 Apr 2008 17:26:11 -0400



Kenny Pearce wrote:
Hi,
I'm getting odd classloader behavior with the XMLConfigurator. I am
creating a SAML extension (an additional message type), so I made a new
XML file and after calling DefaultBootstrap.bootstrap, I call
XMLConfigurator.load with an InputStream to my XML file (please tell me
if this is not the correct way to do this).

This sounds correct. I would personally probably actually extend DefaultBootstrap, override bootstrap() and after calling super.bootstrap() call the code to load the new providers from there. That way you just have one single thing to call. But same thing.


During loading I get a
ClassNotFoundException for my builder, which is the first class
mentioned in the XML.
I took a look at the XMLConfigurator code and the offending section
(lines 328-329) looks like this:

ClassLoader classLoader = this.getClass().getClassLoader();
Class clazz = classLoader.loadClass(className);

The first thing I noticed is that the javadoc for Class.getClassLoader
says: "Some implementations may use null to represent the bootstrap
class loader. This method will return null in such implementations if
this class was loaded by the bootstrap class loader." So this is
technically a bug in that it relies on a particular feature of the Sun
JVM which is not required by the Java spec. I'm not totally sure what
the correct way to do this is; guess you can check if it's null and
call the static method ClassLoader.getSystemClassLoader if it is.

I guess this is technically true, but it is extremely unlikely that opensaml code would be loaded in the JVM's bootstrap classloader. You'd have to do some deliberate and uncommon stuff to make this happen. Only thing I could think of off-hand would be if you used opensaml to implement a Java security provider (of some kind, not clear what...), and so needed to put the jars in jre/lib/ext.

Note this is *not* the system classloader (stuff typically loaded from CLASSPATH env var or JRE -cp/-classpath args).


This,
however, is neither here nor there as I am getting a
ClassNotFoundException and not a NullPointerException.
I next tried inserting the line
"this.getClass().getClassLoader().loadClass("my.class.name");" into my
code immediately before I call XMLConfigurator.load, where
"my.class.name" is copied directly from the exception output and so is
exactly the same. It does not throw an exception in my code.

Are you saying that putting that line in just doesn't throw an exception in your code, and that the XMLConfigurator still fails with the class not found exception? If so, that makes sense, see below...

I don't know if this is relevant, but I am running under Tomcat and my
code is in WEB-INF/classes, whereas the OpenSAML library code is in a
jar in a directory specified in the shared.loader property. Any idea what's going on?


Yes, as Xavier already noted, I believe this is exactly your problem. Tomcat's classloader hierarchy is documented here for 5.5:

http://tomcat.apache.org/tomcat-5.5-doc/class-loader-howto.html

(BTW, I noticed that they have apparently removed the Shared and Catalina classloaders in Tomcat 6.0 and collapsed the hierarchy (unless their docs are wrong). Didn't know that...)

Without getting into the nitty-gritty details: this error makes sense. Since you're loading XMLConfigurator in the shared classloader, and because as you pointed out that makes use of its own classloader to load classes defined in the config file, it can never see/load any classes in your web app classloader (/WEB-INF). The classloaders never delegate down in the hierarchy (to children), only up (to their parent).

So you would need to put your extension provider jars/classes in the same classloader as the rest of the opensaml stack jars (or possibly above them in the hierarchy, I suppose). I would personally put them all in your web app classloader, rather than shared, unless you have a good reason for doing otherwise.

Loading them programmatically in your app code, as someone else suggested, may also work, since all the work is done in the web app's classloader. However, we make use of reflection in other parts of the library. We have not tested things in this kind of split classloader setup, and so just FWIW you may run into other problems down the road. Note this really isn't an issue with opensaml in particular. Issues with classloading, in particular with reflection, are a common thing when you dealing with complex classloader environments such as you usually see with servlet or application containers.

HTH,
Brent





Archive powered by MHonArc 2.6.16.

Top of Page