-2

There are modules A, B and C. Module A is a dependency for modules B and C. All jar-s built in the module A are to be distributes into Maven Central but only after integration tests in modules B and C are passed.

To achieve the goal above, I decided to implement a multi-module project with a dedicated module D just for distribution.

As the distribution module D has its own specific coordinates, jar-s from module A are to be renamed.

My idea was to copy jar-s from module A as dependencies to the target dir of the module D with renaming according to the module D coordinates. Here's the module D pom:

<parent>
    <groupId>...</groupId>
    <artifactId>parent</artifactId>
    <version>0.1.0-SNAPSHOT</version>
</parent>

<groupId>...</groupId>
<artifactId>...</artifactId>
<packaging>pom</packaging>

...

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-dependency-plugin</artifactId>
            <version>3.1.1</version>
            <executions>
                <execution>
                    <id>copy</id>
                    <phase>package</phase>
                    <goals>
                        <goal>copy</goal>
                    </goals>
                    <configuration>
                        <artifactItems>
                            <artifactItem>
                                <groupId>...</groupId>
                                <artifactId>...</artifactId>
                                <version>${project.version}</version>
                                <type>jar</type>
                                <overWrite>true</overWrite>
                                <outputDirectory>${project.build.directory}</outputDirectory>
                                <destFileName>${project.artifactId}-${project.version}.jar</destFileName>
                            </artifactItem>
                            <artifactItem>
                                <groupId>...</groupId>
                                <artifactId>...</artifactId>
                                <version>${project.version}</version>
                                <type>jar</type>
                                <classifier>sources</classifier>
                                <overWrite>true</overWrite>
                                <outputDirectory>${project.build.directory}</outputDirectory>
                                <destFileName>${project.artifactId}-${project.version}-sources.jar</destFileName>
                            </artifactItem>
                            <artifactItem>
                                <groupId>...</groupId>
                                <artifactId>...</artifactId>
                                <version>${project.version}</version>
                                <type>jar</type>
                                <classifier>javadoc</classifier>
                                <overWrite>true</overWrite>
                                <outputDirectory>${project.build.directory}</outputDirectory>
                                <destFileName>${project.artifactId}-${project.version}-javadoc.jar</destFileName>
                            </artifactItem>
                        </artifactItems>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

jar-s are copied from the module A to the module's D target directory but only module's D pom is updated in my local repository after install phase is completed. There are no records about installing of copied jar-s in build log either.

At the same time, jar-s from module A are successfully installed.

I tried to change packaging of the module D to jar, but only jar with binaries was installed after that, and jar-s with sources and javadoc weren't installed.

At the moment the following workaround is found:

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

Is there any other less clumsy solution?

Thanks.

Thed
  • 23
  • 7
  • Sorry, it is unclear why are trying to copy around and rename artifacts. – J Fabian Meier May 23 '21 at 17:12
  • @JFabianMeier, added more details. – Thed May 23 '21 at 17:23
  • Can you explain more in detail what you mean by: `but only after integration tests`... ? – khmarbaise May 23 '21 at 17:48
  • @khmarbaise, there's certain functionality with integration tests those depend on the module A. That functionality is not to be distributed and therefore is extracted to separate modules. But those integration tests in fact test module A as well, thus, if they fail, module A shouldn't be distributed. – Thed May 23 '21 at 18:09
  • Can you give concrete examples what kind of function is tested here? – khmarbaise May 24 '21 at 17:00
  • The main module, that's to be distributed, is a set of utilities facilitating certain kind of unit testing. Not a specialized test framework yet, but just a set of utilities. It's main functionality is to provide a wrapper over `Iterable` for parameterized unit tests. Test utilities should be compatible with JUnit4, JUnit5 and TestNG. A number of integration tests is implemented to test this compatibility. As it's at least quite problematic for surefire to run such a mix inside one module, integration tests were extracted to separate modules. – Thed May 24 '21 at 17:14

2 Answers2

1

The approach is overly complicated.

What you should do instead:

  • build A
  • test A with B and C
  • deploy A

Depending on your approach, there are different possibilities to achieve this. You could e.g. use the property deployAtEnd of the maven deploy plugin.

J Fabian Meier
  • 33,516
  • 10
  • 64
  • 142
  • In case modules B and/or C build fails, the overall build should fail. Thus, modules B and C are dependencies of specially created module D that's to be the final one where both **install** and **deploy** phases are to be executed with proper coordinates. – Thed May 23 '21 at 18:55
  • I understood that. But I would not do it that way. I would do it in the way I sketched. Which build server or CI solution do you use? – J Fabian Meier May 24 '21 at 08:54
  • Ah! I understood. So, you suggest to use some CI over Maven to implement this build flow, right? Actually, I also doubt it could be done with Maven only without hacks and tricks. – Thed May 24 '21 at 13:46
  • 1
    Yes. Generally, for professional development you need some CI solution. I would either use Jenkins or the CI tool of your platform (e.g. gitlab ci, github actions...) – J Fabian Meier May 24 '21 at 13:56
