How does Maven handle transitive dependencies inherited from parent? - maven

Given the parent and child pom below and lib1 and lib2 both include the class foo.bar.Test.
parent pom
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>foo</groupId>
<artifactId>foo-parent</artifactId>
<version>1.0</version>
<dependencies>
<dependency>
<groupId>my.transitive</groupId>
<artifactId>lib1</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
</project>
child pom
<project>
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>foo</groupId>
<artifactId>foo-parent</artifactId>
<version>1.0</version>
</parent>
<artifactId>foo-child</artifactId>
<dependencies>
<dependency>
<groupId>my.transitive</groupId>
<artifactId>lib2</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
</project>
If I include foo-child as a dependency in myApp and instantiate foo.bar.Test, which version of the class would Maven resolve to? And why?
my app pom
<project>
<modelVersion>4.0.0</modelVersion>
<artifactId>myApp</artifactId>
<groupId>myApp</groupId>
<version>1.0</version>
<dependencies>
<dependency>
<groupId>foo</groupId>
<artifactId>foo-child</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
</project>

The short answer would be: it depends on which one is found on the classpath first.
Having 2 of the same classes packaged with an application is not ideal as it can lead to many difficult to debug errors... If your myApp project is just going to be a jar then it would be best to compile it using the same library as what is going to be available to it at runtime.
I believe maven uses the order it is written to the pom to build. One way of looking at this would be to run the following command for myApp:
mvn dependency:tree -Dverbose
This will print the dependencies in the order that they should appear on the classpath per spec. You can always use exclusions to exclude any inherited library you might not want. Hope this helps.

Related

I found mvn dependency transitive not work, why it happened?

my project A import a dependency jar B, and B import dependency jar C.they all use compile scope.
when I use "mvn dependency:tree" command to show all the dependencies, I could not found
the jar C in my project. And i also could not saw any jar C in my IDE External Libraries.
Is there some special mechanism in mvn?
I display the code below.
1、project A dependency gfintertrade-common-service-nearby
<parent>
<groupId>com.alipay.findataprod.service</groupId>
<artifactId>findataprod-parent</artifactId>
<version>1.0-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.alipay.findataprod.service</groupId>
<artifactId>findataprod-biz-service-impl</artifactId>
<version>1.0-SNAPSHOT</version>
<name>Alipay findataprod-biz-service-impl</name>
<description>Alipay findataprod</description>
<url>http://home.alipay.com</url>
<packaging>jar</packaging>
<dependencies>
<!-- project depends -->
<dependency>
<groupId>com.alipay.gfintertrade</groupId>
<artifactId>gfintertrade-common-service-nearby</artifactId>
<version>1.0.0.20200930</version>
</dependency>
</dependencies>
2、gfintertrade-common-service-nearby dependency cryptprod-common-service-crypto
<parent>
<groupId>com.alipay.gfintertrade</groupId>
<artifactId>gfintertrade-parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.alipay.gfintertrade</groupId>
<artifactId>gfintertrade-common-service-nearby</artifactId>
<version>1.0.0.20200930</version>
<name>Alipay gfintertrade-common-service-nearby</name>
<description>Alipay gfintertrade-common-service-nearby</description>
<url>http://home.alipay.net</url>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>com.alipay.cryptprod</groupId>
<artifactId>cryptprod-common-service-crypto</artifactId>
<version>1.2.2.20180516</version>
</dependency>
</dependencies>
3、I found project A not dependency cryptprod-common-service-crypto
gfintertrade-common-service-nearby is from remote repository

Compiling classes with dependent jar files in maven

