Always display the current active profiles during the compile phase in Maven - maven

I have a Spring Boot application which supports two profiles: dev and release. Obviously, the dev profile is used when working locally, and release profile is used by Jenkins as part of a CI/CD pipeline when actually deploying the application on a server.
Profiles definition
<profiles>
<profile>
<id>dev</id>
<properties>
<activatedProperties>dev</activatedProperties>
</properties>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<profile>
<id>release</id>
<properties>
<activatedProperties>release</activatedProperties>
</properties>
</profile>
</profiles>
dev profile is activated by default since this is where developers spend most of their time: developing. I want them to specify the release profile when exporting the application somewhere else, but even better, delegate that task to Jenkins.
I just discovered the following command to see which profiles are active:
mvn help:active-profiles
So I can use this in my Jenkins pipeline script
mvn clean compile -Prelease help:active-profiles
That works. BUT, I wonder if there is a way to always run help:active-profiles goal during the compile phase, so all developers can clearly see which profile they are using.
Thank you

You can add Maven Help Plugin as shown below:
<plugin>
<artifactId>maven-help-plugin</artifactId>
<version>2.2</version>
<executions>
<execution>
<id>print-profile</id>
<phase>compile</phase>
<goals>
<goal>active-profiles</goal>
</goals>
</execution>
</executions>
</plugin>
You can expect the log with the below message:
[INFO] --- maven-help-plugin:2.2:active-profiles (print-profile) # testProject ---
[INFO]
Active Profiles for Project 'com.test.testProject:jar:1.0.0-SNAPSHOT':
The following profiles are active:
- sonar (source: external)
- release (source: external)
- dev (source: com.test.testProject:jar:1.0.0-SNAPSHOT)

Related

Show Maven Profile

I want to build a spring-boot Java project without running the integration tests. I'm taking the approach of adding annotation
#Category(IntegrationTest.class)
and defining interface
public interface IntegrationTest {}
I have this in my pom.xml
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${maven-surefire-plugin.version}</version>
<configuration>
<skipTests>${maven-surefire-plugin.skipUnitTests}</skipTests>
<excludedGroups>
com.test.annotationtype.IntegrationTest
</excludedGroups>
</configuration>
</plugin>
When I run mvn install, it runs the integration test.
It's a multi-profile pom.xml, and I'd like to at least verify that the profile I think I'm running, really is the one actually run.
<profile>
<id>woodsman-default</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
...
</profile>
When I run
mvn -debug install
no where in the log do I see the profile id woodsman-default. How can I get Maven to show me which profile it decided to use?
Bonus points for suggesting why it's not ignoring integration tests, but I'd settle for the easy answer.
Thx
Woodsman

activate spring boot profile from maven profile

I want to separate my junit test and integration test separate. So I created a separate profile in pom.xml for the integration test as follows:
<profiles>
<profile>
<id>integration-test</id>
<properties>
<test>IntegrationTestTrigger</test>
<spring.profiles.active>integration-test</spring.profiles.active>
</properties>
</profile>
<profiles>
The when I run the maven command mvn test -Pintegration-test, it is picking the test class as defined in the <properties> tag shown above as IntegrationTestTrigger. But it is not setting the spring.profiles.active property. So the test is starting with default profile. It is working fine with the maven command mvn test -Dtest=IntegrationTestTrigger -Dspring.profiles.active=integration-test
But as per my organisations jenkins setting, I need to run mvn test -Pintegration-test for the integration test, so I cannot add any extra environment variables to mvn command
Indeed as #gtivari333 said, profile/properties section is only to be used for substitution in POM files (and other files processed by maven, if so desired).
To set JVM properties aka "system properties" in POM directly, for use during test execution, you need to set them using surefire plugin configuration like this:
<profiles>
<profile>
<id>integration-test</id>
<build>
<plugins>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<groupId>org.apache.maven.plugins</groupId>
<configuration>
<systemProperties>
<foo>bar</foo>
<spring.profiles.active>integration-test</spring.profiles.active>
</systemProperties>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
The properties at the is meant for property substitution at the .properties/.yml file inside resources folder.
Example:
application.yml:
spring:
profiles:
active: '#spring.profiles.active#'
pom.xml:
<profile>
<id>dev</id>
<properties>
<spring.profiles.active>dev</spring.profiles.active>
</properties>
</profile>
Here, the #spring.profiles.active# will be replaced with dev during compile(by maven-resources-plugin plugin). Spring Boot uses # as the resource delimiter at the spring-boot-starter-parent pom. You can change it to any character by changing the following property
//pom.xml
<project .....>
<properties>
<resource.delimiter>#</resource.delimiter>
...
</properties>
See https://github.com/gtiwari333/spring-boot-blog-app/blob/master/pom.xml#L436 for an complete example
See also: https://docs.spring.io/spring-boot/docs/current/reference/html/howto.html#howto-automatic-expansion-maven

