58

I'd like to place my output jar and jar-with-dependencies into another folder (not in target/ but in ../libs/).

How can I do that?

peterh
  • 11,875
  • 18
  • 85
  • 108
yelo3
  • 5,613
  • 5
  • 26
  • 23
  • 5
    One little Maven tip - don't fight it's preferences, it'll drive you insane :). But you can always use something like the ant plugin do do basically everything you want, like copying at the end of the build from target to ../libs... – cdegroot Jul 14 '11 at 06:59

7 Answers7

75

You can use the outputDirectory parameter of the maven-jar-plugin for this purpose:

<project>
  ...
  <build>
    <plugins>
      ...
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-jar-plugin</artifactId>
        <version>2.3.1</version>
        <configuration>
          <outputDirectory>../libs</outputDirectory>
        </configuration>
      </plugin>
      ...
    </plugins>
  </build>
  ...
</project>

But as cdegroot wrote, you should probably better not fight the maven way.

Torsten
  • 6,184
  • 1
  • 34
  • 31
  • 2
    Maybe it's better to copy jars instead of moving them? – yelo3 Jul 14 '11 at 14:10
  • By the book I strongly suggest using the maven-dependency-plugin (http://maven.apache.org/plugins/maven-dependency-plugin/) to resolve inter-module dependencies (If you need to transfer to a different module). – Torsten Jul 14 '11 at 14:27
  • 1
    You should never use maven-dependency-plugin to use it as a dependency for inter module dependencies. Usually you can simply define a dependency this works...if that does not work there some other issue in your build... – khmarbaise Feb 08 '18 at 19:55
  • @Torsten It puts the jar into outputDirectory and proguard isn't able to find jar to obfuscate. How to make this work with proguard-maven-plugin? – Gaurav Sep 08 '18 at 08:53
  • @gaurav I suggest that you ask this question in a separate post as this is not related to the original question. Thisway it is also easier to find for others. I personally have no experience with the proguard plugin. – Torsten Sep 10 '18 at 09:30
  • why not fight the maven way? what's disadvantageous about this solution? – theonlygusti Nov 07 '18 at 12:05
47

If you want to copy the artifact into a directory outside your project, solutions might be:

  • maven-jar-plugin and configure outputDirectory
  • maven-antrun-plugin and copy task
  • copy-maven-plugin by Evgeny Goldin

Example for the copy-maven-plugin is:

<plugin>
    <groupId>com.github.goldin</groupId>
    <artifactId>copy-maven-plugin</artifactId>
    <version>0.2.5</version>
    <executions>
        <execution>
            <id>deploy-to-local-directory</id>
            <phase>install</phase>
            <goals>
                <goal>copy</goal>
            </goals>
            <configuration>
                <skipIdentical>false</skipIdentical>
                <failIfNotFound>false</failIfNotFound>
                <resources>
                    <resource>
                        <description>Copy artifact to another directory</description>
                        <targetPath>/your/local/path</targetPath>
                        <directory>${project.build.directory}</directory>
                        <includes>
                            <include>*.jar</include>
                        </includes>
                    </resource>
                </resources>
            </configuration>
        </execution>
    </executions>
</plugin>
timomeinen
  • 3,101
  • 3
  • 33
  • 46
  • 1
    This plugin is lacking in documentation. – Hamdi Dec 24 '14 at 21:28
  • 14
    This plugin does not work as is, it throws the exception `java.lang.ClassNotFoundException: org.sonatype.aether.RepositorySystem` – Joe Almore Nov 27 '15 at 23:40
  • It is not true that the path in outputDirectory must be relative. – ACV Jan 29 '16 at 15:52
  • @ACV You are right! `outputDirectory` is simply a File as can be seen in the [source](https://svn.apache.org/viewvc/maven/plugins/tags/maven-jar-plugin-2.6/src/main/java/org/apache/maven/plugin/jar/AbstractJarMojo.java?view=markup). I edited my answer. – timomeinen Feb 02 '16 at 10:53
  • Can this place jars into the remote server? – zygimantus Mar 07 '17 at 10:51
25

Another way would be maven-resources-plugin (find the current version here):

<plugin>
   <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-resources-plugin</artifactId>
    <version>3.0.2</version>
    <executions>
        <execution>
            <id>copy-files-on-build</id>
            <phase>package</phase>
            <goals>
                <goal>copy-resources</goal>
            </goals>
            <configuration>
                <outputDirectory>${basedir}/[TO-DIR]</outputDirectory>
                <resources>
                    <resource>
                        <directory>[FROM-DIR]</directory>
                        <!--<include>*.[MIME-TYPE]</include>-->
                        <filtering>false</filtering>
                    </resource>
                </resources>
            </configuration>
        </execution>
    </executions>
</plugin>
Stefan
  • 12,108
  • 5
  • 47
  • 66
  • 1
    this doesn't copy across on the first build, only on subsequent ones – theonlygusti Nov 07 '18 at 11:47
  • @theonlygusti I've tried it and it worked pretty well. Maybe you have some eclipse-maven lifecycle mapping problem? – peterh Jan 25 '19 at 16:18
  • 4
    @theonlygusti pretty sure that's because the phase that it runs on is `validate`. You can change it to `package` or `install` to have it work on the first build as well. – Shams Ul Azeem Aug 01 '19 at 14:52
  • Update `validate` to `install` or `package` – Shams Ul Azeem Aug 01 '19 at 14:53
  • I think `install` worked for me like I wanted it to. – Shams Ul Azeem Aug 01 '19 at 15:19
  • I need to give the copied artifact a different name, but it is not clear that this is possible using maven-resources-plugin. – Ed Randall Jan 09 '21 at 09:25
  • 1
    I think it's the most concise one ⭐ It just works, and doesn't require much configuration. @Stefan there is but a small problem: need to specify `org.apache.maven.plugins`, otherwise it can't find the stuff. – vintprox Feb 25 '22 at 12:37
  • 1
    In case you need to copy the SpringBoot repackaged jar, replace package phase with install, and run mvn install to copy the jar. – david euler May 31 '22 at 10:27
16

I would do it this way:

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-antrun-plugin</artifactId>
            <version>1.8</version>
            <executions>
                <execution>
                    <phase>install</phase>
                    <configuration>
                        <target>
                            <copy file="target/${project.artifactId}-exec.jar" tofile="../../docker/${project.artifactId}.jar"/>
                        </target>
                    </configuration>
                    <goals>
                        <goal>run</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
veben
  • 19,637
  • 14
  • 60
  • 80
zjor
  • 994
  • 2
  • 12
  • 22
5

This technique worked well for me:

http://maven.apache.org/plugins/maven-dependency-plugin/examples/copying-artifacts.html

<project>
  [...]
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-dependency-plugin</artifactId>
        <version>2.10</version>
        <executions>
          <execution>
            <id>copy</id>
            <phase>package</phase>
            <goals>
              <goal>copy</goal>
            </goals>
            <configuration>
              <artifactItems>
                <artifactItem>
                  <groupId>junit</groupId>
                  <artifactId>junit</artifactId>
                  <version>3.8.1</version>
                  <type>jar</type>
                  <overWrite>false</overWrite>
                  <outputDirectory>${project.build.directory}/alternateLocation</outputDirectory>
                  <destFileName>optional-new-name.jar</destFileName>
                </artifactItem>
              </artifactItems>
              <outputDirectory>${project.build.directory}/wars</outputDirectory>
              <overWriteReleases>false</overWriteReleases>
              <overWriteSnapshots>true</overWriteSnapshots>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
  [...]
</project>
Jason White
  • 4,462
  • 4
  • 23
  • 23
  • Second to the maven-assembly-plugin technique I found this to be the simplest and most mainstream solution, since assembly-plugin requires an additional descriptor file. – Ed Randall Jan 09 '21 at 10:33
  • In this case giving the context from the element of the `pom.xml` made it easier for me to include in my own `pom.xml` – Juan Javier Triff Cabanas Jun 17 '21 at 20:07
1

I specially like the solution using maven-resources-plugin (see here) because is already included in maven, so no extra download is needed, and also is very configurable to do the copy at a specific phase of your project (see here to learn & understand about phases). And the best part of this approach is that it won't mess up any previous processes or build you had before :)

<project>
  ...
  <build>
    <plugins>
      <plugin>
        <artifactId>maven-resources-plugin</artifactId>
        <version>3.2.0</version>
        <executions>
          <execution>
            <id>copy-resources</id>
            <!-- here the phase you need -->
            <phase>validate</phase>
            <goals>
              <goal>copy-resources</goal>
            </goals>
            <configuration>
              <outputDirectory>/dir/where/you/want/to/put/jar</outputDirectory>
              <resources>          
                <resource>
                  <directory>/dir/where/you/have/the/jar</directory>
                  <filtering>false</filtering>
                  <includes>
                     <include>file-you-want-to.jar</include>
                     <include>another-file-you-want-to.jar</include>
                  </includes>
                </resource>
              </resources>              
            </configuration>            
          </execution>
        </executions>
      </plugin>
    </plugins>
    ...
  </build>
  ...
</project>

Of course you can also use interpolated variables like ${baseDir} and other good stuff like that all over your XML. And you could use wild cards as they explain here

0

Maven dependency plugin is perfectly capable of copying all dependencies and just built artifact in a custom location. Following example will copy all runtime dependencies and a built artifact in a two execution phases.

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-dependency-plugin</artifactId>
    <version>3.3.0</version>
    <executions>
        <execution>
            <id>copy-dependencies</id>
            <phase>package</phase>
            <goals>
                <goal>copy-dependencies</goal>
            </goals>
            <configuration>
                <includeScope>runtime</includeScope>                     
                <outputDirectory>${project.build.directory}/jars</outputDirectory>
                <overWriteReleases>false</overWriteReleases>
                <overWriteSnapshots>false</overWriteSnapshots>
                <overWriteIfNewer>true</overWriteIfNewer>
            </configuration>
        </execution>
        <execution>
            <id>copy-artifact</id>
            <phase>package</phase>
            <goals>
                <goal>copy</goal>
            </goals>
            <configuration>
                <artifactItems>
                    <artifactItem>
                        <groupId>${project.groupId}</groupId>
                        <artifactId>${project.artifactId}</artifactId>
                        <version>${project.version}</version>
                        <type>${project.packaging}</type>
                    </artifactItem>
                </artifactItems>
                <outputDirectory>${project.build.directory}/jars</outputDirectory>
                <overWriteIfNewer>true</overWriteIfNewer>
            </configuration>
        </execution>
    </executions>
</plugin>

While documentation of dependency plugin states in its documentation that in order to copy built artifact you have to use any phase after the package phase, that is not true if you are building jars. In that situation you can use package phase. At least in 3.3.0 version of plugin.

Talijanac
  • 1,087
  • 9
  • 20