using maven variables defined in two separate profiles - maven-2

I have two profiles in my pom.xml, dev and stage:
<profiles>
<profile>
<id>dev</id>
<properties>
<hostname>vl-wlp1.hk.oracle.com</hostname>
</properties>
<id>stage</id>
<properties>
<hostname>vl-wcfs.hk.oracle.com</hostname>
</properties>
</profile>
</profiles>
And I'd like use these in my site documentation at:
src/site/apt/index.apt
like so:
Dev Site: ${dev.hostname}
Stage Site: ${stage.hostname}
Can I do that or something else that has the same effect?

Not without a huge hack, no.
If you want to read both property values independently, they will have to be two different properties.
How about a pragmatic solution like this:
<properties>
<dev.host>vl-wlp1.hk.oracle.com</dev.host>
<stage.host>vl-wcfs.hk.oracle.com</stage.host>
</properties>
<profiles>
<profile>
<id>dev</id>
<properties>
<hostname>${dev.host}</hostname>
</properties>
<id>stage</id>
<properties>
<hostname>${stage.host}</hostname>
</properties>
</profile>
</profiles>
src/site/apt/index.apt:
Dev Site: ${dev.host}
Stage Site: ${stage.host}
(The huge hack mentioned above would mean programmatically iterating over the current project's profiles and parsing each profile's properties manually, you could do that in a custom maven plugin or in a Groovy Script using GMaven)

Related

Maven not picking up property defined in settings.xml in .m2

I have defined the property like so:
<profile>
<id>dand</id>
<properties>
<workSpace>s:/_java/</workSpace>
</properties>
...repos
</profile>
<activeProfiles>
<activeProfile>dand</activeProfile>
</activeProfiles>
I am attempting to access the property with
<outputDir>${workSpace}/src/main/java</outputDir>
I would start by exectugin mvn help:active-profiles to test that dand profile is effectively enabled. Let us know what you see.

How to exclude a module from a Maven reactor build?

We have a Maven 2 project with lots of modules in it. Example:
<modules>
<module>common</module>
<module>foo</module>
<module>data</module>
<module>bar</module>
... more ...
</module>
Let's say the "data" module is time consuming to build and we want to exclude it when the project is build by a CI server. Currently we use two pom.xml files to achieve this. One has all modules in it and the other one has all modules except the ones which can be left out for CI. But that's pretty annoying because sometimes we forget to put a new module into both files.
Is there a solution which doesn't need two separate module lists?
With Maven 3.2.1, you can now use -pl !<module_name>,!<module_name> to exclude certain modules from the reactor build.
See this feature request: https://issues.apache.org/jira/browse/MNG-5230
The easiest might be to use profiles like this:
<project>
...
<modules>
<module>common</module>
<module>foo</module>
<module>bar</module>
<modules>
...
<profiles>
<profile>
<id>expensive-modules-to-build</id>
<modules>
<module>data</module>
</modules>
</profile>
</profiles>
</project>
You should then check out ways you can activate profiles
The projects to build can also be specified on the mvn command line. This would remove the need for a separate pom, but instead you would have to change the CI configuration everytime there is a new module.
-pl,--projects <arg> Comma-delimited list of specified
reactor projects to build instead
of all projects. A project can be
specified by [groupId]:artifactId
or by its relative path.
Maybe a combination of this flag and --also-make-dependents or --also-make would reduce this maintenance burden again.
-am,--also-make If project list is specified, also
build projects required by the
list
-amd,--also-make-dependents If project list is specified, also
build projects that depend on
projects on the list
I assume you want the default build to always build everything, regardless of speed, so that new developers can get started quickly without having to understand lots about the POM. You can use profiles like this:
<modules>
<module>common</module>
<module>foo</module>
<module>bar</module>
</modules>
...
<profiles>
<profile>
<id>expensive-modules-to-build</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<modules>
<module>data</module>
</modules>
</profile>
</profiles>
</project>
The problem with this is that if a developer specifies another profile on the command line, then the expensive-modules-to-build isn't included (unless the developer also specifies it). This makes it complicated to remember which profiles need to be included.
Here is a hacky way around that. Both profiles are always included, because the pom.xml file always exists. So to exclude the expensive modules, you can use -P!full-build on the command line.
<profiles>
<profile>
<id>full-build</id>
<activation>
<file>
<exists>pom.xml</exists>
</file>
</activation>
<modules>
<module>data</module>
</modules>
</profile>
<profile>
<id>short-build</id>
<activation>
<file>
<exists>pom.xml</exists>
</file>
</activation>
<modules>
<module>common</module>
<module>foo</module>
<module>bar</module>
</modules>
</profile>
</profiles>
Another idea: Reactor modules can be nested, so it should be possible to group your fast and slow-building modules into separate poms and then add another aggregator pom containing these two as modules. Your CI Server could then only reference the pom containing the fast building modules.
<artifactId>fast</artifactId>
<modules>
<module>fast-a</module>
<module>fast-b</module>
<module>fast-c</module>
</module>
<artifactId>all</artifactId>
<modules>
<module>fast</module>
<module>slow</module>
</module>
You could be to use maven profiles. In our build environment, we created a profile quick that disables many plugins and test execution.
This is done by
<profile>
<id>quick</id>
<properties>
<skipTests>true</skipTests>
<!-- others... -->
</properties>
<build>
<plugins>
<!-- configuration... -->
</plugins>
</build>
</profile>
And then we invoke maven the following way
mvn groupId:artifactId:goal -P quick
You could maybe disable compilation and other standard plugins in the pom of your module to speed it up.
Not exactly the answer these folks were asking for. My situation was I wanted to deploy only the parent pom. I'm using the spring-boot-thin-layout in a child module. This requires the parent module be deployed into artifactory. I added the following into my project. It enables skipping of install and/or deploy phase.
In my parent pom:
<properties>
<disable.install>true</disable.install>
<disable.deploy>true</disable.deploy>
<enable.deployAtEnd>true</enable.deployAtEnd>
</properties>
<profiles>
<profile>
<id>deploy-parent</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<disable.install>true</disable.install>
<disable.deploy>true</disable.deploy>
<deployAtEnd>${enable.deployAtEnd}</deployAtEnd>
</properties>
<build>
<finalName>${project.version}</finalName>
</build>
</profile>
</profiles>
And the in my child pom(s) or any module you don't want deployed with parent:
<properties>
<maven.install.skip>${disable.install}</maven.install.skip>
<maven.deploy.skip>${disable.deploy}</maven.deploy.skip>
<deployAtEnd>${enable.deployAtEnd}</deployAtEnd>
</properties>
So effectively when I run mvn deploy on the parent pom, it will compile all the modules, not run install on anything, and then at the end deploy any module not having <maven.deploy.skip>${disable.deploy}</maven.deploy.skip> in it's properties. So in my case only deploying the parent.

