Maven: Is it possible to have more than one settings.xml files? - maven

I have a multimodule project. All of the modules, but one are different. There are some things in the settings.xml file that I want to be different in the one module than from the rest.
Is it possible to have two settings.xml file and use them for different modules?

Think of the settings.xml as the configuration for your installation of maven. It determines the behavior of maven across it's use in your various projects.
This being said, if an individual project, i.e. a pom, requires something unique, it should be in that pom.
I think the thing to remember is that the project should be able to build on an individual dev's machine without any special intervention. In other words, the ideal case is that a given pom can successufl execute mvn install in a vanilla environment. So, don't put something in it that requires tweaking for a dev to get it to work. Also don't put anything in your settings.xml that enables a project to build, but then puts the burden on other devs to know what secrets are in your settings.xml.

You can set up different things in your individual pom files. What's in the pom files will override what's in settings. For instance, if your child poms sets up different repositories they'll be used over what is defined in settings.xml. Settings.xml is the default is nothing else applies. Depending on exactly what you want to do you might also take a look at the profiles feature.

Related

Maven settings.xml to include build tag properties

According to http://maven.apache.org/settings.html we have an example and explanation of all the elements.
But I want, for example, customize some build settings for ALL projects, not to be pushed in every project pom.xml.
Other people looking for this, too, but still no solution.
Maven ignoring build segment in settings.xml?
But, surprisingly, build tag is NOT available in settings.xml.
Is there a way to inject build parameters, like target dir into settings.xml using profiles, etc?
Two things:
The standard way is to create a company parent POM that is used as parent for all the projects. It can configure plugins and other build information.
If you want things be overridden by the settings.xml, use properties and then define the properties in the settings.xml.

Is it possible to localise a Maven artefactID?

Suppose a team in the US has a project containing this local library
<dependency><artifactId>garbage</artifactId></dependency>
but the UK version of our project has a pom.xml with this dependency listed instead:
</dependency><artefactId>rubbish</artefactId><dependency>
which specifies the localised build of the artefact.
Currently, a script takes the garbage project, builds it with UK localisation, but then has to patch up the .jar files after the fact so that the artefactId reflects the localisation, including if the string has been copied as part of the build process. This method has proven to be unreliable, however: Is there a way of migrating to a system which uses Maven, alone, to change the build ID depending on something like the LANG environment variable?
Or; is it not possible to introduce configuration into the pom.xml configuration file itself?
If you need to build a project for different environments, you can use Maven Profiles:
http://maven.apache.org/guides/introduction/introduction-to-profiles.html
You can put different dependencies into different profiles and activate/deactivate the profiles in build process, on the command line or e.g. by marker files.

Maven module dependency source instead of repository jars

