36

I have a maven project with quite a few submodules. What I am looking for is a way to get all the .jar files produced by the sub-modules included in the aggregating POM's /target/ directory, so they can be conveniently used afterwards.

  • They don't need to be merged. Preferably not, but if they must be then that is ok.
  • Don't care about dependancies
  • This is primarily for convenience, at this point

A basic version of what I am looking at doing:

Prj1/pom.xml  =>  prj1/target/proj1.jar  (and classes/generated-sources/etc)
Prj2/pom.xml  =>  prj2/target/proj2.jar
Main/pom.xml  =>
                  main/target/proj1.jar
                  main/target/proj2.jar
                  ... classes/generated-sources not needed at all,
                  ... but they could be combined here.  I assume they will be

I've been reading, and using some suggestions from SO as well. So far I haven't found a way to do this, but I'm sure it is there.

edit:

I've given up on getting this to work in a simple way, for all included subprojets. The best answer I have so far is using the dependancy plugin to manually specify (again), each and every sub-module to be included. The idea was to be able to configure the POMs easily for the dozens of clients, simply including the modules necessary and then having it magically stick all the sub-modules's jars in one location. Maven is pretty nice, when you don't do much with it, but the angle bracket tax is incredible when you try.

I still find it odd that such standard-seeming tasks (judging from the questions asked on SO, and what any normal project would do) are so difficult. Is maven3 better?

Andrew
  • 8,322
  • 2
  • 47
  • 70

3 Answers3

32

You could try the maven-dependency-plugin:copy plugin:goal.

You will have to add this to the pom of all submodules that you want to copy. EDIT: Or just in the parent pom (see comments).

    <build>
        <plugins>
            <plugin>
              <groupId>org.apache.maven.plugins</groupId>
              <artifactId>maven-dependency-plugin</artifactId>
              <executions>
                <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>../Main/target/dependencies</outputDirectory>
                  </configuration>
                </execution>
              </executions>
            </plugin>
        </plugins>
    </build>

If you do put this in the parent pom, keep in mind that it will work nicely only if your whole project is one module deep. Meaning that if the the modules under the parent module have their own submodules, they will not end up in the desired folder. Your folder structure will look like this:

- Parent
  - Module 1
    - Sub module 1
    **Main**
  - Module 2
  **Main**

To prevent this, create a dedicated module with above configuration, and specify manually each module that you want to copy. This way all modules, no matter how deep they are will end up in one folder.

Anton
  • 2,282
  • 26
  • 43
Brambo
  • 835
  • 7
  • 12
  • Looks promising. I like that 'copy-artifact' bit :) I'll see if I can't find a way to do it without modifying sub-projects first, since we will have many different poms, I think. – Andrew Nov 28 '11 at 09:11
  • @AndrewBacker You can also just define this in your aggregating POM (Main/pom.xml). It might very well work. – Brambo Nov 28 '11 at 09:23
  • This works, but I end up having to specify each dep. manually. I can't use "*" for artifact ID. But it DOES work! – Andrew Nov 29 '11 at 02:57
  • 2
    OMG, this works like a charm in the parent project. Great, Thanks! – jelies Feb 07 '13 at 16:07
  • it's doesn't works for me when it's only declared in the parent pom. The plugin doesn't launched – herau Jun 06 '14 at 12:18
  • 1
    this works but if I run "mvn clean install" then the parent's target directory is deleted automatically in the end. Parent project has packaging as "pom" and it does not accept any other packaging. Any setting for not deleting parent project's target directory – Nitiraj Nov 08 '16 at 11:19
15

I have spent the entire day trying to solve this... and finally it works, so even though I am on a tough schedule, I will share it here, if I can only save someone's frustration in the future...

Step 1. Create an additional Maven project that will be a parent of all the projects that you want to copy together. Let's call this project parent.

This project is needed to tell Maven, which projects to build together. Also, you will declare in your other projects that their parent is parent, so they will see the MyDir property that you define here.

<groupId>com.your.domain</groupId>
<artifactId>parent</artifactId>
<version>0.0.1</version>
<packaging>pom</packaging>
<properties>
    <MyDir>/your/path/to/copy/to</MyDir>
</properties>
<modules>
    <module>../project1</module>
    <module>../project2</module>
    <module>../project2</module>
</modules>

Step 2. For every project that you want to be copied to the same location, specify that it's parent is the parent project (make sure you specify correct groupId and artifactId and version of your parent project):

<parent>
    <groupId>com.your.domain</groupId>
    <artifactId>parent</artifactId>
    <version>0.0.1</version>
    <relativePath>../parent</relativePath>
</parent>

And also, for each of these projects, also specify the jar and dependency plugins settings, like so:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <version>2.4</version>
      <configuration>
        <outputDirectory>${MyDir}</outputDirectory>
        <archive>
          <manifest>
            <addClasspath>true</addClasspath>
            <classpathPrefix>lib/</classpathPrefix>
            <mainClass>com.your.domain.Program</mainClass>
          </manifest>
        </archive>
     </configuration>
</plugin>
<plugin>
    <artifactId>maven-dependency-plugin</artifactId>
    <executions>
      <execution>
        <phase>install</phase>
        <goals>
          <goal>copy-dependencies</goal>
        </goals>
        <configuration>
          <outputDirectory>${MyDir}/lib</outputDirectory>
        </configuration>
      </execution>
    </executions>
</plugin>

Then just run mvn install on the parent project. Bam!

P.S. The above assumes all projects are located in the same directory (parent project next to children), but you can change relative paths as you wish.

akuz
  • 607
  • 7
  • 14
3

One way to achieve this would be to use the moduleSet option of maven assembly plugin.

You could create an assembly descriptor like this (a variation of the example in the link) and use it in assembly plugin declaration in the pom.

<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
  <id>bin</id>
  <formats>
    <format>dir</format>
  </formats>
  <includeBaseDirectory>false</includeBaseDirectory>
  <moduleSets>
    <moduleSet>
      <useAllReactorProjects>true</useAllReactorProjects> 
      <binaries>
        <outputDirectory>/</outputDirectory>
        <unpack>false</unpack>
      </binaries>
    </moduleSet>
  </moduleSets>
</assembly>
Raghuram
  • 51,854
  • 11
  • 110
  • 122
  • I've been trying to get this working. I have it wired up, with help from the linked pages. I get a message complaining about , which is odd since I have version 2.2.1 (and 2.2+ is required). Removing that causes complaints about "does not have an artifact with a file.". I never thought I would prefer ms-build, but wow they can make this stuff insanely xml-y and confusing. – Andrew Nov 28 '11 at 10:14
  • @Andrew Backer. http://stackoverflow.com/questions/1410141/creating-an-archive-of-all-jars-and-source-jars-for-a-multi-module-project seems to indicate it is not all that rosy on this front. – Raghuram Nov 28 '11 at 11:03
  • Sigh. I'll keep poking experimentally, but this is what frustrates me about going back to java. All the ceremony :) There must be away, since this seems like a common thing to want to do. – Andrew Nov 28 '11 at 17:32
  • I can't get this to work, not matter what I try. When I get an assembly.xml that works (even if it does nothing), packaging the child projects manually fails since they can't find the referenced assembly.xml. The refer to a , which is the main POM. Not sure where to go from here. – Andrew Nov 29 '11 at 03:34