I want to compile some java files which have multiple dependent jars and make a jar file. I have kept all dependent jars under src/main/lib. after running mvn clean install, i get compilation failure of the classes. Dependent jars are not being copied to class path it seems. Anyone can tell whats going wrong her.
<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>test</groupId>
<artifactId>test</artifactId>
<version>1.0</version>
<repositories>
<repository>
<id>external-jars</id>
<name>external-jars</name>
<url>file://${project.basedir}\src\main\lib\</url>
</repository>
</repositories>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>jars</groupId>
<artifactId>jars</artifactId>
<version>1.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/src/main/lib/*</systemPath>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<finalName>finaljar</finalName>
<sourceDirectory></sourceDirectory>
</build>
</project>
You construction
<dependency>
<groupId>jars</groupId>
<artifactId>jars</artifactId>
<version>1.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/src/main/lib/*</systemPath>
</dependency>
does not work. In Maven, each artifact is addressed through groupId, artifactId and version. You cannot add a directory, but only separate jars.
While it is possible to add jars through system paths, it is much better to use a repository. Look at the possibilities in
How to add local jar files to a Maven project?

Avoid wrong version interpolation if child's pom version is different from those of the parent's aggregator pom and its sub modules

Problem description
We have a Maven aggregator pom with some child poms (modules) all having the same version:
pom.xml (parent zoo, version 2.0.0)
|-- pom.xml (child module cat, version 2.0.0)
|-- pom.xml (child module dog, version 2.0.0)
|-- ...
Within the dependency management section all children are declared with the project version to ease declaration of dependencies.
The parent pom looks like
<groupId>com.acme</groupId>
<artifactId>zoo</artifactId>
<version>2.0.0</version>
<packaging>pom</packaging>
<modules>
<module>cat</module>
<module>dog</module>
</modules>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.acme</groupId>
<artifactId>cat</artifactId>
<version>${project.version}</version>
</dependency>
<!-- other child modules go here -->
</dependencies>
</dependencyManagement>
The child poms are defined as
<parent>
<groupId>com.acme</groupId>
<artifactId>zoo</artifactId>
<version>2.0.0</version>
</parent>
<groupId>com.acme</groupId>
<artifactId>cat</artifactId>
<dependencies>
<dependency>
<groupId>com.acme</groupId>
<artifactId>dog</artifactId>
</dependency>
</dependencies>
There is another pom which declares the parent pom as its parent too (inheritance) but is not listed as sub module in this parent (no aggregation). This pom has a different version.
<parent>
<groupId>com.acme</groupId>
<artifactId>zoo</artifactId>
<version>2.0.0</version>
</parent>
<groupId>com.acme</groupId>
<artifactId>boo</artifactId>
<version>1.0.0</version>
<dependencies>
<dependency>
<groupId>com.acme</groupId>
<artifactId>dog</artifactId>
</dependency>
</dependencies>
Actually we have expected that the version of the dependency com.acme.dog is pulled from the dependency management section of the parent pom com.acme.zoo and is equal to 2.0.0. However the Maven documentation on project interpolation and variables says
One factor to note is that these variables are processed after inheritance as outlined above. This means that if a parent project uses a variable, then its definition in the child, not the parent, will be the one eventually used.
That is: in the reactor build the variable ${project.version} used in the dependency management section of the parent pom com.acme.zoo is evaluated with respect to com.acme.bar and equal to 1.0.0 what is not as intended.
Note
There is a workaround with using a variable in the parent pom which has to be kept in sync with the parent pom versions. However, this solution is incompatible with the Maven Release Plugin.
Question
How can we achieve the desired behaviour
aggregator pom with children having the same version
declaration of children in the dependency management section to ensure that all dependencies have the same version
use of inheritance together with different versions
compatibility with maven-release-plugin
without the pitfalls of project interpolation of variables?
The maven release plugin is able to change the versions of the dependencies managed in the parent pom.
So if you define your maven parent like this:
<groupId>com.acme</groupId>
<artifactId>zoo</artifactId>
<version>2.0.0-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>cat</module>
<module>dog</module>
</modules>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.acme</groupId>
<artifactId>cat</artifactId>
<version>2.0.0-SNAPSHOT</version>
</dependency>
<!-- other child modules go here -->
</dependencies>
</dependencyManagement>
As you see the versions of the parent and the managed dependency are the same. I set them to a SNAPSHOT version because the release plugin will create the final versions on release:perform
Your child poms can stay as you had them.
Because in your setup, your parent project is also the reactor you can then call
mvn release:perform -DautoVersionSubmodules=true
which will update the version of the parent in all submodules when you run this command. That option is essentially the same as if you run
mvn versions:update-child-modules
meaning it will change the child poms.
After you run the mvn release:perform command your parent pom will look like this:
<groupId>com.acme</groupId>
<artifactId>zoo</artifactId>
<version>2.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>cat</module>
<module>dog</module>
</modules>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.acme</groupId>
<artifactId>cat</artifactId>
<version>2.0.1-SNAPSHOT</version>
</dependency>
<!-- other child modules go here -->
</dependencies>
</dependencyManagement>
and your child poms like this
<parent>
<groupId>com.acme</groupId>
<artifactId>zoo</artifactId>
<version>2.0.1-SNAPSHOT</version>
</parent>
<groupId>com.acme</groupId>
<artifactId>cat</artifactId>
<dependencies>
<dependency>
<groupId>com.acme</groupId>
<artifactId>dog</artifactId>
</dependency>
</dependencies>
The final versions will only exist in the tag created by the release:prepare command.
PS: You may define other versions for the final and the next development version when they are prompted after running the release:prepare command.
The simplest solution is modify pom of zoo and replace <version>${project.version}</version> with <version>2.0.0</version>
Please note:
when you change version to next number, for example 2.0.1, with
versions-maven-plugin, dependency management section will be also
updated.
Spring use simplest solution, see
http://central.maven.org/maven2/org/springframework/spring-framework-bom/4.2.7.RELEASE/spring-framework-bom-4.2.7.RELEASE.pom
Summary: using <version>${project.version}</version> in dependency management is wrong idea.
From Maven Introduction to the pom : http://maven.apache.org/guides/introduction/introduction-to-the-pom.html
Project Inheritance > Example 1 > The Solution
Alternatively, if we want the groupId and / or the version of your
modules to be the same as their parents, you can remove the groupId
and / or the version identity of your module in its POM.
<project>
<parent>
<groupId>com.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<version>1</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>my-module</artifactId>
</project>
My approach to that is to track it in the child POM. It's a bit less typing overall, close to where the actual dependency lives and is low maintenance for most projects. YMMV
<dependencies>
...
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>foo-sibling</artifactId>
<version>${project.version}</version>
</dependency>
...
</dependencies>

Estructuration of multi module project. how to packaging modules?

i'm creating the estructure of a multi modul project with maven.
The parent's 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>cat.base.gpt</groupId>
<artifactId>gpt</artifactId>
<version>0.0.1</version> <!-- application version -->
<packaging>pom</packaging>
<name>gpt</name>
<parent>
<groupId>cat.base.baseframe</groupId>
<artifactId>projecte-pare-baseframe</artifactId>
<version>0.0.11.a</version>
</parent>
<modules>
<module>gpt.domini</module>
<module>gpt.ui</module>
<module>gpt.logica</module>
<module>gpt.ejb</module>
<module>gpt.ear</module>
</modules>
<dependencies>
<!-- dependencies pel testeig TDD -->
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>6.7</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>1.9.5-rc1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.kubek2k</groupId>
<artifactId>springockito</artifactId>
<version>1.0.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.4</version>
<scope>provided</scope>
</dependency>
<!-- A més, en el cas de provatures UI, s'ha d'afegir la següent dependència:-->
<dependency>
<groupId>cat.base.baseframe</groupId>
<artifactId>baseframe-test-swf</artifactId>
<version>1.0.0-SNAPSHOT</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Ok, first question, i put all the dependencies at paren's pom is this really correct?
and the most interesting part, i don't know hos to compile the grafic interfade project,(i call ui), it's better create a war or create and ear with all the necessary (ui+logica+domini+ejb) i 'm a litlle bit confused about that, i uset o work with projects already estructure created. I hope you to unsderstand my question, i put the rest of pom to keep an eye. ty.
pom's gpt.domini.
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>gpt</artifactId>
<groupId>cat.base.gpt</groupId>
<version>0.0.1</version>
</parent>
<groupId>cat.base.gpt.domini</groupId>
<artifactId>gpt.domini</artifactId>
<packaging>jar</packaging>
<name>gpt.domini</name>
<description>Definició del model de dades i de la façana del servei</description>
</project>
pom's gpt.ear
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>gpt</artifactId>
<groupId>cat.base.gpt</groupId>
<version>0.0.1</version>
</parent>
<groupId>cat.base.gtp.ear</groupId>
<artifactId>gpt.ear</artifactId>
<name>gpt.ear</name>
<packaging>ear</packaging>
<description>Paquet de l'aplicació J2EE</description>
<dependencies>
<dependency>
<groupId>${project.parent.groupId}</groupId>
<artifactId>${project.parent.artifactId}.domini</artifactId>
<version>${project.parent.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>${project.parent.groupId}</groupId>
<artifactId>${project.parent.artifactId}.ejb</artifactId>
<version>${project.parent.version}</version>
<type>ejb</type>
</dependency>
<dependency>
<groupId>${project.parent.groupId}</groupId>
<artifactId>${project.parent.artifactId}.logica</artifactId>
<version>${project.parent.version}</version>
<type>jar</type>
</dependency>
</dependencies>
</project>
pom's gpt.logica
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>gpt</artifactId>
<groupId>cat.base.gpt</groupId>
<version>0.0.1</version>
</parent>
<groupId>cat.base.gtp.logica</groupId>
<artifactId>gpt.logica</artifactId>
<name>climbing.logica</name>
<packaging>jar</packaging>
<description>Implementació del servei</description>
<dependencies>
<!-- de moment nomes el domini -->
<dependency>
<groupId>${project.parent.groupId}</groupId>
<artifactId>${project.parent.artifactId}.domini</artifactId>
<version>${project.parent.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
pom's gpt.ejb
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>gpt</artifactId>
<groupId>cat.base.gpt</groupId>
<version>0.0.1</version>
</parent>
<groupId>cat.base.gtp.ejb</groupId>
<artifactId>gpt.ejb</artifactId>
<name>gpt.ejb</name>
<packaging>ejb</packaging>
<description>Publicació d'un servei en forma EJB</description>
<dependencies>
<dependency>
<groupId>${project.parent.groupId}</groupId>
<artifactId>${project.parent.artifactId}.domini</artifactId>
<version>${project.parent.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>${project.parent.groupId}</groupId>
<artifactId>${project.parent.artifactId}.logica</artifactId>
<version>${project.parent.version}</version>
</dependency>
<dependency>
<groupId>${project.parent.groupId}</groupId>
<artifactId>${project.parent.artifactId}.logica</artifactId>
<version>${project.parent.version}</version>
<classifier>tests</classifier>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.ejb</groupId>
<artifactId>ejb-api</artifactId>
<version>3.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>jboss</groupId>
<artifactId>jboss-annotations-ejb3</artifactId>
<version>4.2.2.GA</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>2.5.6</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.client</groupId>
<artifactId>jbossall-client</artifactId>
<version>4.2.3.GA</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
pom's gpt.logica
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>gpt</artifactId>
<groupId>cat.base.gpt</groupId>
<version>0.0.1</version>
</parent>
<groupId>cat.base.gtp.logica</groupId>
<artifactId>gpt.logica</artifactId>
<name>climbing.logica</name>
<packaging>jar</packaging>
<description>Implementació del servei</description>
<dependencies>
<!-- de moment nomes el domini -->
<dependency>
<groupId>${project.parent.groupId}</groupId>
<artifactId>${project.parent.artifactId}.domini</artifactId>
<version>${project.parent.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
pom's gpt.ui
here all the dependencies of spring-rich.faces..or better at parent's pom?
packaging like a war?? or inside de module ear?? ty.
Although there is already an accepted answer, I believe it worth to give more information to you as it seems to me that, both the questioner and the accepted answer got messed up with different concepts in Maven.
1) Aggregation vs Parent POM
There are two concepts in Maven often got mixed up. Aggregation (aka Multi-module) POM and Parent POM are something irrelevant, although it is fine to use one POM to serve for both purpose.
Multi-module project aims to describe the aggregation relationship between projects, so that we can build multiple related project as a whole, and all sub-projects are built in the same reactor. Parent project aims to provide shared project settings. It can even exists out of the project structure (e.g. I may have a company-wise parent POM)
Personally I recommend to have a multi-module POM only to declare the aggregation (hierarchy) of projects, and having a separate parent POM to be used to declare shared settings.
i.e.
my-proj // aggregation only
+ my-proj-parent // parent POM
+ my-proj-main
+ my-proj-web
+ my-proj-ear
2) Shared Dependency for POM vs in EAR
Again, these are two separate concepts.
It is fine to put dependencies in parent POM. When you put it there, it means the inherited project is going to have such dependency. There is no right or wrong on this, as long as you know what you are doing (personally I am using different way, will be described later).
However, whether to put shared JARs in EAR and keep skinny WAR, or have a plain EAR with a "full" WAR has nothing to do with your dependency. It is more about the packaging strategy of EAR. Therefore, changing scope of Maven dependency just because you are going to package the project as skinny war, such approach is simply messing up the whole concept of maven dependency. Even more horrible is, when creating your EAR, you need to find out all the dependencies of its included WARs and add it one by one to the EAR POM, that's doubtless not an optimal solution
A pity that current Maven EAR plugin still has no way to declare a skinny war packaging strategy. However there are some workarounds which allow you to do so, without messing around the Maven dependency scope. http://maven.apache.org/plugins/maven-ear-plugin/examples/skinny-wars.html http://maven.apache.org/plugins/maven-war-plugin/examples/skinny-wars.html
(Update: The skinny war receipe seems updated and one of the workaround seems gone. http://docs.codehaus.org/display/MAVENUSER/Solving+the+Skinny+Wars+problem?focusedCommentId=212631587#comment-212631587 This is to include WAR type POM as POM type, so that we do no need to declare the dependencies again in EAR)
3) Use of shared dependencies in parent POM
As I mentioned before, there is no right or wrong to put dependencies in parent. However you should know that, such way actually means all inherited project is going to have such dependency, which is mostly incorrect.
for example, I have a foo-a and foo-b projects under foo, which both inherits foo-parent. Assume foo-a is using spring-core while whole logic of foo-b has nothing to do with it, if you put spring-core as dependency in foo-parent, when you look at foo-b, it is unncessarily having unrelated dependencies spring-core.
The proper way to do is only include dependencies (and other settings) in parent POM that should be shared across all inherited projects. For example, unit testing related dependencies may be a good choice. Dependencies for integration testing may be another example.
However, it doesn't mean we should declare dependencies in each project individually. One of the biggest problem is such approach is going to be hard to maintain same version of dependencies across the whole project.
In order to solve such issue, my recommendation is to make use of dependencyManagement in parent POM, which declares the version (and maybe other settings like scope, excludes). Declaring dependencyManagement is not introducing actual dependencies in inherited POM. It simply declare: "If you declare such dependency, this will be the settings to use". In each inherited POM, simply declare the dependencies' group and artifact (and maybe some project specific settings), so that you can follow the version declared in parent POM.
Maybe a bit hard to understand, here is an example:
foo-parent
<project>
<dependencyManagement> // dependency management doesn't bring actual dependency
<dependencies>
<dependency>
<groupId>org.springframework<groupId>
<artifactId>spring-core<artifactId>
<version>3.1.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.hibernate<groupId>
<artifactId>hibernate-core<artifactId>
<version>3.6</version>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies> // actual shared dependency
<dependency>
<groupId>junit<groupId>
<artifactId>junit<artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
.....
<project>
foo-a
<project>
<dependencies>
<dependency> // note: no version declared
<groupId>org.springframework<groupId>
<artifactId>spring-core<artifactId>
</dependency>
// junit dependency is inherited
<dependencies>
<project>
Ok, first question, i put all the dependencies at paren's pom is this
really correct?
No, your shared dependencies should be put in the ear pom. In the other poms you have to reference the shared dependencies using <scope>provided</scope>.
For example in your ear pom add a dipendency:
<dependency>
<groupId>somegroup</groupId>
<artifactId>someartifact</artifactId>
<version>1.0</version>
</dependency>
In the logica and ui module pom, for example, add these lines:
<dependency>
<groupId>somegroup</groupId>
<artifactId>someartifact</artifactId>
<version>1.0</version>
<scope>provided</scope>
</dependency>
In this way the dependency artifact is added only once in the ear package.
and the most interesting part, i don't know hos to compile the grafic
interfade project,(i call ui), it's better create a war or create and
ear with all the necessary (ui+logica+domini+ejb) i 'm a litlle bit
confused about that, i uset o work with projects already estructure
created. I hoper unsderstand my question, i put the rest of pom to
keep an eye. ty.
I don't know if I understand it right. EAR is better suited for project that can have multiple war and/or ejb modules. In your case you can get rid of modularization at all and use a single war package.
finally this is my ear's pom.
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>gpt</artifactId>
<groupId>cat.base.gpt</groupId>
<version>0.0.1</version>
</parent>
<groupId>cat.base.gpt.ear</groupId>
<artifactId>gpt.ear</artifactId>
<name>gpt.ear</name>
<packaging>ear</packaging>
<description>Paquet de l'aplicació J2EE</description>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>gpt.domini</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>gpt.ejb</artifactId>
<version>${project.version}</version>
<type>ejb</type>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>gpt.logica</artifactId>
<version>${project.version}</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>gpt.ui</artifactId>
<version>${project.version}</version>
<type>war</type>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-ear-plugin</artifactId>
<configuration>
<description>GPT</description>
<displayName>Gestió posicions tributarias</displayName>
<encoding>${project.build.sourceEncoding}</encoding>
<version>1.4</version>
<generateApplicationXml>true</generateApplicationXml>
<modules>
<ejbModule>
<groupId>${project.groupId}</groupId>
<artifactId>${project.parent.artifactId}.ejb</artifactId>
<bundleFileName>${project.parent.artifactId}-ejb.jar</bundleFileName>
</ejbModule>
<jarModule>
<groupId>${project.groupId}</groupId>
<artifactId>gpt.logica</artifactId>
<includeInApplicationXml>true</includeInApplicationXml>
</jarModule>
<webModule>
<groupId>${project.groupId}</groupId>
<artifactId>gpt.ui</artifactId>
<contextRoot>/gpt</contextRoot>
</webModule>
</modules>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<configuration>
<excludeScope>runtime</excludeScope>
</configuration>
</plugin>
</plugins>
</build>
</project>

Maven 3 regression: Profile dependencies lost?

I observed a change behavior between Maven 2 and Maven 3. Is this a bug or a feature? I couldn't find anything in the Maven 3.x Compatibility Notes
I use two different profiles to add dependencies for different environment in a multi-module project.
parent-pom:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>group</groupId>
<artifactId>main</artifactId>
<packaging>pom</packaging>
<version>1.0.0-SNAPSHOT</version>
<modules>
<module>common</module>
<module>portal</module>
</modules>
</project>
The common-pom has the profile in it:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>group</groupId>
<artifactId>common</artifactId>
<packaging>jar</packaging>
<version>1.0.0-SNAPSHOT</version>
<parent>
<groupId>group</groupId>
<artifactId>main</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<profiles>
<profile>
<id>development</id>
<dependencies>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.14</version>
</dependency>
</dependencies>
</profile>
<profile>
<id>production</id>
<dependencies>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.1</version>
</dependency>
</dependencies>
</profile>
</profiles>
</project>
The portal-pom has only the common dependency and should include the transitive dependency from the common module:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>group</groupId>
<artifactId>portal</artifactId>
<packaging>war</packaging>
<version>1.0.0-SNAPSHOT</version>
<parent>
<groupId>group</groupId>
<artifactId>main</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<dependencies>
<dependency>
<groupId>group</groupId>
<artifactId>common</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
Building this project (from the parent) via Maven2 mvn -P production package results in a WAR which includes the transitive dependency. (I used those simple dependencies for easy reproduction)
Executing via Maven3, I get only the common.jar in the WAR, but not the transitive dependency.
Is this a desired behavior?
To make things even "interesting": If one of the profiles is activated by default (explicit in the common-pom as the activation is not derived from the parent to the child modules) these transitive dependencies are always add to the portal.
But filtering or property-setting via profiles works as expected.
This comment solves it the one way:
the situation described above does work when profile activation using properties is used
With property activation (and not via -P) it works in Maven2 and 3
But the real solution was "caused" by the release plugin:
The profile must be submitted to release-plugin via
-Darguments=-Pproduction
Not a solution, but your use case looks similar to this open maven bug. Interestingly, according to the bug details, it happens on earlier maven versions as well.

Resources