I have a multi-module project, i.e.
parent
module1
module2
In one dev cycle, I added a class mod1.A to module1. Class mod2.B in module2 depends on it.
I do not have the artifacts in my local .m2/repository. Running this:
$ cd prj/module2
$ mvn -o exec:java -Dexec.mainClass=mod2.B
results in an error along the lines of:
The following artifacts could not be resolved: com.example:module1:jar:1.0-SNAPSHOT
After I install the artifacts via mvn install while in the prj folder, it all works as expected.
However, this presents an issue in at least two ways:
I have to go through the slower install phase instead of the faster compile phase
I have two versions of the same project and conflicting modifications in these. I cannot run the same Java class with their respective modifications, only the currently installed modifications, considering they are both the same SNAPSHOT version
There are workaround for both (skip parts of the build for the first, different snapshot versions for the second), but they are far from usable in practice.
Is there a way to make maven use the local modules, instead of using artifacts from local maven repository?
If I understand your question correctly, it seems like you are living a bit outside the norm here: you have two local "copies" of the project with different modifications, that you want to work with alternately when running "exec:java". And Maven is getting in your way: it expects your local .m2 repository area to be in play, but the version strings in each copy are the same, so you end up with the changes interfering among the copies.
To me, it sounds like what you are trying to do is to test your changes. I suggest you just write an actual JUnit or TestNG test in module2 that tests what you want (it can just call mod2.B Main if you want). Then, from your chosen project directory, you can run mvn test -Dtest=MyTestName. It won't "install" anything and it will find the dependencies the way you want it to.
Otherwise, I can see three options.
Change the version string locally in one of the copies (mvn versions:set -DnewVersion=B-SNAPSHOT can do this for you). That way any "installed" jars from your work on that copy will not be considered by the other copy, and vice-versa. You refer to this as being "far from usable" ... I think it should be fine? These are different versions of the project! They should have different version strings! I strongly recommend this option out of the three. (You can do mvn versions:revert when done if you used :set, or you can rely on version control to undo the change.)
Select a different local repository used by Maven when working on one of the projects, with a command-line flag as per https://stackoverflow.com/a/7071791/58549. I don't really think this is a good solution, since you would have to be very careful about using the right flags every time with both projects. Also you'd end up having to re-download Maven plugins and any other dependencies into your new local repository anyway, which is kind of a waste of time.
Try to avoid using any local repository at all. You seem to be trying to make this option work. I don't think this is a great approach either; you're fighting against Maven's expectations, and it limits your flexibility a lot. Maven will indeed find dependencies from the "reactor" (i.e., the executing mvn process) first, but this means all of the required modules must be available in the reactor to be found, which means you can only run mvn at the top level. So if instead you want to just do "mvn exec:java" inside a single module, mvn needs to find that module's dependencies somewhere ... and that's what the local repo is generally used for.
If you're dead set on going with option 3 (instead of option 1), then I suggest you follow the comments on your question and create a profile that runs your exec selectively against module2 and binds it to a lifecycle phase. But this is in practice very close to just wrapping it with a test.
For IntelliJ users:
I solved this problem using IntelliJ's Run configuration. It has the options Resolve workspace artifacts and Add before launch task -> Build. See this picture for clarification:
Run configuration example
The whole point of modules in Maven is to create decoupling between them. You either build each module independently, so that you can work on one module without touching the other, or include both modules as sub-modules in the parent pom and build the parent, which will resolve dependencies between its sub-modules and trigger their builds.
It looks like you have two options here:
Review the structure of your project. Do you really need to split it into two separate modules, if you change code in both of them simultaneously?
Import the project into a Maven-aware IDE (IntelliJ IDEA is very good at working with Maven), and let the IDE handle the compilation. Once finished and stabilized the code-base, build normally with Maven.

Maven how to handle multiple projects and settings.xml in same PC

I want to have multiple (local) settings.xml files in my PC for my Maven projects, one per project. What is the best way of handling these settings.xml (hopefully somehow through version control)?
I know that each developer (and the CI server) will want to have some different variables in those settings.xml.
I am thinking something like one settings.xml in subversion per project, to provide a skeleton with some empty fields so that everyone can copy and paste the settings.xml file to their local directory where it gets picked up by Maven and also fill in the blank values that are unique per environment/user. Bear in mind, I am not referring to stuff that can be set via profiles, it's more like usernames and passwords and such.
This leaves us with the problem of multiple settings.xml files. IntelliJ as I see has Maven configuration per project so I shouldn't have any trouble setting separate locations for every project. As for the command line, do I really need to type in the path to my settings.xml file every time I run something (via the -s command)?

Multiple Maven modules with dependency on a JAR

In my multi-module Maven project, suppose I have two modules, car and horse. They both depend on a JAR file, transport.jar, a file not available in any online Maven repositories. As such, I need to find a way to make these modules depend on a file found somewhere in the project folder structure.
From what I understand, the default Maven solution would be to manually register the JAR file in the local repository. While this would work on a development machine, it breaks on the build server, which clears its local repository before each build.
I've been searching online on how to do this on and off for a while and found some helpful things, but nothing that completely works.
For instance, a common answer is to add a dependency to the file using <scope>system</scope>. However, not only do others claim that it's extremely bad practice to do so, it also doesn't work on the build server. (On a side note, I would also like to point out that using absolute paths to the JAR is also out of the question due to, again, it being built on several different machines.)
A more useful method I found was to define a local repository in the POM file, pointing towards the path file:${project.basedir}/lib. (Such as in this article) Unfortunately, if I place the JAR and repository definition in the car POM, I cannot successfully add a dependency to the JAR in horse. I've tried both with and without an additional reference to car in horse, as well as defining a second repository in horse, pointing to file:${project.basedir}/../car/lib. This problem would also remain if I tried to make a third module, transport-lib, specifically for wrapping the JAR dependency.
I could most likely add the JAR file to both modules and define two separate module-local repositories, but I really don't want to unless I have to due to the need to keep the two (often updated) JARs in sync etc.
So, my question is as follows: Can someone give me a confirmed-to-work method to have two modules depend on the same JAR file inside the project, given the parameters and restrictions mentioned?
Best solution is to use a repository manager like Archiva, Artifactory or Nexus and install that artifact into the repository manager. Afterwards you can use this artifact directly in your pom files without any issue.
Don't use the scope system, cause it will cause other problem after a release for other etc.

Resources