How to configure Maven to run a SonarQube project analysis with two different quality profiles?

We run SonarQube analyses for our Java projects via Maven. Maven somehow does this automagically; all we did was add the sonar-maven-plugin to our pom.xml:
<pluginManagement>
<plugins>
...
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>sonar-maven-plugin</artifactId>
<version>2.2</version>
</plugin>
</plugins>
</pluginManagement>
This works fine.
But now we need to run the SonarQube analysis twice, with different quality profiles. Since you can't easily change the project key from Maven, we use SonarQube's branch property to differentiate the SonarQube projects, like this (again from pom.xml):
<properties>
<sonar.profile>MyQualityProfile1</sonar.profile>
<sonar.branch>Dev_${sonar.profile}</sonar.branch>
...
</properties>
This way, we end up with two project entries in the SonarQube UI, both of which contain the exact same code, but have different issues depending on their quality profile (one used quality profile 1, and the other used quality profile 2).
Problem: In order to achieve this, I must manually change the pom.xml properties and run the entire build twice.
Question: How can I configure maven to simply run the sonar:sonar goal twice with different properties?
This would save us a lot of time on our builds. I already found this similar question, but no answers so far. Thanks!
Expanding on the previous answer given by Eldad AK regarding profiles:
Create two maven profiles as follows:
<properties>
<sonar.branch>Dev_${sonar.profile}</sonar.branch>
</properties>
<profiles>
<profile>
<id>QualityProfileOne</id>
<properties>
<sonar.profile>MyQualityProfile1</sonar.profile>
</properties>
</profile>
<profile>
<id>QualityProfileTwo</id>
<properties>
<sonar.profile>MyQualityProfile2</sonar.profile>
</properties>
</profile>
</profiles>
Then run the following:
$ mvn clean install -DskipTests
$ mvn sonar:sonar -PQualityProfileOne
$ mvn sonar:sonar -PQualityProfileTwo
(you may need to perform a clean between running sonar, not sure)
Try to configure two executions of your plugin. Something like this:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>sonar-maven-plugin</artifactId>
<executions>
<execution>
<id>s1</id>
<phase>verify</phase>
<goals>
<goal>sonar</goal>
</goals>
<configuration>
<sonar.branch>MyQualityProfile1</sonar.branch>
</configuration>
</execution>
<execution>
<id>s2</id>
<phase>install</phase>
<goals>
<goal>sonar</goal>
</goals>
<configuration>
<sonar.branch>MyQualityProfile2</sonar.branch>
</configuration>
</execution>
</executions>
</plugin>
This will start two executions of sonar in phases verify and install, each with another sonar.branch value. In Sonar you can then configure the required quality profiles after the first analysis.
A combination of maven and Ant might work: Use Maven for the first sonar analysis as you already do and use the Maven Antrun Plugin to execute another SonarQube configuration defined using the SonarQube Ant Task.
I would opt for the maven profiles.
Each profile would have its own properties.
I hope this helps.

GlassFish 3 + Maven + remote deploy

