How to access elements from settings.xml in pom.xml with Maven? - maven

According to https://maven.apache.org/pom.html#properties it should be possible to use ${settings.x} to access the element <settings><x>value</x></settings> from the settings.xml file in the pom.xml file.
However, when I try something like
<profiles>
<profile>
<activation>
<file>
<exists>${settings.localRepository}/path/to/file</exists>
</file>
</activation>
</profile>
</profiles>
in my pom.xml it isn't replaced in the effective pom.xml. When I replace ${settings.localRepository} with ${user.home}/.m2/repository it works fine but that's not what I want. Is there anything I can do to fix that? (Tested with Apache Maven 3.6.0.)
Background information:
I have a dependency that isn't present in an online maven repository and I can't change that. It must be compiled by users and can be installed to the local repository. Instead of doing this manually, I'm trying to do this automatically in my pom.xml. For this I have to ignore the dependency if it's not present in the local repository. Hence the profile that checks if the file is present in the local repository. Without the profile, maven wouldn't even start the life cycle because the dependency can't be resolved. Of course the project won't compile the first time the pom.xml is executed. But all dependencies are automatically installed and the project will compile in a second pass. I know that this isn't a clean solution but I think it's better than telling users to compile and install dependency xy manually before this project can be compiled. I also include a build script that first runs mvn clean initialize to install the dependencies and then mvn clean compile.

Put the source of the external dependency in an own project like:
+- main
+- pom.xml ... <packaging>pom...<module>external...<module>internal
|
+- external
| +- ... Maven dirs as usual ...
| + pom.xml
|
+- internal
+- ... Maven dirs as usual ...
+- pom.xml ... <dependency>external
Such when building main the Maven Reactor takes care of the projects' build order (build external first, then internal in this case) and you can forget about dealing with settings.xml, repositories, profiles or properties.

Related

How to compile specific dependencies using maven

