Is it possible to use a maven property to activate a profile based upon a file? - maven

I would like to download the JACOB dlls when they're not in my local repository.
As a consequence, I have those two profiles
<profile>
<id>use-jacob-dll</id>
<activation>
<file>
<exists>${settings.localRepository}/com/hynnet/jacob/1.18/jacob-1.18-x64.dll</exists>
</file>
</activation>
<dependencies>
<dependency>
<groupId>${jacob.groupId}</groupId>
<artifactId>jacob</artifactId>
<type>dll</type>
<classifier>x64</classifier>
<version>${jacob.version}</version>
</dependency>
</dependencies>
</profile>
<profile>
<id>download-jacob-dll</id>
<activation>
<file>
<missing>${settings.localRepository}/com/hynnet/jacob/1.18/jacob-1.18-x64.dll</missing>
</file>
</activation>
But, even when download-jacob-dll has accomplished its goal, a call to mvn help:active-profiles indicates the following
The following profiles are active:
- tests-for-eclipse (source: com.capgemini.admdt:kpitv:1.2.4-SNAPSHOT)
- download-jacob-dll (source: com.capgemini.admdt:kpitv:1.2.4-SNAPSHOT)
I suspect it is due to the fact that I use the ${settings.localRepository} in my activation property.
Question: Is it the cause of the failure? And if so, how can I activate my profile only when dependency is missing ?

Is it possible to use a maven property to activate a profile based upon a file?
No, as stated by the Maven documentation on profiles
Supported variables are system properties like ${user.home} and environment variables like ${env.HOME}. Please note that properties and values defined in the POM itself are not available for interpolation here, e.g. the above example activator cannot use ${project.build.directory} but needs to hard-code the path target.
However, from the POM documentation we also get that
a given filename may activate the profile by the existence of a file, or if it is missing. NOTE: interpolation for this element is limited to ${basedir}, System properties and request properties.
Hence, indeed no Maven properties except ${basedir} are allowed.
And if so, how can I activate my profile only when dependency is missing?
By hardcoded path to the dependency or concerned file would be a solution, even though not portable like the solution you meant.
Alternatively you could use a request property as mentioned by the documentation above, thus need to configure the activation with a property which then must be passed from the command line (more portable but more fragile as well):
<activation>
<file>
<missing>${path}/com/hynnet/jacob/1.18/jacob-1.18-x64.dll</missing>
</file>
</activation>
Then invoke maven as following:
mvn clean install -Dpath=path_to_local_rep
The solution above could be reasonable in some contexts like Jenkins jobs.

Related

Custom alternative configurations for Maven life cycles

How can I add custom alternative configurations to the default life cycles in the pom.xml?
So that I for example can still call mvn package (default behavior), but also mvn quickPackage which runs the default package life cycle, but has e.g. skipTests true and the XML equivalents for other command line parameters...?
All I could find was either directing me into:
Using extra special plugins, even write my own, which I'm not allowed here.
Apply the configuration to everything, or at least always to a certain life cycle. Removing the default behavior of e.g. package.
Do I have to fallback to use command line scripts (which counters the point of having a build management system)? Or is there a pom.xml solution?
You can use Maven Profiles for that, e.g.:
<profiles>
<profile>
<id>quick</id>
<properties>
<bla.bla.bla>true</bla.bla.bla>
<this.that.then>true</this.that.then>
<everything.now>true</everything.now>
<feature.set.extra>true</feature.set.extra>
</properties>
</profile>
</profiles>
Activate it with:
mvn ... -Pquick ...

Setting Environment Variables in Maven pom files

