Search code examples
mavenjarwarear

Include specific JAR files in skinny WARs with Maven


I've been having some problems with a WAR module and its difficulty in loading a taglib. I kept getting this exception:

JSPG0047E: Unable to locate tag library for uri http://www.springframework.org/tags/form 
    at com.ibm.ws.jsp.translator.visitor.tagfiledep.TagFileDependencyVisitor.visitCustomTagStart(TagFileDependencyVisitor.java:76)
    at com.ibm.ws.jsp.translator.visitor.JspVisitor.processJspElement(JspVisitor.java:366)
    at com.ibm.ws.jsp.translator.visitor.JspVisitor.processChildren(JspVisitor.java:419)
    at com.ibm.ws.jsp.translator.visitor.JspVisitor.processJspElement(JspVisitor.java:369)
...

After a bit of searching, I found a lot of suggestions that the spring jars need to be on the application's classpath. I checked in my EAR's lib folder and sure enough, spring-web and spring-webmvc were there.

It should be noted that the EAR is built with skinny WARs - since they use most of the same libraries, all library files are in MyAppEAR/lib instead of MyAppEAR/MyWAR1/WEB-INF/lib, MyAppEAR/MyWAR2/WEB-INF/lib, MyAppEAR/MyWAR3/WEB-INF/lib, etc...

I did finally manage to resolve this missing taglib error, but I had to move spring-web and spring-webmvc to MyAppEAR/MyWAR1/WEB-INF/lib.

So I have a couple of questions:

  1. Is this the only way to fix this problem?
  2. If so, how can I build a sort-of skinny WAR using maven? Currently, the EAR part of the POM looks like this:

    <plugin>
      <artifactId>maven-ear-plugin</artifactId>
      <version>2.8</version>
      <configuration>
        <applicationName>MyAppEAR</applicationName>
        <defaultLibBundleDir>lib</defaultLibBundleDir>
        <skinnyWars>true</skinnyWars>
    

I guess I could turn off skinny WARs and then have some other step remove all libraries from the WAR files and copy them to MyAppEAR/lib except for the spring web jars, but I am hoping there's a better solution.


Solution

  • I think I got it working.

    In the WAR's POM file:

    <plugin>
      <artifactId>maven-war-plugin</artifactId>
        <version>2.2</version>
        <configuration>
          <warSourceDirectory>src/main/webapp</warSourceDirectory>
          <packagingExcludes>WEB-INF/lib/*.jar,WEB-INF/*.xmi</packagingExcludes>
          <archive>
            <manifest>
                 <addClasspath>true</addClasspath>
                 <classpathPrefix>../../WEB-INF/lib/</classpathPrefix>
           </manifest>
          </archive>
        </configuration>
    </plugin>
    

    This causes the generated WAR file to have a META-INF/MANIFEST.MF file with classpath entries that look like ../WEB-INF/lib/$someJarFile - that is the relative path from the WAR to the EAR's library folder. I guess the WAR needs to have the classpath specified, having the libraries in the EAR just isn't enough.