1 Reply Latest reply on Mar 15, 2013 7:10 AM by jrantav

    Class.forName() in an osgi library jar - ModuleClassLoader throws ClassNotFound

    jrantav

      I have spring libraries installed as osgi modules. Spring-security is started up with giving a strategy class name in the initializer, and then it uses Class.forName() to load that, like:

       

      private static void initialize() {

          if ((strategyName == null) || "".equals(strategyName)) {

              // Set default

              strategyName = MODE_THREADLOCAL;

          }

       

          if (strategyName.equals(MODE_THREADLOCAL)) {

              strategy = new ThreadLocalSecurityContextHolderStrategy();

          } else if (strategyName.equals(MODE_INHERITABLETHREADLOCAL)) {

              strategy = new InheritableThreadLocalSecurityContextHolderStrategy();

          } else if (strategyName.equals(MODE_GLOBAL)) {

              strategy = new GlobalSecurityContextHolderStrategy();

          } else {

              // Try to load a custom strategy

              try {

                  Class<?> clazz = Class.forName(strategyName);

                  Constructor<?> customStrategy = clazz.getConstructor();

                  strategy = (SecurityContextHolderStrategy) customStrategy.newInstance();

              } catch (Exception ex) {

                  ReflectionUtils.handleReflectionException(ex);

              }

          }

       

          initializeCount++;

      }

       

      so now I get

       

      Caused by: java.lang.ClassNotFoundException: my.path.to.ServiceSecurityContextHolderStrategy from [Module "deployment.org.springframework.security.core:3.1.3.RELEASE" from Service Module Loader]

              at org.jboss.modules.ModuleClassLoader.findClass(ModuleClassLoader.java:190) [jboss-modules.jar:1.1.3.GA]

              at org.jboss.modules.ConcurrentClassLoader.performLoadClassUnchecked(ConcurrentClassLoader.java:468) [jboss-modules.jar:1.1.3.GA]

              at org.jboss.modules.ConcurrentClassLoader.performLoadClassChecked(ConcurrentClassLoader.java:456) [jboss-modules.jar:1.1.3.GA]

              at org.jboss.modules.ConcurrentClassLoader.performLoadClassChecked(ConcurrentClassLoader.java:423) [jboss-modules.jar:1.1.3.GA]

              at org.jboss.modules.ConcurrentClassLoader.performLoadClass(ConcurrentClassLoader.java:398) [jboss-modules.jar:1.1.3.GA]

              at org.jboss.modules.ConcurrentClassLoader.loadClass(ConcurrentClassLoader.java:120) [jboss-modules.jar:1.1.3.GA]

              at java.lang.Class.forName0(Native Method) [rt.jar:1.6.0_24]

              at java.lang.Class.forName(Class.java:169) [rt.jar:1.6.0_24]

              at org.springframework.security.core.context.SecurityContextHolder.initialize(SecurityContextHolder.java:105) [SecurityContextHolder.class:]

              ... 35 more

       

       

      for my own class, contained in the deployment. It looks like Spring tries to load the class with its own moduleclassloader, which can't see my class. How am I supposed to circumvent this? I cannot just edit the spring libraries to contain a reference to my class. I've went through https://community.jboss.org/wiki/ModuleCompatibleClassloadingGuide, but I can't change Spring code having Class.forName().

        • 1. Re: Class.forName() in an osgi library jar - ModuleClassLoader throws ClassNotFound
          jrantav

          Basically spring-security class loading is broken. This same issue occurs if you use either osgi, jboss modules or any other modular classloading.

           

          In this case, the possible workarounds are:

          • patch spring-security
          • package spring-security with the app
          • package our custom security context holder strategy together with spring-sec in a separate library
          • use reflection to set custom security context holder strategy to spring-sec

           

          We went with using reflection, as that gives as more workable upgrade path with spring-sec.