10 Replies Latest reply on Jul 27, 2004 9:28 AM by spiritualmechanic

    Classloading Question

      I have a question concerning classloading in JBoss4. I'm trying to construct a RARDeployment programmatically, such that it picks up the jbosstestadapter.rar and creates the connection factory.

      I get the following error:

      15:31:40,208 INFO [STDOUT] Registered RARDeployment
      15:31:40,218 INFO [STDOUT] Registered RARDeployment ... create
      15:31:40,218 ERROR [RARDeployment] Could not find ManagedConnectionFactory class
      : org.jboss.test.jca.adapter.TestManagedConnectionFactory
      java.lang.ClassNotFoundException: org.jboss.test.jca.adapter.TestManagedConnecti
      onFactory
      at java.net.URLClassLoader$1.run(URLClassLoader.java:199)
      at java.security.AccessController.doPrivileged(Native Method)
      at java.net.URLClassLoader.findClass(URLClassLoader.java:187)
      at java.lang.ClassLoader.loadClass(ClassLoader.java:289)
      at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:274)
      at java.lang.ClassLoader.loadClass(ClassLoader.java:235)
      at org.jboss.resource.connectionmanager.RARDeployment.startService(RARDe
      ployment.java:543)



      The code I have is pretty minimal (I create an MBeanServer programmatically) and it picks up my jbosstestadapter.rar, just looking through the logs and making sure it was there.

      RARDeployment rd = new RARDeployment(); rd.setManagedConnectionFactoryClass("org.jboss.test.jca.adapter.TestManagedConnectionFactory");
      ObjectName oldName = new ObjectName("jboss.jca:name='jbosstestadapter.rar',service=RARDeployment");
      rd.setOldRarDeployment(oldName);
       rd.setConnectionDefinition("javax.resource.cci.ConnectionFactory");
       ObjectName name = new ObjectName("jboss.jca:service=ManagedConnectionFactory,name='jbosstestadapter.rar'");
      server.registerMBean(rd, name);
      System.out.println("Registered RARDeployment");
      server.invoke(name, "create", null, null);
      System.out.println("Registered RARDeployment ... create");
      
      server.invoke(name, "start", null, null);






      I don't think this is anything JCA-specific (although I may be wrong). I think there's something I need to do with the MBeanServer classloader or something?

      Thanks,

        • 1. Re: Classloading Question

          I did a small test to see what the classloader is for the MBean for jbosstestadapter.rar:

          ObjectName oldName = new ObjectName("jboss.jca:name='jbosstestadapter.rar',service=RARDeployment");
          
          ClassLoader loader = server.getClassLoaderFor(oldName);
          System.out.println("ClassLoader is: " + loader);


          The output I get is:

          09:46:56,789 INFO [STDOUT] ClassLoader is: org.jboss.mx.loading.UnifiedClassLoa
          der3@97d026{ url=file:/C:/eclipse/workspace/jbossserver/bin/./server/default/tmp
          /deploy/tmp53524jbosstestadapter.rar ,addedOrder=4}


          So it does seem to be loading somewhere, but my other code can't see it when I get inside my unit test.

          Hmmm. Here's another test:

          ClassLoader parent1 = loader.getParent();
          System.out.println("Parent1 is: " + parent1);
          while (parent1 != null) {
           parent1 = parent1.getParent();
           System.out.println("Parent1 is: " + parent1);
          }


          I'm wonder. If I remember correctly (I'll do some research on this), a child classloader can see its parent's classes, but not vice versa. I bet I'm running into that. My JUnit class is the parent, initing the .rar in a child loader, which doesn't help my programmatic creation of the ManagedConnectionFactory MBean.


          • 2. Re: Classloading Question
            starksm64

            Usually a parent cannot see child class loaders but our default class loading model is a peer model such that there is no notion of parent/child within a deployment. Create a bug report on sourceforge with the test deployment in question if you want me to look at it.

            • 3. Re: Classloading Question

              Sure thing. Just so you know, I'm not bootstrapping JBoss under the usual process. I'm creating the MBeanServer similar to something that Andrew Oliver did for his unit testing on jboss-mail.

              I'll put it on sourceforge with source, jars, etc.

              Thanks,

              • 4. Re: Classloading Question

                What are the classes involved in the Default class loading model? (i.e. extensions of ClassLoader). I see NoAnnotationURLClassLoader in the jboss-system project. Are there any others?

                Maybe if load the

                RARDeployment rd = new RARDeployment();

                in the right classloader it will see everything whenever I start the MBean. I'll experiment with this a little bit.

                • 5. Re: Classloading Question
                  starksm64

                  The MBeanServer LoaderRepository implementation which defaults to the org.jboss.mx.loading.UnifiedLoaderRepository3 is what sets up the default class loading layer. In standalone mode there will also be the main app class loader.

                  • 6. Re: Classloading Question

                    Is there any way I can add the top classloader to the LoaderRepository? If I do that maybe my JUnit constructions will be seen by the MBeanServer.

                    Something like:

                    ClassLoader cl = Thread.currentThread().getContextClassLoader();
                    LoaderRepository.addClassLoader(cl);

                    Then when I do:

                    RARDeployment rd = new RARDeployment();

                    My rd will be able to see the TestManagedConnectionFactory.

                    • 7. Re: Classloading Question
                      starksm64

                      Yes, non-UnifiedClassLoaders may be added to the repository.

                      • 8. Re: Classloading Question

                         

                        UnifiedLoaderRepository3 rep = (UnifiedLoaderRepository3) server.getClassLoaderRepository();
                         rep.addClassLoader(Thread.currentThread().getContextClassLoader());


                        This didn't seem to solve it. Still got the same NoClassDefFound for TestManagedConnectionFactory.

                        There's obviously something I still don't understand about class loaders. :) Still looking.
                        Steve

                        • 9. Re: Classloading Question

                          Scott:

                          I created a patch on sourceforge with the sample test zipped up if you want to look at it.

                          • 10. Re: Classloading Question

                            Scott:

                            Oops, you asked for bug report. I put a patch. Let me know if you need me to move it or something.