Activate different Maven profiles depending on current module? - maven-2

We have a multi module build with modules using different technologies, like Java and Flex. Is it somehow possible to activate different profiles based on the module that is compiled currently?
I tried it with an activation like
<profile>
<id>flex</id>
<activation>
<file>
<exists>${basedir}/src/main/flex</exists>
</file>
</activation>
...
</profile
But it didn't work, although the use of ${basedir} is documented in the Maven documentation (this is a bug in Maven). Is there a different possibility to have different activations based on the current module? Or does Maven only allow to activate a profile for all modules or not at all?

After some more research I finally came to the conclusion that this is not possible for two reasons in the current Maven version (2.1.0):
Maven profiles are not inherited, so you can't define a profile in a parent POM and activate that in a child POM.
I haven't found a possibility to activate a profile from a POM itself. The activation does not work with ${basedir} and the property activation response only to system settings, which are globally specified through the -D option.

For those like myself reading this question looking for answers, this use case now works in Maven 3.
There is was a bug affecting this feature in early versions of 3 (see http://jira.codehaus.org/browse/MNG-2363) but it works for me correctly using Maven 3.0.4.

In 2.2.1, profiles are inherited but the ${basedir} issue is still there. I'm in the same boat - I need to activate a profile based on the existence of a file in a given project. My child builds run individually just fine (inherited profile activated by local file existance), but if I run the build from the top parent, they fail because the file isn't found.

With regard to file-based activation, you can try removing ${basedir}. We use it like this:
<activation>
<file>
<missing>target/jboss/conf/jboss-service.xml</missing>
</file>
</activation>

I dont know if this helps, but I solved a similar problem with the following approach:
I created and described the profile in the parent POM, which has activeByDefault=false. The PluginManagement-Section then contains the configurations for different plugins.
The children can reuse this profile, and set activeByDefault=true
This makes the profile active, but still none of the plugins are activated.
But fortunately the described plugin configurations are available. You can reuse them in children by defining them in the Plugins-Section. You just provide the group- and the artifactID, and set inherited=true for each plugin you want to reuse in the children.
I hope that helps. Sorry for not including any code snippets, but I hope even so the soutions is understandable.

You can set a property in each module that you want to use the profile, and then use "property" activation in your profiles.

Related

Activate certain Maven profile in Intellij IDEA only

I'm looking for a way to activate the certain profile, which includes some dependencies and settings, related to the development mode only, when the project is opened in IDEA.
I know that you can specify the profile to be used - on project import, or in "Maven projects" tab. However it requires some interactions, which are easy to forget.
So it would be nice to instruct idea to always activate the appropriate profile, may be by providing some property or runtime configuration, or whatever.
This profile should be active only for IDEA import.
For auto-activation of the profile, you can base the activation on a system property that is only present when running through the IDEA embedded Maven:
idea.maven.embedder.version
idea.version
Example:
<profile>
<id>idea-only</id>
<activation>
<property>
<name>idea.maven.embedder.version</name>
</property>
</activation>
...
</profile>
idea.maven.embedder.version works with IDEA's bundled Maven and also works if you override that with your own locally installed version of Maven in preferences - the idea.maven.embedder.version property is always set when executed from within the IDEA when importing, generating sources, etc.
If you import a maven project in intellij, you can choose profiles in the maven tool window (usually on the right of the screen). Once these profiles are selected they will persist in the project configuration for that project and will become effective every time the project loads, until you choose to change them. These profile selections will only affect intellij and instances of maven run within intellij.
Another way to achieve this is in Intellij's maven configuration, by specifying a settings file that is specific to intellij development. This can be a copy of your standard settings, named something like intellij-settings.xml, but you can add an active profiles section to it:
<activeProfiles>
<activeProfile>intellij-specific-profile</activeProfile>
</activeProfiles>
Be sure to specify the settings file in your intellij maven config before importing the project. That way it will apply to all projects on import.

avoid instantiating maven dependency plugin

I would like to use the "deploy"-phase of maven to deploy some files to my appliance (using a custom maven plugin), but I don't need the maven-deploy-plugin.
There are several answers on stackoverflow and the rest of the web on how to avoid a plugin being run, for example:
maven exclude plugin defined in parent pom
Disable a Maven plugin defined in a parent POM
I have tried setting <phase>none, <skip>true and <inherited>false. However, the plugin is still configured, which fails with message:
failed to configure plugin parameters for org.apache.maven.plugins maven-deploy-plugin 2.4
because there is no distributionManagement-element in my pom.
Is there a way to completely remove the dependency-plugin from the maven lifecycle?
In my opinion, this is unlikely to work even with those workarounds simply because the maven-deploy-plugin is a core plugin, like it or not.
Therefore, here's another hack:
Create a profile.
Define your plugin in it and attach it to the install phase.
Trigger the deployment, by invoking your profile.
Not as fancy as you would have hoped for, but it should do the trick. If anyone has better ideas, I would also like to hear them, as I've faced this sort of issue as well.

Maven profile activation with multiple conditions

I'm working on getting the rpm-maven plugin setup in a project. In our staging and production environments, the build occurs on Red Hat boxes, but we have several Windows boxes that are used for development and testing so I wanted the RPM build process to be part of a profile that is only active on a box that has rpmbuild installed.
This was my first attempt at an activation condition:
<activation>
<os>
<family>unix</family>
</os>
<file>
<exists>/usr/bin/rpmbuild</exists>
</file>
</activation>
My initial testing only involved building on a Windows box and building on a CentOS box, and both gave me the results I expected. Later, the build broke on a Linux machine that didn't have rpmbuild available. It looks like having two conditions like this isn't supported. Is this the case? I realize I can probably just get rid of the <os/> element and get the results I want, but for future reference is there a better way to create profiles with multiple activation conditions?
Maven <activation> block is a list of OR -- the profile will be activated as soon as the first criteria is met. So, it is less likely that your problem has a solution at least until this bug-report gets fixed https://issues.apache.org/jira/browse/MNG-4565
Update:
it's fixed in 3.2.2 now – sfussenegger (via comment)
And worst you can mix condition of different type for example file, jdk and property as described here http://www.sonatype.com/books/mvnref-book/reference/profiles-sect-activation.html, but you can't even put two condition of same type, for example two properties
<activation>
<property>
<name>integrationTest</name>
</property>
<property>
<name>packaging</name>
<value>swf</value>
</property>
</activation>
This won't work as only one <property> tag will be allowed.
Associated JIRA : https://issues.apache.org/jira/browse/MNG-3328
And the bug described above is still open... 5 years it's just a shame !
Just fixed by me :)
Starting from 3.2.2 it will work as expected: multiple conditions will be ANDed
Reference - https://github.com/apache/maven/commits/master, search by MNG-4565
Commit URL - https://github.com/apache/maven/commit/c6529932f9e3efdfc86ed73f59a307a8f8b6ea5f
I think this is what these Maven extensions do:
Maven EL Profile Activator Extension
This one is pretty simple, have a look at the source
Maven Profile Activation Extension
This one has more options for the actual activation expression, including Scala.
However, since it's an extension (not a plugin), every project using it will have to register the extension. And there's a risk that the project author will abandon it and it won't work in future maven versions.