I have a situation where in i need to clean and install couple of dependencies of my maven project. While I am working on this project i am making changes in these dependencies and have to manually clean and install for every small change i am making. I am trying to find a maven command which will make my life easy.
project-bpm-process <-- parent project
project-odata-service - < dependency >
project-core-service - < dependency >
I cannot put them as sub modules as they are not really modules of my this project, they are simply dependencies. So, literally group-id does not match in complete sense (there is a partial match but does not help in any way).
Update 1:
Tried the option 2 suggested by Mark. I see below error which indicates that the sub modules (aggregated projects) are not found under the parent project's folder.
[ERROR] [ERROR] Some problems were encountered while processing the
POMs: [ERROR] Child module
E:\STS-Workspaces\default-workspace\project-bpm-process-artificial\project-core-service
of
E:\STS-Workspaces\default-workspace\project-bpm-process-artificial\pom.xml
does not exist #
[ERROR] Child module
E:\STS-Workspaces\default-workspace\project-bpm-process-artificial\project-odata-service
of
E:\STS-Workspaces\default-workspace\project-bpm-process-artificial\pom.xml
does not exist #
[ERROR] Child module
E:\STS-Workspaces\default-workspace\project-bpm-process-artificial\project-bpm-process
of
E:\STS-Workspaces\default-workspace\project-bpm-process-artificial\pom.xml
does not exist #
I just created a new maven project with packaging "pom" type and added other projects as modules. Now, "project-bpm-process-artificial" has become artificial parent of all the three projects I was talking about.
From maven documentation, i see that the path is relative.
Update 2:
Location of actual pom is located at: *E:\STS-Workspaces\default-workspace\project-bpm-process-artificial*
But other referenced projects are in *C:\Users\ramgo\git* and *E:\git-repos*. These projects are imported into eclipse for development.
The pom.xml is here:
<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.mycompany</groupId>
<artifactId>project-bpm-process-artificial</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<name>project-bpm-process-artificial</name>
<url>http://maven.apache.org</url>
<modules>
<module>project-core-service</module>
<module>project-odata-service</module>
<module>project-bpm-process</module>
</modules>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Solution: For all practical reasons I found option 1 is easy to implement (option 1 provided by Marks). It hardly took 5 minutes to write a batch script. Here is the one for handy reference.
set core=<directory_path_of_core_project>
set module_one=<<directory_path_of_module_one>>
set module_two=<<directory_path_of_module_two>>
cd %core%
call mvn clean install
cd %module_one%
call mvn clean install
cd %module_two%
call mvn clean install
Option 2 seems interesting but not feasible in my case. Links don't work and no way to refer absolute path for sub modules.
.....
The notion of Maven dependency assumes that the artifact is build externally (not even necessarily with maven) and available to your project as a third-party jar.
So, the terminology in the question is misleading to me.
If you have some third-parties (I assume having their own pom.xml) but are external to your project, then obviously in your project you can't manage them. Maven can't build external stuff.
So, based on these assumptions, the choices are:
Option 1
Create a script that will:
enter the dependency directory
run mvn install on that directory
enter your project's directory
run mvn whatever on your project
Option 2
Create an "artificial" pom.xml that will have packaging type "pom" and will list both your project and the dependencies as submodules (your project and dependencies will be peers):
|__some_folder
|__pom.xml
|__dependency1
| |__pom.xml
|__dependency2
| |__pom.xml
|__your-project
|__pom.xml
In this case you will be able to operate with both your project sources like one project and you'll be able to use the following:
cd some_folder
mvn clean install --projects <your-project> --also-make
So that if your project has dependencies in other modules, they'll also be built
I would probably go with the second option, but its your choice really
Update 1
Based on the information you've provided:
Don't really count on eclipse, its not really relevant at this point. You should try to get to the point where running maven from command line should work. The eclipse will follow your poms once you've done everything right.
If you place the "artificial" pom into E:\STS-Workspaces\default-workspace\project-bpm-process-artificial then all the modules should be in sub-folders:
E:\
|_ STS-Workspaces
|_ default-workspace
|_ project-bpm-processes-artificial
|_ project-core-service
| |_pom.xml of that module
| |_.git // it can be a root of git repo
| |_src
|_ project-odata-service
| ...
|_ project-bpm-process
After that you can do the following to check yourself:
cd E:\STS-Workspaces\default-workspace\project-bpm-process-artificial
mvn clean install
It should compile all the libraries and your project
Then if you want to build your project (assuming its called project-bpm-process) then you can do from the same folder:
mvn clean install --projects project-bpm-process --also-make
If it has a dependency on project-core-service but, say, not on project-data-service then only the project-core-service will be rebuilt
Now when the maven if sorted out, you can add eclipse workspace in any other folder. I can't comment much on eclipse since I'm an IntelliJ user. In intelliJ you can just import this artificial pom and it will automatically recognize all the projects. In eclipse I think it should work similarly

Maven says it cannot find something in the "reactor"

