Thursday, November 01, 2007

Maven: Making a War and Jar at the Same Time

Maven 2 nice automates building WAR files, but it places your compiled classes in WEB-INF/classes instead of making a new jar in /WEB-INF/lib.

If you want your stuff to be compiled as a .jar as well as a .war, you can do this by specifying the jar goal in the command line:

[shell>mvn clean jar install

Note this will make myproject.jar in target/, not in target/myproject/WEB-INF/lib, so you will need to use the Ant plugin to move this stuff around.

But this is not always an option: for deep, modular builds using the reactor, you may want to build your whole thing using one "mvn install". To do this, do the following:
  1. Specify "war" packaging at the top of your pom.xml.
  2. Then add the following to your build section.
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<id>make-a-jar</id>
<phase>compile</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

And that's it. Do a " maven install" and you get a jar and a war.

17 comments:

Lynn W said...

Thanks for posting this. I found it helpful. In addition for those interested in also having the jar file installed in the local repository I added the following to do so:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId>
<executions>
<execution>
<phase>install</phase>
<goals>
<goal>install-file</goal>
</goals>
<configuration>
<packaging>jar</packaging>
<artifactId>${project.artifactId}</artifactId>
<groupId>${project.groupId}</groupId>
<version>${project.version}</version>
<file>
${project.build.directory}/${project.artifactId}-${project.version}.jar
</file>
</configuration>
</execution>
</executions>
</plugin>

Eóin said...

Thanks for this - I had tried and failed with a few attempts before I stumbled upon this elegant solution

Арцём said...

And what do you think about this solution:

<plugin>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<archiveClasses>true</archiveClasses>
</configuration>
</plugin>

Sami said...

Thanks for a nice solution :) In addition to installing to the local repository, one may be interested in deploying the Jar to the release repository as well. It can be accomplished like this:

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<executions>
<execution>
<phase>deploy</phase>
<goals>
<goal>deploy-file</goal>
</goals>
<configuration>
<packaging>jar</packaging>
<generatePom>true</generatePom>
<url>${project.distributionManagement.repository.url}</url>
<artifactId>${project.artifactId}</artifactId>
<groupId>${project.groupId}</groupId>
<version>${project.version}</version>
<file>${project.build.directory}/${project.artifactId}-${project.version}.jar</file>
</configuration>
</execution>
</executions>
</plugin>

dhartford said...

note: the install and deploy options assume you do NOT have finalName defined, make sure you comment it out or adjust.

dhartford said...

Identified an issue - the url configuration needs to change between SNAPSHOT and production builds.

Also, it looks like SNAPSHOT deploy builds to not follow previous SNAPSHOT configurations (i.e. I turn off unique versions, but this deploy turns it back on by default).

CmaJ said...

Great!!

Works like a charm.

Thanks.

JakeToronto said...

I used all three plugins, and was able to force the deploy-file plugin to use my SNAPSHOT version, instead of a unique version, by adding this line within the configuration element:

false

JakeToronto said...

I addded this line:

false

to the configuration element of the deploy-file plugin to allow my repository to continue using SNAPSHOT.

mpc755 said...

Thanks. Exactly what I was looking for.

Alireza said...

Great, It was so helpful! Thanks.

vraskin said...

Sami,
Can you please share more information about your setup ?

I am trying to setup 3rd party maven repository to share with our team.

Can I deploy jar file to artifactory repository using your setup ?

Thanks,
Viktor

Giri said...

Thanks a lot
It very use full to me

And i have a question

How can i create a different META_INF for jar ?

I used following tags under Configuration tag but no luck

< useDefaultManifestFile > true < /useDefaultManifestFile >

< addMavenDescriptor > false < /addMavenDescriptor >


Thanks
Giri

Ajay said...

The proposed solution is not working if the webapps having any resources, it is just making whole thing as a jar, but expected was only classes should go in jar.

Rashmi Shetty said...


maven-war-plugin

true



Is the best of all .

sab said...

Great! i thought i want something wrong, but here it is.
Thanks to Lynn W for install issue solution.

James Albright said...

I came across this post looking for how to publish my war file and it's jar'd classes at the same time. It was definitely helpful, but then I discovered the maven-war-plugin now has a configuration parameter: attachClasses which does the same thing when set to true. I just thought I'd pass that along.