Maven Profile - Activate Profile depending on packaging

I have a POM which declares web application stuff that is common to my projects. I use this as the parent for all web applications.
Is it possible to activate a profile only when the packaging is war? I have tried the property approach, but that doesn't work (as it isn't a system/environment property).
Since this fails the build, I can simply disable that profile when installing the POM, but I'd like it to be more intelligent on its own.
Walter
You can simply check the existence of src/main/webapp. Each web application that uses the Maven standard directory layout should contain this folder. So you avoid unnecessary dummy files.
<profile>
<id>custom-profile-eclipse-project-generation-webapp</id>
<activation>
<file>
<exists>${basedir}/src/main/webapp</exists>
</file>
</activation>
<build>
</build>
</profile>
More precise you can also check for the the existence of ${basedir}/src/main/webapp/WEB-INF/web.xml. That should definitively identify a war-project.
For myself I use this configuration in my common super-pom to configure the maven-eclipse-plugin for different project types. Thats very handy to get homogenous eclipse-configurations over the same project type in our organization, especially when developers straightforwardly run eclipse:eclipse on multi-module-projects.
I know this isn't answering your question directly, but the usual workaround for problems like this is to just use specialization (as with classes).
So you have your MasterPom with all common behavior.
MasterWarPom that extends MasterPom (is it's parent), and put any 'packing is war' specializations in here.
Likewise you could have MasterJarPom, etc ...
That way the differences are split out nicely.
There's no clean way to do that, the parent module has no way of knowing the child's packaging. (Non-clean solutions would involve creating a plugin that parses the child module's pom etc.)
The best I've been able to come up with for these sorts scenarios has been to use a file-based activation trigger.
eg my parent pom has
<profile>
<id>maven-war-project</id>
<activation>
<file><!-- add a file named .maven-war-project-marker to webapp projects to activate this profile -->
<exists>${basedir}/.maven-war-project-marker</exists>
</file>
</activation>
<build>
<plugins>
<!-- configuration for webapp plugins here -->
</plugins>
</build>
and webapp projects that inherit from this parent contain a file named
'.maven-war-project-marker'
that activates the profile
This looks pretty obtuse but works fairly reliably whereas
- using property-activation is unreliable if a different person or system does the build,
- inheriting from type-specific parents became a bit cumbersome for me as the grandparent-pom changes version relatively frequently as it is used to define 'standard' or preferred versions of common dependencies which in turn required corresponding releases of all of the type-specific parents with no change other than the grandparent version
Try in this way ?
mvn package -Dmaven.test.skip=true -Dwar
<project ×××××>
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>××××</groupId>
<artifactId>×××××</artifactId>
<version>×××××</version>
<relativePath>../../</relativePath>
</parent>
<artifactId>×××××</artifactId>
<name>${project.artifactId}-${project.version}</name>
<description>${project.artifactId}-${project.version}</description>
<properties>
<packaging.type>jar</packaging.type>
</properties>
<profiles>
<profile>
<activation>
<property>
<name>war</name>
</property>
</activation>
<properties>
<packaging.type>war</packaging.type>
</properties>
<build>
<finalName>ROOT</finalName>
</build>
</profile>
</profiles>
<packaging>${packaging.type}</packaging>
<dependencies>
<dependency>
... ...
</dependency>
... ...
</dependencies>

maven release plugin ignores releaseProfile

I am using two profiles: development and production.
Development should be active on default; production should be used when I am releasing.
In my pom.xml I have:
[...]
<plugin>
<artifactId>maven-release-plugin</artifactId>
<version>2.0-beta-9</version>
<configuration>
<useReleaseProfile>false</useReleaseProfile>
<goals>deploy</goals>
<arguments>-Pproduction</arguments>
</configuration>
</plugin>
[...]
<profiles>
<profile>
<id>production</id>
<properties>
<profile.name>production</profile.name>
</properties>
[...]
</profile>
<profile>
<id>development</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<profile.name>development</profile.name>
</properties>
[...]
</profile>
[...]
It just does not work.
useReleaseProfiles doesn't work either:
http://jira.codehaus.org/browse/MRELEASE-459
The development profile should be always active but not when running mvn release:perform.
How do you achieve this?
[UPDATE]:
I have seen with the debug flag that my production profile is used, but development profile is used too, because it is activeByDefault. This cant be overridden by the releaseProfile argument. It would be nice to force the release plugin to use only the "production" profile.
The maven-release-plugin documentation encourages using the releaseProfiles configuration parameter to automatically invoke profiles during the release process.
This is a better approach than manually invoking release profiles from the command-line. One reason, is because the profiles used in the release will be documented in the pom.xml and stored with the tagged code. This makes the build process easier to understand and easier to repeat later, exactly the same way the project was originally released.
If using maven-release-plugin older than 2.4 see this bug preventing use of the above mentioned parameter.
Be aware that in case of a multi-module project you'll have to put the "releaseProfiles" configuration in the root pom! See also this issue for more information about that.
I think you should simply activate your profiles through a property.
<profiles>
<profile>
<id>production</id>
<activation>
<property>
<name>build</name>
<value>release</value>
</property>
</activation>
[...]
</profile>
<profile>
<id>development</id>
<activation>
<property>
<name>build</name>
<value>develop</value>
</property>
</activation>
[...]
</profile>
<profiles>
Do your builds by executing something like this
mvn -Dbuild=develop package
mvn -Dbuild=develop test
mvn -Dbuild=release release:prepare
mvn -Dbuild=release release:perform
If you check "Introduction to Build Profiles", "Deactivating a profile":
mvn groupId:artifactId:goal -P !profile-1,!profile-2
I guess you could use this to deactivate your default profile?
This is a very old post but I came across this issue quite recently. The releaseProfile only worked for me when I set the releaseProfiles to profile called release. Any other profile gives same error.
Sample code:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
<version>2.5.3</version>
<configuration>
<tagNameFormat>#{project.artifactId}-#{project.version}</tagNameFormat>
<autoVersionSubmodules>true</autoVersionSubmodules>
<releaseProfiles>release</releaseProfiles>
<allowTimestampedSnapshots>true</allowTimestampedSnapshots>
</configuration>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>release</id>
<properties>
<connectionUrl>${scm-base}/tags/${project.artifactId}-${project.version}</connectionUrl>
</properties>
</profile>
</profiles>

maven conditional dependencies

We would like to bundle library dependencies from (Alfresco or Jackrabbit or ...) based on the customer choice. The number of dependencies actually varies based on the chosen vendor. How do we provide hooks at the maven level, so that the final product just includes the dependent jars as per customer selection.
You could achieve this by putting the needed dependencies into vendor-specific profiles in your pom:
<profiles>
<profile>
<id>Alfresco</id>
<dependencies>
...
</dependencies>
</profile>
<profile>
<id>Jackrabbit</id>
<dependencies>
...
</dependencies>
</profile>
</profiles>
Then you can activate the desired profile for your build like:
mvn -PJackrabbit install