Conditionally Execute JMeter Maven Plugin - java

I'm trying to figure out how to execute my JMeter performance test plan conditionally. I want to have my Jenkins CI job execute it, but when developers run mvn clean install I don't want the below plugins to run. Any ideas on how I can modify my pom.xml to conditionally run the below plugins?
Maven POM.xml JMeter Plugins:
<plugin>
<groupId>com.lazerycode.jmeter</groupId>
<artifactId>jmeter-maven-plugin</artifactId>
<version>1.8.1</version>
<executions>
<execution>
<id>jmeter-tests</id>
<phase>verify</phase>
<goals>
<goal>jmeter</goal>
</goals>
</execution>
</executions>
<configuration>
<testFilesDirectory>${project.basedir}/src/test/jmeter</testFilesDirectory>
<ignoreResultFailures>true</ignoreResultFailures>
<testResultsTimestamp>false</testResultsTimestamp>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>xml-maven-plugin</artifactId>
<version>1.0</version>
<executions>
<execution>
<phase>verify</phase>
<goals>
<goal>transform</goal>
</goals>
</execution>
</executions>
<configuration>
<transformationSets>
<transformationSet>
<dir>${project.build.directory}/jmeter/results</dir>
<stylesheet>${project.basedir}/src/test/resources/jmeter-results-detail-report_21.xsl</stylesheet>
<outputDir>${project.build.directory}/jmeter/results</outputDir>
<fileMappers>
<fileMapper implementation="org.codehaus.plexus.components.io.filemappers.RegExpFileMapper">
<pattern>(.*?)\s(.*?)</pattern>
<replacement>$1$2</replacement>
<replaceAll>true</replaceAll>
</fileMapper>
<fileMapper implementation="org.codehaus.plexus.components.io.filemappers.FileExtensionMapper">
<targetExtension>.html</targetExtension>
</fileMapper>
</fileMappers>
</transformationSet>
</transformationSets>
</configuration>
</plugin>
<plugin>
<groupId>ch.fortysix</groupId>
<artifactId>maven-postman-plugin</artifactId>
<version>0.1.2</version>
<executions>
<execution>
<id>send a mail</id>
<phase>install</phase>
<goals>
<goal>send-mail</goal>
</goals>
<inherited>false</inherited>
<configuration>
<from>admin#test.com</from>
<subject>Load Test Results</subject>
<failonerror>true</failonerror>
<mailhost>relay.apple.com</mailhost>
<htmlMessageFile>${project.build.directory}/jmeter/results/LoadTestPlan.html</htmlMessageFile>
<receivers>
<receiver>email#me.com</receiver>
</receivers>
<fileSets>
<fileSet>
<directory>${project.build.directory}/jmeter/results</directory>
<includes>
<include>LoadTestPlan.html</include>
</includes>
</fileSet>
</fileSets>
</configuration>
</execution>
</executions>
</plugin>

The best way to achieve this is with profiles. You define a profile which contains your plugin configuration. This profile would by default be turned off (so when a developer executes mvn clean install it is not activated), and you would only activate it during your Jenkins job.
So for example in your pom you would have something along these lines:
<project>
...
<profiles>
<profile>
<id>ci-environment</id>
<activation>
<activeByDefault>false</activeByDefault>
<property>
<name>build.environment</name>
<value>jenkins</value>
</property>
</activation>
<build>
<plugins>
<plugin>
<groupId>com.lazerycode.jmeter</groupId>
<artifactId>jmeter-maven-plugin</artifactId>
<!-- rest of your jmeter configuration goes here -->
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>xml-maven-plugin</artifactId>
<!-- rest of your xml-maven configuration goes here -->
</plugin>
<plugin>
<groupId>ch.fortysix</groupId>
<artifactId>maven-postman-plugin</artifactId>
<!-- rest of your postman configuration goes here -->
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>
So by default this profile is not active, and the plugins wont execute. On Jenkins you would configure the build to be executed as follows:
mvn clean install -Dbuild.environment=jenkins
As the profile has an id you can also configure Jenkins to specifically use the profile by name as follows:
mvn clean install -Pci-environment
For details on possible ways to activate a profile see the following sonatype resource:
http://books.sonatype.com/mvnref-book/reference/profiles-sect-activation.html

Related

Using plugin and execution steps based on Profiles