Sorry for asking a question that many will say it has been asked again and again, however I couldn't find a satisfactory or complete answer.
I have to build a maven project. Inside it I have the following:
<profile>
<id>windows</id>
<activation>
<os>
<family>Windows</family>
</os>
</activation>
<properties>
<weblogic.home>${env.WEBLOGIC_SERVER_HOME}</weblogic.home>
<weblogic.precompilation.java.home>${env.JAVA_64_HOME}</weblogic.precompilation.java.home>
</properties>
</profile>
and I get the error:
[ERROR] 'dependencyManagement.dependencies.dependency.systemPath' for weblogic:weblogic.jar must specify an absolute path but is ${env.WEBLOGIC_SERVER_HOME}/server/lib/weblogic.jar # ..\pom.xml
Of course, by setting the absolute path to the above:
<weblogic.home>c:/Oracle/Middleware/wlserver_10.3</weblogic.home>
the problem is solved, but how can I actually set env.WEBLOGIC_SERVER_HOME in my system so that maven finds it?
I setup a new environment variable:
WEBLOGIC_SERVER_HOME = c:/Oracle/Middleware/wlserver_10.3
in my Windows machine but no luck. I tried setting configuration environmentVariables in maven-surefire-plugin as explained in [How to set up an environment variable in mvn pom? (but didn't pass it via -D in the command line), tried to set a property like here [How to refer environment variable in POM.xml? but no chance.
I thought that once I setup the environment variable (WEBLOGIC_SERVER_HOME) in my OS, I could then access it from my pom using ${env.WEBLOGIC_SERVER_HOME}. But I guess this is not enough.
In my IDE (NetBeans), I cannot set the environment variable for the maven project since it displays the "Resolve Project Problems" dialog box instead.
Any help is appreciated.

Conditional processing in Maven projects

I have some configuration settings that are in the Maven project that I'd like to keep there for building into a newly set up system but not touched if the configuration setting already exists. One of the problems I had is that when I deleted the setting from the build, it also deleted the setting from the target server when I did a build.
What would good alternatives be?
A possible solution could be to move the particular set-up for the new systems in a Maven profile and activate the profile only based on either an environment variable or the existence/non-existence of a file.
For instance, from official documentation, you can activate the profile if a certain environment variable exists, not exists or exists with a certain value.
<profiles>
<profile>
<activation>
<property>
<name>environment</name>
<value>test</value>
</property>
</activation>
...
</profile>
</profiles>
Please also note that, as from official documentation:
Note: Environment variables like FOO are available as properties of the form env.FOO. Further note that environment variable names are normalized to all upper-case on Windows.
Alternatively, the profile can be activated on a certain file (existing or missing), as following:
<profiles>
<profile>
<activation>
<file>
<missing>path/to/missing/file</missing>
</file>
</activation>
...
</profile>
</profiles>
If your set-up cannot be applied to any of these two cases, you could (as an example) anyway adapt it to create an harmless file which would then deny any further set-up.
harmless file missing > profile activated > set-up performed
harmless file existing > profile not activated

OS-Specific Maven Profile is always activated

I'm trying to define a profile that is activated only in case two conditions fit:
a special folder exists
the correct operating system
<profile>
<id>test</id>
<activation>
<file>
<exists>file</exists>
</file>
<os>
<family>windows/unix/etc...</family>
</os>
</activation>
</profile>
I tried to define it that way, but in case the operating system matches the profile is activated, even the folder does not exist. But I want to run some plugins in case the folder exists, in case a binary is required the operating system must match.
Thanks in advance..
According to the Maven JIRA, this is an open issue: http://jira.codehaus.org/browse/MNG-4565
The comments for the above-linked issue point to a Maven extension that provides the functionality you are looking for: https://github.com/johnjcool/and-activation-profile-selector

Enable certain Maven tests by passing a command line switch

I have a single module project that has some unit tests that require an external hardware device. I don't want these tests to execute unless I indicate that the device is available.
I feel like this is solvable using Maven properties and the SureFire exclusion/inclusion configuration, but I can't quite see how to do it. A similar question shows how to disable/enable all the tests in a project based on a Maven property, but doesn't quite answer my issue.
In summary, I wish to identify a pattern (e.g. **/*ResourceTest.java) that describes the tests I don't want to run, unless I pass a Maven property to enable them.
E.g.
mvn clean install (runs the standard tests, but skips device-related tests)
mvn -Drun.device.tests=true clean install (runs all the tests)
Thanks in advance.
(Edited to remove the misleading usage of the word "resource" > replaced with "hardware device").
You also can just use the JUnit Assume methods to decide (inside the test) if a test should be executed or skipped.
The best option IMHO would however be to 'declare' the device dependend tests to be "integration tests" and let them be executed by the Maven Failsafe Plugin. I think this would be the "build in" maven solution without any profile 'magic'.
The link you provided gave the good answer.
The right way
Use a mix of Profile Management and Surefire Configuration inclusion / exlcusion is the right way.
You should ask yourself WHY you want to activate some tests dependings on a resource. The resource should always been in your classpath.
If not, you probably just want to activate some test manually, for some tricky reasons. In that case consider this is a bad use of Maven (how would you automate that on a distant server for instance ?)
What you asked
If you really really want to do that, because you have some good reasons that we are not aware of, simply use this :
This example will trigger the profile when the generated file target/generated-sources/axistools/wsdl2java/org/apache/maven is missing.
Example from Maven official doc : http://maven.apache.org/guides/introduction/introduction-to-profiles.html
<profiles>
<profile>
<activation>
<file>
<missing>target/generated-sources/axistools/wsdl2java/org/apache/maven</missing>
</file>
</activation>
...
</profile>
</profiles>
As of Maven 2.0.9, the tags and could be interpolated. Supported variables are system properties like ${user.home} and environment variables like ${env.HOME}. Please note that properties and values defined in the POM itself are not available for interpolation here, e.g. the above example activator cannot use ${project.build.directory} but needs to hard-code the path target.
You could find more information here : http://www.sonatype.com/books/mvnref-book/reference/profiles-sect-activation.html
Hope that will help.
Don't hesitate to challenge my point of view with you own reasons (even legacy code ;) ) or experience
To expand on #Jean-Rémy answer, I have done the following in my project POM file:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.12</version>
<configuration>
<excludes>
<exclude>${tests.to.skip}</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<!-- This profile will be used when running tests without a device -->
<id>default-profile</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<tests.to.skip>**/*DeviceTest.java</tests.to.skip>
</properties>
</profile>
<profile>
<id>device-profile</id>
<activation>
<property>
<name>device</name>
<value>true</value>
</property>
</activation>
<properties>
<!-- Unsure how to match nothing -->
<tests.to.skip>NOTHING</tests.to.skip>
</properties>
</profile>
This creates two profiles, the default profile will exclude the device tests, whereas the "device-profile" will execute all tests.
To execute the device profile, one can execute mvn -Ddevice=true test.

Resources