Download Maven artifact with version range - maven

I need download specific Maven artifact using version range e.g.:
GroupId:org.apache.logging.log4j
ArtifactId=log4j-api
Version=[2.17.1,)
Right now I need it in one CI job.
How can I do it?

I was hoping to find an easier solution, but at least this works:
Create pom.xml file
<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>cz.vondr</groupId>
<artifactId>maven-dependency-download</artifactId>
<version>1.0.0</version>
<properties>
<dep.group>org.apache.commons</dep.group>
<dep.artifact>commons-lang3</dep.artifact>
<dep.version>3.12.0</dep.version>
<dep.type>jar</dep.type>
<dep.classifier></dep.classifier>
</properties>
<dependencies>
<dependency>
<groupId>${dep.group}</groupId>
<artifactId>${dep.artifact}</artifactId>
<version>${dep.version}</version>
<type>${dep.type}</type>
<classifier>${dep.classifier}</classifier>
</dependency>
</dependencies>
</project>
And then use it to download artifact using command:
mvn dependency:copy-dependencies "-DoutputDirectory=./downloaded-dependencies" -Ddep.group="org.apache.logging.log4j" -Ddep.artifact="log4j-api" -Ddep.version="[2.17.1,)"
Additional information
Basic description is here:
http://vondrnotes.blogspot.com/2022/09/download-maven-artifact-with-version.html
Working example is here:
https://github.com/bugs84/download-maven-dependency-with-version-range

Related

How to find the source for an artifact version in Maven?