I have a maven project and I'm using this --projects command from the root of the project to run several pom files.
mvn clean install --projects proj1, then-proj2
The proj1 and then proj2 are the artifact ids of the projects I want to run. That is, I go to the pom.xml for each project and use the "artifact id" there.
Both proj1 & then-proj2 are themeslves sub modules of projects in the main pom file.
Say proj1 is in A, and then-proj2 is in B, and both A & B are in the main pom file.
When I run this, maven tells me: "could not find the selected project in the reactor: proj1".
This is really frustrating - why not tell me what all the projects in the reactor are? Anyway, what am I doing wrong?
If you only use the artifactId's of the given project you have to define that correctly on command line:
help output of Maven (mvn --help)
Comma-delimited list of specified reactor projects to build of all
projects. A project can be specified by [groupId]:artifactId or by its
relative path
This means in your case you have to define:
mvn clean install --projects :proj1,:then-proj2
Try this:
mvn clean install -pl A/proj1, B/then-proj2
check this out: https://stackoverflow.com/a/23076358/1680793
Another thing is to make sure that you have listed your child projects inside the
<modules>
<module>
sections of the corresponding parent multimodule projects.
For example in the below project structure:
main
A
proj1
proj1A
B
then-proj2
Let's say you are trying to build proj1A. When you try
mvn package -pl A/proj1/proj1A
from the main's pom directory you will still have this same reactor error if you don't have:
"A" as a module in "main", or
"proj1" as a module in "A", or
"proj1A" as a module in "proj1"
If your modules are distinguished based on profiles then make sure to consider profiles too. Eg:
mvn -P profile1 -pl relative/path/to/project1 clean install
For this kind of setting, the pom would be:
<profiles>
<profile>
<id>profile1</id>
<modules>
<module>project1</module>
</modules>
</profile>
<profile>
<id>profile2</id>
<modules>
<module>project2</module>
</modules>
</profile>
</profiles>
Not mentioning profile would also give the Not Found in reactor.
A solution that worked for me, run the below command from the root directory.
mvn clean install --projects :projA, :projB -am
assuming that projB is dependent on projA
-am
If project list is specified, also
build projects required by the
list
The command used by you :
mvn clean install --projects 'submodule1','submodule2`
works on the sub-modules submodule1 and submodule2 specified in the pom.xml of the module where you're executing this command.
The guide to Working with Multiple modules shall help you understand the reactor and its sorting order. A general structure of the module for such use case would look like:
<groupId>stackoverflow</groupId>
<artifactId>mainmodule</artifactId>
<packaging>pom</packaging>
<version>1.2.3</version>
<modules>
<module>submodule1</module>
<module>submodule2</module>
... others
</modules>
... other tags

Execute JAR of dependent artifact in Maven

I'm working on a multi-module Maven project which looks like this:
Parent-project (pom)
+- Module1 (executable-jar)
+- Module2 (executable-jar)
+- Module3 (jar)
+- ...
+- Distribution (pom)
The Distribution module lists dependencies on Module1, Module2, and Module3. I want the Distribution module to test the project and package it up. I'm using this module for testing since the distribution already contains all the necessary configuration files. If I were to start the tests manually from the command line it would look something like this:
$ # Pre-integration-test:
$ java -Djava.rmi.server.codebase=file:module3.jar -jar module1.jar
$ java -Djava.rmi.codebase=file:module3.jar -jar module2.jar
I've looked at the exec-maven-plugin for binding these calls to the pre-integration-test phase, but the plugin only includes the JARs on the classpath instead of the directory holding the JAR itself. I think I would benefit most from a plugin which can easliy execute jars produced by a project's dependencies. That way, I can do something like this in the Distribution POM:
...
<plugin>
<artifactId>some-magic-plugin</artifactId>
<executions><execution>
<phase>pre-integration-test</phase>
<goals><goal>exec-dependency</goal></goals>
<configuration>
<artifactId>module1</artifactId>
<vmArguments>...</vmArguments>
<arguments>...</arguments>
</configuration>
</execution></executions>
</plugin>
Is there already a plugin for this? Ideally, it would be able to:
Execute a JAR artifact given its Maven-coordinates
Put directories containing the artifacts' JARs on the path (so I can include the JARs with command line arguments)
I've laso looked at dependency:copy goal to try and copy all JARs to a common path first, but it seems unnecessary since the jars are already built as part of the project. (I'm also not sure which directory would make the best copy-destination).

How to activate a Maven Profile for a specific module in a mutli-module project

We have a multi-module Maven project consisting of a parent POM and 5 or more modules.
Each module can be deployed to a running server as part of the build if we activate our custom "auto-deploy" profile, which is defined explicitly in each module because how/what gets deployed is a little different for each of the modules.
When building from the parent POM though, if I activate the "auto-deploy" profile, Maven will end up deploying all modules, which is almost never what we need to do (based on our dev process etc). But we do want to build from the root as there can be changes across multiple modules and there are dependencies between some modules.
Is there a way, when building from the parent POM, to activate our custom "auto-deploy" Profile for just one of the Modules, but not all of them?
Thanks
If each of your modules will have it's own "auto-deploy" profile, and profile activation will be triggered by variables passed to mvn command, you will be able to run single mvn command on parent module and decide which modules should be deployed simply by declaring activation variables
<profiles>
<profile>
<id>profileId</id>
<activation>
<property>
<name>profileIdEnabled</name>
<value>true</value>
</property>
</activation>
<properties></properties>
</profile>
</profiles>
and then
mvn -DprofileIdEnabled=true
Check out Maven: The Complete Reference - Section 6.2. Using Advanced Reactor Options.
Starting with the Maven 2.1 release, there are new Maven command line options which allow you to manipulate the way that Maven will build multimodule projects. These new options are:
-rf, --resume-from
Resume reactor from specified project
-pl, --projects
Build specified reactor projects instead of all projects
-am, --also-make
If project list is specified, also build projects required by the list
-amd, --also-make-dependents
If project list is specified, also build projects that depend on projects on the list
To build only module-b from the root directory:
$ mvn --projects module-b install

