How can I set a environment variables in Maven per run? - maven

In my project, we've created a Maven module to get the specific JBoss AS and unpacked.
Then all the test cases can be run under this Jboss AS as embedded container.
We're using jboss-ejb3-embedded-standalone to call the embedded container, however, it just find the JBOSS_HOME from environment variables and use that one to run.
Thus we have to update the JBOSS_HOME per mvn install.
I tried to do this in maven by introduce exec-maven-plugin as below:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<configuration>
<executable>env</executable>
<environmentVariables>
<JBOSS_HOME>
C:/Sample/embedded-container/jboss-${version.org.jboss.jbossas}
</JBOSS_HOME>
</environmentVariables>
</configuration>
<executions>
<execution>
<id>resetJbossHome</id>
<phase>integration-test</phase>
<goals>
<goal>exec</goal>
</goals>
</execution>
</executions>
</plugin>
In the output of console, I can see
[INFO] --- exec-maven-plugin:1.2.1:exec (resetJbossHome) # test-embedded ---
....
JBOSS_HOME=C:/Sample/embedded-container/jboss-6.1.0.Final
....
But when launching JBOSS, it's still running the one with origin JBOSS_HOME set.
Besides, I've tried using maven-antrun-plugin too.
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>copyRelease</id>
<phase>pre-integration-test</phase>
<configuration>
<tasks>
<exec executable="env">
<env key="JBOSS_HOME" value="C:/Sample/embedded-container/jboss-${version.org.jboss.jbossas}"/>
</exec>
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
It turns out the same.
Am I wrong on the configuration or there're some better way?

Take a look at the Maven profiles.
You can define one profile for testing, one for production, with different properties, such as
<profiles>
<profile>
<id>test</id>
<jboss.home>PATH TO JBOSS TEST INSTANCE</jboss.home>
</profile>
<profile>
<id>prod</id>
<jboss.home>PATH TO JBOSS PROD INSTANCE</jboss.home>
</profile>
</profiles>
And in your exec plugin :
<environmentVariables>
<JBOSS_HOME>
${jboss.home}
</JBOSS_HOME>
</environmentVariables>

Related

Maven failsafe is not complaining that an inexistent profile was specified