0

It turns out that it's not enough just to copy needed jar-s to target, but those jar-s are to be additionally attached using build-helper-maven-plugin.

So, here's the parent pom (a bit simplified to be consistent with the question details and for the sake of clearness):

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xmlns="http://maven.apache.org/POM/4.0.0"
     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0      http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.example.internal</groupId>
<artifactId>parent</artifactId>
<version>0.1.0-SNAPSHOT</version>
<packaging>pom</packaging>

<modules>
    <module>A</module>
    <module>B</module>
    <module>C</module>
    <module>D</module>
</modules>

</project>

Here's the pom of the distributed module D (a bit simplified as well):

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xmlns="http://maven.apache.org/POM/4.0.0"
     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
    <groupId>com.example.internal</groupId>
    <artifactId>parent</artifactId>
    <version>0.1.0-SNAPSHOT</version>
</parent>

<groupId>com.example</groupId>
<artifactId>D</artifactId>
<packaging>pom</packaging>

<properties>
    <moduleToDistributeGroupId>com.example.internal</moduleToDistributeGroupId>
    <moduleToDistributeArtifactId>A</moduleToDistributeArtifactId>
    <sourcesClassifier>sources</sourcesClassifier>
    <javadocClassifier>javadoc</javadocClassifier>
    <binaryArtifactName>${project.artifactId}-${project.version}.jar</binaryArtifactName>
    <sourcesArtifactName>${project.artifactId}-${project.version}-${sourcesClassifier}.jar</sourcesArtifactName>
    <javadocArtifactName>${project.artifactId}-${project.version}-${javadocClassifier}.jar</javadocArtifactName>
</properties>

<dependencies>
    <dependency>
        <groupId>com.example.internal</groupId>
        <artifactId>A</artifactId>
    </dependency>
    <dependency>
        <groupId>com.example.internal</groupId>
        <artifactId>B</artifactId>
        <version>${project.version}</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>com.example.internal</groupId>
        <artifactId>C</artifactId>
        <version>${project.version}</version>
        <scope>test</scope>
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-dependency-plugin</artifactId>
            <version>3.1.1</version>
            <executions>
                <execution>
                    <id>copy</id>
                    <phase>package</phase>
                    <goals>
                        <goal>copy</goal>
                    </goals>
                    <configuration>
                        <artifact>
                        </artifact>
                        <artifactItems>
                            <artifactItem>
                                <groupId>${moduleToDistributeGroupId}</groupId>
                                <artifactId>${moduleToDistributeArtifactId}</artifactId>
                                <version>${project.version}</version>
                                <type>jar</type>
                                <overWrite>true</overWrite>
                                <outputDirectory>${project.build.directory}</outputDirectory>
                                <destFileName>${binaryArtifactName}</destFileName>
                            </artifactItem>
                            <artifactItem>
                                <groupId>${moduleToDistributeGroupId}</groupId>
                                <artifactId>${moduleToDistributeArtifactId}</artifactId>
                                <version>${project.version}</version>
                                <type>jar</type>
                                <classifier>${sourcesClassifier}</classifier>
                                <overWrite>true</overWrite>
                                <outputDirectory>${project.build.directory}</outputDirectory>
                                <destFileName>${sourcesArtifactName}</destFileName>
                            </artifactItem>
                            <artifactItem>
                                <groupId>${moduleToDistributeGroupId}</groupId>
                                <artifactId>${moduleToDistributeArtifactId}</artifactId>
                                <version>${project.version}</version>
                                <type>jar</type>
                                <classifier>${javadocClassifier}</classifier>
                                <overWrite>true</overWrite>
                                <outputDirectory>${project.build.directory}</outputDirectory>
                                <destFileName>${javadocArtifactName}</destFileName>
                            </artifactItem>
                        </artifactItems>
                    </configuration>
                </execution>
            </executions>
        </plugin>
        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>build-helper-maven-plugin</artifactId>
            <version>3.2.0</version>
            <executions>
                <execution>
                    <id>attach-artifacts</id>
                    <phase>package</phase>
                    <goals>
                        <goal>attach-artifact</goal>
                    </goals>
                    <configuration>
                        <artifacts>
                            <artifact>
                                <file>${project.build.directory}/${binaryArtifactName}</file>
                                <type>jar</type>
                            </artifact>
                            <artifact>
                                <file>${project.build.directory}/${sourcesArtifactName}</file>
                                <classifier>${sourcesClassifier}</classifier>
                                <type>jar</type>
                            </artifact>
                            <artifact>
                                <file>${project.build.directory}/${javadocArtifactName}</file>
                                <classifier>${javadocClassifier}</classifier>
                                <type>jar</type>
                            </artifact>
                        </artifacts>
                    </configuration>
                </execution>
            </executions>
        </plugin>
        <!--other plugins-->
    </plugins>
</build>

</project>

After artifacts are attached they're automatically recognized by all other plugins, e.g., gpg, install, deploy, etc.

Thed
  • 23
  • 7