0

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?

spiralfuzet
  • 75
  • 10
  • What can't you add the plugins to your framework pom and have them reside outside your framework codes? Is it solely because you have Test projects and you only want to add the dependency to the framework project only without defining any plugins in the test project POM? – allkenang Apr 08 '19 at 09:04
  • I want to keep the plugin code separately. I inverted the dependency and the plugins depend on the framework not the other way around. This way any jar which implements an interface and has a proper descriptor xml can be a plugin. And you don't have to change the framework code. The end-to-end tests can be in another project. I don't insist to keep them under the plugin pom project. It can be on the same level as the framework. – spiralfuzet Apr 08 '19 at 09:41

2 Answers2

0

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>
Gerold Broser
  • 14,080
  • 5
  • 48
  • 107
  • Thanks for the answer! I think I didn't misunderstood maven local repository. The misunderstanding arises from the fact that maven's parent-child relationship is only representing build order and can't create a plugin-style framework with auto-discover functionality. You have to create it by hand. By its own this is not the end of the world but I need end-to-end tests. – spiralfuzet Apr 08 '19 at 10:41
  • What do you mean by build time? I understand that java needs run-time dependencies when compiling but the build process contains test phase too. – spiralfuzet Apr 08 '19 at 10:45
  • You're right concerning Maven's parent-child relationship. By build time I mean performing `mvn install` or generally `mvn `. – Gerold Broser Apr 08 '19 at 10:49
  • At this point a can't escape from the feeling that I try to abuse maven. By "fails to create the same structure" I meant that I can't deviate from the default behavior. – spiralfuzet Apr 08 '19 at 10:50
  • That came into my mind, too, when I read your question first. ;) – Gerold Broser Apr 08 '19 at 10:53
0

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

J Fabian Meier
  • 33,516
  • 10
  • 64
  • 142
  • Thanks for the answer! Unfortunately this is true. A project can't deviate from the default behavior no mater what. Everything else is just hacking. – spiralfuzet Apr 08 '19 at 11:41