I’m new to maven. (I have searched for hours for the answer but without luck. mvn dependency:copy-dependencies do not solve my problem)
I need to copy all the dependencies of a project (in the form of jars) and if one of my jars depend on another artifact copy that artifact as well.
Example project1 pom.xml:
<?xml version="1.0"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 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>project1</groupId>
<artifactId> project1.utils</artifactId>
<version>1.0</version>
<name> project1. utils </name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>project2</groupId>
<artifactId>project2.artifact</artifactId>
<version>2.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<archive>
<index>true</index>
<manifestEntries>
<Build-Number>${buildNumber}</Build-Number>
<Revision>${Revision}</Revision>
</manifestEntries>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>
“project1” have a dependency of project2.artifact.jar. When I use “mvn dependency:copy-dependencies”, I get project2.artifact.jar but I do not get project3.artifact.jar that is a dependency of “project2”.
I do not have the pom of project2, but it is installed in my local repository.
How can I get all the dependencies of project 1 including the second jar (“project3.artifact.jar”)?
Pom of project2 would look something like this, but I don't have it when I go to a client. So I install project2.artifact.jar, project3.artifact.jar manually using "mvn install".
Project2 pom.xml:
<?xml version="1.0"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 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>project2</groupId>
<artifactId>project2.artifact</artifactId>
<version>2.0</version>
<name>project2.artifact</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>project3</groupId>
<artifactId>project3.artifact</artifactId>
<version>3.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<archive>
<index>true</index>
<manifestEntries>
<Build-Number>${buildNumber}</Build-Number>
<Revision>${Revision}</Revision>
</manifestEntries>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>
Please use the latest version of dependency plugin:
mvn org.apache.maven.plugins:maven-dependency-plugin:2.10:copy-dependencies
If not works please check:
mvn org.apache.maven.plugins:maven-dependency-plugin:2.10:tree
mvn org.apache.maven.plugins:maven-dependency-plugin:2.10:list
copy-dependency goal copies the same artifacts which is resolved and displayed by tree and list goals.
For testing I prepare project3 pom.xml:
<?xml version="1.0"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 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>project3</groupId>
<artifactId>project3.artifact</artifactId>
<version>3.0</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>
I have such directory structure:
pr1
pom.xml - from question
pr2
pom.xml - from question
pr3
pom.xml - as shown above
Now I do:
cd pr3
mvn clean innstall
cd ../pr2
mvn clean innstall
mvn dependency:tree
dependency:tree output:
[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) # project2.artifact ---
[INFO] project2:project2.artifact:jar:2.0
[INFO] \- project3:project3.artifact:jar:3.0:compile
So project2 depends on project3
next:
cd ../pr1
mvn clean install
mvn dependency:tree
dependency:tree in project1 output:
[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) # project1.utils ---
[INFO] project1:project1.utils:jar:1.0
[INFO] \- project2:project2.artifact:jar:2.0:compile
[INFO] \- project3:project3.artifact:jar:3.0:compile
So it is also ok.
And now copy:
mvn dependency:copy-dependencies
With result:
[INFO] --- maven-dependency-plugin:2.8:copy-dependencies (default-cli) # project1.utils ---
[INFO] Copying project3.artifact-3.0.jar to ...\pr1\target\dependency\project3.artifact-3.0.jar
[INFO] Copying project2.artifact-2.0.jar to ...\pr1\target\dependency\project2.artifact-2.0.jar
If you also want to copy project1 artifact add it to dependency in project1 pom.xml
...
<dependencies>
<dependency>
<groupId>project2</groupId>
<artifactId>project2.artifact</artifactId>
<version>2.0</version>
</dependency>
<dependency>
<groupId>project1</groupId>
<artifactId>project1.utils</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
...
Now:
mvn clean dependency:copy-dependencies we have:
[INFO] --- maven-dependency-plugin:2.8:copy-dependencies (default-cli) # project1.utils ---
[INFO] Copying project3.artifact-3.0.jar to ...\pr1\target\dependency\project3.artifact-3.0.jar
[INFO] Copying project2.artifact-2.0.jar to ...\pr1\target\dependency\project2.artifact-2.0.jar
[INFO] Copying project1.utils-1.0.jar to ...\pr1\target\dependency\project1.utils-1.0.jar
Related
I need to publish an artifact twice - each with a different set of dependencies. I'm happy to give the artifacts different ids but would like to use the same pom.xml file. I've attempted this with profile-specific dependencies, but I can't seem to get these dependencies visible as transitive dependencies in the artifacts. Is that possible?
pom1.xml - creates profile-specific builds. The A profile adds a dependency on commons-collections 3.2.2 and profile B depends on 3.2.1.
pom2.xml - simply defines a dependency on pom1's artifact.
src/main/java/tt.java - defines an empty class to provide something to compile by pom1.
mvn version is 3.8.5.
% mvn -f pom1.xml -P A dependency:tree
...
[INFO] org.acme:testing:jar:testing
[INFO] \- commons-collections:commons-collections:jar:3.2.2:compile
...
% mvn -f pom1.xml -P B dependency:tree
...
[INFO] org.acme:testing:jar:testing
[INFO] \- commons-collections:commons-collections:jar:3.2.1:compile
...
% mvn -f pom1.xml -P A clean install
...
% mvn -f pom2.xml dependency:tree
...
[INFO] org.acme:testing2:jar:testing
[INFO] \- org.acme:testing:jar:testing:compile
[INFO] \- commons-collections:commons-collections:jar:3.2.1:compile
It seems to me pom2's dependencies should have been on 3.2.2 from profile A.
Any idea on how I might make the dependencies from profile A transitive to dependent poms?
pom1.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 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>org.acme</groupId>
<artifactId>testing</artifactId>
<version>testing</version>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>A</id>
<properties>
<profile.name>cuda11.2</profile.name>
</properties>
<dependencies>
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.2.2</version>
</dependency>
</dependencies>
</profile>
<profile>
<id>B</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<profile.name>cpu</profile.name>
</properties>
<dependencies>
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.2.1</version>
</dependency>
</dependencies>
</profile>
</profiles>
<!-- If I move this dependency out of the profile, then it becomes visible
as a transitive depenency to other projects referencing this pom's artifact.
<dependencies>
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.2.2</version>
</dependency>
</dependencies>
-->
</project>
pom2.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 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>org.acme</groupId>
<artifactId>testing2</artifactId>
<version>testing</version>
<dependencies>
<dependency>
<groupId>org.acme</groupId>
<artifactId>testing</artifactId>
<version>testing</version>
</dependency>
</dependencies>
</project>
I wanted to configure failsafe with failIfNoTests in a parent pom because we are currently upgrading Spring Boot in our microservices, and tests might not be properly detected if they are still using JUnit 4 (you need to migrate them or use junit-vintage).
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<configuration>
<failIfNoTests>true</failIfNoTests>
</configuration>
</plugin>
The problem however is that this causes the plugin to also run in the build of the parent pom. I don’t want to put this in <pluginManagement> because I want to make sure that the plugin is running in child projects (otherwise they still have to declare the plugin and it might be forgotten).
Is there a way to prevent the failsafe plugin from running with pom packaging?
Note that I did the same with surefire, but there is no issue with that one as its goals are managed by Maven’s default lifecycle, which depends on the pom packaging. However for failsafe the goals are declared in spring-boot-starter-parent’s <pluginManagement> so it applies for all packaging types.
For the moment, I did it with a profile based on this question, but I find this quite dirty:
<profile>
<id>disable-integration-tests-for-pom-packaging</id>
<!-- this profile detects that we are not building an artifact, so we shouldn’t run failsafe -->
<activation>
<file>
<!-- can’t rely on ${project.*} for profile activation -->
<missing>${basedir}/src</missing>
</file>
</activation>
<properties>
<skipITs>true</skipITs>
</properties>
</profile>
Full poms
Parent:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<!-- if changed, update spring-boot.version too! -->
<version>2.6.6</version>
<relativePath />
</parent>
<groupId>org.example</groupId>
<artifactId>parent</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<configuration>
<failIfNoTests>true</failIfNoTests>
</configuration>
</plugin>
</plugins>
</build>
</project>
mvn verify output:
[INFO] Scanning for projects...
[INFO]
[INFO] -------------------------< org.example:parent >-------------------------
[INFO] Building parent 1.0-SNAPSHOT
[INFO] --------------------------------[ pom ]---------------------------------
[INFO]
[INFO] --- maven-failsafe-plugin:2.22.2:integration-test (default) # parent ---
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.619 s
[INFO] Finished at: 2022-04-14T14:07:56+02:00
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-failsafe-plugin:2.22.2:integration-test (default) on project parent: No tests to run! -> [Help 1]
microservice pom:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>parent</artifactId>
<groupId>org.example</groupId>
<version>1.0-SNAPSHOT</version>
<!-- just to be able to build since I can’t actually install the parent -->
<relativePath>../parent</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>microservice</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Build should succeed as long as there are integration tests (and of course all of them are succeeding).
If you want a plugin to not run in the parent, but run in the child, you can add something along the following in the <plugins> section of your parent POM:
<plugin>
<artifactId>maven-source-plugin</artifactId>
<executions>
<execution>
<id>attach-sources</id>
<inherited>false</inherited>
<phase>none</phase>
</execution>
</executions>
</plugin>
This is for the maven source plugin, but you can adapt it for the failsafe plugin as well.
I am trying to build a multi module maven project with kotlin and spring. I get an error when the kotlin-maven-plugin runs the compile phase.
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-clean-plugin:3.1.0:clean (default-clean) # starter ---
[INFO] Deleting /Users/pnts/IdeaProjects/getyour/base/starter/target
[INFO]
[INFO] --- git-commit-id-plugin:2.2.6:revision (default) # starter ---
[INFO]
[INFO] --- git-commit-id-plugin:2.2.6:revision (get-the-git-infos) # starter ---
[INFO]
[INFO] --- kotlin-maven-plugin:1.3.41:compile (compile) # starter ---
[INFO] Applied plugin: 'spring'
[ERROR] /Users/pnts/IdeaProjects/getyour/base/starter/src/main/kotlin/org/getyour/webdesign/PlainStarter.kt: (6, 9) Unresolved reference: WebsiteEntryPoint
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary for parent 0.0.1-SNAPSHOT:
[INFO]
[INFO] parent ............................................. SUCCESS [ 1.178 s]
[INFO] common ............................................. SUCCESS [ 0.021 s]
[INFO] platform-api ....................................... SUCCESS [ 4.238 s]
[INFO] platform-core ...................................... SUCCESS [ 0.215 s]
[INFO] platform-bom ....................................... SUCCESS [ 0.012 s]
[INFO] platform-parent .................................... SUCCESS [ 0.061 s]
[INFO] starter ............................................ FAILURE [ 0.343 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 6.399 s
[INFO] Finished at: 2019-09-27T08:57:04+02:00
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.jetbrains.kotlin:kotlin-maven-plugin:1.3.41:compile (compile) on project starter: Compilation failure
[ERROR] /Users/pnts/IdeaProjects/getyour/base/starter/src/main/kotlin/org/getyour/webdesign/PlainStarter.kt:[6,9] Unresolved reference: WebsiteEntryPoint
[ERROR]
[ERROR] -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoFailureException
[ERROR]
[ERROR] After correcting the problems, you can resume the build with the command
[ERROR] mvn <goals> -rf :starter
The funny thing is when I clean my build with "mvn clean" and run the project it compiles and run the spring application.
Spring starts normal
I dont know what causes this issue. Maybe I am missing something.
Here are my poms and my project structure. Hope somebody can help me with this.
parent pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.8.RELEASE</version>
<relativePath/>
</parent>
<version>0.0.1-SNAPSHOT</version>
<artifactId>parent</artifactId>
<groupId>org.getyour.webdesign</groupId>
<packaging>pom</packaging>
<modules>
<module>common</module>
<module>starter</module>
</modules>
<!-- properties -->
<properties>
<kotlin.version>1.3.41</kotlin.version>
<spring.boot.version>2.1.8.RELEASE</spring.boot.version>
<java.version>1.8</java.version>
<main.class>org.getyour.webdesign.WebsiteEntryPoint</main.class>
</properties>
<!-- repositories -->
<repositories>
<repository>
<id>maven-central</id>
<url>http://central.maven.org/maven2/</url>
</repository>
</repositories>
<build>
<sourceDirectory>src/main/kotlin</sourceDirectory>
<testSourceDirectory>src/test/kotlin</testSourceDirectory>
<pluginManagement>
<plugins>
<plugin>
<!-- Import dependency management from Spring Boot -->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring.boot.version}</version>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring.boot.version}</version>
</plugin>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<version>${kotlin.version}</version>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<!-- kotlin spring compiler plugin -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring.boot.version}</version>
<configuration>
<mainClass>${main.class}</mainClass>
</configuration>
</plugin>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<version>${kotlin.version}</version>
<executions>
<execution>
<id>compile</id>
<goals><goal>compile</goal></goals>
<phase>process-sources</phase>
</execution>
<execution>
<id>test-compile</id>
<goals><goal>test-compile</goal></goals>
<phase>process-test-sources</phase>
</execution>
</executions>
<configuration>
<args>
<arg>-Xjsr305=strict</arg>
</args>
<compilerPlugins>
<plugin>spring</plugin>
</compilerPlugins>
</configuration>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-allopen</artifactId>
<version>${kotlin.version}</version>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib-jdk8</artifactId>
<version>${kotlin.version}</version>
</dependency>
</dependencies>
</plugin>
<plugin>
<groupId>pl.project13.maven</groupId>
<artifactId>git-commit-id-plugin</artifactId>
<version>2.2.6</version>
<executions>
<execution>
<id>get-the-git-infos</id>
<goals>
<goal>revision</goal>
</goals>
</execution>
</executions>
<configuration>
<dotGitDirectory>${project.basedir}/.git</dotGitDirectory>
<prefix />
<verbose>false</verbose>
<generateGitPropertiesFile>true</generateGitPropertiesFile>
<generateGitPropertiesFilename>${project.build.outputDirectory}/git.properties
</generateGitPropertiesFilename>
<format>properties</format>
<gitDescribe>
<skip>false</skip>
<always>false</always>
<dirty>-dirty</dirty>
</gitDescribe>
</configuration>
</plugin>
</plugins>
</build>
</project>
starter pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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>
<artifactId>parent</artifactId>
<groupId>org.getyour.webdesign</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<version>0.0.1-SNAPSHOT</version>
<artifactId>starter</artifactId>
<packaging>jar</packaging>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.getyour.webdesign</groupId>
<artifactId>platform-bom</artifactId>
<version>0.0.1-SNAPSHOT</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.getyour.webdesign</groupId>
<artifactId>platform-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-reflect</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib-jdk8</artifactId>
</dependency>
</dependencies>
</project>
WebsiteEntryPoint.kt
package org.getyour.webdesign
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
/**
* Start class of the application
*
* #author p.tsivelekidis
* Created by p.tsivelekidis on 2019-09-20
*/
#SpringBootApplication
class WebsiteEntryPoint {
companion object {
fun main(args: Array<String>) {
runApplication<WebsiteEntryPoint>(*args)
println("Hello!")
}
}
}
PlainStarter.kt
package org.getyour.webdesign
class PlainStarter
fun main(args: Array<String>) {
WebsiteEntryPoint.main(args)
}
Here is my project structure. Notice that when I run the "mvn clean install" command I get this.
project structure after mvn clean install
When I clean my project and just run I get this structure.
project structure after clean and just run project
When I run the mvn clean install it does not create the target classes and I guess for that reason it cant find my WebsiteEntryPoint.
Hope somebody can help me with that. Thanks a lot.
i had the same issue with compiling a kotlin multi module project in intellij.
Command mvn clean install produced the same error with the unresolved dependencies.
As i can see your source directories are named kotlin (as in my project before).
After renaming the source directories in my project to java the problem was solved...
I simplify my project structure and find some clues. My project structure looks like the following:
-------- project 1 ---------
parent
|_ project-a
|_ src
|_ pom.xml
|_ pom.xml
------- project 2 ----------
project-b
|_ src
|_ pom.xml
---------------------------
In project 1, parent is maven parent for project-a, it's pom.xml looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- spring boot parent -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.6.RELEASE</version>
<relativePath/>
</parent>
<groupId>com.demo</groupId>
<artifactId>parent</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<name>A custom project using myfaces</name>
<url>http://www.myorganization.org</url>
<modules>
<module>project-a</module>
</modules>
<dependencies>
</dependencies>
</project>
In parent's pom, it declares spring boot as it's maven parent and project-a as it's module. In project-a, it's pom is as follows:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>parent</artifactId>
<groupId>com.demo</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>project-a</artifactId>
<packaging>jar</packaging>
<name>project-a Maven Webapp</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.11</version>
<scope>runtime</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<testSource>1.8</testSource>
<testTarget>1.8</testTarget>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.0.1</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
project-b is a standalone project, it's pom looks like the following:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- parent declaration is the key point of this problem! -->
<parent>
<artifactId>parent</artifactId>
<groupId>com.demo</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<groupId>com.demo</groupId>
<artifactId>project-b</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>A custom project using myfaces</name>
<url>http://www.myorganization.org</url>
<!-- Project dependencies -->
<dependencies>
<dependency>
<groupId>com.demo</groupId>
<artifactId>project-a</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<executable>true</executable>
<classifier>exec</classifier>
<includeSystemScope>true</includeSystemScope>
</configuration>
</plugin>
</plugins>
</build>
</project>
After installing project 1 by mvn install, the dependency tree of project-b is as follows:
[INFO] --- maven-dependency-plugin:3.1.1:tree (default-cli) # project-b ---
[INFO] com.demo:project-b:jar:1.0-SNAPSHOT
[INFO] \- com.demo:project-a:jar:1.0-SNAPSHOT:compile
[INFO] \- mysql:mysql-connector-java:jar:8.0.16:runtime
But if I remove the parent declaration in project-b's pom, the dependency tree of project-b is what I expected:
[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) # project-b ---
[INFO] com.demo:project-b:jar:1.0-SNAPSHOT
[INFO] \- com.demo:project-a:jar:1.0-SNAPSHOT:compile
[INFO] \- mysql:mysql-connector-java:jar:8.0.11:runtime
I also have tried to remove the parent dependency of spring boot in project 1 parent's pom, after reinstalling project 1, and the result is what I expected too. so I guess the parent declaration is the key point, but why?
Best Regards.
This is because parent's dependency has more higher priority than project-a's one.
You can refer to this document.
https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html
Dependency mediation - this determines what version of an artifact will be chosen when multiple versions are encountered as dependencies. Maven picks the "nearest definition". That is, it uses the version of the closest dependency to your project in the tree of dependencies. You can always guarantee a version by declaring it explicitly in your project's POM. Note that if two dependency versions are at the same depth in the dependency tree, the first declaration wins.
"nearest definition" means that the version used will be the closest one to your project in the tree of dependencies. For example, if dependencies for A, B, and C are defined as A -> B -> C -> D 2.0 and A -> E -> D 1.0, then D 1.0 will be used when building A because the path from A to D through E is shorter. You could explicitly add a dependency to D 2.0 in A to force the use of D 2.0.
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.6.RELEASE</version>
Since this module also has a dependency of mysql-connector-java(8.0.16), maven use this instead of project-a's one.
https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-parent/2.1.6.RELEASE
project-b
parent
|----mysql-connector-java(8.0.16) <- maven choose this because its level is higher
|----project-a
|----mysql-connector-java(8.0.11)
Maybe like this..? (please let me know if I'm miss understood)
I have several projects that all have a similar Maven build. Each of the project POMs extend from a parent POM containing all of the common dependencies, plugins, etc. that are available to each project. I also have a multi-module POM, currently separate from the parent POM. The purpose of this multi-module POM is to have a single place I can run a target on all of the modules with one command.
If I try to run a plugin, say JS Duck, off of the multi-module POM, I get the following output (project names changed for simplicity):
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary:
[INFO]
[INFO] Project 1 .......................................... SUCCESS [7.850s]
[INFO] Project 2 .......................................... SUCCESS [0.803s]
[INFO] Project 3 .......................................... SUCCESS [8.488s]
[INFO] Multi-Module POM ................................... FAILURE [0.477s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 22.780s
[INFO] Finished at: Fri Dec 14 09:31:52 EST 2012
[INFO] Final Memory: 17M/81M
[INFO] ------------------------------------------------------------------------
[ERROR] No plugin found for prefix 'jsduck' in the current project and in the plugin groups [org.apache.maven.plugins, org.codehaus.mojo] available from the repositories
It fails because I don't have the JS Duck plugin specified in my multi-module POM.
Why is it trying to run the plugin on the multi-module POM at all?
I can go the other route and include the modules in my parent POM instead of having a separate multi-module POM, but that has a different problem. In that case, the build succeeds because this time the JS Duck plugin is declared in the multi-module/parent POM. However, it runs the JS Duck plugin against the multi-module/parent POM which essentially generates a garbage 'target' directory because there is no code there to analyze.
For reference, my project structure is:
dev
|- Project1
|- pom.xml
|- Project2
|- pom.xml
|- Project3
|- pom.xml
|- pom.xml (parent POM)
|- all-pom.xml (multi-module POM)
Is there any recommended suggestions in this situation? Is there any way to stop Maven from trying to build the multi-module POM itself? Maybe a different <packaging> type that would do that?
Thanks for your suggestions!
[EDIT]
Here is the all-pom.xml... some details changed for privacy.
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.nate</groupId>
<artifactId>projects-all</artifactId>
<packaging>pom</packaging>
<version>1.0</version>
<name>Multi-Module POM</name>
<description>Builds all projects</description>
<modules>
<module>Project1</module>
<module>Project2</module>
<module>Project3</module>
</modules>
<repositories>
...
</repositories>
<pluginRepositories>
...
</pluginRepositories>
</project>
And here is the parent POM... including the addition of child modules.
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.nate.pom</groupId>
<artifactId>js-master</artifactId>
<packaging>pom</packaging>
<version>1.0</version>
<name>JavaScript Project POM</name>
<description>Parent POM for all JavaScript projects.</description>
<!-- inherit license and other company-wide configuration -->
<parent>
<groupId>com.nate</groupId>
<artifactId>master</artifactId>
<version>1.1</version>
</parent>
<modules>
<module>Project1</module>
<module>Project2</module>
<module>Project3</module>
</modules>
<properties>
<release.version>1.0.0</release.version>
</properties>
<scm>
...
</scm>
<issueManagement>
...
</issueManagement>
<ciManagement>
...
</ciManagement>
<developers>
...
</developers>
<build>
<finalName>${project.artifactId}</finalName>
<sourceDirectory>src/main/js</sourceDirectory>
</build>
<profiles>
<profile>
<id>javascript</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
...
</properties>
<dependencies>
...
</dependencies>
<build>
<plugins>
...
<plugin>
<groupId>nl.secondfloor.mojo.jsduck</groupId>
<artifactId>jsduck-maven-plugin</artifactId>
<version>0.1.1-SNAPSHOT</version>
<configuration>
<javascriptDirectory>src/main/js</javascriptDirectory>
<targetDirectory>target/site/api</targetDirectory>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<repositories>
...
</repositories>
<pluginRepositories>
...
</pluginRepositories>
</project>
You can explicitly deactivate the plugin in the all-pom
<plugin>
<groupId>nl.secondfloor.mojo.jsduck</groupId>
<artifactId>jsduck-maven-plugin</artifactId>
<version>0.1.1-SNAPSHOT</version>
<executions>
<execution>
<phase>none</phase>
</execution>
</executions>
</plugin>
The pom which contains the modules list:
<modules>
<module>..</module>
..
</modules>
must have the packaging type pom.