I have a pom as below
<project xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>X.0.0</modelVersion>
<parent>
<groupId>asdasd</groupId>
<artifactId>asdasd</artifactId>
<version>0.334.0-SNAPSHOT</version>
<relativePath>../something/pom.xml</relativePath>
</parent>
<!-- ======================================================================= -->
<!-- P R O J E C T -->
<!-- ======================================================================= -->
<artifactId>dfdfd</artifactId>
<name>xxxxx</name>
<packaging>content-package</packaging>
<properties>
<sonar.sources>${basedir}/src/main/angular/src</sonar.sources>
<sonar.tests>${basedir}/src/main/angular/src</sonar.tests>
</properties>
<build>
<resources>
<resource>
<directory>${basedir}/src/main/content/jcr_root</directory>
<excludes>
<exclude>**/*.iml</exclude>
</excludes>
<targetPath>jcr_root</targetPath>
</resource>
<resource>
<filtering>true</filtering>
<directory>${basedir}/src/main/content/META-INF/xxx/definition</directory>
<targetPath>../xxx/META-INF/vault/definition</targetPath>
</resource>
</resources>
<sourceDirectory>${basedir}/src/main/content/jcr_root</sourceDirectory>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>xml-maven-plugin</artifactId>
</plugin>
<!-- start frontend -->
<plugin>
<groupId>com.github.eirslett</groupId>
<artifactId>frontend-maven-plugin</artifactId>
<version>1.8.0</version>
<inherited>false</inherited>
<configuration>
<nodeVersion>v16.17.0</nodeVersion>
<npmVersion>8.15.0</npmVersion>
<nodeDownloadRoot>xxxxx</nodeDownloadRoot>
<npmDownloadRoot>xxxxx</npmDownloadRoot>
<installDirectory>src/main/angular</installDirectory>
<workingDirectory>src/main/angular</workingDirectory>
</configuration>
<executions>
<execution>
......
</execution>
<execution>
<id>npm rebuild node-sass</id>
<goals>
<goal>npm</goal>
</goals>
<configuration>
<arguments>rebuild node-sass</arguments>
</configuration>
</execution>
<execution>
<id>npm run e2e</id>
<goals>
<goal>npm</goal>
</goals>
<configuration>
<arguments>run e2e</arguments>
</configuration>
</execution>
</executions>
</plugin>
<!-- end frontend -->
</plugins>
</build>
</project>
I want to run execution step with id npm run e2e based on profile. What I have in mind is 2 profiles default and e2eTests. With default, I can set activeByDefault as true and skip the e2e test. And when I pass e2eTests using -P , I should be able to run all execution including id=npm run e2e
I tried to move them into <profiles> but then the <sourceDirectory> was complaining. I found some links like this for it, but the problem comes on how to access plugins when I have <profiles> outside of <build>
I am not able to structure it properly.
Normally, it is not required to copy entire <build> configuration into profile definition - it should be enough to just define extra plugin execution, smth. like that:
<profiles>
<profile>
<id>e2eTests</id>
<build>
<plugins>
<plugin>
<groupId>com.github.eirslett</groupId>
<artifactId>frontend-maven-plugin</artifactId>
<version>1.8.0</version>
<executions>
<execution>
<id>npm run e2e</id>
<goals>
<goal>npm</goal>
</goals>
<configuration>
<arguments>run e2e</arguments>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
However, I would configure that in different way:
either bind execution of e2e tests to the lifecycle phase designed for that (integration-test) - in this case mvn package won't trigger e2e tests:
...
<execution>
<id>npm run e2e</id>
<phase>integration-test</phase>
<goals>
<goal>npm</goal>
</goals>
<configuration>
<arguments>run e2e</arguments>
</configuration>
</execution>
...
or take advantage of properties and profiles, for example:
<properties>
...
<skip.e2e>true</skip.e2e>
...
</properties>
<profiles>
<profile>
<id>e2eTests</id>
<properties>
<skip.e2e>false</skip.e2e>
</properties>
</profile>
</profiles>
...
<execution>
<id>npm run e2e</id>
<phase>integration-test</phase>
<goals>
<goal>npm</goal>
</goals>
<configuration>
<skip>${skip.e2e}</skip>
<arguments>run e2e</arguments>
</configuration>
</execution>
...

SonarQube to take the coverage from Clover.xml

I have generated a clover.xml report for my service. I want to integrate that with my SonarQube report which is not showing the coverage at all.
I am not sure what exact plugin to add to my pom.xml so sonar can read it.
Here is part of my pom.xml:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>sonar-maven-plugin</artifactId>
<version>2.7.1</version>
<executions>
<execution>
<id>add-test-source</id>
<phase>generate-sources</phase>
<goals>
<goal>add-test-source</goal>
</goals>
<configuration>
<sources>
<source>src/it/java</source>
</sources>
</configuration>
</execution>
</executions></plugin><plugin>
<groupId>com.atlassian.maven.plugins</groupId>
<artifactId>maven-clover2-plugin</artifactId>
<configuration>
<excludes>
<exclude>**/*Constants.java</exclude>
<exclude>**/*LatestTimeSeriesDataServiceImpl.java</exclude>
<exclude>**/TestWebRequest.java</exclude>
</excludes>
<sonar.dynamicAnalysis>reuseReports</sonar.dynamicAnalysis>
<sonar.core.codeCoveragePlugin>clover</sonar.core.codeCoveragePlugin>
<sonar.clover.reportPath>target\site\clover\clover.xml</sonar.clover.reportPath>
<sonar.surefire.reportsPath>target\surefire-reports</sonar.surefire.reportsPath>
<sonar.core.codeCoveragePlugin>clover</sonar.core.codeCoveragePlugin>
<sonar.clover.version>${clover.version}</sonar.clover.version>
</configuration>
and this is part of my setting.xml:
<id>sonar</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<sonar.jdbc.url></sonar.jdbc.url>
<sonar.jdbc.driver></sonar.jdbc.driver>
<sonar.jdbc.username></sonar.jdbc.username>
<sonar.jdbc.password></sonar.jdbc.password>
<sonar.host.url>http://localhost:9000/</sonar.host.url>
</properties>
I hided some values I am not sure if they are confidential or not..
these are the values to my sonar-project.properties:
sonar.projectKey=org.sonarqube:java
sonar.projectName=org.sonarqube:java
sonar.projectVersion=1.0
sonar.sources=path
sonar.tests=path
sonar.language=java
sonar.sourceEncoding=UTF-8
sonar.core.codeCoveragePlugin=clover
sonar.clover.reportPath=target/site/clover/clover.xml
sonar.java.binaries=target/classes
sonar.dynamicAnalysis=reuseReports
in addition i tried to enforce the properties through command line as well:
mvn sonar:sonar -s menlo_settings.xml -Dsonar.host.url=http://localhost:9000/ org.codehaus.mojo:sonar-maven-plugin:2.7.1:sonar -Dsonar.core.codeCoveragePlugin=clover -Dsonar.clover.reportPath=target/site/clover/clover.xml
Nothing is working and I am frustrated!! If anyone know about it please let me know!