Jenkins and maven multi module Projects missing artifacts

This is a simplified example of an ear project, the parent pom aggregates the EAR, the EJBs, and the jars.
I have this structure in a Maven project, stored in SVN:
parent/
|- pom.xml
|- modulA/
| |- pom.xml
|- modulB/
| |- pom.xml
modulB has a Dependency of modulA
The pom.xml have the modules section
<modules>
<module>modulA</module>
<module>modulB</module>
</modules>
And a Dependency Management section
<dependencyManagement>
<dependencies>
<dependency>
<groupId>group</groupId>
<artifactId>modulA</artifactId>
<version>0.0.2-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>group</groupId>
<artifactId>modulB</artifactId>
<version>0.0.2-SNAPSHOT</version>
</dependency>
</dependencies>
</dependencyManagement>
The sub-modules reference the parent
<parent>
<groupId>group</groupId>
<artifactId>parent</artifactId>
<version>0.0.2-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
in my PC when I compile for the first time with maven 2.2.1 (windows)
mvn clean compile
I don't have any problems
but.... when Jenkins try to compile for first time (Maven 2.2.1 Linux RedHat)
Missing:
----------
1) modulA:jar:0.0.2-SNAPSHOT
Try downloading the file manually from the project website.
Then, install it using the command:
mvn install:install-file -DgroupId=group -DartifactId=modulA -Dversion=0.0.2- SNAPSHOT -Dpackaging=jar -Dfile=/path/to/file
Alternatively, if you host your own repository you can deploy the file there:
mvn deploy:deploy-file -DgroupId=group -DartifactId=modulA -Dversion=0.0.2-SNAPSHOT -Dpackaging=jar -Dfile=/path/to/file -Durl=[url] -DrepositoryId=[id]
Path to dependency:
1) modulB:ejb:0.0.2-SNAPSHOT
2) modulA:jar:0.0.2-SNAPSHOT
----------
1 required artifacts are missing.
Why????????
After that if I deploy the project from my pc to Artifactory, Jenkins doesn't have problems, because Jenkins downloads the artifact from the repository... but why does Jenkins depend on the artifacts in the repository?
:(
Thanks in Advance
EDIT:
I thought the dependencyManagement section only "defines" the dependencies, but if a submodule doesn't use the dependency, the dependency isn't added to the submodule.
I drop the dependencyManagement section and the problem in Jenkins still occurs.
It works on my PC without problems.
I hope above dependency management section is inside the parent pom. According to your requirement modulB has a Dependency of modulA. So I suggest you to include dependency in moduleB instead of having it in the parent pom. I think when it runs in first time maven is looking for both dependencies since you have mentioned in in the parent pom.Look at your project build order. First it builds module A and then B. In your case I hope you have include all other dependencies in moduleA's pom file and once it built it will deploy a jar file in to m2 repository. And then moduleB start to build and since your dependency is already in the m2 repository it wont shout and project will build successfully.
The first time you build parent project, your Jenkins user's maven repository won't have modulA installed. clean compile is then run successfully in modulA, but nothing is installed. When it is run in modulB, the dependency on modulA can't be resolved.
If your Jenkins job's goal was clean install instead of clean compile, then modulA's artifacts would be installed to the Jenkins user's repository before the modulB build begins, and all would work.
Presumably this worked on your own machine because either you had run mvn install at least once in modulA, or because your IDE's classpath resolved the problem for you.

Resources