1 2 Previous Next 18 Replies Latest reply on Dec 2, 2010 1:12 AM by ohmygod

    JBossXB should swap out the Context ClassLoader before initi

    rodos77

      Please refer to the following discussion for a detailed description of the problem:

      http://www.jboss.org/index.html?module=bb&op=viewtopic&t=158645

      The problem is caused by the fact that at the time of xerces parser initialization, the context classloader is set to the war classloader while the current classloader is the deployer classloader. This leads to a ClassCastException because the various xerces classes are loaded by the 2 different classloaders mentioned.

      The solution is for JBossXB to set the context classloader to the current classloader before initializing xerces and then to restore the context classloader to its old value after the initialization is completed.

      I've seen numerous posts about this issue in the forums and none of the workarounds offered resolve the underlying problem. The solution must allow a war to bundle and use it's own version of the xerces jars without causing the app server to throw ClassCastExceptions.

        • 1. Re: JBossXB should swap out the Context ClassLoader before i

          We are currently in the process of evaluating the migration of our application from JBoss 4.x to JBoss 5.1.0.GA and are experiencing what seems to be the same issue. The only way we have been able to get around this problem is to disable the WarClassLoaderDeployer (by commenting it out in war-deployers-jboss-beans.xml), however, this is not an ideal workaround. Any help would be appreciated.

          • 2. Re: JBossXB should swap out the Context ClassLoader before i
            rodos77

             

            "pfrontiero" wrote:
            The only way we have been able to get around this problem is to disable the WarClassLoaderDeployer (by commenting it out in war-deployers-jboss-beans.xml), however, this is not an ideal workaround.


            If you application depends on using the version of xerces included in your war, this approach will not work as it essentially forces your app to use the xerces bundled with JBoss. If you're going to use this approach, you may as well just remove the xercesImpl.jar from your war. This way you will at least keep the war classloader isolation for yours, and other apps on the server.

            The other way to achieve the same result as with your approach is to use jboss-classloading.xml and set parent-first=true as specified in the linked post above. But again, this will change the standard servlet spec classloading semantics and will still not allow you to use your xerces version.

            • 3. Re: JBossXB should swap out the Context ClassLoader before i
              aloubyansky

              org.apache.xerces.xni.parser.XMLParserConfiguration in this case is loaded by the bootstrap classloader.

              I am not sure whether it should be fixed in XB. It is supposed to work with the context classloader, which is what XB is doing. I'd think this is a deployers issue. Other opinions?

              • 4. Re: JBossXB should swap out the Context ClassLoader before i
                aloubyansky

                BTW, if I do set the context classloader to the current one in XB before creating the parser and re-setting it back right after that, the WAR still fails to deploy with

                15:30:31,315 ERROR [org.apache.catalina.startup.TldConfig] Exception processing JAR at resource path C:\Users\avoka\svn.jboss.org\jbossas\trunk\build\
                output\jboss-6.0.0.Alpha1\server\default\tmp\abc3-lk3pm-fyk3ox7w-1-fyk3pue5-9p\nexj-web.war\WEB-INF\lib\xercesImpl.jar in context /nexj-web: java.io.F
                ileNotFoundException: C:\Users\avoka\svn.jboss.org\jbossas\trunk\build\output\jboss-6.0.0.Alpha1\server\default\tmp\abc3-lk3pm-fyk3ox7w-1-fyk3pue5-9p\
                nexj-web.war\WEB-INF\lib\xercesImpl.jar (Access is denied)
                 at java.util.zip.ZipFile.open(Native Method)
                 at java.util.zip.ZipFile.<init>(ZipFile.java:203)
                 at java.util.jar.JarFile.<init>(JarFile.java:132)
                 at java.util.jar.JarFile.<init>(JarFile.java:97)
                 at org.apache.catalina.startup.TldConfig.tldScanJar(TldConfig.java:461)
                 at org.apache.catalina.startup.TldConfig.execute(TldConfig.java:301)
                 at org.apache.catalina.core.StandardContext.processTlds(StandardContext.java:4540)
                 at org.apache.catalina.core.StandardContext.start(StandardContext.java:4308)
                 at org.jboss.web.tomcat.service.deployers.TomcatDeployment.performDeployInternal(TomcatDeployment.java:310)
                 at org.jboss.web.tomcat.service.deployers.TomcatDeployment.performDeploy(TomcatDeployment.java:142)
                 at org.jboss.web.deployers.AbstractWarDeployment.start(AbstractWarDeployment.java:462)
                 at org.jboss.web.deployers.WebModule.startModule(WebModule.java:116)
                 at org.jboss.web.deployers.WebModule.start(WebModule.java:95)


                • 5. Re: JBossXB should swap out the Context ClassLoader before i

                  I actually had a couple of issues during startup which seem to be a result of the classloader changes in 5.1.0.GA:

                  1. Caused by: java.lang.LinkageError: loader constraint violation: when resolving method "javax.xml.parsers.DocumentBuilder.setEntityResolver(Lorg/xml/sax/EntityResolver;)V" the class loader (instance of org/jboss/classloader/spi/base/BaseClassLoader) of the current class, org/springframework/beans/factory/xml/DefaultDocumentLoader, and the class loader (instance of ) for resolved class, javax/xml/parsers/DocumentBuilder, have different Class objects for the type org/xml/sax/EntityResolver used in the signature

                  Our web app is deployed is as follows:

                  default
                  /lib
                  saxon.jar
                  /deploy
                  /app.ear
                  /app.war

                  In order to resolve this issue (without disabling the WarClassLoaderDeployer) I had to copy saxon.jar to the WEB-INF/lib directory of app.war. If I moved it, I received other ClassNotFoundExceptions during startup. Not sure why this would be.

                  2. Caused by: java.lang.ClassCastException: org.apache.xerces.jaxp.DocumentBuilderFactoryImpl cannot be cast to javax.xml.parsers.DocumentBuilderFactory

                  This is the error which lead me to this forum posting. We do not have xercesImpl as part of our app, only saxon.jar, which I moved there in order to get past the first issue.

                  • 6. Re: JBossXB should swap out the Context ClassLoader before i
                    rodos77

                    I also think this is a deployer issue which is why I posted this problem in that forum first, however, the deployer guys are saying this is a JBossXB issue.

                    All I know is that this needs to get resolved. Any ideas on how to decide this and to stop passing the buck around? I don't know what the JBoss process is for dealing with this but can this perhaps be escalated or something like that? Perhaps a JIRA can be created that will eventually be assigned to the right person?

                    In my opinion, this is a somewhat of a serious issue and there are now more and more posts on the forums about it.

                    • 7. Re: JBossXB should swap out the Context ClassLoader before i
                      aloubyansky

                      You've done everything right reporting the issue. We are going to discuss it here.

                      • 8. Re: JBossXB should swap out the Context ClassLoader before i
                        rodos77

                        Ok, I've created 2 patches for swapping out the context classloader. One for a class in the jbossweb project and one for a class in the JBossXB project. Either patch, when applied to the corresponding project, resolves the issue. You can now decide in which project it is more appropriate to fix this issue and apply the patch to the corresponding source repository to resolve this once and for all.

                        JBossXB patch:

                        *** orig\org\jboss\xb\binding\UnmarshallerFactory.java 2009-04-19 20:18:06.000000000 -0400
                        --- new\org\jboss\xb\binding\UnmarshallerFactory.java 2009-08-19 12:13:34.345631600 -0400
                        ***************
                        *** 90,95 ****
                        --- 90,98 ----
                         {
                         public Unmarshaller newUnmarshaller()
                         {
                        + ClassLoader oldCl = Thread.currentThread().getContextClassLoader();
                        + Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
                        +
                         UnmarshallerImpl unmarshaller;
                         try
                         {
                        ***************
                        *** 99,104 ****
                        --- 102,111 ----
                         {
                         throw new JBossXBRuntimeException(e.getMessage(), e);
                         }
                        + finally
                        + {
                        + Thread.currentThread().setContextClassLoader(oldCl);
                        + }
                        
                         JBossXBParser parser = unmarshaller.getParser();
                         if(validation != null)
                        
                        


                        jbossweb patch:
                        *** orig\org\jboss\web\tomcat\service\deployers\JBossContextConfig.java 2009-05-22 09:10:46.000000000 -0400
                        --- new\org\jboss\web\tomcat\service\deployers\JBossContextConfig.java 2009-08-19 12:32:46.517506600 -0400
                        ***************
                        *** 542,547 ****
                        --- 542,550 ----
                        
                         protected void processContextConfig(String resourceName, boolean local)
                         {
                        + ClassLoader oldCl = Thread.currentThread().getContextClassLoader();
                        + Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
                        +
                         ContextMetaData contextMetaData = null;
                         try
                         {
                        ***************
                        *** 593,598 ****
                        --- 596,605 ----
                         ok = false;
                         return;
                         }
                        + finally
                        + {
                        + Thread.currentThread().setContextClassLoader(oldCl);
                        + }
                        
                         if (contextMetaData != null)
                         {
                        


                        • 9. Re: JBossXB should swap out the Context ClassLoader before i
                          jaikiran

                           

                          "rodos77" wrote:
                          I also think this is a deployer issue which is why I posted this problem in that forum first, however, the deployer guys are saying this is a JBossXB issue.


                          If you are referring to me, then i am not a deployer guy :) I was just curious so started looking into it, given the number of users reporting it.

                          "alex.loubyansky@jboss.com" wrote:
                          I'd think this is a deployers issue. Other opinions?


                          Ales might know better. But since i have spent some time looking into this, i'll update this thread later tomorrow with the details (sorry, can't do it now because i don't have access to the system where i tried this).


                          • 10. Re: JBossXB should swap out the Context ClassLoader before i
                            aloubyansky

                            I pinged Ales. He's enjoying his vacation at the moment and we'll be back in business on Monday.

                            • 11. Re: JBossXB should swap out the Context ClassLoader before i
                              alesj

                              I guess if there is no explicit CL passed, XB should work on top of TCCL. (which is what it is doing now)

                              The question is why this behavior was changed in war deployer?
                              I'll try to track down the "culprit" that changed this, and see if there is some reason behind it.

                              • 12. Re: JBossXB should swap out the Context ClassLoader before i
                                alesj

                                 

                                "alesj" wrote:

                                The question is why this behavior was changed in war deployer?
                                I'll try to track down the "culprit" that changed this, and see if there is some reason behind it.

                                Found this:
                                - http://fisheye.jboss.org/browse/JBossAS/branches/Branch_5_x/server/src/main/org/jboss/web/deployers/AbstractWarDeployment.java?r=57669

                                Looks like a port from some old code I cannot trace or it could be even brand new.
                                I'll ping Scott for some answers. :-)

                                • 13. Re: JBossXB should swap out the Context ClassLoader before i
                                  starksm64

                                  The AbstractWarDeployment code is a port of old 4.x code to the new deployment framework. When this was done, the unit class loader was supposed to be the class loader as configured by the class loading deployers. What is the difference between the unit class loader and the class loader for the JBossContextConfig class? These both should be the war class loader. I'll take a look at the nexj-web.war rodos77 posted to see what the conflicting class loaders are.

                                  • 14. Re: JBossXB should swap out the Context ClassLoader before i
                                    starksm64

                                    The issue is classes loaded by the jbossweb.sar class loader interacting with factories that make use of the tccl need to reset the tccl to avoid mixing classes visible to the app.

                                    Part of the issue is that the war deployment is initiating the creation of the war application classes in its start and this is what the tccl is set to the war deployment class loader. Finishing the migration to mc beans should improve this. The parsing of the metadata should also have happened before the application is being started.

                                    The best workaround in the meantime does look to be setting/clearing the tccl as proposed by rodos77.

                                    1 2 Previous Next