Maven - activate child profile based on property

Scenario:
Given
Parent POM which defines a profile and a child (as module)
Child project(s) that will be using the profile by referring to the parent POM.
The intent is to skip profile execution in the parent and execute it in the child only
Profile has activation section <activation><property><name>foo</name></property><activation>
Since parent does not define foo property - the profile is inactive and will not be executed for the parent build
Now, I'm defining <properties><foo>true</foo></properties> in the child with hope that the property will be picked up when child build is executed and profile will be activated. No such luck. Profile is never activated, which tells me that property is never set.
Just to note: mvn package -Dfoo=true activates profile in both parent and child
Am I trying to do the impossible or just doing it wrong?
P.S. Hmmm - even if I define property in the parent, the profile is not triggered. What gives?
To expand on #rich-seller's answer, and #Bostone's self-answer, it seems to be impossible to have a setup where the parent POM defines a few profiles as alternatives, and child POMs select one of these profiles by default, while allowing you to override the choice for a child temporarily (i.e. on the CLI). Consider a parent POM for projects which use some framework and an associated plugin, both of whose versions we can assume are defined by properties:
<profiles>
<profile>
<id>newest</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<framework.version>2.0</framework.version>
<plugin.version>2.0</plugin.version>
</properties>
</profile>
<profile>
<id>older</id>
<activation>
<property>
<name>older.framework</name>
<value>true</value>
</property>
</activation>
<properties>
<framework.version>1.1</framework.version>
<plugin.version>1.1</plugin.version>
</properties>
</profile>
</profiles>
Now a child inheriting from this parent POM by default will use 2.0 as you would expect, and -Polder or -Dolder.framework=true will work to try building it with the older framework (e.g. to test compatibility). However you cannot write in the child POM
<properties>
<older.framework>true</older.framework>
</properties>
and have the older profile be activated automatically. You could use file-based activation to make this module build against 1.1 if newest were not active by default, but then it is not easy to temporarily run it against 2.0: as far as I know both older and newest profiles would be active if you passed -Pnewest, so you need to explicitly disable other profiles which is unreasonable if you have a dozen of them. So there is just no solution except to copy the profile information to the child POM:
<properties>
<framework.version>1.1</framework.version>
<plugin.version>1.1</plugin.version>
</properties>
at which point -Pnewest will not work to override these properties, so you need to use -Dframework.version=2.0 -Dplugin.version=2.0.
In other words, the profiles are only useful if all the child modules can use the same profile (here newest) by default. If some of them are normally built with 1.1 and some with 2.0, the profiles are useless.
Seems like this is a use case for a Maven core enhancement, or perhaps a Maven 3 build extension. http://docs.codehaus.org/display/MAVEN/Custom+Profile+Activators and https://github.com/maoo/maven-tiles come to mind.
The profile can only be activated by properties passed from the command line. This is because properties in the POM can only be processed once the POM has been parsed, at which point it is too late to resolve the profile activation.
You're in a bit of a catch-22 with this approach unless you are able to pass the property from the command line, specify profile activation in your settings.xml (generally not a great idea), or use the workaround in my previous answer to use the presence of a marker file.
One final alternative if you're on Maven 2.1.0+ is to deactivate the profile via the command line for the parent POM only, this is still obviously not ideal.
You can deactivate a profile with either the character '!' or '-' like this:
mvn install -P !profile-1,!profile-2
To directly answer my own question: in multi-module build all properties are set before build is run so it is impossible to activate/deactivate profile in one of the modules during the build based on setting the propety in the child POM. However if you are looking for way of doing it by using other means please read this comment

