1 Reply Latest reply on Apr 10, 2018 8:53 AM by jewellgm

    NoClassDefFoundError in subdeployment when a class is called in EAR/lib that extends a class in the subdeployment's WEB-INF/lib

    bryon.williams

      In transitioning a functioning application from JBOSS EAP 6.2 (JBOSS AS 7.3) up to JBOSS EAP 7.1 (WildFly Core 3.x (WildFly 11)), I am encountering an issue with classloading that I am stumped on and am looking for input from the community...

       

      Context --

      This is an EAR deployment with a structure that resembles the following:

      master.ear

      + lib/

         - a.jar

         - b.jar

         - ...

      + app1.war

         WEB-INF/lib

           - app_foundation_a.jar

       

      Where:

      • a.jar has a class that extends an interface that is located in app_foundation_a.jar
      • ear isolated deployments is false
      • the error is thrown when using the web app in app1.war

       

      The Error:

      2018-04-09 14:35:23,019 ERROR [io.undertow.request] (default task-3) UT005023: Exception handling request to /some/app/resource.jsp: java.lang.NoClassDefFoundError: Failed to link com/company/app/extensions/AppPostLoginProvider (Module "deployment.master.ear" from Service Module Loader): com/vendor/coolApplication/extensibility/login/PostLoginProvider
              at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
              at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
              at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
              at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
              at org.jboss.modules.ModuleClassLoader.defineClass(ModuleClassLoader.java:446)
              at org.jboss.modules.ModuleClassLoader.loadClassLocal(ModuleClassLoader.java:274)
              at org.jboss.modules.ModuleClassLoader$1.loadClassLocal(ModuleClassLoader.java:77)
              at org.jboss.modules.Module.loadModuleClass(Module.java:713)
              at org.jboss.modules.ModuleClassLoader.findClass(ModuleClassLoader.java:190)
              at org.jboss.modules.ConcurrentClassLoader.performLoadClassUnchecked(ConcurrentClassLoader.java:412)
              at org.jboss.modules.ConcurrentClassLoader.performLoadClass(ConcurrentClassLoader.java:400)
              at org.jboss.modules.ConcurrentClassLoader.loadClass(ConcurrentClassLoader.java:116)
              at java.lang.Class.forName0(Native Method)
              at java.lang.Class.forName(Class.java:264)
          ...
      

       

      This worked as is under JBOSS AS7.2, but with the new isolated classloader and class loading structure, it now seems that jboss fails to link the class located in ear/lib/a.jar to its base class in ear/app1.war/WEB-INF/lib/app_foundation_a.jar

       

      Aside from moving app_foundation_a.jar to the ear/lib (which breaks other subdeployments, so not an option), and moving a.jar into the war's WEB-INF/lib (which *does* work, but is not officially supported by the application vendor), is there any way to get this dependency to link properly?

        • 1. Re: NoClassDefFoundError in subdeployment when a class is called in EAR/lib that extends a class in the subdeployment's WEB-INF/lib
          jewellgm

          Per the "Class Loading in WildFly 10" page, setting the ear-subdeployments-isolated parameter to false doesn't affect war files:

           

          The ear-subdeployments-isolated element value has no effect on the isolated classloader of the .war file(s). i.e. irrespective of whether this flag is set to true or false, the .war within a .ear will have a isolated classloader and other sub-deployments within that .ear will not be able to access classes from that .war. This is as per spec.

           

          The AS7 documentation also makes this same claim, but may have been broken on that baseline.

           

          I don't fully understand why moving a.jar into the war's WEB-INF/lib is a problem.  If there are no other subdeployments in the ear that depend on a.jar, then I don't think it would be a problem. Of course, any other jars in the ear's lib directory that have dependencies on a.jar would also have to be relocated.

           

          You can also try to use a Class-Path entry in the ear's MANIFEST.MF.  I have never tried to point the classpath to embedded jars in other modules, so I don't know the exact syntax, but I would guess something like the following:

           

          Class-Path: ../app1.war/WEB-INF/lib/app_foundation_a.jar

           

          Using jboss-deployment-structure.xml may also be an option.  Like the Class-Path technique, I don't know the syntax of pointing to a subdeployment within the ear.