3 Replies Latest reply on Jul 29, 2013 9:24 AM by Matt Jensen

    AS 7: Excluding a container library from WAR classpath

    Matt Jensen Newbie

      Hello, I've been digging on this one for several hours to no avail.  The problem I'm having is that I have a legacy WAR that I need to deploy within AS 7.1, and the WAR is a Cocoon-based app.  Cocoon (apparently) uses Eclipse JDT to do its thing, but AS 7 is exposing a version of JDT (via the "org.jboss.as.web" module) which is not compatible with the version of Cocoon in the WAR.  It's the typical classloader nuttiness that we've all been dealing with for a decade or more now--a NoSuchMethodError in this particular case.  But the cause is the classic "wrong version of library on the classpath" issue.

       

      For the life of me, I cannot figure out how to get AS 7 to keep its version of JDT to itself and not expose it to the web app (which is deployed as a standalone WAR--it is not packaged in an EAR file.)

       

      I have tried many, many different combinations of things in jboss-deployment-structure.xml, using the 1.2 schema.  The documentation at https://docs.jboss.org/author/display/AS71/Class+Loading+in+AS7 seems to imply that something like this would be correct (derived from the chuck on the "org.javasisst" module in the example jboss-deployment-structure.xml file):

       

      <jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.2">

          <deployment>

              <exclusions>

                  <module name="org.jboss.as.web"/>

              </exclusions>

              <dependencies>

                  <module name="deployment.customjbossweb"/>

              </dependencies>

          </deployment>

          <module name="deployment.customjbossweb">

              <dependencies>

                  <module name="org.jboss.as.web">

                      <imports>

                          <exclude path="/org/eclipse/jdt/**"/>

                          <include path="/**"/>

                      </imports>

                  </module>

              </dependencies>

          </module>

      </jboss-deployment-structure>

       

      The "org.javasisst" module in the example does the opposite of what I'm trying to do--pokes a container package through to the app, whereas I want to hide a container package from the app--but it seems sensical:

       

      1. Exclude the standard module.
      2. Derive a custom module from the standard module, but exclude some classes from import.
      3. Depend on the custom module.

       

      In the end, the only part of this that appears to work is the exclusion: I get ClassNotFoundExceptions referencing org.apache.jasper, org.apache.catalina, etc. on startup.  I'm guessing this means I've lost the entire cast of packages and classes that come with the "org.jboss.as.web" module.  Kind of hard to stand up a web app without those classes...

       

      I have also done the typical trial-and-error stuff.  Got rid of the exclusion altogether and tried an explicit dependency on the "org.jboss.as.web" module, with an appropriate nested <imports> structure, to no avail.

       

      I can work around this my modifying the module.xml file for the "org.jboss.as.web" module, at the server config/implementation level, and excluding "org/eclipse/jdt" from export.  But this is obviously not an ideal solution.  I'm essentially modifying the server itself to work around an application issue.

       

      For the life of me, I can't figure out why JDT is exposed through web app classloaders in the first place.  But I don't know all of the issues involved in implementing an application server.

       

      Any hints?  Class loading seems to be a soft spot in the documentation/knowledge base surrounding AS 7 at the moment..

        • 1. Re: AS 7: Excluding a container library from WAR classpath
          Matt Jensen Newbie

          I believe that I have found a solution for this problem.  For anyone else who might run into a similar issue in the future, here is the jboss-deployment-structure.xml file which ended up working for me (in AS 7.2.0.Final-redhat-8.)  This general pattern should (?) be applicable in any situation where you're getting classes from the container which you do not want to get--you want classes from your WEB-INF/lib instead:

           

          <jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.2">

              <deployment>

                  <exclusions>

                      <module name="org.jboss.as.web"/>

                  </exclusions>

                  <dependencies>

                      <module name="deployment.customjbossweb"/>

                  </dependencies>

              </deployment>

              <module name="deployment.customjbossweb">

                  <dependencies>

                      <module name="org.jboss.as.web">

                          <exports>

                              <exclude path="org/eclipse/jdt/**"/>

                              <include path="**"/>

                          </exports>

                      </module>

                  </dependencies>

              </module>

          </jboss-deployment-structure>

           

          Note that none of this works if you put leading slashes in the @path attributes under the <exports>.  It appears that the globber matches nothing when you do that, and you end up with nothing exported.  The web app then fails to start with ClassNotFoundExceptions in org.apache.jasper, etc.  That is what was tying me in knots for the better part of a day.

           

          --Matt

          • 3. Re: AS 7: Excluding a container library from WAR classpath
            Matt Jensen Newbie

            Thank you. I voted on the issue. Just didn't want to create one myself in case I was doing something horribly wrong and just missing some bit of documentation.