4 Replies Latest reply on Jul 25, 2009 12:27 AM by jason.greene

    JBAS-7032 or ClassLoader::getResources

    alesj

      Moving this discussion to the forum.

      "jaikiran" wrote:

      I could reproduce this issue:

      1) Deploy an non-scoped/non-isolated Seam Ear application in 5.1.0 AS
      2) Start the server which has the admin console
      3) Access the admin console http://localhost:8080/admin-console

      09:28:24,728 ERROR [[/admin-console]] Exception sending request initialized lifecycle event to listener instance of class org.jboss.on.embedded.LazyStartupListener
      java.lang.RuntimeException: error while reading /WEB-INF/components.xml
      at org.jboss.seam.init.Initialization.initComponentsFromXmlDocument(Initialization.java:221)
      at org.jboss.seam.init.Initialization.create(Initialization.java:124)
      at org.jboss.seam.servlet.SeamListener.contextInitialized(SeamListener.java:34)
      at org.jboss.on.embedded.LazyStartupListener.initialize(LazyStartupListener.java:182)
      at org.jboss.on.embedded.LazyStartupListener.requestInitialized(LazyStartupListener.java:240)
      at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:180)
      at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:190)
      at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:92)
      at org.jboss.web.tomcat.security.SecurityContextEstablishmentValve.process(SecurityContextEstablishmentValve.java:126)
      at org.jboss.web.tomcat.security.SecurityContextEstablishmentValve.invoke(SecurityContextEstablishmentValve.java:70)
      at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
      at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
      at org.jboss.web.tomcat.service.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:158)
      at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
      at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:330)
      at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:829)
      at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:598)
      at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
      at java.lang.Thread.run(Thread.java:595)
      Caused by: java.lang.RuntimeException: Error loading element Identity with component name null and component class null
      at org.jboss.seam.init.Initialization.installComponentsFromXmlElements(Initialization.java:342)
      at org.jboss.seam.init.Initialization.initComponentsFromXmlDocument(Initialization.java:217)
      ... 18 more


      A bit of debugging shows that the real issue appears to be the way BaseClassLoaderDomain.getResources is implemented:

      void getResources(BaseClassLoader classLoader, String name, Set<URL> urls, boolean allExports) throws IOException
      {
      1) beforeGetResources()
      2) GetResourcesFromTheClassloader()
      3) GetResourcesFromTheParentClassloader()
      }


      This method behaves unlike the getResource() method which returns immidiately after finding the resource from the first classloader which has access to the resource. The getResources() on the other hand pulls out the resource URLs from *all* the classloaders in the hierarchy and their exports.

      So in this scenario when the admin-console is being processed and a request for META-INF/components.xml is made from within this app's classloader:

      1) Finds the META-INF/components.xml within the jar(s) of this admin-console.war
      2) Goes to the parent of this admin-console.war classloader which exposes META-INF/components.xml available in the non-scoped/non-isolated Seam EAR.
      3) Effectively, this returns a list of URLs from different (unrelated) applications and messes up the admin console


      From my understanding of the semantics of Classloader.getResources(String name) and the javadoc, i think the BaseClassLoaderDomain.getResources(BaseClassLoader cl, String name, Set<URL>urls, boolean allExp) is probably incorrect.

      As an workaround, i think we should probably set the EAR deployments to be isolated by default. That way we won't have a broken admin-console when some other user application with Seam does not isolate their app.

      P.S: There's one more issue i see with the handling of jboss-classloading.xml/jboss-web.xml classloading scoping for war deployments. But i will create a separate thread for that.


        • 1. Re: JBAS-7032 or ClassLoader::getResources
          jaikiran

          To make this more generic, this issue isn't specific to Seam. If there are 2 applications (one of it non-scoped/non-isolated) and the other application is isolated and if the isolated application invokes getResources(resourceName) on the classloader then it will end up getting resources from the non-isolated classloader too (which looks incorrect).

          • 2. Re: JBAS-7032 or ClassLoader::getResources
            ssilvert

            So how does the resource become available to getResources(resourceName)?

            In the case of Seam/Webbeans faces-config.xml, this is added to the classpath by a deployer, right?

            Can't the deployer make the resource available to the web classloader as if it were packaged with the WAR? That would fix the problem no matter how isolation is set.

            Stan

            • 3. Re: JBAS-7032 or ClassLoader::getResources
              alesj

               

              "stan.silvert@jboss.com" wrote:

              Can't the deployer make the resource available to the web classloader as if it were packaged with the WAR? That would fix the problem no matter how isolation is set.

              That's how I fixed it now in the WB-ri-int trunk.
              Can you check if that really solves the problem?

              • 4. Re: JBAS-7032 or ClassLoader::getResources
                jason.greene

                 

                "jaikiran" wrote:

                From my understanding of the semantics of Classloader.getResources(String name) and the javadoc, i think the BaseClassLoaderDomain.getResources(BaseClassLoader cl, String name, Set<URL>urls, boolean allExp) is probably incorrect.


                This is the correct behavior; getResources is supposed to pull from all "parent" classloaders, which in our domain model is the entire domain.