How to handle two Maven submodules that share a code dependency - maven

I have what I think is a fairly common setup. I have a project with two modules, each with its own pom.xml. Above that, I have a pom.xml for the project, which depends upon its submodules. The two submodules have a shared dependency, namely log4j. How should I deal with this dependency? Should I simply just have each submodule have log4j as a dependency, or should the higher level project module get involved, claiming it as a project dependency? If I have both submodules listing the dependency, will Maven be smart and only pull down log4j once, or will each submodule pull down its own private copy of log4j ? If the project module has the dependency, will the log4j package be available at the right time for the submodules? What would you do, or what have you done in this situation?

The best way to do this is with the dependencyManagement tag.
The dependency management section is a mechanism for centralizing dependency information. When you have a set of projects that inherits a common parent it's possible to put all information about the dependency in the common POM and have simpler references to the artifacts in the child POMs.
To summarize the effect, you put the tag in the parent pom and have the children refer to it. They don't refer to the version number though. The benefit is at any time you can update the version of log4j in the parent pom and all your child poms get the new version without modifying their poms.

You are able to set the dependency at the higher level project. This will cover the dependency for both modules of your project.
Source: This is what my team does in one of our projects.

Related

How two know when a maven project has the same transitive dependenciy twice of different versions?

I have to add a new dependency to a maven project. This dependency has four transitive dependencies(according to http://mvnrepository.com/) and between them, there is spring-data-jpa jar.
The maven project I am working in has many dependencies configured in the pom so I understand there could be a big possibility that there is already a spring-data-jpa dependency in the project(transitive or not).
When you work in a large project with many dependencies and you have to add a new one, how to check if there is already the same transitive dependency of a different version? I have to check manually the transitive dependencies for each direct dependency configured? Has maven a warning for this situation?
How maven works in this situation? I mean, there could be two spring-data-jpa jars of different versions(this would be a problem) or maven resolves this in another way?
The simple answer is that the dependency plugin can tell you. The longer answer is that there are a number of different situations to consider about transitive dependency management, and how the plugin helps and what to do about it differs for each one.
Maven automatically chooses which dependency to include if two dependencies have the same coordinates (groupId, artifactId) with different versions. Broadly speaking, it picks the version that's highest in the tree - effectively overriding dependencies defined in downstream transitive dependency poms. So, if you have two different versions of exactly the same dependency then you will still only find one version of the dependency on the relevant classpath.
The dependency plugin can help you identify this situation by highlighting points where its made a decision, but you probably want to use the dependencyManagement section of your top-level pom to ensure that the dependencies which you bring in are the ones you expect.
Separate difficulties can arise when a dependency changes its groupId or artifactId. Then you can get two dependencies on the classpath - one with an old version on the old coordinates and one with the new version on the new coordinates. As examples, Spring, Hibernate and Apache commons have all found themselves doing this at some point or another. In this case all you can do is use to the dependency plugin to identify duplicated dependencies and then use exclusions tags to explicitly exclude them as transitive dependencies from the dependencies which are pull them in.
It's important to note that all of this dependency management can cause unintended breakage. If the thing that your application depends on really does depend on some specific version of a package as a transitive dependency then you can break it by overriding that version. So testing the features that you use is essential.
Have you tried the Maven Dependency Plugin? There's some useful goals you can run, such as mvn dependency:tree etc.

Prevent usage of unmanaged dependencies in modules of maven project

For my project, I would like to prevent in maven modules the usage of dependencies that would not be declared in the dependencyManagement in the parent pom, is there a way to achieve this ?
Thanks
First, you will never be able to completely block the user to add dependency.
User can still add the jar manualy in his code.
Secondly yo can also decompres a module jar and put it in your project.
(actually the same as with a ant build)
It's a good start to maintain a central place with all the version of your dependencies. In a kind of "corporate parent pom".
If your company have a nexus/artifactory, you can "close the door" at that point.
I think that's utopic to have the same version of your dependencies for all your applications. You always want to be able to use the latest feature of the latest version of the dependency.

How to deploy a parent pom file without executing plugins

I am doing some re-factoring to use parent poms and put common configuration in a common place.
I have a separate git repo to house the parent poms. Some of the common configuration specifies directories/files that will exist relative to the child projects, but not relative to the parent pom (they are in different git repos).
When I try to deploy the pom, one of the plugins is failing because the path does not exist.
How is this supposed to work?
I'd expect that if the artifact has "pom" packaging then it wouldn't actually try to run the plugins (at least that is what I want). Or do the plugins I use need to be responsible for knowing that it is a "pom" artifact?
The parent should, probably, only have pluginManagement, not plugin.
The pluginManagement section of the parent pom is used to share plugin versioning and base configuration across modules. This is in line with the dependency management section of the parent, which allows you to configure versions and exclusions across modules. For example, you could configure the site plugin in the parent to provide a standard look and feel across all modules, while the modules override the site plugin with module specific details.

maven import scope and profiles

i have a maven multi-module project:
root
commons
common-module
plugins
plugin
commons and plugins don't have the same parent, and are "standalone".
in commons-module i define 2 profiles, projectA and projectB. in each of these profiles i define properties, such as dep.version, dep1.version etc...
later i use these properties in dependencyManagemnt for the version part in the dependencies of "dep" and "dep1" section.
in plugins (who is parent for plugin) i have a dependency scope import on commons-module to obtain the list of dependencies.
when i build the plugin module, it doesn't seem to matter if i do -PprojectA or -PprojectB: maven says they don't exist. they do exist, but in commons module, which i import.
so the dependencies i get don't have the correct versions when i mvn dependency:tree
is what i'm trying to achieve possible, am i don't something wrong, is this a maven bug, or a none-supported feature? anyone got a clue?
thanks,
Nathan.
Import scope only imports the dependencyManagement, not the dependencies themselves. You still need to declare the dependency on the artifact, and then the version, and scope etc will be picked up from the dependencyManagement.
I don't think import will work for pluginManagment sections. The documentation you linked to only mentions dependencyManagement, and the only other mention I've seen is this unanswered question to the mailing list.
Dependencies aren't allowed to change the POM of modules that simply use those dependencies. It wouldn't be a safe thing to do. Imagine that you're adding another dependency to your project, and suddenly the build stops working because the dependency actually overrides some of your settings.
POM interpolation inherits settings only from ancestor projects, going up the <parent> chain.
You are trying to use the import scope with profiles. However, profiles are not activated transitively, so the different dependencies in your import-scoped dependency's POM aren't being activated.
It's probably not recommended, but you could have two different commons modules, and include the import-scoped dependency in profiles that refer to one or the other in your current project.

Maven - include all submodules of a pom as dependencies in another module

We have a maven module that is set up as so:
a (parent)
-> b (submodule)
-> c (submodule)
-> d (submodule)
This list of submodules is set to grow as time goes on (to a list of 20 or so). We have another module that will include as dependencies all submodules of a. Is there a neat way of doing this, rather than having to manually keep the submodule list in sync with the dependencies list. I.e. is there any way of including a and all submodules as a dependency?
You have a few choices here:
No change. List all dependencies in each pom. However, if they have a common parent, you can use dependencyManagement in the parent pom to set the versions for the different dependencies. In the child poms, you do not need to list the version. See this section from Maven By Example. A downside of this approach is that you have to re-list the same dependencies over and over.
Create a parent pom which lists all shared dependencies. See an example here. A downside here is you are restricting all projects that want to take advantage of this to use a parent project when they may need to use another parent project for some reason.
Wait for Maven mixins, which last I heard were still not ready.
Rethink your design. Does it make sense for projects to depend on so many different modules and interfaces? To reduce coupling, you may want to create one interface that these new projects can use. Several open source multi-module projects, such as Apache Axis2, follow this pattern. One module contains your 20 dependencies and exposes an interface which the new modules can call. The new modules can just list that one main module as a dependency and all of the 20 dependencies are pulled in as transitive dependencies.
I think choice #4 is probably right, but I am not familiar enough with your situation.
Design considerations aside, this is easily done - simply include <type>pom</type> in your dependency pointing at the parent pom. E.g:
<dependency>
<groupId>my.group.id</groupId>
<artifactId>a</artifactId>
<version>0.0.1-SNAPSHOT</version>
<type>pom</type>
</dependency>
The only way dependencies get "automatically" included is via the transitive dependency mechanism, and it only works by pulling in dependencies of dependencies, so unless you have a pom that depends on all the submodules, no, you won't get them without listing them all out. A need to do this points to a flaw in your project design. If the modules are "all or none", then they're probably not separate modules.

Resources