Why does <value>!0</value> match a default value of 0? - java

I am trying to set up a .pom file that will use one plugin if forkCount is 0, and a different plugin otherwise. Furthermore, I want 0 to be the default value. In other words, I want
mvn run_tests and mvn -DforkCount=0 run_tests to both use plugin "A", where mvn run_tests -DforkCount=5 will use plugin "B".
I have a .pom file with the following segments:
<project ...>
...
<properties>
<forkCount>0</forkCount>
</properties>
...
<profiles>
<profile>
<!-- if forkCount==0, don't invoke any of the parallel execution configuration -->
<id>no-parallel-execution</id>
<activation>
<property>
<name>forkCount</name>
<value>0</value>
</property>
</activation>
<build>
<plugins>
<plugin>
<! --- nothing in here references forkCount -->
</plugin>
</plugins>
</build>
</profile>
<profile>
<profile>
<!-- forkCount!=0, use the parallel execution configuration -->
<id>parallel-execution</id>
<activation>
<property>
<name>forkCount</name>
<value>!0</value>
</property>
</activation>
<build>
<plugins>
<plugin>
...
<configuration>
...
<forkCount>${forkCount}</forkCount>
...
</configuration>
</plugin>
</plugins>
</build>
...
The only references to forkCount are included in above.
Everything works as expected if I pass a value for forkCount on the command line (i.e., plugin "A" is used when forkCount is 0; and plugin "B" is used otherwise). However, if I run mvn run_tests, then plugin "B" gets activated, even though ${forkCount} has a value of 0. What's going on?
For what it's worth:
>mvn -DforkCount=0 clean verify help:active-profiles
The following profiles are active:
- no-parallel-execution (source: ....
>mvn clean verify help:active-profiles
The following profiles are active:
- parallel-execution (source: ....

try
mvn -DforkCount=0 help:active-profiles
to verify that the profiles you really want to be active are active (and the ones you really don't want to be active are not).
-- updating answer to accommodate new information --
Thanks for the updates to the answer, the problem seems pretty clear now.
I believe the issue is that "" is not "0". With this understanding, this means that "!0" is going to activate on a '' or missing forkCount value.
My tests confirm this interpretation.
Perhaps you can redo this, using more profiles. One to detect the condition of the property not being set, and one to detect the conditions of the property being zero. Both of these profiles might leave an artifact, say a touched file in the $target directory. Then you might use this file to know you are doing a single-threaded call, and without the file, a multi-threaded call.
Code used to confirm these ideas
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>edwinbuck.com</groupId>
<artifactId>example-properties</artifactId>
<version>1.0</version>
<packaging>pom</packaging>
<profiles>
<profile>
<id>unspecified-forkCount</id>
<activation>
<property>
<name>!forkCount</name>
</property>
</activation>
</profile>
<profile>
<id>zero-forkCount</id>
<activation>
<property>
<name>forkCount</name>
<value>0</value>
</property>
</activation>
</profile>
<profile>
<id>parallel-execution</id>
<activation>
<property>
<name>forkCount</name>
<value>!0</value>
</property>
</activation>
</profile>
</profiles>
</project>
command line calls used to confirm these ideas
mvn help:active-profiles
mvn -DforkCount=0 help:active-profiles
mvn -DforkCount=3 help:active-profiles
results
profiles: unspecified-forkCount parallel-execution
profiles: zero-forkCount
profiles: parallel-execution

Related

Inheriting Maven profiles and activation

My maven project defines a profile with activation condition and has a child module. The activation condition of the parent project is ignored and I have to copy it to the child.
Parent:
<profiles>
<profile>
<id>container</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<profile>
<id>local</id>
<activation>
<property>
<name>spring.profiles.active</name>
<value>local</value>
</property>
</activation>
</profile>
</profiles>
Child:
<profiles>
<profile>
<id>local</id>
<!-- Remove comments and it will work: -->
<!--
<activation>
<property>
<name>spring.profiles.active</name>
<value>local</value>
</property>
</activation>
-->
<dependencies>
<!-- (...) --->
</dependencies>
</profile>
</profiles>
Then I run
mvn package -Dspring.profiles.active=local -P !container
and the dependecies of profile "local" are missing in the artifacts. If I remove the comments around the activation, the dependencies are available. The result equal when I run mvn package from the parent and from the child project's directory.
Strange thing is that help:active-profiles says the profile is avaiable if the activation is commented out in the child, as expected:
C:\myproject> cd child
C:\myproject\child> mvn help:active-profiles -Dspring.profiles.active=local -P !container
(...)
The following profiles are active:
- local (source: org.example:myproject:1.0.0-SNAPSHOT)
What is wrong here?
It is likely that profiles are not merged with the one in the parent, but that a profile with the same name completely overrides the profile from the parent.
So your construction will probably not work.

Setting default arguments for Maven [duplicate]

I have a Maven pom.xml with a plugin that I want to be able to control on the command line. Everything works otherwise fine, except even after searching the net a while I can't figure out how to set a default value for my control property:
<plugin>
...
<configuration>
<param>${myProperty}</param>
</configuration>
...
</plugin>
So if I run Maven with
mvn -DmyProperty=something ...
everything's fine, but I'd like to have a specific value assigned to myProperty also without the -DmyProperty=... switch. How can this be done?
You can have the property default value defined in <build>/<properties> or in a profile like shown below. When you supply the property value on command line with -DmyProperty=anotherValue then it will override the definition from the POM. That is, all definitions of property values in the POM are set only a default value for the properties.
<profile>
...
<properties>
<myProperty>defaultValue</myProperty>
</properties>
...
<configuration>
<param>${myProperty}</param>
</configuration>
...
</profile>
Taylor L's approach works fine, but you don't need the extra profile. You can just declare property values in the POM file.
<project>
...
<properties>
<!-- Sets the location that Apache Cargo will use to install containers when they are downloaded.
Executions of the plug-in should append the container name and version to this path.
E.g. apache-tomcat-5.5.20 -->
<cargo.container.install.dir>${user.home}/.m2/cargo/containers</cargo.container.install.dir>
</properties>
</project>
You can also set properties in your user settings.xml file in the event that you want each user to be able to set their own defaults. We use this approach to hide credentials that the CI server uses for some plug-ins from regular developers.
You could use something like below:
<profile>
<id>default</id>
<properties>
<env>default</env>
<myProperty>someValue</myProperty>
</properties>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
#akostadinov's solution works great for common usage... But if the desired property shall be used by reactor component during dependency resolution phase (very early in mvn pom hierarchy processing...) you should use profile "none activation" test mechanism to ensure the optional command line provided value is always prioritized regarding the value provided inside pom.xml. And this whatever deep is your pom hierarchy.
To do so, add this kind of profile in your parent pom.xml :
<profiles>
<profile>
<id>my.property</id>
<activation>
<property>
<name>!my.property</name>
</property>
</activation>
<properties>
<my.property>${an.other.property} or a_static_value</my.property>
</properties>
</profile>
</profiles>
This might work for you:
<profiles>
<profile>
<id>default</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<build>
<plugin>
<configuration>
<param>Foo</param>
</configuration>
</plugin>
</build>
...
</profile>
<profile>
<id>notdefault</id>
...
<build>
<plugin>
<configuration>
<param>${myProperty}</param>
</configuration>
</plugin>
</build>
...
</profile>
</profiles>
That way,
mvn clean will use "foo" as your default param. In cases when you need to override, use mvn -P notdefault -DmyProperty=something
I took sal's approach but flatten it a bit.
<profiles>
<profile>
<id>default</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<build>
<plugin>
<configuration>
<version>LATEST</version>
</configuration>
</plugin>
</build>
</profile>
</profiles>
Now you have 2 options:
Using default value: MVN install (all $version will be replaced with LATEST)
Using own value: MVN install -P! Default -Dversion=0.9 (all $version will be 0.9)

Maven compiler configuration via built-in properties?

The Maven Compiler Plugin compile goal indicates (as many of you already know) that I can turn off debug information by setting <debug>false</debug>.
<project …>
…
<profiles>
<profile>
<id>production</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<debug>false</debug>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>
I note however that the same documentation indicates that the "user property" for this setting is maven.compiler.debug. What does it mean that something is a "user property"? Does this mean that I can simply set the maven.compiler.debug property to false in my profile, and not even mention anything about a plugin, like this?
<project …>
…
<profiles>
<profile>
<id>production</id>
<properties>
<maven.compiler.debug>false</maven.compiler.debug>
</properties>
</profile>
</profiles>
</project>
As answered in another question:
"User property" specifies the name of the Maven property that can be used to set a plugin parameter. This allows configuring a plugin from outside the section. Note that this only works if the parameter is not specified in the section (see MNG-4979 - Cannot override configuration parameter from command line).
The "User property" on Maven3 can be used on the command line, by specifying
-Dmaven.compiler.debug=false or
in a POM profile like example below, as per your question:
<properties>
<maven.compiler.debug>false</maven.compiler.debug>
</properties>

In maven, how to name war file different in release than in snapshot build

I'm using the maven-war plugin. I've also looked at the maven-versions plugin. In neither case do I see how to give a different name to a snapshot build than a release build.
I've seen examples using profiles but the docs seem to indicate that the use of profiles in the pom.xml is not a good idea.
How should this be done?
Try the below
<build>
<plugins>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<webXml>src\main\webapp\WEB-INF\web.xml</webXml>
<classifier>${envClassifier}</classifier>
</configuration>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>snapshot</id>
<properties>
<envClassifier>snapshot</envClassifier>
</properties>
</profile>
<profile>
<id>release</id>
<properties>
<envClassifier>release</envClassifier>
</properties>
</profile>
</profiles>
Now, run command mvn clean install -Psnapshot Or mvn clean install -Prelease to get your desired artifacts. Hope this helps
You can control final war file name by warName attribute

How to read maven settings in .m2/settings.xml file from plugin

Three questions in decreasing order of importance - Links will do.
I need to read certain maven settings such as proxies, servers in my maven plugin. How do I read them from my plugin. I can read from .m2/settings.xml file but I think there must be an easier way (some API that already does it).
I see from developers cookbook there is a class org.apache.maven.project.MavenProject What dependency I need for this to be available in my plugin - I feel this would be good to have.
Is it possible to have my own properties in settings.xml say for example
<users> <user> <username>user_name1</username> <password>encrypted_password</password> </user></users>
How ?
PS: I am a beginner.
Update 1
I was able to create and read custom properties following Injecting POM Properties via Settings.xml. However I would like to have configuration similar to what cargo provides. E.g.
<servers>
<server>
<id>tomcat7_local</id>
<configuration>
<cargo.hostname>localhost</cargo.hostname>
<cargo.remote.uri>http://localhost:8080/manager/text</cargo.remote.uri>
<cargo.remote.username>my_username</cargo.remote.username>
<cargo.remote.password>my_password</cargo.remote.password>
<cargo.servlet.port>8080</cargo.servlet.port>
</configuration>
</server>
<server>
<id>tomcat6_local</id>
<configuration>
<cargo.hostname>localhost</cargo.hostname>
<cargo.remote.uri>http://localhost:8080/manager</cargo.remote.uri>
<cargo.remote.username>my_username</cargo.remote.username>
<cargo.remote.password>my_password</cargo.remote.password>
<cargo.servlet.port>8080</cargo.servlet.port>
</configuration>
</server>
</servers>
How do I achieve this. Have a kind of workaround for my 3rd problem not sure if its the right way.
Edit
Thanks Jordan002! I know I can have multiple profiles but I didn't know to use them. This way by having profiles I can set my variable's value or rather inject the value in my plugin by saying something like #Parameter(alias = "cargo.hostname")
private String hostname; But as I see, for cargo plugin all it requires is defined like below
<servers>
<server>
<id>someId</id>
<configuration>
<!-- Configurations are placed here -->
</configuration>
</servers>
Similarly, or may be not so similar as there is no configuration here
<proxies>
<proxy>
<active>true</active>
<protocol>http</protocol>
<host>My_proxy_host</host>
<port>My_proxy_port</port>
</proxy>
</proxies>
is where I can put proxy information that maven uses. Now, I don't want to redefine it inside some profiles and I don't want to parse this file to get informations.
Further, I would like do something like cargo is doing. It lets me write all the configuration inside servers and in project's pom I only have to do following
<plugin>
<groupId>org.codehaus.cargo</groupId>
<artifactId>cargo-maven2-plugin</artifactId>
<configuration>
<container>
<containerId>tomcat7x</containerId>
<type>remote</type>
</container>
<configuration>
<type>runtime</type>
<properties>
<cargo.server.settings>tomcat7_local</cargo.server.settings>
</properties>
</configuration>
<deployer>
<type>remote</type>
</deployer>
<deployables>
<deployable>
<groupId>${project.groupId}</groupId>
<artifactId>${project.artifactId}</artifactId>
<type>war</type>
<properties>
<context>${project.artifactId}</context>
</properties>
</deployable>
</deployables>
</configuration>
</plugin>
And cargo picks up configurations(s) that I defined for tomcat7_local, no need to write a profile for this.
Inject the setttings component as described here http://maven.apache.org/plugin-tools/maven-plugin-tools-annotations/
Its in Maven core org.apache.maven:maven-core:3.0.5
use properties directly and not nested. e.g. http://maven.apache.org/examples/injecting-properties-via-settings.html
I'm not too familiar with the Cargo plugin, but from the documentation, it appears to be configurable as any other Maven plugin would be. What I would change from your 'Update 1' would be to make tomcat6 and tomcat7 profiles:
<profiles>
<profile>
<id>tomcat6_local</id>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<properties>
<cargo.hostname>localhost</cargo.hostname>
<cargo.remote.uri>http://localhost:8080/manager/text</cargo.remote.uri>
<cargo.remote.username>my_username</cargo.remote.username>
<cargo.remote.password>my_password</cargo.remote.password>
<cargo.servlet.port>8080</cargo.servlet.port>
</properties>
</profile>
<profile>
<id>tomcat7_local</id>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<properties>
<cargo.hostname>localhost</cargo.hostname>
<cargo.remote.uri>http://localhost:8080/manager</cargo.remote.uri>
<cargo.remote.username>my_username</cargo.remote.username>
<cargo.remote.password>my_password</cargo.remote.password>
<cargo.servlet.port>8080</cargo.servlet.port>
</properties>
</profile>
</profiles>
and indicate at run time which tomcat you would like to start/stop by passing in the appropriate profile:
mvn install -P tomcat6_local
Hope this helps.

Categories