I have 2 Maven projects, A and B. Project A is entirely independent, while B requires A as a dependency. Currently, B is getting A from the maven repository:
<dependency>
<groupId>com.myproject</groupId>
<artifactId>projectA</artifactId>
<version>2.0.0-SNAPSHOT</version>
</dependency>
What I would like to do is set up the dependency such that B can reference the local instance of A. I can do the following:
<dependency>
<groupId>com.myproject</groupId>
<artifactId>projectA</artifactId>
<version>2.0.0-SNAPSHOT</version>
<scope>system</scope>
<systemPath>${basedir}/../projectA/target/projectA-2.0.0-SNAPSHOT.jar</systemPath>
</dependency>
but this only works if A is already built (so projectA-2.0.0-SNAPSHOT.jar already exists).
Is there a way to force A to build before B in cases where I don't already have a build of A?
One way is you create a parent pom, and add these projects as child modules. So, the directory structure would look like this:
+ pom.xml
|
+-A
| \
| + pom.xml
+-B
\
+ pom.xml
The parent pom would have <modules> tag, adding A and B projects as child modules:
<groupId>com.myproject</groupId>
<artifactId>parent</artifactId>
<version>2.0.0-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>A</module>
<module>B</module>
<modules>
And then, add A module as dependency to B module. Just keep the group-id same for parent, A and B. And then refer the module using artifact-id.
pom.xml for B would be like:
<parent>
<groupId>com.myproject</groupId>
<artifactId>parent</artifactId>
<version>2.0.0-SNAPSHOT</version>
</parent>
<artifactId>projectB</artifactId>
<dependencies>
<dependency>
<groupId>com.myproject</groupId>
<artifactId>projectA</artifactId>
<version>2.0.0-SNAPSHOT</version>
</dependency>
</dependencies>
Now, build the parent pom. It will take care of build order.
Related
I am tired of having to manually change the dependency version for every repository and run the build and tests.
Are there any good solutions/tools out there to centralize this, so that you only have to change the version in one file?
A requirement is that you still can override the desired version from the local repository.
In my Maven projects i use a parent pom for dependency management. I use the "dependencyManagement" tag in parent pom for declare al available dependencies and his versions for child modoules.
DIRECTORY HERARCHY
- project-name
- module-A
- pom.xml
- pom.xml
In parent pom.xml I specify the depencyManagement tag:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.test</groupId>
<artifactId>artifact</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
</dependencyManagement>
In module-A pom.xml there is something like:
<parent>
<artifactId>module-A</artifactId>
<groupId>com.test</groupId>
<version>1.0</version>
</parent>
<dependencies>
<!-- The version is inherited from parent pom -->
<dependency>
<groupId>com.test</groupId>
<artifactId>artifact</artifactId>
</dependency>
</dependencies>
This way permits change the version of dependencies only in parent pom.xml. Al child modules will use it.
You can find more details in Maven's official documentation: https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html
I want to use the classes of one child module into another child module present in multi-module maven project. I have followed many existing solution. I am doing exactly same thing as in existing solution. But still it does not works.
Project structure:
Parent A: sampleproject
|-- child A: Gui
|-- child B: calculator
This is how pom.xml of parentA looks like:
<groupId>com.example</groupId>
<artifactId>sampleproject</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>Gui</module>
<module>calculator</module>
</modules>
pom.xml of child A looks like:
<parent>
<groupId>com.example</groupId>
<artifactId>sampleproject</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>Gui</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>calculator</artifactId>
<version>${project.version}</version>
<type>jar</type>
</dependency>
<dependencies>
pom.xml of child B looks like:
<parent>
<groupId>com.example</groupId>
<artifactId>sampleproject</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>calculator</artifactId>
<packaging>jar</packaging>
When I perform mvn install on parent project. jar files are created in calculator/target/name_of_jar.jar and Gui/target/name_of_jar.jar. But when I check in maven dependencies of Gui project, only directory of calculator is created rather than jar file.
Here is image of maven dependencies in Gui project.
Links I have followed: use-a-class-from-the-other-child-module-in-maven and share-classes-within-modules-in-maven-project
It is about Maven POM's
If i would like to have the Version of my Parent also to be the Version of my Dependencies i must set a Property thats value is ${project.parent.version}.
The Problem then happen when a Child of my Main POM (Which has the ${project.parent.version} Property inside of it because it's Parent it some Project I don't Administrate) recalculate the property and think that the value of the created Property is now the version of my Main POM.
--SuperParent (not in my Administration) | Version = 1.2.3
----MainPom | Version = 1.0.0 | Property <test>${project.parent.version}</test> -> 1.2.3
------Child Pom | Version 1.0.0 | Property ${test} is now 1.0.0
<project>
<!-- Super Pom -->
<groupId>groupId</groupId>
<artifactId>artifactId</artifactId>
<version>1.2.3</version>
</project>
<project>
<!-- MainPom -->
<groupId>othergroupId</groupId>
<artifactId>otherartifactId</artifactId>
<version>1.0.0</version>
<parent>
<groupId>groupId</groupId>
<artifactId>artifactId</artifactId>
<version>1.2.3</version>
</parent>
<properties>
<dependency.version>${project.parent.version}</dependency.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>dependencyGroupId<groupId>
<artifactId>dependency</artifactId>
<version>${dependency.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
<project>
<!-- ChildPom -->
<groupId>childGroupId</groupId>
<artifactId>childArtifactId</artifactId>
<version>1.0.0</version>
<parent>
<groupId>othergroupId</groupId>
<artifactId>otherartifactId</artifactId>
<version>1.0.0</version>
</parent>
<dependencies>
<dependency>
<groupId>dependencyGroupId<groupId>
<artifactId>dependency</artifactId>
</dependency>
</dependencies>
</project>
In the End is the Property ${dependency.version} in the Child Pom 1.0.0 instead of 1.2.3.
Is this a wanted behavior of Maven? And what could I to do make it work?
Things that can't be changed:
SuperPom
Main Pom Version
Maven first process inheritance to build the effective pom and then process variables expansion.
In others words, the parent and child pom contents are processed as a single merged file for each child pom. So when your child pom is being processed the ${project.parent.version} is 1.0.0, not 1.2.3.
I couldn't find a way to reference the "grandparent" of a pom, so it seems that the only solution is to put the version as a static number both in the parent.version and properties.dependency.version.
I started to learn maven and now I'm trying to make some realworld projects with beginning simple ones. Maybe it looks simple to most of all in here but I really confused about what should I do if I want to package both parent and children projects at the same time.
(PS: I'm using intellij idea btw)
here is my configuration
Project A
assume that it depends on guava and gson
Project B
it will depend on Project A
Project C
it will depend on Project B
when I set packaging attribute of Project A to jar, it gives an error basically saying that "you must set packaging element as pom if it's in a parent pom". But I know that if I set packaging element as pom it wont create the package.
So I decided to create another project as multimodule to manage the packaging issues but dont figure it out how! Shortly how can I generate jar files for each of them at the same time?
EDIT - HERE IS WHAT I DID
MODULE 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">
<modelVersion>4.0.0</modelVersion>
<groupId>com.deneme.module</groupId>
<artifactId>ModuleGroup</artifactId>
<packaging>pom</packaging>
<version>1.0.1</version>
<modules>
<module>A</module>
<module>B</module>
</modules>
</project>
PROJECT A
<?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>
<groupId>com.mg.A</groupId>
<artifactId>A</artifactId>
<version>1.0.2</version>
<packaging>pom</packaging>
<dependencies>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.2.3</version>
</dependency>
</dependencies>
</project>
PROJECT B
<?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>
<packaging>jar</packaging>
<parent>
<artifactId>A</artifactId>
<groupId>com.mg.A</groupId>
<version>1.0.2</version>
<relativePath>../A/pom.xml</relativePath>
</parent>
<groupId>com.mg.B</groupId>
<artifactId>B</artifactId>
<version>1.0.1</version>
</project>
If your project A declares B and C as modules, it must have the packaging element set to pom. It also means that it shouldn't contains any code and will not generate an artifact by itself. It's merely a way of grouping projects together.
In maven, parent pom are used to define common configuration (properties, etc.) that will be inherited by all children projects.
In your case I would guess that you need a parent project (pom packaging) with 3 childrens : A, B and C :
parentProject
* module A
* module B
* module C
When running mvn install on parentProject, all sub-modules will be built and produce the corresponding jar (say A.jar, B.jar and C.jar ).
Note that you do not need to declare the parent in child pom to achieve this result, you only need to declare them as modules in the parent pom, which is called project aggregation. Declaring the parent in the child is called project inheritance. You can look at the following documentation for more details :
https://maven.apache.org/guides/introduction/introduction-to-the-pom.html#Project_Inheritance_vs_Project_Aggregation
I think you are confusing inheritance and dependency.
Inheritance: A child pom inherits all values, like properties, groupId, version, also dependencies. In general you should not use dependencies in parent poms
Dependency: A pom depends on some other jar/pom and uses it's contents and also uses/depends on transitive dependencies
As far as i understand your problem you have the following:
Project A - a library depending on external packages like gson and guava
Project B - a library depending on Project B, and transitively on gson and guava
Project C - an application depending on Project B, and transitively on Project A, gson and guava
I suggest you use this directory structure:
Workspace
|- ModuleProject
|- ProjectA
|- ProjectB
\- ProjectC
and the poms would look like this (header stripped):
Module pom:
<groupId>com.deneme.projectname</groupId>
<artifactId>ModuleGroup</artifactId>
<packaging>pom</packaging>
<version>1.0.1</version>
<modules>
<module>../ProjectA</module>
<module>../ProjectB</module>
<module>../ProjectC</module>
</modules>
Project A:
<parent>
<groupId>com.deneme.projectname</groupId>
<artifactId>ModuleGroup</artifactId>
<version>1.0.1</version>
<relativePath>../ModuleProject/</relativePath>
</parent>
<artifactId>A</artifactId>
<version>1.0.2</version>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.2.3</version>
</dependency>
</dependencies>
Project B:
<parent>
<groupId>com.deneme.projectname</groupId>
<artifactId>ModuleGroup</artifactId>
<version>1.0.1</version>
<relativePath>../ModuleProject/</relativePath>
</parent>
<artifactId>B</artifactId>
<version>1.0.2</version>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>com.deneme.projectname</groupId>
<artifactId>A</artifactId>
<version>1.0.2</version>
</dependency>
</dependencies>
Project C:
<parent>
<groupId>com.deneme.projectname</groupId>
<artifactId>ModuleGroup</artifactId>
<version>1.0.1</version>
<relativePath>../ModuleProject/</relativePath>
</parent>
<artifactId>C</artifactId>
<version>1.0.2</version>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>com.deneme.projectname</groupId>
<artifactId>B</artifactId>
<version>1.0.2</version>
</dependency>
</dependencies>
I have the following setup:
Master: has modules A and B
A: declares a dependency on B, Master as its parent
B: Master as its parent
So basically Master has a parent pom which builds A and B where A has a dependency on B.
My problem is that I want to put all of the 3rd party dependencies in B (things like JUnit etc.). But when I do this, A does have access to the dependencies declared by B. Why is this happening? I thought maven handles transitive dependencies.
Here are snippets of my poms just in case:
Master:
<modules>
<module>../A</module>
<module>../B</module>
</modules>
A:
<parent>
<groupId>com.project</groupId>
<artifactId>Master</artifactId>
<version>1</version>
<relativePath>../Master/pom.xml</relativePath>
</parent>
...
<dependency>
...
<artifactId>B</artifactId>
...
</dependency>
B:
<parent>
<groupId>com.project</groupId>
<artifactId>Master</artifactId>
<version>1</version>
<relativePath>../Master/pom.xml</relativePath>
</parent>
...
<dependency>
...
<artifactId>JUnit</artifactId>
...
</dependency>
Why doesn't A have access to JUnit?
If the JUnit dependency in Project B has scope 'test' then I don't believe it will be visibile as a transitive dependency in Project A. See the table in Maven Introduction to the Dependency Mechanism: Dependency Scope.