0 Replies Latest reply on Feb 12, 2009 7:48 AM by nvtmorch

    Loading taglibs of EAR

    nvtmorch Newbie

      Hi,

      First my environment:
      Java: 1.5.0_16
      JBoss Application Server: 4.0.5.GA (but the Problem seems to be present in 4.2 and 5.0 too)

      I'm facing a problem during packaging some WAR archives into an EAR, moving the depending libraries into the EAR and add them to the appropriate MANIFEST.MF.

      But now the server does not find the tld's. We are using Maven and don't want to put the tld's into the WEB-INF and web.xml since this would break the dependency management of maven. The server should find the tld's within the jars in the META-INF folder. This works perfectly if the jars are stored in WEB-INF/lib. But we don't want duplicate jars in multiple WAR archives. The exact goal of an EAR.

      So I looked into the sources code. And I think I found the Problem, but I'm not sure if the current behavior is the expected or this is a bug. So here is what I found:

      In deploy\jbossweb-tomcat55.sar\conf\web.xml you set 'engineOptionsClass' to 'org.jboss.web.tomcat.tc5.jasper.JspServletOptions' (with jBoss 4.2 the package changed, but the file seems to be the same). This class uses 'org.jboss.web.tomcat.tc5.jasper.TagLibCache' to search for TLDs. TagLibCache is derived from the Tomcat default class TldLocationsCache. The Tomcat version searches the classpath for jar's with tld's but the jboss version does not. Both are seaching in web.xml and the file system below WEB-INF.
      The getLocation method of jboss only looks into his own map. If the super method wold be called too, you could save work in your implementation and the class path would be considered too.
      The method may be look like this:

       public String[] getLocation(String uri) throws JasperException
       {
       if (mappings == null)
       init();
       String[] locations = (String[]) mappings.get(uri);
       if (locations == null){ // new
       locations = super.getLocation(uri); // new
       } // new
       return locations;
       }
      


      But unfortunately this does not work ether. The next problem is the ClassLoader. The appropriate ClassLoader is the UnifiedClassLoader3 and his super classes RepositoryClassLoader and URLClassLoader. Within URLClassLoader there is this member ucp, which has URLs to the JARs we are looking for. TldLocationsCache uses URLClassLoader.getURLs() to get the URLs. Nearly perfect! But RepositoryClassLoader overrides this method and returns an empty array. The comment says:
       /**
       * Return an empty URL array to force the RMI marshalling subsystem to
       * use the <tt>java.server.codebase</tt> property as the annotated codebase.
       *
      

      So TldLocationsCache can't get the URLs to the JARs in EAR and can't find the tlds.

      On this point I stopped digging into the code. The questions left for me are: Why does RepositoryClassLoader override getURLs()? Is it possible to get the URLs in a different way? In my opinion jboss should be able to load TLDs from JARs within the EAR.

      I would be pleased about your opinion on the problem.

      Thanks.