I have two profiles in my pom:
<profiles>
<profile>
<id>functional-tests</id>
<build>
<plugins>
<plugin>
<artifactId>maven-failsafe-plugin</artifactId>
<configuration>
<testSourceDirectory>test/test-functional/java</testSourceDirectory>
<includes>
<include>**/*FT.java</include>
</includes>
</configuration>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>it-tests</id>
<build>
<plugins>
<plugin>
<artifactId>maven-failsafe-plugin</artifactId>
<configuration>
<testSourceDirectory>test/test-it/java</testSourceDirectory>
<includes>
<include>**/*IT.java</include>
</includes>
</configuration>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
...
I can trigger each of these two profiles like this:
mvn failsafe:integration-test -Pfunctional-tests
mvn failsafe:integration-test -Pit-tests
But when I run this:
mvn failsafe:integration-test -PrandomWord
It triggers it-tests profile. I was wondering why and if there is a way to have failsafe plugin output something like unrecognised profile.
Thank you for your help
In case it matters, here is my failsafe-plugin:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
</goals>
</execution>
</executions>
</plugin>
Answering your question about why it triggers it-tests. In fact, it does not activate any of the profiles, hence default plugin configuration is used which has **/*IT.java in include list. So, it runs all IT tests by default.
This is weird approach to manage plugin executions by profiles. I doubt there is a reasonable way to validate profile names as you describe. I would recommend another approach here.
Approach 1. Use <id> and cli with #
You could just specify two executions of the plugin with id and then you could do this: How to execute maven plugin execution directly from command line?
<plugin>
<artifactId>maven-failsafe-plugin</artifactId>
<executions>
<execution>
<id>it-tests</id>
<phase>none</phase> <!-- detach this execution from default lifecycle -->
<configuration>
<testSourceDirectory>test/test-it/java</testSourceDirectory>
<includes>
<include>**/*IT.java</include>
</includes>
</configuration>
</execution>
<execution>
<id>functional-tests</id>
<phase>none</phase> <!-- detach this execution from default lifecycle -->
<configuration>
<testSourceDirectory>test/test-ft/java</testSourceDirectory>
<includes>
<include>**/*FT.java</include>
</includes>
</configuration>
</execution>
</executions>
</plugin>
Now you could execute it from command line:
mvn failsafe:integration-test#it-tests
mvn failsafe:integration-test#functional-tests
Update: No need to specify goals as it is relevant to lifecycle only, we type it in command line anyway.
Approach 2. Use <skip> and properties
Keep both executions as a part of lifecycle but control execution by providing skip flags. I.e. define two properties e.g. skip.tests.it=true, skip.tests.ft=true and add <skip>${skip.tests.ft}</skip> to relevant configuration sections. Then you could just do
# run with no tests by default
mvn verify
# run with only FT
mvn verify -Dskip.tests.ft=false
# run with all tests
mvn verify -Dskip.tests.ft=false -Dskip.tests.it=false
to run full lifecycle together with desired tests.

Maven wildfly deployment with multiple servers (standalone)

in my environment I have two wildfly server where I want to deploy with the wildfly-maven-plugin.
The servers differ in the name dev01 and dev02 but have the same port 9993 and username and password.
My understanding is that the wildfly-maven-plugin support only single server deployment.
If the problem are not big enough we use a module/submodule structure where the war file will be build in a submodule.
I'm using two profiles wildfly-deploy-dev01 and wildfly-deploy-dev02.
<profiles>
<profile>
<id>wildfly-deploy-dev01</id>
<build>
<plugins>
<plugin>
<groupId>org.wildfly.plugins</groupId>
<artifactId>wildfly-maven-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
<executions>
<execution>
<phase>install</phase>
<goals>
<goal>deploy</goal>
</goals>
<configuration>
<skip>true</skip>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>wildfly-deploy-dev02</id>
<build>
[...]
<profiles>
In the main module I skipped it.
In the war submodule:
<profiles>
<profile>
<id>wildfly-deploy-dev01</id>
<build>
<finalName>${project.artifactId}-v1.0</finalName>
<plugins>
<plugin>
<groupId>org.wildfly.plugins</groupId>
<artifactId>wildfly-maven-plugin</artifactId>
<configuration>
<skip>false</skip>
<id>wildfly-credentials<id>
<hostname>dev01.example.com</hostname>
<protocol>remote+https</protocol>
<port>9993</port>
</configuration>
<executions>
<execution>
<phase>install</phase>
<goals>
<goal>deploy</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>wildfly-deploy-dev01</id>
<build>
[same as above for hostname dev02.example.com]
</profiles>
First I was thinking everthing works fine but then I found out that only the last server will be deployed.
mvn wildfly:deploy -P wildfly-deploy-dev01,wildfly-deploy-dev02
I played around by setting the configration after the execution tag without success. It looks that the second profile overwrite the first one.
Futher I hardcoded the finalname because the parsedVersion is not parsed.
<finalName>${project.artifactId}-v${parsedVersion.majorVersion}.${parsedVersion.minorVersion}</finalName>
At the moment I'm lost with Maven. Has anybody an idea how I can deploy with the plugin on two servers?
Thanks,
Markus
Ways which I tried:
https://github.com/tsotzolas/wildfly_maven_plugins_examples/blob/master/deployToMultiplesServer/pom.xml
wildfly-maven-plugin not deploying when multiple profiles selected
Cannot access parsedVersion value in pom properties
You should be able to do this in a single profile with different executions. There shouldn't be a need to multiple profiles.
<profiles>
<profile>
<id>wildfly-deploy</id>
<build>
<plugins>
<plugin>
<groupId>org.wildfly.plugins</groupId>
<artifactId>wildfly-maven-plugin</artifactId>
<configuration>
<skip>false</skip>
<id>wildfly-credentials<id>
<protocol>remote+https</protocol>
<port>9993</port>
</configuration>
<executions>
<execution>
<id>deploy-dev1</id>
<phase>install</phase>
<goals>
<goal>deploy</goal>
</goals>
<configuration>
<hostname>dev01.example.com</hostname>
</configuration>
</execution>
<execution>
<id>deploy-dev2</id>
<phase>install</phase>
<goals>
<goal>deploy</goal>
</goals>
<configuration>
<hostname>dev02.example.com</hostname>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<profiles>
With this you'd just have to do mvn clean install -Pwildfly-deploy.

Maven: How to print the current profile on the console?

I'm trying to print the current profile that is active running a build of a Maven Project.
I'm using the maven-antrun-plugin in order to print messages on the console, in combination with a property that refers to the current profile.
I have tried the following properties:
${project.activeProfiles[0].id}
${project.profiles[0].id}
But in both cases it prints the "string" as it is written, without resolving the variable.
This is my test:
<build>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<phase>generate-resources</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<tasks>
<echo>current active profile: ${project.activeProfiles[0].id}</echo>
</tasks>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
But this is the result that I obtain:
main:
[echo] current active profile: ${project.activeProfiles[0].id}
Any suggestion will be appreciated.
Thanks.
The maven-help-plugin offers what you need. It has an active-profiles goal.
You can add it to your pom or even call it from the command line (include it in your maven build call). The How can I tell which profiles are in effect during a build? section of the Maven profile introduction page will show you how. In short:
mvn help:active-profiles
As this does not work for you (see comments) here is another solution:
I think the active profiles (there can be more than one!) are not propagated as available variables - but properties are.
So set a custom property in the profile section and use that, like
<profiles>
<profile>
<id>default</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<myProfile>default</myProfile>
</properties>
</profile>
<profile>
<id>debug</id>
<activation>
<property>
<name>debug</name>
</property>
</activation>
<properties>
<myProfile>debug</myProfile>
</properties>
</profile>
</profiles>
<build>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<phase>generate-resources</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<tasks>
<echo>current active profile: ${myProfile}</echo>
</tasks>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
you can add the maven-help-plugin in your pom to display always the active profile
<build>
<plugins>
<!-- display active profile in compile phase -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-help-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>show-profiles</id>
<phase>compile</phase>
<goals>
<goal>active-profiles</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
source: https://www.mkyong.com/maven/maven-profiles-example

How to bind two plugins in Maven

Using Maven, I need to automatically deploy a web application to a Tomcat server, then run a MainClass in order to do some post-deploy operations.
These two things alone are already working, through cargo-maven2-plugin respectively exec-maven-plugin. However I don't know how bind them together.
I see two options:
Making the "official" maven deploy goal to simply execute cargo-plugin, then exec-maven and nothing else
Binding the execution of exec-maven to the completion of cargo:deploy
The first is my favouire. Unfortunately I don't know how to implement any of them.
The current pom.xml:
<plugin>
<groupId>org.codehaus.cargo</groupId>
<artifactId>cargo-maven2-plugin</artifactId>
<version>1.4.15</version>
<configuration>
<container>
<containerId>tomcat8x</containerId>
<type>remote</type>
<systemProperties>
<cargo.jvmargs>-XX:MaxPermSize=256M -Xmx1024m</cargo.jvmargs>
</systemProperties>
</container>
<configuration>
<type>runtime</type>
<properties>
<cargo.hostname>${my.hostname}</cargo.hostname>
<cargo.servlet.port>${my.port}</cargo.servlet.port>
<cargo.tomcat.manager.url>${my.hostname}/manager</cargo.tomcat.manager.url>
<cargo.remote.username>tomcat</cargo.remote.username>
<cargo.remote.password>tomcat</cargo.remote.password>
</properties>
</configuration>
<deployables>
<deployable>
<location>${project.build.directory}/${project.build.finalName}.war</location>
<type>war</type>
<properties>
<context>/${project.build.finalName}</context>
</properties>
</deployable>
</deployables>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.4.0</version>
<executions>
<execution>
<!-- NEED TO BE AFTER DEPLOY -->
<phase>package</phase>
<goals>
<goal>java</goal>
</goals>
<configuration>
<mainClass>ch.MainClass</mainClass>
<arguments>
<argument>Will be forwarded to main()</argument>
</arguments>
</configuration>
</execution>
</executions>
</plugin>
I would suggest to bind cargo-maven2-plugin to the pre-integration-test phase and the exec-maven-plugin in your case to the integration-test phase which is after the package phase. See also the documentation about the default life cycle phases.
The deploy phase is usually used to deploy the generated artifacts to a maven repository so it does not really make sense to bind running an integration test to this phase.
<plugin>
<groupId>...</groupId>
<artifactId>...</artifactId>
<version>...</version>
<executions>
<execution>
<phase>integration-test</phase>
<goals>
<goal>xxxx</goal>
</goals>
<configuration>
....
</configuration>
</execution>
</executions>
</plugin>
The above configuration can be applied to both of your plugins exec-maven-plugin as well as cargo-maven2-plugin...
The best approach is to separate such integration test scenarios into a separate module or if you have only a single module use a profile to active integration tests.

Is isolation of failsafe and surefire runs from each other using a skip approach possible?

The value of property skipITs when overridden on the command line appears to be ignored by maven if used in conjunction with -Dit.test=full.Classname. The specified failsafe test will not be run (case one).
As opposed to this specifiing skipITs without the it.test switch leads to running of existing failsafe tests (case two).
Background: Am trying to isolate surefire tests from failsafe tests runs by namely either running both types of them or one of each only. The maven calls are:
mvn -Pintegration -DskipTests=true -DskipITs=false -Dit.test=full.Classname verify
in the first case and:
mvn -Pintegration -DskipTests=true -DskipITs=false verify
in the second.
The relevant configuration (pom.xml, snippets only) being:
<properties>
<skipTests>false</skipTests>
<skipITs>false</skipITs>
</properties>
(those are defaults) and
<profiles>
<profile>
<id>integration</id>
<build>
<plugins>
<plugin>
<artifactId>maven-failsafe-plugin</artifactId>
<executions>
<execution>
<id>custom<id>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
<configuration>
<skipTests>${skipITs}</skipTests>
<skip>${skipITs}</skip>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
Did you observe that too or have you eventually found a better working approach?
By default, the Surefire plugins runs during the test phase and usually you configure the Failsafe plugin to run during the integration-test and verify phase like this:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.18.1</version>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
To run the Surefire tests only, use
mvn clean test
To run both the Surefire and the Failsafe tests, use
mvn clean verify
You can completely skip any plugin by using the <skip> configuration option. If you configure the Surefire plugin like this:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.18.1</version>
<configuration>
<skip>${skip.surefire}</skip>
</configuration>
</plugin>
you can run only the Failsafe tests by calling
mvn clean verify -Dskip.surefire=true
If the integration test (it.test) has a non-default name I need to add an include pattern accordingly, like in (pom.xml snippet):
<profiles>
<profile>
<id>dbUnit</id>
<build>
<plugins>
<plugin>
<artifactId>maven-failsafe-plugin</artifactId>
<executions>
<execution>
<id>custom</id>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
<configuration>
<skipTests>${skipITs}</skipTests>
<skip>${skipITs}</skip>
<includes>
<include>**/*DbTest.java</include>
</includes>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
But that appears valid only for the original approach. Also observe that the default inclusion patterns might need to be added too in case for your integration tests you followed different naming schemes.

Resources