Are Maven repository declarations transitive? - maven

Suppose I have the following project, a library which declares some 3rd party repository that it needs to use to grab an artifact.
<project ...>
<groupId>com.mygroup</groupId>
<artifactId>library</artifactId>
<version>1.0.0</version>
<repositories>
<repository>
<id>some-id</id>
<url>https://some.repo.com</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>com.thirdparty</groupId>
<artifactId>used-at-compile-time</artifactId> <!-- like Lombok, say -->
<version>1.0.0</version>
<scope>provided</scope> <!-- so, not transitive -->
</dependency>
</dependencies>
</project>
Then I have a totally separate project which depends upon that library
<project ...>
<groupId>com.mygroup</groupId>
<artifactId>some-app</artifactId>
<version>2.0.0</version>
<dependencies>
<dependency>
<groupId>com.mygroup</groupId>
<artifactId>library</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
</project>
Does Maven try to include the repository definition in all dependent projects? Will some-app ever try to access https://some.repo.com?
I'd always been under the impression that this didn't happen, but I've started seeing build failures which contract that belief.
It might initially seem convenient if that's how it worked, but what if the repo was internal and was not publicly accessible over the internet? The project which declared it might use it for some compile-time dependencies, like in my example above. If that repo were dragged in, the dependent project might try to access a repository that it can't for some other non-Maven Central dependencies.
So I can see valid reasons for either behaviour, but as far as I can see, the documentation for repositories doesn't say one way or another what happens, and neither does the POM reference.

