Activating a Child Profile from a Parent Profile - maven

I have the following parent pom.xml file:
<profile>
<id>build_full</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<modules>
<module>mymodule_interface</module>
<module>mymodule_switch</module>
<module>mymodule_switch_simulator</module>
<module>mymodule_switch_controller</module>
<module>mymodule_server</module>
</modules>
</profile>
and in my child pom for mymodule_server, I have the following:
<profile>
<id>subprofile</id>
<modules>
<module>...various modules...</module>
</modules>
</profile>
<profile>
<id>default</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<modules>
<module>...various modules...</module>
</modules>
</profile>
How, when I invoke maven: mvn -P build_full, can I force the child module (mymodule_server) to use profile subprofile rather than default?

No, you can't activate a child profile from a parent profile. More generally, you can't activate or deactivate any profile from any other profile (there is a JIRA feature-request MNG-3309). What you can do is activate two profiles based on the same property.
First of all, using a profile that is activated by default is generally not a good idea. What you want is to activate a profile based on some condition (OS version, system property...). To solve your problem, you can activate build_full profile when a certain system property is present, and make sure that subprofile is also activated when that same property is present.
A sample configuration would be the following, where both profiles are activated when the fullBuild system property is set to true. Invoking Maven with mvn -DfullBuild=true ... will thus activate both profiles.
<profile>
<id>build_full</id>
<activation>
<property>
<name>fullBuild</name>
<value>true</value>
</property>
</activation>
<modules>
<module>mymodule_interface</module>
<module>mymodule_switch</module>
<module>mymodule_switch_simulator</module>
<module>mymodule_switch_controller</module>
<module>mymodule_server</module>
</modules>
</profile>
<profile>
<id>subprofile</id>
<activation>
<property>
<name>fullBuild</name>
<value>true</value>
</property>
</activation>
<modules>
<module>...various modules...</module>
</modules>
</profile>

In your case, from the top parent/aggregator folder, you could just run:
mvn clean install -Pbuild_full,!default,subprofile
It will disable any profile having name default (and hence disable the profile in the concerned sub-module) and enable any profile having name subprofile (and hence enable the profile you wanted).
Alternatively, you could configure subprofile as such:
<profiles>
<profile>
<id>subprofile</id>
<activation>
<property>
<name>subprofile</name>
<value>true</value>
</property>
</activation>
....
and then run as following:
mvn clean install -Dsubprofile=true -Pbuild_full
It will have the same effect. You can even avoid the value element and simply specify -Dsubprofile, its existence would be enough to activate the profile (in that case a more meaningful name is suggested, like -DactivateSubprofile). Since you active a different profile, automatically Maven will deactivate the default one.

Related

Maven - Profile&Modules - Activation by property?

Could someone help me understand this issue below? Approach #1 below works as expected, when the IDE asks maven to build the project it rebuilds moduleA and include it as a dependency; everybody happy. Approach #2 which is what I want to use does not behave the same way, myProperty is a system property I've defined and toggling it between true/false does activate the profile BUT it does not build moduleA, why?
#1
...
<profiles>
<profile>
<id>testProfile</id>
<activation>
<activationByDefault>true</activationByDefault>
</activation>
</profile>
<modules>
<module>../moduleA</module>
</modules>
</profiles>
...
#2
...
<profiles>
<profile>
<id>testProfile</id>
<activation>
<property>
<name>myProperty</name>
<value>true</value>
</property>
</activation>
</profile>
<modules>
<module>../moduleA</module>
</modules>
</profiles>
...
Oh, after hours up and down the documentation I found my problem. Was not aware that the name of the config file mattered, so I had named it jvm.config as I saw the bash script looked after such a file for maven options. Apparently it was supposed to be in maven.config

Creating exclusive profiles in maven

I currently have a pom with platform specific profiles (e.g. linux 32bit, windows 64 bit, etc...). Additionally, I have set it up to automatically choose the invoker's platform as a default.
Now, assume I am in a linux 32 machine: I also want to build for win64 by invoking mvn -Pwin64 pakage but in doing so, both the linux32 and win64 profiles get activated. I have tried activating the local platform profile with activeProfiles and using ativation tags. The trouble is that -P does not disable all other profiles as explained in the documentation:
This option takes an argument that is a comma-delimited list of
profile-ids to use. When this option is specified, no profiles other
than those specified in the option argument will be activated.
Am I understanding this wrong? How would you handle this?
Note: I know I could run mvn -P-linux32,win64 but that is only valid on linux32 platforms, and any mistakes may result in a bloated build with duplicate classes.
Thanks!
This statement from the profile docs:
As of Maven 3.0, profiles in the POM can also be activated based on properties from active profiles from the settings.xml.
Would lead me to try the solution below. Each developer defines his default platform as a property in his settings.xml file and overrides it on the cmdline if needed.
Developer's settings.xml
<profile>
<id>platform-config</id>
<property>
<name>build.platform</name>
<value>win32</value>
</property>
</profile>
....
<activeProfiles>
<activeProfile>platform-config</activeProfile>
</activeProfiles>
Project's pom.xml
<project>
...
<profiles>
<profile>
<id>win32</id>
<activation>
<property>
<name>build.platform</name>
<value>win32</value>
</property>
</activation>
...
</profile>
<profile>
<id>linux32</id>
<activation>
<property>
<name>build.platform</name>
<value>linux32</value>
</property>
</activation>
...
</profile>
</profiles>
Then, mvn install should activate the win32 profile because the default value for the build.platform property is win32, while mvn install -Dbuild.platform=linux32 will override the default property setting and use the Linux profile instead.
Why don't you use the profile activation by plattform like this:
<project>
...
<profiles>
<profile>
<id>win32</id>
<activation>
<activeByDefault>false</activeByDefault>
<os>
<name>Windows XP</name>
<family>Windows</family>
<arch>x86</arch>
<version>5.1.2600</version>
</os>
</activation>
...
</profile>
</profiles>
</project>

