Setting application-specific properties on deploy by maven - maven

I would like to deploy java app twice to one tomcat server, each time with different environment properties.
I would like to find a way like
mvn tomcat7:deploy -Denvironment=local
I don't mind using other maven plugin.
With no need to change files after deploy.
Is it somehow possible?
Thank you for you answer.

You can have a configuration file (something like e.g. application.properties) that you enable resource filtering for. You could then parameterize the values in that configuration file, and pass in different parameter values for each of the deployments (-Dkey1=value1 -Dkey2=value2).
You could pass the different parameter values on the command-line, or you could cement them in different profiles, and just activate the appropriate profile from the command-line (-Psecond-deployment).
What seems a little unfortunate from the suggested approach in your question is: in its most basic sense Maven is a build tool, meant to produce a consistent artifact from a build. This is no longer the case with the suggested approach in your question. If this is a web application that is never used as a dependency of other module, this may be fine. But just highlighting that different deployment configurations is a deployment concern, not a build concern.

I used little workaround.
I created different profiles which I use to update application property.
example:
In my POM I have:
<profiles>
<profile>
<id>local</id>
<properties>
<environment>local</environment>
....
</properties>
</profile>
and in application.property file I have
environment=#environment#
(That # are correct! )
This way I can deploy my app with defined environment by using command
mvn -P local tomcat7:deploy
and use environment variable anywhere else as ${environment}

Related

In maven, can I define a variable used in another pom?

I'm getting an error when running maven build (unable to load a dependency).
[ERROR] Failed to execute goal on . . .
Could not transfer artifact my.group:libme1:${someVariable} from/to . . .
I believe that the developer that published this artifact was supposed to be setting the variable ${someVariable} but didn't. I think this is a bug but I'm trying to work around it by setting the variable.
The POM for the JAR I'm depending on my.group:libme1:1.2.3 looks like this (snippet highlighting the issue):
<groupId>my.group</groupId>
<artifactId>libme1</artifactId>
<parent>
<groupId>my.group</groupId>
<artifactId>libme1-parent</artifactId>
<version>${someVariable}</version>
</parent>
I tried defining it by adding -DsomeVariable=1.2.3 on the command line but it didn't work. For example, this command
mvn -DsomeVariable=1.2.3 clean install
should work based on Baeldung's article but doesn't.
I also ran:
mvn -DsomeVariable=1.2.3 help:effective-pom
and I see the variable being set, so I know he POM I'm using has that defined, but for some reason another POM doesn't pick up that value (or that is how it appears to me).
Is there any way to set the variable so it can be used in another POM? I'm guessing this is not possible.
Searching for an answer I found:
The maven doc
https://maven.apache.org/settings.html#Activation
If you know that this is bug, please let me know. I'm also reaching out to the publish of the artifact to ask them how this is supposed to work.
Basically the dependency's pom is invalid, the reasoning is following:
maven allows developers to do following things:
define dependencies in parent pom
impose restrictions on dependencies via <dependencyManagement> in both current and parent pom
use placeholders ${...} in <version> element, which somehow get resolved via system properties and current/parent pom properties
all those features mentioned above are very convenient from development perspective, however when you publish artifacts those features cause a pain in behind: that became not possible to use external library without it's parent pom, because parent pom may define dependencies and properties.
In your particular case someone have define version of parent pom as ${someVariable}, that in turn means it is not possible to use that library without information about the value of ${someVariable}. However, even if you had known the "correct" value of ${someVariable} and might specify it via system properties, that would cause some weird behaviour: today you may specify one value for ${someVariable}, tomorrow you (or someone else) will specify another value and ultimately you will get different builds, due to that maven denies such configurations (that is much better to fail a build rather than build something unreliable), that would be wiser to initially deny publishing such poms, but we have what we have.
It might be that the variable was stored in some user's settings.xml.
This would allow checking out an older version already in production for writing patches.
<settings>
...
<profiles>
<profile>
<id>work-in-progress</id>
<properties>
<someVariable>1.2.3</someVariable>
</properties>
</profile>
</profiles>
<activeProfiles>
<activeProfile>work-in-progress</activeProfile>
</activeProfiles>
</settings>
So you might do that too. And search in users' directories, .m2 repo directories where usually the settings.xml is stored.

Setting the developerConnection for the Maven Release Plugin from the command line

I am currently trying to configure the Maven Release Plugin for our build server.
For that I am trying to set the <scm><developerConnection> through the command line. I read that
project.scm.developerConnection
is the command line property(https://maven.apache.org/guides/mini/guide-releasing.html). I tried to set it but it seems to have no effect. When I start the build, it uses a constructed URL (parent pom url + artifactId) that fails.
I have looked at the source code of the plugin but did not find the command line property mentioned above.
Can anybody shed light on this?
It looks that you cannot pass this property directly from command line. See:
https://issues.apache.org/jira/browse/MRELEASE-707
But you should get it working by specifying it through a custom property in your pom.xml:
<properties>
<my.developer.connection />
</properties>
<scm>
<developerConnection>${my.developer.connection}</developerConnection>
<tag>HEAD</tag>
</scm>
And running maven with, for example:
-Dmy.developer.connection=scm:git:ssh://user#host/repo.git
I use this approach to keep my pom.xml clean when generating a public release that should not contain information about my company's internals.
When you run mvn release:prepare, Maven forks. The arguments supplied on the command line are passed to the initial Maven call (the one you/build server ran) not to the fork.
To pass args to the release plugin, supply the arguments as shown:
mvn release:prepare -Darguments="-Dproject.scm.developerConnection=..." ...
Depending on what I'm trying to do, sometimes I've had to specify in two places, so both original and forked processes get the args:
mvn release:prepare -DsomeArg=val -Darguments="-DsomeArg=val" ...
The first example in the release plugin FAQ shows an example of where the latter is useful.
---- Update ----
I found the property in the maven-scm-plugin code.
Maybe project.scm.developerConnection is read-only? Try setting scmDeveloperConnection instead, as it's listed as the property name.

Custom alternative configurations for Maven life cycles

How can I add custom alternative configurations to the default life cycles in the pom.xml?
So that I for example can still call mvn package (default behavior), but also mvn quickPackage which runs the default package life cycle, but has e.g. skipTests true and the XML equivalents for other command line parameters...?
All I could find was either directing me into:
Using extra special plugins, even write my own, which I'm not allowed here.
Apply the configuration to everything, or at least always to a certain life cycle. Removing the default behavior of e.g. package.
Do I have to fallback to use command line scripts (which counters the point of having a build management system)? Or is there a pom.xml solution?
You can use Maven Profiles for that, e.g.:
<profiles>
<profile>
<id>quick</id>
<properties>
<bla.bla.bla>true</bla.bla.bla>
<this.that.then>true</this.that.then>
<everything.now>true</everything.now>
<feature.set.extra>true</feature.set.extra>
</properties>
</profile>
</profiles>
Activate it with:
mvn ... -Pquick ...

Maven: Define SuperPOM property project.build.directory over command line

I am building my maven project with GitLab CI on a docker file.
I would like to configure my pipeline with a "compile" stage and a "test" stage. To be able to do that, I need to set the property project.build.directory, which is defined in the maven super POM, to the docker cache so the compiled artefact does not get lost between the jobs.
project.build.directory is a predefined maven property. Therefore I would think that I am able define it with the CL parameter -Dproject.build.directory=anotherDir. This somehow does not work and my project still gets built to the default directory target.
If I modify my POM with
<properties>
<buildDir>target</buildDir>
</properties>
<build>
<directory>${buildDir}</directory>
</build>
and call mvn clean install -DbuildDir=customTargetDir, my project gets built to the customTargetDir as expected.
Why is that? I really don't see a difference. I both cases, I define the value of an existing property.

Maven: Only execute plugin when a command line flag is present

I want Maven to only run a certain plugin when there is a flag on the command line when I call the mvn command.
for example:
Let's say I have a plugin called maven-foo-plugin. I only want maven to run this plugin when the flag --foo is present when I call the maven command.
So, instead of saying...
mvn install
...I would say...
mvn install --foo
The first one should NOT use/call the plugin maven-foo-plugin, but the second one should. By default, I don't want this plugin to run, but if and only if, the --foo is present. Is there another parameter that I add to this maven-foo-plugin to make it do this?
The plugin I'm using is the maven-antrun-plugin that has the task that unzips a file. Of course, sometimes this file is present and sometimes not. Sometimes, it's not present and I don't need it. So, I need a way (Preferably through command line unless someone has a better idea) to turn on/off this plugin.
As #Gab has mentioned, using Maven profiles is the way to go. Create a profile and configure your plugin in the profile. Then in the profile's activation section, reference the environment variable, with or without a value:
<profiles>
<profile>
<activation>
<property>
<name>debug</name>
</property>
</activation>
...
</profile>
</profiles>
The above example would activate the profile if you define the debug variable when calling Maven:
mvn install -Ddebug
Please note that you have to prefix environment variables with -D in order to pass them to the JVM running Maven.
More details can be found here: http://maven.apache.org/guides/introduction/introduction-to-profiles.html
The correct way to trigger conditional action in maven is to use profile.
You can so configure a specific profile including the plugin activation, you will then trigger the execution using
mvn targetPhase -P myprofile
(you can also specify a specific property value to activate the profile)
see Maven: Using a Plugin Based On Profile

Resources