Repositories are context aware, in the context of their pom. Dependencies from com.mygroup:library can use the repo's central and some-id.
On the other hand, dependencies from com.mygroup:some-app will only use central.
When running Maven from the commandline, you'll see the repositories it'll try to download the artifacts from (in case the first one fails, it'll go for the next).
When publishing to Central, there are several requirements. However, based on the last paragraph repositories are not banned, you're advised not to use them.
You might wan't to read this classic article: Why Putting Repositories in your POMs is a Bad Idea

Related

Maven BOM-of-BOM to capture submodules

I'm trying to make an internal-bom of related Maven projects, many of which have their own sub-modules. I don't want to reference every sub-module so am looking to produce a bom-of-bom using their reactor.
To the best of my knowledge, Maven's <scope>import</scope> inlines the <dependencyManagement> of a given artifact. I would like something similar that pulls in (only) the modules of a POM. It is not uncommon for a reactor to also be a parent which manages common external dependencies as well as inter-module references. internal-bom should not have any external references.
<!-- Couldn't Maven declare a new scope that inlines GAV references of these modules :( -->
<modules>
<module>apple</module>
<module>banana</module>
</modules>
<dependencyManagement>
<dependencies>
<!-- Here are the module dependencies we'd like -->
<dependency><groupId>${project.groupId}</groupId><artifactId>apple</artifactId><version>${project.version}</version><dependency>
<dependency><groupId>${project.groupId}</groupId><artifactId>banana</artifactId><version>${project.version}</version><dependency>
<!-- Here are an arbitrary number of common externals -->
<dependency><groupId>org.junit</groupId><artifactId>junit</artifactId><version>4.11</version><dependency>
</dependencies>
</dependencyManagement>
Is there any way to achieve this? I'm aware I could update every project to also include a project-bom module that only has those module references. It's a lot of busy-work for little gain.
The question is probably coming from the same thought as Maven BOM: Super BOM which gathers all BOMs? and Publish a bom from a multi-module-project

Maven doesn't find an existing remote artifact

I'm trying to use docker-compose-rule to run docker-compose files in junit integration tests.
I use the following dependency in my pom.xml file:
<dependency>
<groupId>com.palantir.docker.compose</groupId>
<artifactId>docker-compose-rule-core</artifactId>
<version>0.32.0</version>
<type>pom</type>
</dependency>
<!-- https://mvnrepository.com/artifact/com.palantir.docker.compose/docker-compose-rule-junit4 -->
<dependency>
<groupId>com.palantir.docker.compose</groupId>
<artifactId>docker-compose-rule-junit4</artifactId>
<version>0.32.0</version>
</dependency>
but for some reason the artifact is not found by maven (for none of the available versions).
As far as I can say, the artifact is found in the jcenter as shows in bintray.
It also exists on maven repository.
Can someone please tell why can't I use these libraries?
Alternatively, can I reference maven to take the library from a specific url with a specific jar file, for example from github, or from here?
According to mvnrepository, the jar you are looking for is not in the maven default Central repository, but is in the Palantir repository. You can add
<repositories>
<repository>
<id>Palantir</id>
<url>https://dl.bintray.com/palantir/releases/</url>
</repository>
</repositories>
into your pom.xml, and try again.

Relative path for Maven pom versions

Forgive my ignorance here, as I'm new to maven. I have a Remote Repository that my project pom is using to download dependencies from. A general structure of my pom.xml is like this:
<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>MVNProject</groupId>
<artifactId>MVNProject</artifactId>
<version>0.0.1</version>
<packaging>war</packaging>
<dependency>
<groupId>org.scala-lang.modules</groupId>
<artifactId>scala-parser-combinators_2.11</artifactId>
<version>1.0.1</version>
</dependency>
</dependencies>
</project>
Now I know that if I have to get a new version of the dependency scala-parser-combinators I just have to specify the new version. Something like this:
<dependency>
<groupId>org.scala-lang.modules</groupId>
<artifactId>scala-parser-combinators_2.11</artifactId>
<version>1.0.1</version>
</dependency>
But what I would like to do is, without making any change to pom.xml I'd like to replace my old jar with the upgraded jar in my remote repository(which I'm able to do).
So what I'd like to know is whether there is a way to specify in pom to take whatever version is available in the remote repository for a particular artifact i.e., something like this(and this is just a guess):
<dependency>
<groupId>org.scala-lang.modules</groupId>
<artifactId>scala-parser-combinators_2.11</artifactId>
<version>${CurrentVersion}</version>
</dependency>
Some guidance would be very much appreciated.
If you are using maven2, then using LATEST or RELEASE value in version tag can solve the dependency updation automatically. Albeit , this solution will not work in maven3 (it is deprecated).
If you are using maven3, then you have to update the settings.xml a bit. The snapshots repository will get an addition updatePolicy tag. Something like this:-
<repositories>
<repository>
<id>you-snapshots</id>
<url>http://host/nexus/repos/snapshots</url>
<snapshots>
<updatePolicy>always</updatePolicy>
</snapshots>
<releases>
<updatePolicy>always</updatePolicy>
</releases>
</repository>
</repositories>
Also , There is a Versions plugin for Maven which allows you to update your pom to the latest greatest SNAPSHOTS in visible repositories. It does this by inspecting your pom and comparing against remote repositories and then modifying as required.
It is a useful tool but I would definitely like to see an equivalent to the deprecated LATEST option. I find this kind of dependency particularly useful in continuous integration scenarios.
Some things to notice:
You should not delete a specific release version of an artifact from a remote repository and replace it, like having 1.0.1 in your remote repository, removing it and uploading a different artifact under 1.0.1 again. Maven caches release versions in the local repository, so you will never know which artifact you get.
If you have a newer version, give it a newer version number (like 1.0.2).
Now the way to go is not to use RELEASE or LATEST, but to use the versions plugin to update your dependencies (like versions:use-latest-releases).

Update pom to use released versions

