Install modular maven project jars into the parent directory inside the local repository

466 Views Asked by At

I have the following project structure:

parent (packing: pom)
    + framework (packing: jar)
    + plugins (packing: pom)
        + plugin_1 (packing: pom)
            + impl (packing: jar)
            + e2e_test (packing: jar)
        + plugin_2 (packing: pom)
            + impl (packing: jar)
            + e2e_test (packing: jar)

Inside the plugin_1.impl and plugin_2.impl I have a resource.xml which describes the plugin.

The build is fine, meaning when I want to build the whole project it builds in order. However the installation fails to create the same structure. After install the local repository looks like this:

com/company
    + parent/version
        + pom file
    + framework/version
        + jars
    + plugins/version
        + pom file
    + plugin_1/version
        + pom file
    + plugin_1.impl/version
        + jar
    + plugin_1.e2e_tests/version
        + jar
    + plugin_2/version
        + pom file
    + plugin_2.impl/version
        + jar
    + plugin_2.e2e_tests/version
        + jar

But I want:

com/company/parent/version
    + framework.jar
    + plugins
        + plugin_1.jar
        + plugin_1.xml (renamed resource.xml)
        + plugin_2.jar
        + plugin_2.xml (renamed resource.xml)

Is there a way to create the desired structure?

I have tried maven-install-plugin e.g.:

mvn org.apache.maven.plugins:maven-install-plugin:3.0.0-M1:install-file \
    -Dfile=parent/plugins/plugin_1/impl/resource.xml \
    -DgroupId=com.company \
    -DartifactId=parent \
    -Dversion=1.0-SNAPSHOT \
    -Dpackaging=file \
    -DgeneratePom=true

or the pom.xml equivalent of this (but for the jar):

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-install-plugin</artifactId>
    <version>3.0.0-M1</version>
    <executions>
        <execution>
            <phase>install</phase>
            <goals>
                <goal>install-file</goal>
            </goals>
            <configuration>
                <groupId>${project.groupId}</groupId>
                <artifactId>${project.parent.parent.artifactId}</artifactId>
                <version>${project.version}</version>
                <packaging>jar</packaging>
                <file>${project.build.directory}/${project.build.finalName}.jar</file>
            </configuration>
        </execution>
    </executions>
</plugin>

But this will always rename the file according to the artifactId and I end up overwriting the same file.

I was able to create the described structure by using copy-rename-maven-plugin inside the upmost parent's target directory.

I want this structure because:

  1. The framework can use any jar put inside the plugins directory with a proper descriptor.
  2. I don't want to do this by hand every time I recompile or change something inside multiple plugins.
  3. End to end tests for a module works by calling framework plugin_1 (args) inside a test and checks the result. For this I need working structure inside a local repository for the test project to depend on.

Is there a way to create the desired structure inside local repository?

2

There are 2 best solutions below

5
Gerold Broser On

It seems that you are misunderstanding Maven (local) repositories in a few ways:

  1. A local repository is a cache for artifacts in remote repositories (though you don't have to use the latter for artifacts created by you if you don't have to share them with others).
  2. A repository is meant to resolve dependencies at build time, not at runtime.
  3. A complete path in a repository identifies a certain artifact (JAR, WAR, EAR, ... or just POM) with a certain version since its path is derived from its Maven Coordinates with its identifying triad GAV (groupId, artifactId, version). Where:

    <groupId>com.my.company</groupId>
    <artifactId>my-artifact</artifactId>
    <version>1.0.0</version>
    

    becomes the directory structure:

    ~/.m2/repositories
      + com
        + my
          + company
            + my-artifact
              + 1.0.0
                + my-artifact-1.0.0.jar  [or war, ear, ...]
                + my-artifact-1.0.0.pom
    

    There is no idea of dependencies (or resources like *.xml) in a hierachical (sub-)structure of an artifact in a Maven repo (local or remote) to be used dynamically during runtime (of tests).

    That's why you see all the artifacts on the same level com/company after your build (including install). They are all coequal. None of them is preferred over an other in terms of Maven.

UPDATE

Possible solution:

Add framework and the corresponding plugin implementation as dependencies to your test projects and use them in the test code accordingly:

plugin_1.e2e_tests:

<dependency>
    <groupId>com.mycompany</groupId>
    <artifactId>framework</artifactId>
    <version>...</version>
</dependency>
<dependency>
    <groupId>com.mycompany</groupId>
    <artifactId>plugin_1.impl</artifactId>
    <version>...</version>
</dependency>

plugin_2.e2e_tests:

<dependency>
    <groupId>com.mycompany</groupId>
    <artifactId>framework</artifactId>
    <version>...</version>
</dependency>
<dependency>
    <groupId>com.mycompany</groupId>
    <artifactId>plugin_2.impl</artifactId>
    <version>...</version>
</dependency>
1
J Fabian Meier On

The Maven local repository has a fixed directory structure. This structure should not be changed. It reflects the Maven coordinates (groupId, artifactId, version).