Search code examples
javaservletsjettyjndi

Jetty Classloading issue


I'm using the jetty maven plugin to run a webapp locally and I'm getting a class cast exception when I try to pull in a JNDI resource.

I have a jetty config with a resource object, which is a configuration bean that is utilized via JNDI. This class resides in a different jar on the classpath that is in the lib directory:

<Configure class="org.mortbay.jetty.Server">
    <New class="org.mortbay.jetty.plus.naming.Resource">
        <Arg>config/MyConfigObject</Arg>
        <Arg>
            <New class="my.config.ConfigObject">
                <Set name="foo">bar</Set>
            </New>
        </Arg>
    </New>
</Configure>

This is retrieved via Spring:

<bean id="MyConfigObject" class="org.springframework.jndi.JndiObjectFactoryBean">
        <property name="jndiName" value="java:comp/env/config/MyConfigObject" />
</bean>

Inside of a servlet, I'm grabbing the object manually:

final MyConfigObject config = (MyConfigObject) applicationContext.getBean("MyConfigObject");

But when I try to access the servlet, I get:

java.lang.ClassCastException: my.config.MyConfigObject cannot be cast to my.config.MyConfigObject

I'm pretty sure the problem is due to class loading, but I'm not 100% certain. MyConfigObject's class loader is the default sun class loader, while the thread's current class loader is jetty's WebAppClassLoader. My jar is in WEB-INF/lib, and I've even added it manually to extraClasspath in the maven plugin configuration:

<plugin>
                <groupId>org.mortbay.jetty</groupId>
                <artifactId>maven-jetty-plugin</artifactId>
                <version>6.1.25</version>
                <configuration>
                    <jettyConfig>${basedir}/test/jetty.xml</jettyConfig>
                    <webAppSourceDirectory>${basedir}/target/${project.artifactId}</webAppSourceDirectory>
                    <webXml>${basedir}/war/WEB-INF/web.xml</webXml>
                    <webAppConfig>
                        <extraClasspath>${basedir}/target/${project.artifactId}/WEB-INF/lib/myConfigJar-1.0.jar</extraClasspath>
                    </webAppConfig>
                </configuration>
                <dependencies>
                    <dependency>
                        <groupId>testing</groupId>
                        <artifactId>myConfigJar</artifactId>
                        <version>1.0</version>
                    </dependency>
                </dependencies>
            </plugin>

I'm kind of stuck at this point. Does anyone know how to resolve this?


Solution

  • The problem is that you've got the jar listed in too many places - you attempts to add it to extraClasspath will actually make it worse, not better.

    You say it's in WEB-INF/lib, but I assume it's also listed as a dependency in your pom.xml

    You don't want to do that, you need to have 1 single reference to it. Either as a dependency in your pom.xml or in your lib directory, or in extraClasspath, but only in 1 place.

    (Hint: pom.xml is almost certainly the right place, get rid of the others)