Trying to find a way to update a pom to use latest versions of a RELEASED dependency instead of SNAPSHOT.
We have a assembly project that assembles an image to be deployed that during development uses SNAPSHOT dependencies.
But now I want to update the dependencies to use the latest released dependencies. Tried using versions:use-latest-releases but it only affects already released versions in the pom.
Any ideas?
EDIT (can not for security reasons post the pom but here's an example)
<project>
....
<dependencies>
<dependency>
<groupId>a.b.c</groupId>
<artifactId>c-d-f</artifactId>
<version>1.0.1-SNAPSHOT</version>
<type>war</type>
</dependency>
<dependency>
<groupId>a.b.c</groupId>
<artifactId>g-h-i</artifactId>
<version>1.1.6-SNAPSHOT</version>
<type>war</type>
</dependency>
...
</dependencies>
...
</project>
Given that component a-b-c and g-h-i has been released with version 1.0.1 and 1.1.6 I want to replace their versions in this pom with these version numbers. Basically remove any snapshot dependencies in the pom.
EDIT
I should add that is to be an automated process with minimal human interaction. For some reason I can only get versions:update-properties to work if versions are already in release state. If I have a snapshot version 0.0.1-SNAPSHOT and want to update it to 0.0.1 it doesn't happen and I have verified the release exists. Same thing with versions:use-latest-relese, and versions:use-releases does nothing at all.
I see two approaches here:
You can create multiple profiles in your maven pom. Best way is to create a profile of "snapshot" and one for "release". Described here: Different dependencies for different build profiles in maven
You can use maven pom properties to define variables for your dependency versions. See here: http://books.sonatype.com/mvnref-book/reference/resource-filtering-sect-properties.html#resource-filtering-sect-user-defined
Hope that helps!
You can use maven properties in your pom.xml, such as:
<properties>
<c-d-f.version>1.0.1-SNAPSHOT</c-d-f.version>
<g-h-i.version>1.1.6-SNAPSHOT</g-h-i.version>
</properties>
<dependencies>
<dependency>
<groupId>a.b.c</groupId>
<artifactId>c-d-f</artifactId>
<version>${c-d-f.version}</version>
<type>war</type>
</dependency>
<dependency>
<groupId>a.b.c</groupId>
<artifactId>g-h-i</artifactId>
<version>${g-h-i.version}</version>
<type>war</type>
</dependency>
...
</dependencies>
and when you want to change the versions, you can use maven-versions-plugin, with the following command, such as:
versions:update-properties -Dproperties=[${release_version}] -DincludeProperties={c-d-f.version}
EDIT:
Note that if you wanna use SNAPSHOTS, you need to add -DallowSnapshots. Read here for more options. And yes, the version needs to exist in the repo, otherwise it will fail. BTW did you use brackets, such as -Dproperties=[0.0.1]? after you read the link I sent you, you will see that this commmand's input is a range, so you must use brackets in order to specify a unique version.

Set Maven dependency versions in properties file

We have a couple of different applications which may or may not interact together. When they interact together, there have been issues because of mismatch in third party library versions (Let it be Spring or something else).
The pom files for these applications are separate, but to solve the above issue, we want them to use the same versions of third party libraries. The easiest way to do this is to specify the versions in common properties file, and then let respective pom.xml read the versions from the properties file.
Usually I am used to specify the versions as properties in the parent pom, and let the module pom read it from there. Is there a way I can make pom.xml read the properties file for reading the versions?
Some projects, e.g. spring-cloud and spring-boot, express their 'release train' (a set of dependencies and their versions that are known to work well together) in a 'BOM' (bill of materials). The BOM is nothing but a POM with only a dependencyManagement section, where all these dependencies are listed with the correct version. That BOM is then included in each project's POM that should follow these dependencies/versions in its dependencyManagement section, with scope 'import'.
E.g.
You create your separate project 'my-bom', containing only a pom like this:
<project>
<groupId>your.organication.program</groupId>
<artifactId>my-bom</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.whatever</groupId>
<artifactId>somedependency</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>com.whatever</groupId>
<artifactId>someotherdependency</artifactId>
<version>4.5.6</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
And then you include that in each project that should be aligned with these dependencies/versions:
groupId>your.organication.program.project</groupId>
<artifactId>some-project</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>your.organisation.program</groupId>
<artifactId>my-bom</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencyManagement>
Within the projects the dependencies that are effectively used must still be referenced in dependencies-section, but without the version - the versions are managed by the BOM.

Resources