I couldn't find any clear answer about how to deploy simple Maven based project to remote GlassFish server via maven like
mvn package xxx:deploy
I think only cargo plugin supports GlassFish 3. Right?
I've problems at configuration side.
Any sample remote GlassFish deployment will be great. Cargo is not a must, if others are support remote GlassFish then we can also use it too.
In case you want to only use maven-glassfish-plugin (let say version 2.1), you can do a remote deploy by specifying the "host" parameter. Below is an example where configurations are setup in maven settings.xml and an plugin loads them using a profile:
In settings.xml define a profile:
<profile>
<id>production-config</id>
<properties>
<glassfish.glassfishDirectory>/var/local/glassfish/</glassfish.glassfishDirectory>
<glassfish.user>admin</glassfish.user>
<glassfish.adminPassword>adminadmin</glassfish.adminPassword>
<glassfish.domain.name>prd-domain</glassfish.domain.name>
<glassfish.domain.host>NAMEOFYOURREMOTEHOST</glassfish.domain.host>
<glassfish.domain.adminPort>10161</glassfish.domain.adminPort>
.
.
</properties>
</profile>
Next put this profile in your active profiles:
<activeProfiles>
<activeProfile>production-config</activeProfile>
</activeProfiles>
In your maven project pom.xml, create a profile and add the maven-glassfish-plugin in your list of profiles:
<profile>
<id>production</id>
<activation>
<activeByDefault>false</activeByDefault>
<os>
<arch>x86</arch>
<family>linux</family>
</os>
<property>
<name>profile</name>
<value>production</value>
</property>
<file>
<exists>
${glassfish.glassfishDirectory}/domains/${glassfish.domain.name}/config/domain.passwords
</exists>
</file>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.glassfish.maven.plugin</groupId>
<artifactId>maven-glassfish-plugin</artifactId>
<configuration>
<terse>true</terse>
<echo>true</echo>
<debug>true</debug>
<glassfishDirectory>${glassfish.glassfishDirectory}</glassfishDirectory>
<user>${glassfish.user}</user>
<adminPassword>${glassfish.adminPassword}</adminPassword>
<domain>
<name>${glassfish.domain.name}</name>
<host>${glassfish.domain.host}</host>
<adminPort>${glassfish.domain.adminPort}</adminPort>
</domain>
<components>
<component>
<name>${project.artifactId}</name>
<artifact>${project.build.directory}/${project.build.finalName}.war</artifact>
</component>
</components>
</configuration>
<executions>
<execution>
<goals>
<goal>deploy</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
This should do the trick. You can run this profile using maven : mvn glassfish:deploy -P production or just mvn deploy -P production (since we have added the goal deploy inside the executions part of plugin)
Using the model above you can create different profile per environment (dev, acc, tst, prd), and use different settings. For instance you can create a developer profile where a local glassfish is being used to deploy and run unit/integration tests on it.
Common mistake people make is to mix up the settings for the machine from where you are doing the remote deployment with the host where deployment is to be installed. glassfishDirectory is place from where you are running the deployment plugin from. As a result of mistake plugin just hangs, doing nothing and just waiting giving the impression that something is happening. Another mistake is to specify a password file instead of a password for a remote deploy which will also result in nothing.
As far as I know and could find around, only Cargo delivers (or deploys, in this case).
This is an example tested as working on a Maven OSGi WAR project:
<build>
<plugins>
...
<plugin>
<groupId>org.codehaus.cargo</groupId>
<artifactId>cargo-maven2-plugin</artifactId>
<version>1.1.2</version>
<configuration>
<container>
<containerId>glassfish3x</containerId>
<type>remote</type>
</container>
<configuration>
<type>runtime</type>
<properties>
<cargo.hostname>myhostname</cargo.hostname>
<cargo.remote.username>myusername</cargo.remote.username>
<cargo.remote.password>mypassword</cargo.remote.password>
</properties>
</configuration>
</configuration>
<dependencies>
<dependency>
<groupId>org.glassfish.deployment</groupId>
<artifactId>deployment-client</artifactId>
<version>3.2-b06</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
As you can see, the trick lies in the deployment-client dependency.
For the sake of completeness, you then just mvn package cargo:deploy and Bob's your uncle.

How to skip unittests when using mvn scm:bootstrap

I'm trying to use the mvn scm plugin to check out the daily tag, and create an assembly from that version of the code. I configured the scm plugin and everythhing is working well, except that I can not seem to tell it to not run the unittests.
I tried:
Passing the -Dmaven.test.skip=true command line parameter
Creating a profile where the surefire plugin skips test, and list that profile in the scm configuration "profiles" section
setting the "maven.test.skip=true" as an environment variable
In all cases, when the scm plugin starts running the goals I told it to run in the configuration (see below), it also runs the unittests.
Below is the example I used to skip tests by using a profile:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-scm-plugin</artifactId>
<version>1.0</version>
<configuration>
<goals>install,assembly:assembly</goals>
<profiles>skiptest</profiles>
</configuration>
</plugin>
And this is the profile (I defined this in the pom.xml of the project):
<profiles>
<profile>
<id>skiptest</id>
<build>
<plugins>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
The command I use to do the checkout and bootstrap is:
mvn scm:bootstrap -DscmVersion=daily-20110427-421 -DscmVersionType=tag
I'm running mvn 2.2.1 on a Linux machine, and doing a checkout from a CVS repository. It's an existing project, I have continuous integration and tagging all up and running, I just want to check out a daily tag and create an assembly from that.
Any tips are much appreciated.
Edit: Got it to work with the answer below, but only after I upgraded to maven-scm-plugin version 1.1. Apparently, 1.0 did not propagate profiles.
Try this in the profile:
<profiles>
<profile>
<id>skiptest</id>
<properties>
<maven.test.skip>true</maven.test.skip>
</properties>
</profile>
</profiles>

Resources