1 2 3 Previous Next 68 Replies Latest reply on Apr 17, 2012 8:54 AM by alesj

    How to stop my WAR loading JBoss's provided 3rd party classes?

    jroyals

      Hi folks,

       

      I'd like more control over the class loader so that I can  specify classes to ignore if they are provided outside of my web  application. Is there a way to tell my application's class loader to NOT delegate to the parent for a named list of packages or jars?

       

      For example, if I don't package Hibernate in my WAR and some class attempts to load org.hibernate.SessionFactory, I want a ClassNotFoundException (or similar). I do not want it loading the Hibernate classes from the jar's currently in common/lib.

       

      Constraints are I cannot delete or modify any jars in /common/lib, so I need a different way (maybe jboss-web.xml or jboss-classloader.xml or something) to stop it happening. Is it possible?

       

      Thanks,

      Jason

        • 1. Re: How to stop my WAR loading JBoss's provided 3rd party classes?
          alesj

          This is certainly possible, but unfortunately not completely out-of-the-box aka via configuration.

           

          What you need to do is the following:

          * create new cl domain for your deployment -- can be done via jboss-classloading.xml

          * set default cl domain as your parent cl domain -- can be done via jboss-classloading.xml

          * create parent policy for Module which sets your excludes -- needs some deployer / programmatic

           

          This probably means you would have to create a new deployer which would create custom Module - to override the getDeterminedParentPolicy,

          which would disable the usage of VFSClassLoaderDescribeDeployer --> your similar deployer should kick in.

           

          You can have a crack at it, but let me know if you get stuck, and I'll help you.

          • 2. Re: How to stop my WAR loading JBoss's provided 3rd party classes?
            jroyals

            Thanks Ales, will have a go at it once I'm back from leave.

             

            Cheers,

            Jason

            • 3. Re: How to stop my WAR loading JBoss's provided 3rd party classes?
              manosgeo

              Hi Ales,

              I am facing the same problem with Jason, trying to isolate my web app against the common/lib jars (in JBoss 5.1.0.GA).

              Could you please explain in more detail the third step of your suggested solution?

              Is there any documentation about creating a custom deployer in Jboss 5?

              And also, if i understood correct, should I use this custom deployer for deploying my war (this implies that the TomcatDeployer will not be used?)

               

              Thank you in advance,

              Manos

              • 4. Re: How to stop my WAR loading JBoss's provided 3rd party classes?
                alesj
                Could you please explain in more detail the third step of your suggested solution?

                I'll add this functionality to Deployers trunk asap -- declarative way to create new domains.

                It should be portable to other Deployers versions as well.

                Is there any documentation about creating a custom deployer in Jboss 5?

                * http://java.dzone.com/articles/jboss-microcontainer-virtual-deployment-framework

                 

                And also, if i understood correct, should I use this custom deployer for deploying my war (this implies that the TomcatDeployer will not be used?)

                Deployers in AS5/MC work differently -- read the article to get a better insight.

                It's a chain of deployers, not just a single deployer, hence TomcatDeployer will still kick in.

                • 5. Re: How to stop my WAR loading JBoss's provided 3rd party classes?
                  manosgeo

                  Thanks a million Ales

                  • 6. Re: How to stop my WAR loading JBoss's provided 3rd party classes?
                    alesj

                    OK, just commited changes to AS6_trunk which enable this behavior.

                    The new file is jboss-classloading-domain.xml, e.g.:

                    * http://anonsvn.jboss.org/repos/jbossas/projects/jboss-deployers/trunk/deployers-vfs/src/test/resources/classloading/domain/META-INF/jboss-classloading-domain.xml

                    • 7. Re: How to stop my WAR loading JBoss's provided 3rd party classes?
                      dskiles

                      Is there any documentation on how the jboss-classloading-domain.xml file?  I'm running into a similar situation with CXF in 6.0.0.CR1 and I'd like to give this a try.

                      • 8. Re: How to stop my WAR loading JBoss's provided 3rd party classes?
                        alesj
                        Is there any documentation on how the jboss-classloading-domain.xml file?  I'm running into a similar situation with CXF in 6.0.0.CR1 and I'd like to give this a try.

                        No particular docs, as the usage is quite simple.

                        Simply drop properly configured jboss-classloading-domain.xml file into your app's META-INF and it should work.

                         

                        These two code snippest show how parent policy gets created.

                        (which is what filters cl lookups between cl domains)

                         

                        public ParentPolicy createParentPolicy()
                           {
                              if (parentPolicy == null)
                              {
                                 if (name != null)
                                 {
                                    String upper = name.toUpperCase();
                                    try
                                    {
                                       Field instance = ParentPolicy.class.getField(upper);
                                       parentPolicy = (ParentPolicy) instance.get(null);
                                    }
                                    catch (Throwable t)
                                    {
                                       throw new RuntimeException("Cannot create parent-policy, wrong name perhaps? - " + name, t);
                                    }
                                 }
                                 else
                                 {
                                    ClassFilter before = (beforeFilter != null) ? beforeFilter.createFilter() : ClassFilterUtils.EVERYTHING;
                                    ClassFilter after = (afterFilter != null) ? afterFilter.createFilter() : ClassFilterUtils.NOTHING;
                                    parentPolicy = new ParentPolicy(before, after, description);
                                 }
                              }
                              return parentPolicy;
                           }

                         

                        public ClassFilter createFilter()
                           {
                              // perhaps it's JavaBean
                              if (value instanceof ClassFilter)
                              {
                                 return (ClassFilter) value;
                              }
                              else
                              {
                                 try
                                 {
                                    Class<?> clazz = getClass().getClassLoader().loadClass(filterClassName);
                                    Constructor<?> ctor = (value != null) ? clazz.getDeclaredConstructor(value.getClass()) : clazz.getDeclaredConstructor();
                                    return (ClassFilter) ctor.newInstance(value);
                                 }
                                 catch (Throwable t)
                                 {
                                    throw new RuntimeException("Cannot instantiate filter: " + filterClassName + " / " + value, t);
                                 }
                              }
                           }

                         

                        By default the filterClassName is PackageClassFilter.class.getName().

                         

                        Let me know if you need some more help.

                        • 9. Re: How to stop my WAR loading JBoss's provided 3rd party classes?
                          dskiles

                          Wow, thanks for the quick response.

                           

                          What I'd like to do is exclude the application server's 1.0.com.sun.codemodel package (from jaxb-xjc.jar) from the classpath for my application and use the one that is bundled in my library path instead.  Do I put that package in the before-filter or after-filter element?

                          • 10. Re: How to stop my WAR loading JBoss's provided 3rd party classes?
                            alesj
                            What I'd like to do is exclude the application server's 1.0.com.sun.codemodel package (from jaxb-xjc.jar) from the classpath for my application and use the one that is bundled in my library path instead.  Do I put that package in the before-filter or after-filter element?

                            You need something like this:

                             

                            <?xml version="1.0" encoding="UTF-8"?>

                             

                            <classloading-domain xmlns="urn:jboss:classloading-domain:1.0" name="your-domain-name">
                               <parent-policy>
                                  <before-filter>
                                     <javabean xmlns="urn:jboss:javabean:2.0" class="org.jboss.classloader.plugins.filter.NegatingClassFilter">
                                        <constructor>
                                           <parameter>
                                              <javabean xmlns="urn:jboss:javabean:2.0" class="org.jboss.classloader.spi.filter.PackageClassFilter">
                                                 <constructor>
                                                    <parameter>1.0.com.sun.codemodel</parameter>
                                                 </constructor>
                                              </javabean>
                                           </parameter>
                                        </constructor>
                                     </javabean>
                                  </before-filter>
                               </parent-policy>
                            </classloading-domain>

                            • 11. Re: How to stop my WAR loading JBoss's provided 3rd party classes?
                              dskiles

                              Thanks for the information.  I gave that a try with no luck.

                               

                              The root problem, I think, is that I'm trying to use an older version of CXF for my application than what comes bundled with JBoss AS by default in 6.0.  We can't really upgrade CXF yet and removing it from the app isn't really a possibility due to the fact that it needs to function on multiple application containers.

                               

                              For kicks I also tried org.apache.cxf with no luck.  Am I missing something obvious here?  I've already sidestepped a few issues with the jboss-classloading.xml classloader config, but this one doesn't want to go away.  I've included the stack trace below.

                               


                              Caused by: java.lang.RuntimeException: Error visiting resource: VFSResourceContext @ 1.0/com/sun/codemodel/JConditional.class / BaseClassLoader@66c9153e{vfs:///C:/jboss6/server/default/deploy/warname.war}, visitor: org.jboss.scanning.hierarchy.plugins.HierarchyTypeVisitor@1ec375d4
                                      at org.jboss.scanning.plugins.visitor.IgnoreSetErrorHandler.handleError(IgnoreSetErrorHandler.java:56) [:1.0.0.Alpha7]
                                      at org.jboss.scanning.plugins.visitor.ReflectResourceVisitor.visit(ReflectResourceVisitor.java:91) [:1.0.0.Alpha7]
                                      at org.jboss.scanning.hierarchy.plugins.HierarchyIndexScanningPlugin.visit(HierarchyIndexScanningPlugin.java:91) [:1.0.0.Alpha7]
                                      at org.jboss.scanning.spi.helpers.ScanningPluginWrapper.visit(ScanningPluginWrapper.java:112) [:1.0.0.Alpha7]
                                      at org.jboss.classloading.plugins.visitor.FederatedResourceVisitor.visit(FederatedResourceVisitor.java:101) [jboss-classloading.jar:2.2.0.Alpha9]
                                      at org.jboss.classloading.plugins.vfs.VFSResourceVisitor.visit(VFSResourceVisitor.java:264) [jboss-classloading-vfs.jar:2.2.0.Alpha9]
                                      ... 55 more
                              Caused by: java.lang.ClassNotFoundException: 1.0.com.sun.codemodel.JConditional
                                      at java.net.URLClassLoader$1.run(URLClassLoader.java:202) [:1.6.0_18]
                                      at java.security.AccessController.doPrivileged(Native Method) [:1.6.0_18]

                              • 12. Re: How to stop my WAR loading JBoss's provided 3rd party classes?
                                alesj

                                Hmmm, since you're using .war, your resoources should already come in first -- by the spec.

                                 

                                Since you're actually only filtering a single package,

                                the rest of the stuff still goes to JBoss' CXF version.

                                Which is probably bound to endup in failure due to mix&match. :-)

                                 

                                The idea for this domain xml is that you filter all of the lib also included in JBoss.

                                Dunno if this is the case with you.

                                 

                                You can actually ignore this error with ignoreSet in jboss-scanning-deployers-beans.xml.

                                But this is probably not the right thing to do.

                                • 13. Re: How to stop my WAR loading JBoss's provided 3rd party classes?
                                  dskiles

                                  How would I filter out all jboss libraries?

                                  • 14. Re: How to stop my WAR loading JBoss's provided 3rd party classes?
                                    alesj
                                    How would I filter out all jboss libraries?

                                    What we currently "said" with this config is the following:

                                    * if the package isn't 1.0.com.sun.codemodel, go and look into parent domain

                                    * else don't go into parent domain, only look at my domain (resources)

                                     

                                    e.g. if I wanted to use own Hibernate lib from my jar, I would filter on all org.hibernate.* packages.

                                    (hopefully the Hibernate lib is properly packaged, and doesn't have any classes outside org.hibernate :-))

                                    1 2 3 Previous Next