How can I exclude files of the Code Coverage of SonarQube using JaCoCo maven plugin

I've got a big issue with the integration of JaCoCo maven plugin for the code covering of SonarQube 6.0.
I've got a multi-module Maven project lets say :
master
|--core
|--web
|--process
in the master pom.xml, I've setted a reporting profile like that :
<profile>
<id>reporting</id>
<build>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<executions>
<execution>
<id>pre-unit-test</id>
<!--<phase>test</phase> -->
<goals>
<goal>prepare-agent</goal>
</goals>
<configuration>
<!-- Sets the path to the file to write the execution data to. -->
<destFile>${sonar.jacoco.reportPath}</destFile>
<!-- Connection with SureFire plugin -->
<propertyName>sonarUnitTestArgLine</propertyName>
</configuration>
</execution>
<execution>
<id>post-unit-test</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
<configuration>
<!-- Sets the path to where the execution data is located. -->
<dataFile>${sonar.jacoco.reportPath}</dataFile>
<!-- Sets the output directory for the code coverage report. -->
<outputDirectory>${jacoco.ut.outputdir}</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<forkMode>once</forkMode>
<argLine>${sonarUnitTestArgLine} -XX:MaxPermSize=512M -Xms512m -Xmx512m</argLine>
</configuration>
</plugin>
</plugins>
</build>
</profile>
in the childs, I overload the configuration by adding some exclusions :
<!-- First attempt -->
<properties>
<sonar.jacoco.excludes>**/model/**/*</sonar.jacoco.excludes>
</properties>
<!-- Second attempt -->
<properties>
<sonar.coverage.exclusions>**/model/**/*</sonar.coverage.exclusions>
</properties>
<!-- Third attempt -->
<profiles>
<profile>
<id>reporting</id>
<build>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<configuration>
<excludes>
<!-- Exclude model classes (POJO's) -->
<exclude>**/model/**/*.class</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
the idea here is to remove the Pojo of the code coverage ( we also do it for other types of Class ...)
When I run the mvn command line :
mvn clean generate-sources install verify -P reporting -fn
All my reports are well generated but in Sonar, the exculsions aren't been taking into account ...
Please can you help me fixing this issue ?
After a lot of reasearch, I've found the solution for this problem, I post the answers to help poeple ho'll have the same issue :
In the master-module
<properties>
<sonar.coverage.exclusions>
**/patternA/**/*,
**/patternB/**/*
</sonar.coverage.exclusions>
</properties>
In the sub-modules
<profiles>
<profile>
<id>report</id>
<build>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<configuration>
<excludes>
<!-- Exclude model classes (POJO's) -->
<exclude>**/patternA/**/*.class</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
in the master pom
I tried adding just the below details in properties section and it worked for me.
<sonar.coverage.exclusions>
**/patternA/*.java,
**/patternB/*.java
</sonar.coverage.exclusions>

Maven: same artifactID in shared plugin and profile build plugin

I have a maven pom.xml which will run some group of ant tasks. Some tasks are only for specific profile and some tasks for common for all profile. This is mine
<build>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.1</version>
<executions>
<execution>
<phase>test</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<tasks>
<!-- Some of my common task -->
</tasks>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
<build>
<profiles>
<profile>
<id>developement</id>
<build>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.1</version>
<executions>
<execution>
<phase>test</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<tasks>
<!-- Task specifics for profile -->
</tasks>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
<build>
</profile>
</profiles>
I run the project using the the below command
mvn clean install -P developement
while building this project the common tasks is not running. Tasks in profile only running. Is it happened because of I am using same artifactID in both shared and profile plugin..?
My Env:
Java 1.6
Maven 2.2.1
Windows 7 64 bit
Both of the executions shown are missing <id> elements. Thus, Maven uses its default execution ID, and the profile execution overwrites the common one.
To fix, add IDs to both as shown, with values of your choice.
<!-- common configuration -->
<executions>
<execution>
<id>antrun-common</id>
<phase>test</phase>
....
<!-- development profile configuration -->
<executions>
<execution>
<id>antrun-development</id>
<phase>test</phase>

Avoid Maven profiles to generate duplicated jars

I'm new to Maven and I'm trying to configure Maven to generate 2 jars: one for development and one for production. The only difference between them is a config.properties file that have the database connection different so I thought I could use Maven profiles.
To my surprise I can't generate both files at once. When using profiles, each time you build you have to select the profile and a jar (in my case) will be created using the profile. The thing is that it will create 2 exactly equals jars, one without a classifier and one with the classifier (like myjar.jar and myjar-prod.jar) so if I want to generate the dev and the prod jar I have to create 4 jars (running first Maven with one profile and after that with another profile)
Why is this? Doesn't make any sense to me... but ok...
My question is:
Is there a way I could avoid the two jars from being generated? I mean, I want to have different profiles, and I have accepted (with grief) to execute multiple times the build process (one for each profile), could I avoid to have each time 2 jars and have only one without the classifier?
This is my pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.p2p.</groupId>
<artifactId>LoadACHFiles</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>MyProject</name>
<url>http://maven.apache.org</url>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/resources</directory>
<excludes>
<exclude>config-*.properties</exclude>
</excludes>
</resource>
</resources>
</build>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>org.jasypt</groupId>
<artifactId>jasypt</artifactId>
<version>1.9.0</version>
<type>jar</type>
</dependency>
</dependencies>
<profiles>
<profile>
<id>prod</id>
<build>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<phase>test</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<tasks>
<!--<delete file="${project.build.outputDirectory}/config.properties"/>-->
<copy file="src/main/resources/config-prod.properties"
tofile="${project.build.outputDirectory}/config.properties"/>
</tasks>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.13</version>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<classifier>prod</classifier>
<source>1.6</source>
<target>1.6</target>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>
If you are okay with having classified jars, you may do what you want without profiles, so you may have jars for all environments with a single build command. The key is to understand how Maven filtering works.
This is expanding on an answer I provided to a similar question. Start with that setup. Then:
Create config.properties in your src/main/resources, containing properties your app needs.
my.database.url=${database.url}
my.database.user=${database.user}
my.database.pw=${database.pw}
Now, create prod.properties and dev.properties in ${basedir}/src/main/filters holding appropriate values for each environment.
database.url=URL-for-dev
database.user=user-for-dev
database.pw=pw-for-dev
When you run mvn clean package, Maven will copy the contents of /src/main/resources, including config.properties, doing property replacement during the copy. Because there are multiple executions of both resources and jar plugins, Maven will create separate classified jar files. Each will contain a config.properties file, holding the correct properties for the environment. The filters will not end up in the built jars.
I made it removing the maven jar plugin in the profile section. Changed this:
<profile>
<id>prod</id>
<build>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<phase>test</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<tasks>
<!--<delete file="${project.build.outputDirectory}/config.properties"/>-->
<copy file="src/main/resources/config-prod.properties"
tofile="${project.build.outputDirectory}/config.properties"/>
</tasks>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.13</version>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<classifier>prod</classifier>
<source>1.6</source>
<target>1.6</target>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
For this:
<profile>
<id>prod</id>
<build>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<phase>test</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<tasks>
<!--<delete file="${project.build.outputDirectory}/config.properties"/>-->
<copy file="src/main/resources/config-prod.properties"
tofile="${project.build.outputDirectory}/config.properties"/>
</tasks>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.13</version>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>
</profile>

Categories