12 Replies Latest reply on Jul 3, 2002 4:57 AM by Thierry Giguère

    EAR Classloader problem

    Paul Raby Newbie

      Using JBoss 2.4.4, I'm deploying an ear which contains ejb's and library jars. The ejb calls the library code and providing I modify the manifest of the ejb all is well.

      If I copy the library code (contained in a jar) into the lib/ext directory, the classloader for the ejb delegates first to lib/ext, and not the ear.

      This is a problem where we use third party classes that are also in lib/ext, such as castor. Worse of course is that the lib/ext classloader cannot see the ear classloader so all our library code needs to be packaged into lib/ext otherwise castor cannot load our libraries!

      Question: what would be the implications of modifying the ear classloading mechanism to delegate first to the ear classes (and not lib/ext)? This would allow us to use 3rd party code of a different version to that in lib/ext (such as castor).

      Secondly, if the above implication wasn't too severe, exactly what code would need to be modified?

      Thanks

      Paul

        • 1. Re: EAR Classloader problem
          Adrian Brock Master

          http://main.jboss.org/forums/thread.jsp?forum=46&thread=8041&message=381590&q=castor+class.forname#381590

          Class.forName() :-(
          Thread.currentThread().getContextClassLoader().loadClass() :-)

          Regards,
          Adrian

          • 2. Re: EAR Classloader problem
            Paul Raby Newbie

            Unfortunately, as I explained, the problem is generic (not Castor specific).

            Any class (extends Object) that appears both in the ear and in lib/ext will be loaded from lib/ext by default.

            This isn't good default behavior as it does not allow you to use your own versions of 3rd party libraries from within your ear...

            • 3. Re: EAR Classloader problem
              Adrian Brock Master

              And if ear classes were loaded in preference to
              lib/ext you could replace system classes.
              Accidently or maliciously making the system unstable.

              Having said that, the 2.3 servlet classloader does
              exactly that. But it is careful not to let you replace
              the web server classes.

              Regards,
              Adrian

              • 4. Re: EAR Classloader problem
                Paul Raby Newbie

                Not true. You can't push classes up the classloader hierarchy. You may well deploy an EAR which has, say, j2ee classes that are unstable, but it can only affect the ear, as no other part of the system (such as the jboss classloader covering lib/ext) is allowed to see the classes inside the ear. Completely self contained: but unfortunately not so in the current implementation of jboss 2.4.4...

                I'm quite happy that lib/ext is not allowed to see classes in the ear (makes sense). I'm unhappy that classes in the ear receive second preference to lib/ext. It makes it impossible to use newer versions of third party libraries in your ear than those that come packaged with jboss.

                • 5. Re: EAR Classloader problem
                  Adrian Brock Master

                  As I said at the start lib/ext can load from your
                  ear, if the code uses
                  Thread.currentThread().getContextClassLoader()
                  rather than Class.forName()

                  Yes, it will only affect your ear, until you pass the
                  classes back into the other system code.
                  But, if you are careful it can be made to work.

                  Anyway, 3.0 has a flat classloader model. The application
                  classes and system classes are on an equal footing when
                  it comes to loading from each other.

                  Regards,
                  Adrian

                  • 6. Re: EAR Classloader problem
                    Paul Raby Newbie

                    Thanks warjort, but maybe I stated the problem incorrectly. I don't want to be able to load classes in my ear from lib/ext, rather I want classes in my ear to load other classes in my ear as opposed to loading them from lib/ext.

                    My test case simply did the following:

                    EJB1 calls new Library1();

                    Library1 calls new Library2().

                    Library1 is in a jar in the ear, and in lib/ext. Library2 is in the ear.

                    Library1 fails, with a classnotfound exception.

                    I'm not using class.forName, or Thread.currentThread().getContextClassLoader(), because I am not loading my classes dynamically. Just plain old static classloading.

                    Why is the ear classloader loading library1 from lib/ext, when it is being created from Ejb1, and Ejb1, Library1 and Library2 are all in the ear?!

                    • 7. Re: EAR Classloader problem
                      Adrian Brock Master

                      Do you have a Class-Path specified in the
                      MANIFEST.MF of your ear for your libraries?

                      Regards,
                      Adrian

                      • 8. Re: EAR Classloader problem
                        Paul Raby Newbie

                        Yes: the manifest of my ejb jar contains the classpath references. It points to libraries/library1.jar and libraries/library2.jar. According to the logs both the library jars are loaded upon deployment. Everything is fine providing lib/ext doesn't have it's own copy of library1.jar. As soon as I copy library1.jar into lib/ext then library2 is no longer visible from library1.

                        Obviously this is a simple test case, but proves the point.

                        • 9. Re: EAR Classloader problem
                          Adrian Brock Master

                          Hi,

                          Just to clarify, I didn't pick this up before.

                          You have Library1.class in lib/ext and
                          Library2.class in your ear.
                          with

                          import Library2;
                          public class Library1 {...}

                          No, this won't work.

                          Library1.class is loaded by a parent classloader of the
                          ear. When it tries to resolve the import it will use
                          its own classloader which cannot see classes in the ear.
                          This is standard JVM behaviour.

                          Like I said above, this would work with the JBoss3
                          flat UnifiedClassloader. But it wouldn't work with
                          two different versions of the same library.

                          Regards,
                          Adrian

                          • 10. Re: EAR Classloader problem
                            Paul Raby Newbie

                            Message understood re why library 1 cannot see library2.

                            The question then arises, why is the ejb in the ear loading library1 from lib/ext when it could equally load it from the ear (I deploy it to both the ear and lib/ext in the test)? If it were to load it from the ear, then it would be able to see library2.

                            Why does the ejb load the lib/ext version of the class as opposed to the ear version?

                            • 11. Re: EAR Classloader problem
                              Adrian Brock Master

                              Like I said above, this is for security/consistency
                              i.e. to stop you replacing system classes.

                              A classloader delegates to its parent before
                              trying to load locally.

                              Regards,
                              Adrian

                              • 12. Re: EAR Classloader problem
                                Thierry Giguère Newbie

                                Hi,

                                I clearly support "paulraby" point of view this class loader scope bring a lot of problem! There is application scope problem too! For example my web application (web archive) deployed in exploded directory use class from EJB archive already deployed resulting in error...

                                For myself, there is more concern about application scope protection (deployment issue) than security! May some special classes should be protect to avoid security / consistence problem but it should not bring more problems than solutions.

                                Ok, it's only an opinion...