In Maven, can a profile override the modules (to not include any)

In maven, once you define your modules in you pom.xml all profiles aggregate the modules defined in them: (relevant part only)
<project>
<modules>
<module>module1</module>
</modules>
<profiles>
<profile>
<id>pr1</id>
<modules>
<moudule>module2</module>
</modules>
If you perform a mvn clean it will pass the command to module1.
If you issue mvn clean -Ppr1 it will pass along to module1 and module2.
I wonder if in maven 3 it is possible to have a pom.xml with submodules and override this. I mean to execute a profile that instead of add their own modules to the build force those like:
<project>
<!-- omitted -->
<modules>
<!-- modules -->
</modules>
<build>
<!-- build -->
</build>
<profiles>
<profile>
<!-- This profile with no modules -->
</profile>
</profiles>
</project>
The requirement might sound silly, but I just want to know if there is a mechanism like in plugin configuration.
<configuration self.combine="override"
Regards!
ssedano
It's not possible. Profile configuration is always merged with main configuration, so you only can add modules in your case.
What you can do instead, however, is to create a some kind of "default" profile (by <activeByDefault>true</activeByDefault> in <activation> section) that is enabled when no other profiles are invoked and put your default modules' list there. Then, when no profile is specified on Maven build call, this "default" profile is used, but when you call explicitly at least one profile, it's not, so you can this way define modules' list from scratch.
While the question is old, Google still ranks it highly, so it makes sense to add a new answer.
You can use the activation by absence of a property trick to achieve what you want.
<profiles>
<!-- By default, include the modules -->
<profile>
<id>full-build</id>
<activation>
<!-- Activation by absence of a property. Run normally, without -Dskip-modules -->
<property>
<name>!skip-modules</name>
</property>
</activation>
<modules>
<module>module1</module>
<module>module2</module>
<module>module3</module>
</modules>
</profile>
<!-- No-modules build -->
<profile>
<id>no-modules</id>
<activation>
<!-- Activation by a property. Run with -Dskip-modules to activate -->
<property>
<name>skip-modules</name>
</property>
</activation>
<modules>
</modules>
</profile>
</profiles>
You can do things like this:
<profiles>
<profile>
<id>run-xyz</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<modules>
<module>www-ab</module>
<module>www-cd</module>
</modules>
</profile>
<profile>
<id>run-its</id>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<modules>
<module>www-db</module>
<module>www-it</module>
</modules>
</profile>
</profiles>
If you are talking about such things. But i would recommend to be very carefull about such things.
It's only the question how you set activeByDefault. With this it's possible to create more or less any combination.

Confused that order matters when defining conditional profiles in maven

I have a configurable property line.ending that I used during the assembly phase of the building of my project to specify the line ending type of my application property files. For that I have created two profiles LF_DOS and LF_UNIX, so that when I launch :
mvn install
or
mvn install -P LF_DOS
line.ending equals 'dos', and when I launch :
mvn install -P LF_UNIX
line.ending equals 'unix'.
My first attempt to do this was simply :
<profile>
<id>LF_UNIX</id>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<properties>
<line.ending>unix</line.ending>
</properties>
</profile>
<profile>
<id>LF_DOS</id>
<activation>
<property>
<name>!line.ending</name>
</property>
</activation>
<properties>
<line.ending>dos</line.ending>
</properties>
</profile>
Unfortunately, this always gave me line.ending=dos, whatever LF_UNIX is set or not. Weird... But, the more confusing to me, is that I solved the problem just by changing the profile declaration order, like this :
<profile>
<id>LF_DOS</id>
<activation>
<property>
<name>!line.ending</name>
</property>
</activation>
<properties>
<line.ending>dos</line.ending>
</properties>
</profile>
<profile>
<id>LF_UNIX</id>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<properties>
<line.ending>unix</line.ending>
</properties>
</profile>
This works exactly like I want.
My questions is : is this a bug ? Or is it something to know about maven profiles, a kind of limitation that makes profiles order declaration particularly matter in such a case ?
The confusion lies in your understanding of how profile activation works.
You think that this:
<activation>
<property>
<name>!line.ending</name>
</property>
</activation>
means if I don't have a maven property named "line.ending" set, activate this profile. What it really means if I didn't specify -Dline.ending=X on the command line, activate this profile. So unless you run something like this:
mvn clean install -Dline.ending=unix
You are activating this profile and thus having the value set to dos.

Maven: Only activate profile A if profile B is not activated?

I have two Maven profiles profile-A and profile-B. "B" should only be activated if "A" is not activated.
So if I would call
mvn install
profile-B is executed (but not profile-A).
But if I would call
mvn install -Pprofile-A
then only profile-A is executed (but not profile-B).
Any hints how I need to write my pom.xml to achieve this?
I already tried this, but it doesn't work:
<profiles>
<profile>
<id>profile-A</id>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
...
</profile>
<profile>
<id>profile-B</id>
<activation>
<activeByDefault>true</activeByDefault>
<property>
<name>!profile-A</name>
</property>
...
</activation>
...
</profile>
</profiles>
I think for your example command line to work as expected, all you need is the <activeByDefault>true</activeByDefault> for profile B.
http://maven.apache.org/guides/introduction/introduction-to-profiles.html states:
All profiles that are active by default are automatically deactivated when a profile in the POM is activated on the command line or through its activation config.

Resources