Monthly Archives: December 2014

Dealing with Sun JDK related NoClassDefFoundError under Jboss

On a recent server upgrade from Tomcat to Jboss 7 we kept facing issues related to code that made use of sun jdk classes.

Few of Exceptions were:
java.lang.NoClassDefFoundError: com/sun/net/ssl/internal/ssl/Provider
java.lang.NoClassDefFoundError: sun/net/www/protocol/http/Handler

JBoss was not kind enough to allow such references which tomcat or prior Jboss servers were happy to serve!

The solution:

JBoss has a module “sun.jdk” which is used to load the jdk classes. For some reason not all classes are referenced.

In order to allow for the sun or com related jdk packages which are not getting loaded we need to register them under the “sun.jdk” module.

So, first step is to register the various sun/jdk packages that your application is going to depend upon.

This is done by adding few entries into the module.xml found here:

Eg: jboss-as-7.1.1.Final/modules/sun/jdk/main/module.xml

The complete module.xml for reference:

<module xmlns="urn:jboss:module:1.1" name="sun.jdk">
    <resources>
        <!-- currently jboss modules has not way of importing services from
        classes.jar so we duplicate them here -->
        <resource-root path="service-loader-resources"/>
    </resources>
    <dependencies>
        <system export="true">
            <paths>
                <path name="com/sun/script/javascript"/>
                <path name="com/sun/jndi/dns"/>
                <path name="com/sun/jndi/ldap"/>
                <path name="com/sun/jndi/url"/>
                <path name="com/sun/jndi/url/dns"/>
                <path name="com/sun/security/auth"/>
                <path name="com/sun/security/auth/login"/>
                <path name="com/sun/security/auth/module"/>
                <path name="sun/misc"/>
                <path name="sun/io"/>
                <path name="sun/nio"/>
                <path name="sun/nio/ch"/>
                <path name="sun/security"/>
                <path name="sun/security/krb5"/>
                <path name="sun/util"/>
                <path name="sun/util/calendar"/>
                <path name="sun/util/locale"/>
                <path name="sun/security/provider"/>
		<!-- Registered additional packages below which are not enabled by default -->
		<path name="sun/net/www/protocol/https"/>
		<path name="sun/net/www/protocol/http"/>
		<path name="com/sun/net/ssl/internal/ssl"/>
		<!-- Additional package additions ends here -->

                <path name="META-INF/services"/>
            </paths>
            <exports>
                <include-set>
                    <path name="META-INF/services"/>
                </include-set>
            </exports>
        </system>
    </dependencies>
</module>

Note: In this example I have added the below three packages only:

<path name="sun/net/www/protocol/https"/>
<path name="sun/net/www/protocol/http"/>
<path name="com/sun/net/ssl/internal/ssl"/>

Ok, do not rush off to start the server yet, there is one more part remaining to get rid off that nasty NoClassDefFoundError.
Now, we need to reference the “sun.jdk” module.
There are two options we have now:

Approach 1
Reference the module (“sun.jdk”) from your web application by creating a jboss-deployment-structure.xml under your applications WEB-INF/ folder.
Sample:

<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.1">
    <deployment>
        <dependencies>
                <module name="sun.jdk"/>
        </dependencies>
    </deployment>
</jboss-deployment-structure>

Approach 2
Reference the module (“sun.jdk”) globally which makes it available to any application deployed on the server. With this you can ignore the custom jboss-deployment-structure.xml (No longer required to be put in each of your web applications).
For this you have to edit the standalone.xml and register the module globally.
Find the tag:

<subsystem xmlns="urn:jboss:domain:ee:1.0"/>

Then change it with this:

<subsystem xmlns="urn:jboss:domain:ee:1.0">
   <global-modules>
      <module name="sun.jdk" slot="main" /> 
   </global-modules> 
</subsystem>

With either of the above two approaches done, you can go ahead and start up your server.
You should no longer see the NoClassDefFoundError for the packages that you have registered.

References that helped me arrive at this solution:
http://www.mastertheboss.com/jboss-server/jboss-as-7/how-to-install-a-module-on-jboss-as-7
https://developer.jboss.org/thread/171932?tstart=0

Advertisements