Exclude all the jar's from webapp/WEB-INF/lib - maven

I have the third party jar's in my WEB project placed at /src/main/webapp/WEB-INF/lib/
I have mentioned the dependency for all the required JAR's in the pom.xml.
Now, Since the dependencies are defined in POM, the JAR's will be automatically packed in the lib folder.
I want to exclude all the JAR's in the lib.
The Dependency JAR's should be packaged inside the lib while building the WAR
I CANT DELETE THE LIB FROM WEB-INF BECAUSE ITS USED IN LOCAL DEVELOPMENT
This is what I've tried so far:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<packagingExcludes>META-INF/context.xml</packagingExcludes>
<webResources>
<resource>
<directory>src/main/webapp/WEB-INF/lib</directory>
<excludes>
<exclude>**/**</exclude>
</excludes>
</resource>
</webResources>
</configuration>
</plugin>
Any Idea?

It should be "packagingExcludes" instead of "warSourceExcludes":
<configuration>
<packagingExcludes>WEB-INF/lib/*.jar</packagingExcludes>
....
</configuration>
From http://maven.apache.org/plugins/maven-war-plugin/examples/skinny-wars.html :
In version 2.1-alpha-1, this was incorrectly named warSourceExcludes

Try this:
<configuration>
<warSourceExcludes>WEB-INF/lib/*.jar</warSourceExcludes>
....
</configuration>
However, I do agree with Jarrod that it is bad practice to store your jars in WEB-INF/lib 'manually'. I used this before to avoid that jars coming as a dependency got packaged to be able to repackage it afterwards.

you shouldn't have anything in your WEB-INF/lib directory to begin with. If you are using Eclipse, you can tell it to build its project from the pom.xml and it will know to look in ~/.m2/repository for dependencies, Intellij IDEA does this as well. Putting dependencies in WEB-INF/lib kind of defeats the purpose of using Maven for dependency management. What happens when the dependencies in the pom.xml get out of sync version wise with those in WEB-INF/lib

Related

Maven: include folder in resource folder in the war build

I've a folder named extra-jars in the src/main/rescource, but how can I include these in the build? I want them to be put in the lib folder with the rest of the jars. I tried including them through , but that didnt work.
For jars that are not distributed by a Maven repository, the simplest way is place the extra jars in the src/main/webapp/WEB-INF/lib directory of your project. Maven will by convention, include everything under the src/main/webapp in the final war artifact.
An additional method is to use the Maven War Plugin. It has the ability to add additional files to the final war artifact though plugin configuration.
In the build section of the POM add something like the following:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.4</version>
<configuration>
<webResources>
<resource>
<directory>src/main/resource/extra-jars</directory>
<includes>
<include>*.jar</include>
</includes>
<targetPath>WEB-INF/lib</targetPath>
</resource>
</webResources>
</configuration>
</plugin>
</plugins>
</build>
The <configuration> section is the key to adding additional files.
The <directory> element defines the source location of the resource. The path is relative to pom.xml.
The <includes> element defines what files found in the above directory to include.
The <targetPath> element defines the destination directory in the WAR to which the files are copied.
These jars should be added as Maven dependencies, not by copying them into the lib folder. This is the sort of thing Maven is designed for.

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:
Is this the only way to fix this problem?
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.
I had the same issues myself - I just couldn't access Spring or Sitemesh's TLDs when my spring JAR files were in my ear/lib folder!
Including the classpath in the MANIFEST was causing my app server go haywire (since all dependencies were being loaded twice).
(Yes, I also have skinnyWars set to true in my maven-ear-plugin).
The only way I could have gone round the issue was by including Spring and sitemesh by including them in maven-war-plugin's configuration:
<packagingExcludes>%regex[WEB-INF/lib/(?!spring|sitemesh).*.jar]</packagingExcludes>
Not the most elegant solution, but the least damaging I could find.
This is my full configuration:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.1.1</version>
<configuration>
<!--
Q. Why is this set?
A. maven-ear-plugin in our EAR modules have `skinnyWars` enabled to that WAR files
would not include any third-party libraries in the WAR's WEB-INF/lib folder, however
this does not work for ejbs (like our own EJB modules).
We'll need to exclude them from here anyway (except for a few select JARS)...
-->
<packagingExcludes>%regex[WEB-INF/lib/(?!spring|sitemesh).*.jar]</packagingExcludes>
<archive>
<manifest>
<addClasspath>false</addClasspath>
</manifest>
</archive>
</configuration>
</plugin>
PS. My setup is JBoss EAP 6.x and an ear file with several EJBs, WARs and third-party JARs.
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.

How to get maven assembly plugin to copy artifact?

I have a Maven assembly script that copies resources to build our app. I need to copy some war files from separate, external projects into a /webapps directory in the output. Can't seem to find the magic commands to do it.
I tried adding a dependencySet to the assembly with <include com.mygroup:mywarfile>. This works if I add 'mywarfile' as a war dependency in the project with a scope of compile or runtime. Unfortunately, my project produces a war, and the maven-war-plugin includes the external mywarfile as an overlay, which I don't want.
If I set the scope of the external war dependency to provided or test, the assembly fails with the warning:
[WARNING] The following patterns were never triggered in this artifact inclusion filter:
'com.mygroup:mywarfile'
All I want to do is have the assembly copy an artifact from my local repo to the assembly output. How to do it without messing up other parts of the project?
The maven-assembly-plugin is not intended for copying. The better way to copy dependencies is the maven-dependency-plugin which can copy dependencies etc. If you a talking about deployment into Tomcat etc. than you should take a deeper look into carg2-maven-plugin or the tomcat-maven-plugin which seemed to be more appropriate for that task.
I haven't tried this, but you could try using the exclude feature of overlay configuration of maven war plugin to exclude contents of the dependant war file from being included in your war project. Modified snippet from the Overlay documentation,
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.2</version>
<configuration>
<overlays>
<overlay>
<groupId>com.example.projects</groupId>
<artifactId>warToBeExcluded</artifactId>
<excludes>
<exclude>*</exclude>
</excludes>
</overlay>
</overlays>
</configuration>
</plugin>
</plugins>
</build>
...

How to include resources from war to another maven project

I have a maven project , which needs to copy webapp/WEB-INF/ resources from another maven project which is packaged as a war .
How do I do it ?
PLease suggest
As Bittrance said, you should use the maven dependency plugin.
The better way is to create project that include all your shared resources, probably a type zip, which is build up with the assembly plugin. This is the good "maven way". It's a better solution than unpacking a war.
Then, refer it
<dependency>
<groupId>com.mygroup/groupId>
<artifactId>my-dependencies</artifactId>
<version>1.0.0</version>
<type>zip</type>
</dependency>
Next, you use the maven dependency plugin to unpack your resources, in the directory of your choice (probably WEB-INF/ ?)
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>unpack-cfg-test-resources</id>
<goals>
<goal>unpack-dependencies</goal>
</goals>
<phase>resources</phase>
<configuration>
<outputDirectory>${project.build.directory}/WEB-INF/</outputDirectory>
<includeArtifacIds>my-resources</includeArtifacIds>
<excludeTypes>pom</excludeTypes>
<excludeTransitive>true</excludeTransitive>
</configuration>
</execution>
</executions>
</plugin>
I'm not realy sure of this code snippet (written for another purpose), but this is an example.
For more information, please follow this link : http://maven.apache.org/plugins/maven-dependency-plugin/
If you can't shared a common-project including your files, you can unpack war including only ftl (or whatever you want), but it's not a realy clean solution ;)
There is a lot of posts that deal with this subject :
Unzip dependency in maven
...
Just try with the keywords maven-dependency-plugin, unpack :)
Hope that will help you.
I can see some alternatives:
Use external references in your version control system to point all repos to the same files.
The Maven Dependency module can copy and unpack project dependencies. From there, you can use the Maven Assembly plugin (or Ant targets) to include parts of that dependency in your own installation.
At least for the FTL files, perhaps you could package them in a separate Jar file and then load them as resources through the class loader.
If the resources are filtered, you may get into problem with solution 1 if you want the filtered version and 2, 3 if you want the source version.
Hope this helps.
(This assumes your dependent project is java (jar) and not another web app, if it is a webapp I think the solution is similar).
I suggest a (slightly) different approach:
Instead of reading resources from war, add this to your war pom, to generate a jar in the artifact as well as a war:
<!-- maven war plugin config -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<configuration>
...
<attachClasses>true</attachClasses>
<classesClassifier>some-string</classesClassifier>
</configuration>
<artifactId>maven-war-plugin</artifactId>
<version>3.0.0</version>
</plugin>
...
<resources>
<!-- This is for inclusion in the jar, so dependent module can load it -->
<resource>
<targetPath>some-path</targetPath>
<directory>src/main/webapp/path...</directory>
<includes>
<include>your-resource</include>
</includes>
</resource>
</resources>
And this to your consuming pom, so the generated jar will be loaded:
<dependency>
<groupId>com.company</groupId>
<artifactId>...</artifactId>
<classifier>some-string</classifier>
</dependency>
Then you will be able to load the resources the usual way (getResourceAsStream("some-path/your-resource"))

Maven WAR dependency

I am writing a project for acceptance testing and for various reasons this is dependent on another project which is packaged as a WAR. I have managed to unpack the WAR using the maven-dependency-plugin, but I cannot get my project to include the unpacked WEB-INF/lib/*.jar and WEB-INF/classes/* to be included on the classpath so the build fails. Is there a way to include these files into the classpath, or is there a better way of depending on a WAR?
Many thanks.
There's another option since maven-war-plugin 2.1-alpha-2. In your WAR project:
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.1.1</version>
<configuration>
<attachClasses>true</attachClasses>
</configuration>
</plugin>
This creates a classes artifact which you can use in the acceptance tests project with:
<dependency>
<groupId>your-group-id</groupId>
<artifactId>your-artifact-id</artifactId>
<version>your-version</version>
<classifier>classes</classifier>
</dependency>
Indeed, by design, Maven doesn't resolve transitive dependencies of a war declared as dependency of a project. There is actually an issue about that, MNG-1991, but it won't be solved in Maven 2.x and I'm not sure that I don't know if overlays allow to workaround this issue. My understanding of the suggested solution is to duplicate the dependencies, for example in a project of type pom.
(EDIT: After some more digging, I found something interesting in this thread that I'm quoting below:
I have been helping out with the development of the AppFuse project over
the last month where we make heavy use of the war overlay feature in the
Maven war plugin. It is a really nifty feature!
To get max power with war overlays I have developed the Warpath plugin
that allows projects to use war artifacts as fully fledged dependencies.
In brief:
1) The contents of the /WEB-INF/classes directory in the war dependency
artifacts can be included in the project's classpath for normal compile,
etc tasks.
2) Transitive dependencies from the war dependency artifacts become
available for use by other plugins, e.g. compile and ear - so no more
having to include all the dependencies when creating skinny wars!
The plugin has now been actively used in the AppFuse project for the
last few months, and I feel it is at a point where it is both usable and
stable.
Would the war plugin team be interested in including the warpath
functionality inside the war plugin? It would seem to be the most
natural place to host it.
So, I don't have any experience with it, but the maven warpath plugin actually looks nice and simple and is available in the central repo. To use it,include the following plugin configuration element in your pom.xml file:
[...]
<build>
<plugins>
<plugin>
<groupId>org.appfuse</groupId>
<artifactId>maven-warpath-plugin</artifactId>
<version>1.0-SNAPSHOT</version>
<extensions>true</extensions>
<executions>
<execution>
<goals>
<goal>add-classes</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
[...]
And add the war dependencies you want included in the classpath as warpath type dependencies:
[...]
<dependencies>
<dependency>
<groupId>org.appfuse</groupId>
<artifactId>appfuse-web</artifactId>
<version>2.0</version>
<type>war</type>
</dependency>
<dependency>
<groupId>org.appfuse</groupId>
<artifactId>appfuse-web</artifactId>
<version>2.0</version>
<type>warpath</type>
</dependency>
</dependencies>
[...]
Both the war and warpath dependency types are needed: the war type is used by the Maven war plugin to do the war overlay, the warpath type is used by the Warpath plugin to determine the correct list of artifacts for inclusion in the project classpath.
I'd give it a try.)
Use overlays. First, your test project need to have also packaging war.
Declare dependency of war project you want to test:
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>your-project-arftifactId</artifactId>
<version>${project.version}</version>
<type>war</type>
<scope>test</scope>
</dependency>
then configure maven-war-plugin overlay:
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<webResources>
<resource>
<directory>${basedir}/src/main/webresources</directory>
<filtering>true</filtering>
</resource>
</webResources>
<overlays>
<overlay/>
<overlay>
<groupId>your.group</groupId>
<artifactId>your-project-artifactId</artifactId>
</overlay>
</overlays>
</configuration>
</plugin>
In the above example in test project I overwrite webresources configuration files (like conxtext etc.).
EDIT: This solution wasn't tested with Maven 3.
Good point, Justin. That got me actually solving my problem, namely: including a war into an assembly AND including all its transitive dependencies.
I could not duplicate the war-dependency as 'jar' as you suggested since the assembly plugin would not find a jar referenced by that groupId/artefactId, but
duplicating the war-dependency as type pom
works!
The war and its transitive dependencies are not included in the assembly.
To exclude the (now also appearing) pom file I had to add an exclude element like this:
<excludes>
<exclude>*:pom</exclude>
</excludes>
into my assembly.xml file.
I think this could also be a workaround for the original question of this thread.
If you list the dependency on the war project as a jar dependency it seems to pickup the required jars/resources. I'm using Maven 2.2 + m2eclipse.

Resources