views:

355

answers:

1

I'm running Eclipse with the run-jetty-run plugin to launch my J2EE web apps. My project uses Spring, and the spring configuration uses things like HttpInvokerProxy and properties placeholder.

  1. When the spring jars are on the classpath (I mean configured in the "classpath" tab of the "run configuration") and external (not in WEB-INF/lib), everything works fine.
  2. But when I place spring.jar (or all spring jars) in the WEB-INF/lib/ directory (+referenced in the classpath), the trouble starts. I tried with both values of Jetty's parentLoaderPriority:
    1. when parentLoaderPriority is true, I get a complaint of Xerces saying it can't validate the spring.xml's XSD (so I guess Jetty's embedded different version of xerces conflicting with mine)
    2. when parentLoaderPriority is false, the property placeholder doesn't work anymore and (I tried replacing with the direct values) Spring also fails to convert the HttpInvokerProxy into the correct interface, like some classes are missing
  3. Finally, when I leave all my jars in WEB-INF/lib and remove the matching classpath entries, it can't find the classes: I get a ClassDefNotFoundException com/google/common/collect/Lists although google-collections.jar is in WEB-INF/lib and contains the class file... This with both values of parentLoaderPriority.

Method #3 works fine in Tomcat, though. So I guess this jetty launcher has some classloading configuration I'm doing wrong ?

+1  A: 

It sounds like your application is using something on the 'external' classpath (I'll call it X) and passing it a reference; this works just fine because 'external' is in a parent classloader to your application.

'X' then uses the reference to do something with spring. However, spring is on your app's classpath, but X is on the external classpath. Spring is therefore not visible to X, hence the error.

As you discovered, putting spring into the external classpath is a valid workaround. This should also work if spring is in both the external and web-app classpaths.

As to what 'X' is? The most likely candidate would be commons-logging, which has a long history of screwing around with classloaders. You might want to consider using an slf4j implementation instead (like Logback) and provide the commons-logging interface via jcl-over-slf4j

Resources:

Kevin Wright
+1 but when spring is both in the classpath and in WEB-INF/lib, it doesn't work (it is case #2). Thanks for your detailed answer, I'm accepting it but unfortunately I haven't the time nor decision margin to try your fix yet.
streetpc