Inheriting Maven profiles and activation - java

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.

Related

How can I print property in pom.xml of build?

My current project profiles in pom.xml are following this.
<profiles>
<profile>
<id>local</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<profile>
<id>production</id>
</profile>
<profile>
<id>development</id>
</profile>
</profiles>
I am looking for a way to print to check if this build is on local in .java code.
I also would like to make some functions divided.
System.out.println(isLocal)
/* When it in local. it should be true*/
if(isLocal)
{
XXX
}
else
{
YYY
}
Project is compiled like "mvn compile -P local"
in Eclipse
You probably have to do the following:
Define a property inside the profile.
Define a properties file in your resources.
Use resource filtering to write the property to this properties file.
Load the resource in your Java code and check the property within.

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)

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

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

How to specify packaging in a Maven profile?

I have a project which can be packaged and deployed two different ways, it's either a WAR for Tomcat, or a shaded JAR for AWS Lambda. Currently this isn't working very well, I have to keep changing the pom.xml back and forth when doing a release. Is there a way to accomplish this with Maven profiles?
e.g., I'd like to do
mvn install -Pwar
to generate the WAR, and
mvn install -Plambda
to generate the shaded JAR.
Is this possible?
You can try to include the following in your pom.xml
<packaging>${packaging.type}</packaging>
<profiles>
<profile>
<id>lambda</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<packaging.type>jar</packaging.type>
</properties>
</profile>
<profile>
<id>war</id>
<properties>
<packaging.type>war</packaging.type>
</properties>
</profile>
</profiles>

How to inject Maven profile value into properties file

Little stuck here. I have a pom with 3 profiles. Theese profiles have different version name. I want to inject that version name into properties file when a specific profile is building.
My profiles:
<profiles>
<profile>
<id>dev</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<projectVersion>DEV</projectVersion>
</properties>
</profile>
<profile>
<id>test</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<projectVersion>1.0.0-RC1</projectVersion>
</properties>
</profile>
<profile>
<id>prod</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<projectVersion>1.0.0-Final</projectVersion>
</properties>
</profile>
</profiles>
and filter.properties looks like this:
projectName = defaultName
versionName = defaultVersion
How to do that? Im building project by command:
mvn clean install -D profile_name
What you need to do is to add a new section to your <build> section of your POM file.
Like this:
<build>
<resources>
<resource>
<filtering>true</filtering>
<includes>
<include>**/*.properties</include>
</includes>
<directory>src/main/resources</directory>
</resource>
</resources>
</build>
This will look inside the specified folder (src/main/resources) on the specified files **/*.properties and change the files when it encounters defined variables.
So in order to this work your propertie file must be this way:
projectName = ${defaultName}
versionName = ${defaultVersion}
Be aware with these variables name. Maven will replace it with the defined names by you or the names of the Maven structure like ${projectVersion} will be replaced by the <version>1.0</version> tag of your pom file.
So instead of using:
<properties>
<projectVersion>1.0.0-Final</projectVersion>
</properties>
Change the name (and the version) of this variable to something else like:
<properties>
<defaultVersion>1.0.0-Final</defaultVersion>
<defaultName>someName</defaultName>
</properties>
On all your profiles.
And just run your maven command as:
mvn install -Pprofilename
Be careful with the profiles you shown. All of them are active by default and this is a problem because they all define the same maven property. Instead, you should mark only one as active by default.
You also don't show <resources> filtering to process filter.properties, so this can be a mistake, as well.
And a final though, you are controlling artifact version on maven profiles. I don't think it is a good idea. Please read about maven-release-plugin.

Categories