I have following pom.xml
<project>
<properties>
<buildNumber>dev</buildNumber>
</properties>
<build>
<finalName>${project.artifactId}-${project.version}-${buildNumber}</finalName>
</build>
</project>
This works fine on development machine. If I run mvn package I've got project-1.1-dev.war artifact. If I run mvn package -DbuildNumber=121 I've got package-1.1-121.war.
But out CI server (TeamCity) always got project-1.1-dev.war despite the fact that buildNumber property passed to maven (if I remove default property definition from pom.xml, maven builds artifact with correct filename).
It seems that system property resolve priority is somehow depends on platform (maven version is equals on both developer machine and TC - 2.2.1)?
That's a bit strange... Maybe you can't force the parameter given in the command line to have a highest priority than the one defined in the <properties> tag.
An idea is to use a profile that define the property buildNumber:
<profiles>
<profile>
<id>dev-property</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<buildNumber>dev</buildNumber>
</properties>
</profile>
</profiles>
So by default, buildNumber will be equals to dev value. Now, in your TeamCity command line, disable this profile with the command mvn ... -P !dev-property (the ! before a profile id indicates that the profile must be disabled).
The answer to your question lies in another question here on SO: Maven property overloading
In short, you need to pass -DbuildNumber=121 on the maven command line (on the "3 build step: maven" page), because setting system property "buildNumber" on the "6 properties and variables" page does not override the maven property.
Are you familiar with the concept of SNAPSHOT versions? Sounds like what you are trying to do, and is supported out of the box by Maven. Looks like you want to build major-minor-incremental or major-minor-dev, if you can live with major-minor-incremental-SNAPSHOT instead it should do what you want.
Related
I have one situation where I need to create multiple configuration property file by passing environment.
i.e : I have environment like dev, prod, qa, int, but I want to create jar only for int and dev in one go
My First question is: "Is there any way in maven where we can pass multiple environment value" ?
If this is possible how can I setup my pom.xml to accept the multiple env value ?
It's not quite clear what you mean with "pass multiple environment value".
If you want to activate a set of properties depending on the execution environment you could use maven profiles.
Here is an example for two profiles, which you can add to a pom.xml.
<profiles>
<profile>
<id>prod</id>
<properties>
<value1>a</value1>
<value2>b</value2>
</properties>
</profile>
<profile>
<id>qa</id>
<properties>
<value1>x</value1>
<value2>y</value2>
</properties>
</profile>
</profiles>
You could then for example activate profile "prod" by calling maven with the paramter "-Pprod".
I fear you can't trigger 2 different packaging with per-profile filtered resources in one build.
If you want to activate 2 profile at once you can specify them both using -P or trigger the activation according to the same property (see Maven: Only execute plugin when a command line flag is present)
If I correctly understand your question, i'd suggest to delegate the build of the integration artifact to a continuous integration server which will trigger the appropriate resource filtering using a dedicated profile and to set the dev profile as default one for the daily developers builds.
I use this to build my spring mvc app:
mvn clean package
I use the maven war plugin to create a war file, but the problem I am facing is that in my resources folder I have my development versions of my .properties files for log4j etc.
When I push to production, and run:
java -jar ...
It explodeds the war file, and then at that point I can modify the .properties files with my production settings, but I obviously want to do this during my maven build for production.
Is there a way I can tell maven that this is a production build, so get these files from somewhere else? And during development, keep doing what it is doing now?
User maven profiles. Maven profiles help you in specifying different properties for different profiles. So you can have two profiles - development and production.
Something like this -
<profiles>
<profile>
<id>development</id>
<!-- we'll properties here... -->
</profile>
<profile>
<id>production</id>
<!-- ...and here -->
</profile>
</profiles>
Like this example -
<profile>
<id>development</id>
<properties>
<db.driverClass>oracle.jdbc.driver.OracleDriver</db.driverClass>
<db.connectionURL>jdbc:oracle:thin:#127.0.0.1:1521:XE</db.connectionURL>
</properties>
</profile>
<profile>
<id>production</id>
<properties>
<db.driverClass>oracle.jdbc.driver.OracleDriver</db.driverClass>
<db.connectionURL>jdbc:oracle:thin:#134.0.0.1:3124:XE</db.connectionURL>
</properties>
</profile>
There are a couple of options here. The first (as others have mentioned as well) is to use maven profiles. Instead of having multiple version of your properties files, you would have something like:
mypropsfile.properties
-----------------------
prop1=${prop1.val}
prop2=${prop2.val}
Then in your profiles, you can define values for those properties (make sure you have resource filtering enabled for this to work. see an example http://www.manydesigns.com/en/portofino/portofino3/tutorials/using-maven-profiles-and-resource-filtering).
You can also have your properties file have production values in it but with the ability to override those files in development. Spring profiles are helpful for this. For example, in development mode you can look for a properties file named <user-home>/mypropertiesoverride.properties, which could be used to override any of the production value properties with development specific ones.
I prefer the second method here where you have a default properties file and then you can just override select properties.
I have a lot of maven projects. I have two different global settings.xml for them which I need to merge. Both of them describes their repositories inside the profiles. I merged the two settings.xml by the mirrors and profiles tags.
One of the profiles is activated by the activeProfile tag in settings.xml file.
I want to ask you, how I can change the active profile in the different projects? Can I select it in the project pom.xml file?
Thanks,
Br, Stristi
This document describes how profiles can be activated: Introduction to Build Profiles.
You could activate profiles via environment variables, but if you have many projects, and want to apply profiles per-project basis, then it's a fault solution to change environment variable before each separate project build execution. If you are working with IDE, you can configure launch configuration to set the property for each project, and you have to configure the correct mvn run command within a continuous integration for each project. However, that would make it impossible to build an aggregated build consisting of different projects that should be activated by different profiles.
A possible workaround (which doesn't seem to be elegant, but I'm pretty sure it will work) is activating profiles based on file presence, and managing such 'marker files' for different projects to activate the required one. For example:
<profiles>
<profile>
<activation>
<file>
<exists>.profile-A</exists>
</file>
</activation>
...
</profile>
</profiles>
Expected behavior: This profile gets activated if file with a name '.profile-A' exists in a root folder of a project.
However, at this point one more interesting question arises: what would be the behavior in case of aggregated build?
It sounds you need to use a Repository Manager (Archiva, Artifactory, Nexus alphabetical order) to have a single configuration in your settings.xml file. This will solve the issue of making your build files environment depend.
I prefer this way in my projects:
<profile>
<id>dev</id>
<activation>
<property>
<name>env</name>
<value>dev</value>
</property>
</activation>
...
</profile>
Then you can activate it this way:
mvn your_goal -Denv=dev
Regards,
Boskop
you can simple add the activeByDefault tag to your maven profile:
<profiles>
<profile>
<id>your-profile</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
</profiles>
Is there a way to change the version number without editing the POM?
<groupId>org.example</groupId>
<artifactId>example</artifactId>
<version>1.0.0</version>
We have a CI system where we want to release nightly builds, but without using the -SNAPSHOT solution of Maven, so if 1.0.0 is the current version, we just want to have CI-NIGHTLY-BIULD-20120426.
I suggested this would be possible with something like mvn deploy -Dversion=CI-NIGHTLY-BIULD-20120426, but obviously not. The bad solution would be to let the CI server edit the pom.xml every time, but I think this is very unhandy.
Thank you!
I suggest to use classifier.
<groupId>foo</groupId>
<artifactId>bar</artifactId>
<version>1.0</version>
<properties>
<!-- default classifier is empty -->
<my.project.classifier></my.project.classifier>
</properties>
<build>
...
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.3.1</version>
<configuration>
<classifier>${my.project.classifier}</classifier>
</configuration>
<executions>...</executions>
</plugin>
</plugins>
</build>
and
mvn package -Dmy.project.classifier=NIGHTLY-2012-04-26_02-30
Maven documentation says about classifier:
classifier: You may occasionally find a fifth element on the
coordinate, and that is the classifier. We will visit the classifier
later, but for now it suffices to know that those kinds of projects
are displayed as groupId:artifactId:packaging:classifier:version.
and
The classifier allows to distinguish artifacts that were built from
the same POM but differ in their content. It is some optional and
arbitrary string that - if present - is appended to the artifact name
just after the version number. As a motivation for this element,
consider for example a project that offers an artifact targeting JRE
1.5 but at the same time also an artifact that still supports JRE 1.4. The first artifact could be equipped with the classifier jdk15 and the
second one with jdk14 such that clients can choose which one to use.
Another common use case for classifiers is the need to attach
secondary artifacts to the project's main artifact. If you browse the
Maven central repository, you will notice that the classifiers sources
and javadoc are used to deploy the project source code and API docs
along with the packaged class files.
I think you could also use versions maven plugin. I find it quite useful for things like this.
You could do it in 2 steps:
set necessary version: mvn versions:set -DnewVersion=CI-NIGHTLY-BIULD-20120426
deploy: mvn deploy
in case you need to revert back the changes, use mvn versions:revert (as Mark suggests)
I highly recommend reading Maven Releases on Steroids (part 2, part 3) by Axel Fontaine. It is great, and I'm quite happy using it.
It not only details how you con do what you ask, but also contains good advice how you can tie your build versions with your CI server.
In a nutshell, here are the main points:
Maven Release is slow, needs to be done faster
You parametarize your project version like
<version>${VERSION_NUMBER}</version>
...
<properties>
...
<VERSION_NUMBER>1.0-SNAPSHOT</VERSION_NUMBER>
...
</properties>
Local builds get that version: 1.0-SNAPSHOT
Release builds are done only from your CI server
In your Jenkins/Hudson project configuration you use
clean deploy scm:tag -DVERSION_NUMBER=${BUILD_NUMBER}
That way you get a new release with each Jenkins build, not only nightly.
You can change the configuration to use
clean deploy scm:tag -DVERSION_NUMBER=1.0.0-CI-NIGHTLY-BIULD-${BUILD_ID}
and you would get versions like 1.0.0-CI-NIGHTLY-BIULD-2012-04-26_12-20-24
You could parameterize the version number as
<groupId>foo</groupId>
<artifactId>bar</artifactId>
<version>${my.project.version}</version>
<properties>
<my.project.version>1.0</my.project.version>
</properties>
and drive the version number from command line using
mvn package -Dmy.project.version=NIGHTLY
Although this is possible, Maven 3 discourages it.
I have an external library that needs to be dynamically linked with a test in my java project. The project is setup using maven, and I need to add the following to my vm arguments in eclipse for the test to pass:
-Djava.library.path=${env_var:HOME}/.m2/repository/natives/dist/lib -ea
Unfortunately this means that running the test from maven using: mvn test will always fail.
One work around is to call mvn with a -DargLine argument like so:
mvn test -DargLine="-Djava.library.path=/Users/rob/.m2/repository/natives/dist/lib -ea"
However, clearly this has the problem of being specific to my machine, so I can't put it directly in the pom file. I guess what I'm looking for is a way of modifying that string on a per machine basis kinda like the first line does for eclipse.
I'm also curious how I could put it into the POM file, I've tried placing it inside of <argLine> tags, but that doesn't seems to work, is there something I'm missing:
<argLine>-Djava.library.path=/Users/rob/.m2/repository/natives/dist/lib -ea</argLine>
After some research I've discovered a decent solution to my problem.
In maven your settings.xml file, you can define a location for the localRepository here are the defaults if you set nothing:
Unix/Mac OS X – ~/.m2
Windows – C:\Documents and Settings\username.m2
As you can see this matches at least the first part of the directory I was trying to set: /Users/rob/.m2
Since dynamic linking is OS specific, you may also want to setup a profile for alternate path suffixes. You can do this in a .pom like this:
<profile>
<id>OSX</id>
<activation>
<os>
<family>mac</family>
</os>
</activation>
<properties>
<dynamic.libLoc>${settings.localRepository}/natives/dist/lib</dynamic.libLoc>
</properties>
</profile>
You can then use this property in the .pom for the project you wish to test. Under the plugins category you can add:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>-Djava.library.path=${dynamic.libLoc}</argLine>
</configuration>
</plugin>
Now maven can run those tests without users having to specify the location of the dynamically linked libraries. You can also handle users with different operating systems by just adding another profile.
Note: With regards to my problem with <argLine> earlier. I think I was just using it in the wrong .pom