1 2 Previous Next 19 Replies Latest reply on Sep 29, 2005 10:15 AM by jaikiran pai

    ClassLoader Issue

    stevecoh2 Newbie

      I am trying to deploy some new Application code into our JBoss application. Our developers work using JBoss 3.2.5 but the platform onto which it is deployed is JBoss 3.2.1. We've had no problem with this until now, when we introduce some Application code that uses org.apache.commons.HttpClient. This jar is included at the very top of the JBoss tree: {jboss-root}/lib. In 3.2.1, commons-httpclient.jar is 51KB and it's manifest identifies it as implementation version 1.0.16. In 3.2.5, the jar is 214KB and its manifest identifies it as 2.0-rc1.

      The result of running in this environment is IncompatibleClassChangeError being thrown when our class that imports httpclient classes is first loaded.

      It is possible that we could compile our code against the older version of httpclient and get it to work. Then if we stopped putting commons-httpclient.jar in our war file, it might work. But since the two versions of httpclient are so radically different, I'd rather go the other way if possible and avoid problems caused by now running the application code against an older version of HttpClient than it was developed against. That is, for just this one class, bypass normal class loading and load the version in WEB-INF/lib.

      Will this work, and if so, how do I make it happen, and if not, what other alternatives do I have?

        • 1. Re: ClassLoader Issue
          stevecoh2 Newbie

          Really, has no one had this problem before?

          We are in a situation where we do not control the version of jboss that is in deployment, so we are stuck with 3.2.1. Yet we need to add application functionality that requires HttpClient 2.0, while JBoss 3.2.1 ships with 1.0.x.

          By placing commons-httpclient.jar in /lib instead of /server/lib, JBoss makes it nearly impossible for applications to upgrade this libarary if they need it. Can someone please tell me

          1) whether it is possible to package a later version of HttpClient with my application and have it work without conflicts? I've looked at the wiki about classloader isolation but I don't completely understand it. Are you supposed to replace "unique-archive-name" with a unique archive name - and if so, where does this unique archive have to reside?

          OR

          2) Would it just be simpler to replace the commons-httpclient.jar in the /lib directory with the newer one and would that cause any problems for jboss and/or tomcat?

          • 2. Re: ClassLoader Issue
            stevecoh2 Newbie

            I see people reading this thread but can someone please ANSWER? This is a serious problem and I need some guidance.

            I need
            1) assurance, if someone can give it to me, that replacing HttpClient in JBoss 3.2.1 with a more recent version is possible or assurance that it won't work

            OR

            2) more information on how to get the newer version of HttpClient to load within my application without affecting the entire classloading scheme of JBoss. The JBoss wiki docs on this are insufficient for this purpose.

            Can't someone offer some assistance here? Thanks.

            • 3. Re: ClassLoader Issue
              Raja Master

              Upgrading the Jboss libs should definitely work. If thats not a solution for you, you can try scoped classloading where classes in ur Archive file gets loaded in a separate classloader. There are docs in the "Getting Started" manual about scoped class loading.

              • 4. Re: ClassLoader Issue
                stevecoh2 Newbie

                Thanks for getting back to me, raja05

                I asked the same question on the HttpClient mailing list and got the opposite reply - they were highly doubtful that this would work. Their recommendation was simply to repackage their source code, changing the root package name and storing this jar with our application libraries instead of the regular one.

                However, if you are part of the jboss team, you may know more about this than they do. May I ask if you are part of the jboss team?

                I've looked in the Getting started manual for 3.2.x and find nothing under class loading, classloading or classloader. Are you sure that's where the documentation is? I did find lots of documentation on this subject JBoss Admin Guide, which I found confusing.

                Here's what I'd like to be able to do: without changing global classloading policies either on the server or globally within my application, say to JBoss,
                "when you see any application code in a subpackage of org.apache.commons.httpclient, load this class from WEB-INF/lib, not from the parent classloader. Is this possible, and if so, can you point me to some sample configuration where this is done?

                Thanks.

                • 5. Re: ClassLoader Issue
                  jaikiran pai Master

                  You can package the jar in your own application and have a different Classloader for your application, so that your application uses this jar.
                  Please have a look at:

                  http://wiki.jboss.org/wiki/Wiki.jsp?page=JBossClassLoadingUseCases

                  • 6. Re: ClassLoader Issue
                    stevecoh2 Newbie

                    Thanks jaikiran.

                    This is helpful documentation.

                    However, it doesn't appear to fully explain my situation. My situation is basically that which is labelled "Case 2":

                    Case 2. The Utility.class is present both in the application's archive AND server/default/lib. The deployment is non-scoped.

                    The short story: The version of the class available in server/default/lib/utility.jar will be used by the new deployment. The version of the class packed with the deployment will be ignored.

                    That is in fact what is happening. But the result of this loading is that I get an IncompatibleClassChangeError.

                    Now, my situation possibly differs from case 2 in one respect. My deployment archive is a WAR file, not an application (ear) file. The document goes on to list WAR file deployment as a TODO.

                    I am thinking I could possibly solve this by using scoped class loading. Is that what you are thinking?

                    If so, would this be the correct syntax?

                    <jboss-web>
                    <class-loading>
                    <loader-repository>
                    org.apache.commons.httpclient:loader=my.war
                    </loader-repository>
                    </class-loading>
                    </jboss-web>

                    In this example "my.war" is the war file for which this fragment is the jboss descriptor. If this is not correct, what is the correct way to do this?

                    • 7. Re: ClassLoader Issue
                      jaikiran pai Master

                      Ya, i think you will have to go for scoped class loading for your application. You will find the syntax for the same, here:

                      http://wiki.jboss.org/wiki/Wiki.jsp?page=ClassLoadingConfiguration

                      • 8. Re: ClassLoader Issue
                        jaikiran pai Master

                        Briefly, your jboss-web.xml will be:

                        <jboss-web>
                         <class-loading>
                         <loader-repository>
                         dot.com:loader=unique-archive-name
                         </loader-repository>
                         </class-loading>
                        </jboss-web>


                        The dot.com:loader=unique-archive-name are JMX ObjectName strings that have no significance other than that they must be unique to ensure unique class loading scopes. It might be useful to use the same name as used for the EAR/WAR-file.





                        • 9. Re: ClassLoader Issue
                          stevecoh2 Newbie

                          thanks, janakiran.

                          You are very helpful. I want to get completely clear, however. jboss-web.xml would be deployed inside my.war. Will the jboss class-loading mechanism still be able to find it since this fragment is pointing at the same war in which it is deployed.

                          Can you please confirm that the syntax I proposed in my previous message is correct, or at least, has no obvious flaw?

                          • 10. Re: ClassLoader Issue
                            jaikiran pai Master

                             

                            <jboss-web>
                             <class-loading>
                             <loader-repository>
                             noSpecificMeaning.anything:loader=anyName.anything </loader-repository>
                             </class-loading>
                            </jboss-web>


                            This should work


                            • 11. Re: ClassLoader Issue
                              stevecoh2 Newbie

                              The syntax I proposed worked.

                              I guess I still have questions about what you've written though, in trying to understand.

                              You have suggested as the contents of <loader-repositor> the sample string

                              noSpecificMeaning.anything:loader=anyName.anything

                              This implies that there is no meaning to any of the strings. Yet this makes no sense whatsoever. How could meaningless.string.1:loader=meangless.string.2 do anything useful at all?

                              I would assume that there is syntax and meaning to both sides of the equal sign:

                              x.y.z:loader=my.war

                              I would have assumed that this meant:

                              The loader for package x.y.z (and its subpackages) is to be found in the archive designated with the name my.war.

                              However your post contained this quote:


                              The dot.com:loader=unique-archive-name are JMX ObjectName strings that have no significance other than that they must be unique to ensure unique class loading scopes. It might be useful to use the same name as used for the EAR/WAR-file.


                              which indicates there is no necessary mapping to the war name, but that this is a way of ensuring a unique scope, different from others, for that package.

                              But if the text to the left of :loader does not mean the name of a package, what DOES it signify? Then we are entering bizarro world, where an entirely arbitrary string causes the correct classloader to be used.

                              It seems clear that more and better documentation would be useful.

                              • 12. Re: ClassLoader Issue
                                jaikiran pai Master

                                 

                                noSpecificMeaning.anything:loader=anyName.anything


                                will be used as a JMX ObjectName. To know more about the same, please take a look at:

                                Section "The ObjectName Class" at:

                                http://www.developer.com/java/other/article.php/10936_2212031_6

                                • 13. Re: ClassLoader Issue
                                  stevecoh2 Newbie

                                  OK. That explains what a JMX Object Name is.

                                  But I still want to understand how this works and I'm not clear on the concept yet.

                                  1) Do I have to write MBean code to create a class loader to do my specific loading or is there already an MBean in existence that handles classloading according to some already defined scheme? IN other words, does the presence of a <loader-repository> element properly formed in your jboss-web.xml file automatically cause a change in class loading for your application? I presume so since putting an entry into my jboss-web.xml solved my problem.

                                  2) Assuming that there already is a class-loading MBean, does this particular MBean work by associating the domain in the JMX object name with a package root? For example, suppose I want to have scoped class loading for the packages rooted at com.foo.bar and com.higgledy.piggledy but only for those two packages. What would my jboss-web.xml then look like?

                                  • 14. Re: ClassLoader Issue
                                    jaikiran pai Master

                                     

                                    "stevecoh2" wrote:

                                    1) Do I have to write MBean code to create a class loader to do my specific loading or is there already an MBean in existence that handles classloading according to some already defined scheme? IN other words, does the presence of a <loader-repository> element properly formed in your jboss-web.xml file automatically cause a change in class loading for your application? I presume so since putting an entry into my jboss-web.xml solved my problem.


                                    You do not have to write a MBean for having a classloader for your application. You are right, the presence of a <loader-repository> element properly formed in your jboss-web.xml file automatically cause a change in class loading for your application.

                                    "stevecoh2" wrote:

                                    2) Assuming that there already is a class-loading MBean, does this particular MBean work by associating the domain in the JMX object name with a package root? For example, suppose I want to have scoped class loading for the packages rooted at com.foo.bar and com.higgledy.piggledy but only for those two packages. What would my jboss-web.xml then look like?


                                    You are defining a classloader for your APPLICATION and NOT for a specific package. So whenver a class has to be loaded in your application, the classloader specified by you for the application will be used.


                                    1 2 Previous Next