57

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
  • 1
  • 15
  • 76
  • 99
yelo3
  • 5,253
  • 5
  • 24
  • 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

6 Answers6

70

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,025
  • 1
  • 33
  • 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
  • 2,900
  • 3
  • 30
  • 42
  • 1
    This plugin is lacking in documentation. – Hamdi Dec 24 '14 at 21:28
  • 11
    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
24

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
  • 11,867
  • 5
  • 44
  • 63
  • 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
15

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
  • 14,155
  • 12
  • 57
  • 67
zjor
  • 856
  • 2
  • 11
  • 20
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
  • 3,906
  • 3
  • 21
  • 21
  • 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
0

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