Maven repository configurations

I've asked a similar question in which part of this was addressed, but I'd like to expand in more detail.
When configuring maven to look at internal repositories, is it best to put that information in the project pom or in a user's settings.xml? An explanation on why would be really helpful here.
thanks,
Jeff
You should always try to make the maven project so that it compiles from a clean checkout from source control in your local environment; without a settings.xml. In my opinion this means that you place any overrides to sensible default values in the user's settings.xml file. But the pom should contain sensible values that will work for everyone.
I encourage you to put the repository definition in the POM, this way any developer just grab a copy of the code and run Maven to get it compiled, without having to change things in his settings file.
I find the setting.xml file useful just for hacking Maven's behaviour in special situations, for example when one repository is not accessible due to a firewall and you need to use a mirror. But that's my personal opinion. Maven documentation gives you more freedom:
The settings element in the
settings.xml file contains elements
used to define values which configure
Maven execution in various ways, like
the pom.xml, but should not be bundled
to any specific project, or
distributed to an audience. These
include values such as the local
repository location, alternate remote
repository servers, and authentication
information.
If you have a local repository which is used in every single project you may add that at the settings.xml, just be sure that configuration is well documented, in my current project it's not and new developers struggle at the beginning when they try to compile something.
We use the user's settings.xml and include info in the README about what possible other repos may be needed.
In theory a given group-artifact-version is the same no matter which repo it comes from. It works pretty well for us. If you find yourself with two different assets that have the same group-artifact-version identifier, then that indicates you're doing something really bad.