Assuming I have Maven pom (let's say Maven 3.8) 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>
<parent>
<groupId>some.group</groupId>
<artifactId>my-parent</artifactId>
<version>1.0.0</version>
</parent>
<artifactId>my-app</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>some.group</groupId>
<artifactId>my-artifact</artifactId>
</dependency>
</dependencies>
</project>
...where my-parent has a dependency management section, maybe bom imports and further parents up the chain with it's own dependency management sections, how can I find the source of the version of some.group:my-artifact that actually used in the child pom?
Let's say, I build this and see that the effective pom contains version 1.2.3 for this artifact, how can I find out the pom that actually contains that version?

How to configure/override Maven property used as parent version in dependencies?

Suppose there are two 3rd-party Maven artifacts with the following POM.XMLs:
artifact1 POM.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>group1</groupId>
<artifactId>artifact1</artifactId>
<version>${artifact1.version}</version>
<packaging>pom</packaging>
<properties>
<artifact1.version>0.0.1-SNAPSHOT</artifact1.version>
</properties>
<modules>
<module>../artifact2</module>
</modules>
artifact2 POM.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>
<artifactId>artifact2</artifactId>
<parent>
<groupId>group1</groupId>
<artifactId>artifact1</artifactId>
<version>${artifact1.version}</version>
<relativePath>../artifact1</relativePath>
</parent>
They are built normally using
mvn clean install
Now, if I try to reuse artifact2 in a 3rd POM.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>group2</groupId>
<artifactId>artifact3</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>group1</groupId>
<artifactId>artifact2</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
After executing...
mvn clean install
...the build fails trying to locate group1:artifact1:pom:${artifact1.version}
[ERROR] Failed to execute goal on project artifact3: Could not resolve dependencies for project group2:artifact3:jar:0.0.1-SNAPSHOT: Failed to collect dependencies at group1:artifact2:jar:0.0.1-SNAPSHOT: Failed to read artifact descriptor for group1:artifact2:jar:0.0.1-SNAPSHOT: Could not find artifact group1:artifact1:pom:${artifact1.version} in central (https://repo.maven.apache.org/maven2) -> [Help 1]
And setting the property in the command-line doesn't work either:
mvn clean install -Dartifact1.version=0.0.1-SNAPSHOT
How can I use artifact2 as a dependency?
<parent> doesn't allow variables. Because in order to get a list of variables Maven first has to build Effective POM and for this it needs to resolve parents.
Even if there is some version of Maven that allowed such module to be installed it's not a working solution in general. Maven's ideology is that all the dependencies (including parent) could be downloaded from a repo and are not necessarily present on local FS/in the reactor. With properties in the parent dependency definition you violate this rule.

how to automatically update maven dependencies in a multi-level project?

At my workplace, different groups works on providing different services.
My team consumes these services. Currently, whenever a new version of Service is rolled out, we manually change the pom.xml to the latest version of dependency and then make a build. I am wondering if there is an automatic way of pulling latest release into build.
Here is an example to explain:
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">
<groupId>com.company.product</groupId>
<artifactId>User-Application</artifactId>
<version>1.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<Service1-version>1.0.2</Service-1>
<Service2-version>1.1.2</Service-2>
<Service3-version>2.0.2</Service-3>
</properties>
<dependencies>
<dependency>
<groupId>com.company.product</groupId>
<artifactId>Service1</artifactId>
<version>${Service1-version}</version>
</dependency>
<dependency>
<groupId>com.company.product</groupId>
<artifactId>Service2</artifactId>
<version>${Service2-version}</version>
</dependency>
<dependency>
<groupId>com.company.product</groupId>
<artifactId>Service3</artifactId>
<version>${Service3-version}</version>
</dependency>
.....
....
</project>
When new release of each service is made, we manually change the pom.xml to get the latest dependency. How can this be managed automatically?
The versions-maven-plugin should be able to do this with the task versions:update-properties. See an example here.

Different result by different profile activate method?

I have been using maven for about two years, but I don't think I understand profiles in maven exactly, especially when I encounter the following problem.
I have a maven project with three modules, secweb-parent, secweb-service and secweb-web, secweb-sevice depends on spring-webmvc, and secweb-web depends on secweb-service.
The problem is :
1) When I use 'mvn clean install -Dinclude', it works well, and spring-mvc.jar will be found in secweb-web.war
2) When I use 'mvn clean install -Pinclude-jar', it doesn't work, and spring-mvc.jar can't be found in secweb-web.war
Anybody know why ? And is there something I must pay attention to when I use profiles ?
(I know I can define scope of dependency, this project here just to demo different result of different profile activate method)
pom.xml for secweb-parent
<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>
<properties>
<project.version>1.0.0</project.version>
</properties>
<groupId>com.mediatek.dt</groupId>
<artifactId>secweb-parent</artifactId>
<version>${project.version}</version>
<packaging>pom</packaging>
<modules>
<module>../secweb-web</module>
<module>../secweb-service</module>
</modules>
</project>
pom.xml for secweb-service
<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>com.mediatek.dt</groupId>
<artifactId>secweb-parent</artifactId>
<version>${project.version}</version>
<relativePath>../secweb-parent</relativePath>
</parent>
<artifactId>secweb-service</artifactId>
<profiles>
<profile>
<id>include-jar</id>
<activation>
<property>
<name>include</name>
</property>
</activation>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>2.5</version>
</dependency>
</dependencies>
</profile>
</profiles>
</project>
pom.xml for secweb-web
<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>com.mediatek.dt</groupId>
<artifactId>secweb-parent</artifactId>
<version>${project.version}</version>
<relativePath>../secweb-parent</relativePath>
</parent>
<artifactId>secweb-web</artifactId>
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>com.mediatek.dt</groupId>
<artifactId>secweb-service</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>
You mat check the active profile by using the Maven Help Plugin as the following example
change directory to the parent
e.g. cd /my/project/secweb-parent
Then execute the following command twice for comparing
mvn help:help:active-profiles
mvn help:help:active-profiles -Pinclude-jar
Anyhow the significant point is the version, you have defined as 1.0.0. I would prefer to use the 1.0.0-SNAPSHOT instead.
You may see further information about the SNAPSHOT, here.
Why would you use this? SNAPSHOT versions are used for projects under active development. If your project depends on a software component that is under active development, you can depend on a SNAPSHOT release, and Maven will periodically attempt to download the latest snapshot from a repository when you run a build. Similarly, if the next release of your system is going to have a version "1.4", your project would have a version "1.4-SNAPSHOT" until it was formally released.
As a default setting, Maven will not check for SNAPSHOT releases on remote repositories. To depend on SNAPSHOT releases, users must explicitly enable the ability to download snapshots using a repository or pluginRepository element in the POM.
There is also a useful question and answer about the snapshot at our stackoverflow, here as well.
I hope this may help.

How to override maven property in command line?

I have the following plain pom running by Maven 3.0.4.
<?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.example</groupId>
<artifactId>test</artifactId>
<version>1.0</version>
<packaging>jar</packaging>
</project>
I am trying to override default settings in command line like this:
mvn -Dproject.build.finalName=build clean package
But this this is ignored, and I get test-1.0.jar. I've tried to change another properties, like outputDirectory, directory, artifactId, but also failed.
What is the proper way to do this thing?
See Introduction to the POM
finalName is created as:
<build>
<finalName>${project.artifactId}-${project.version}</finalName>
</build>
One of the solutions is to add own property:
<properties>
<finalName>${project.artifactId}-${project.version}</finalName>
</properties>
<build>
<finalName>${finalName}</finalName>
</build>
And now try:
mvn -DfinalName=build clean package

Resources