Configuration for maven and flyway in multiple environments, plus integration tests - maven

I have a multi-module Maven project and am using Flyway for db migration. Currently, I have this snippet in my pom.xml:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>sql-maven-plugin</artifactId>
<version>1.5</version>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql-connector-java.version}</version>
</dependency>
</dependencies>
<executions>
<execution>
<id>drop-db-before-test-if-any</id>
<phase>process-test-resources</phase>
<goals>
<goal>execute</goal>
</goals>
<configuration>
<driver>${datasource.driver}</driver>
<url>${datasource.url}</url>
<username>${datasource.user}</username>
<password>${dbPass}</password>
<autocommit>true</autocommit>
<srcFiles>
<srcFile>${main.basedir}/db/test/drop_create_database_test.sql</srcFile>
</srcFiles>
</configuration>
</execution>
</executions>
</plugin>
How can I convert this to perform the equivalent of the following, such that it will use the flyway migration sql to better mimic production (in test currently it uses a db-test.properties where jpa.generate_ddl=true so that tables are auto-created from the JPA):
mvn flyway:clean -P test
mvn flyway:init -Dflyway.initVersion=1 -Dflyway.initDescription="Initial Version" -P test
mvn flyway:migrate -P test
Thanks!

If I understood your question correctly then this is what you need.
This assumes that you have baselineOnMigrate=true in the plugin configuration.
<profiles>
<profile>
<id>test</id>
<build>
<plugins>
<plugin>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-maven-plugin</artifactId>
<configuration>
<driver>${datasource.driver}</driver>
<url>${datasource.url}</url>
<user>${datasource.username}</user>
<password>${datasource.password}</password>
</configuration>
<executions>
<execution>
<id>flyway-clean-database</id>
<phase>process-test-resources</phase>
<goals>
<goal>clean</goal>
<goal>migrate</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>

Related

Perform deployment of an application on multiple servers through the same Jenkins Job

I'm using Jenkins CI to automate the deployment of my Java application, and I'm currently using the following build configurations on the pom.xml file:
<!-- teste1 config -->
<deploy.jboss.teste1.host>192.168.0.1</deploy.jboss.teste1.host>
<deploy.jboss.teste1.port>9999</deploy.jboss.teste1.port>
<deploy.jboss.teste1.user>admin</deploy.jboss.teste1.user>
<deploy.jboss.teste1.password>admin</deploy.jboss.teste1.password>
<liquibase.teste1.database>db_01</liquibase.teste1.database>
<liquibase.teste1.host>192.168.0.2</liquibase.teste1.host>
<liquibase.teste1.user>admin</liquibase.teste1.user>
<liquibase.teste1.password>admin</liquibase.teste1.password>
<!-- teste2 config -->
<deploy.jboss.teste2.host>192.168.0.3</deploy.jboss.teste2.host>
<deploy.jboss.teste2.port>9999</deploy.jboss.teste2.port>
<deploy.jboss.teste2.user>admin</deploy.jboss.teste2.user>
<deploy.jboss.teste2.password>admin</deploy.jboss.teste2.password>
<liquibase.teste2.database>db_02</liquibase.teste2.database>
<liquibase.teste2.host>192.168.0.4</liquibase.teste2.host>
<liquibase.teste2.user>admin</liquibase.teste2.user>
<liquibase.teste2.password>admin</liquibase.teste2.password>
<profile>
<id>teste1</id>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.jboss.as.plugins</groupId>
<artifactId>jboss-as-maven-plugin</artifactId>
<version>7.7.Final</version>
<configuration>
<hostname>${deploy.jboss.teste1.host}</hostname>
<port>${deploy.jboss.teste1.port}</port>
<username>${deploy.jboss.teste1.user}</username>
<password>${deploy.jboss.teste1.password}</password>
<name>${backend.deployment-name}</name>
<filename>${project.build.finalName}.war</filename>
<skip>${skipDeployment}</skip>
</configuration>
<executions>
<execution>
<id>deploy-jar</id>
<phase>install</phase>
<goals>
<goal>deploy</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-maven-plugin</artifactId>
<version>3.4.1</version>
<configuration>
<changeLogFile>${liquibase.changelog.file}</changeLogFile>
<diffChangeLogFile>${liquibase.changelog.file}</diffChangeLogFile>
<promptOnNonLocalDatabase>false</promptOnNonLocalDatabase>
<driver>com.mysql.jdbc.Driver</driver>
<url>jdbc:mysql://${liquibase.teste1.host}:3306/${liquibase.teste1.database}?zeroDateTimeBehavior=convertToNull</url>
<username>${liquibase.teste1.user}</username>
<password>${liquibase.teste1.password}</password>
</configuration>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.34</version>
</dependency>
</dependencies>
<executions>
<execution>
<id>update</id>
<phase>deploy</phase>
<goals>
<goal>update</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>teste2</id>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.jboss.as.plugins</groupId>
<artifactId>jboss-as-maven-plugin</artifactId>
<version>7.7.Final</version>
<configuration>
<hostname>${deploy.jboss.teste2.host}</hostname>
<port>${deploy.jboss.teste2.port}</port>
<username>${deploy.jboss.teste2.user}</username>
<password>${deploy.jboss.teste2.password}</password>
<name>${backend.deployment-name}</name>
<filename>${project.build.finalName}.war</filename>
<skip>${skipDeployment}</skip>
</configuration>
<executions>
<execution>
<id>deploy-jar</id>
<phase>install</phase>
<goals>
<goal>deploy</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-maven-plugin</artifactId>
<version>3.4.1</version>
<configuration>
<changeLogFile>${liquibase.changelog.file}</changeLogFile>
<diffChangeLogFile>${liquibase.changelog.file}</diffChangeLogFile>
<promptOnNonLocalDatabase>false</promptOnNonLocalDatabase>
<driver>com.mysql.jdbc.Driver</driver>
<url>jdbc:mysql://${liquibase.teste2.host}:3306/${liquibase.teste2.database}?zeroDateTimeBehavior=convertToNull</url>
<username>${liquibase.teste2.user}</username>
<password>${liquibase.teste2.password}</password>
</configuration>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.34</version>
</dependency>
</dependencies>
<executions>
<execution>
<id>update</id>
<phase>deploy</phase>
<goals>
<goal>update</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
And in Jenkins I created two Jobs, one for each profile, and in each Job the following maven command is executed respectively:
clean package jboss-as:deploy javadoc:javadoc liquibase:update -P teste1
clean package jboss-as:deploy javadoc:javadoc liquibase:update -P teste2
But I would like to deploy the application on two servers at the same time using the same Job, but so far I have not been able to figure out the method to perform such a task, I already tried the following commands but without success:
clean package jboss-as:deploy javadoc:javadoc liquibase:update -P teste1,teste2
clean package jboss-as:deploy javadoc:javadoc liquibase:update -P teste1 -P teste2
clean package jboss-as:deploy javadoc:javadoc liquibase:update -P teste1;clean package jboss-as:deploy javadoc:javadoc liquibase:update -P teste2
In all cases the deployment is done only in one server. Every help is welcome. Thanks.
EDIT:
To accomplish the task I wish I ended up using the "Post Steps" instructions as shown in the image below. It was not the most elegant solution but worked as expected. If someone has a better solution please share.

Configuring jacoco for integration and unit test reporting in Sonarqube with Powermock

I am using Sonarqube to keep track of both unit and integration test coverage for a multi-module Maven project.
This was the existing profile in the parent pom.xml that was used to generate the Sonarqube report locally before I made the change:
Profile that generates all unit test coverage locally in Sonarqube
<profiles>
<profile>
<id>coverage</id>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<sonar.jacoco.reportPaths>${project.basedir}/../target/jacoco.exec</sonar.jacoco.reportPaths>
<sonar.projectName>plan-advantage-serverless-${project.artifactId}</sonar.projectName>
<sonar.projectKey>${project.groupId}-MPA-${project.artifactId}</sonar.projectKey>
<sonar.exclusions>file:**/generated-sources/**,**/*Model.java,**/models/**/*</sonar.exclusions>
<sonar.test.exclusions>**/test/*</sonar.test.exclusions>
<sonar.java.coveragePlugin>jacoco</sonar.java.coveragePlugin>
<sonar.dynamicAnalysis>reuseReports</sonar.dynamicAnalysis>
<sonar.language>java</sonar.language>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.2</version>
<configuration>
<append>true</append>
<excludes>
<exclude>**/test/*</exclude>
</excludes>
</configuration>
<executions>
<execution>
<id>default-instrument</id>
<goals>
<goal>instrument</goal>
</goals>
</execution>
<execution>
<id>default-restore-instrumented-classes</id>
<goals>
<goal>restore-instrumented-classes</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<showWarnings>true</showWarnings>
<compilerArgs>
<arg>-Xlint:all</arg>
<arg>-Xlint:-processing</arg>
</compilerArgs>
</configuration>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.0</version>
<configuration>
<argLine>-XX:-UseSplitVerifier</argLine>
<systemPropertyVariables>
<jacoco-agent.destfile>${sonar.jacoco.reportPaths}</jacoco-agent.destfile>
</systemPropertyVariables>
</configuration>
<dependencies>
<!-- needed for powermock to run correctly with surefire-->
<dependency>
<groupId>org.apache.maven.surefire</groupId>
<artifactId>surefire-junit47</artifactId>
<version>2.22.0</version>
</dependency>
</dependencies>
</plugin>
<plugin>
<groupId>org.sonarsource.scanner.maven</groupId>
<artifactId>sonar-maven-plugin</artifactId>
<version>3.5.0.1254</version>
</plugin>
</plugins>
</build>
</profile>
This is generating the expected test coverage (sans integration tests) in
Sonarqube locally when I run mvn clean install -P coverage sonar:sonar.
I've so far been able to get integration coverage added as a proof of concept using the following addition
to the parent pom.xml:
pom.xml that includes integration test coverage in Sonarqube but excludes some unit tests
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<jacoco.version>0.7.9</jacoco.version> . <sonar.jacoco.reportPaths>${project.basedir}/../target/jacoco.exec</sonar.jacoco.reportPaths>
<sonar.jacoco.itReportPath>${project.basedir}/../target/jacoco-it.exec</sonar.jacoco.itReportPath>
<sonar.language>java</sonar.language>
<sonar.java.coveragePlugin>jacoco</sonar.java.coveragePlugin>
</properties>
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>3.0.0-M3</version>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
<dependencies>
<dependency>
<groupId>org.apache.maven.surefire</groupId>
<artifactId>surefire-junit47</artifactId>
<version>3.0.0-M3</version>
</dependency>
</dependencies>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>${jacoco.version}</version>
<executions>
<execution>
<id>agent-for-ut</id>
<goals>
<goal>prepare-agent</goal>
</goals>
<configuration>
<append>true</append>
<destFile>${sonar.jacoco.reportPaths}</destFile>
</configuration>
</execution>
<execution>
<id>agent-for-it</id>
<phase>package</phase>
<goals>
<goal>prepare-agent-integration</goal>
</goals>
<configuration>
<append>true</append>
<destFile>${sonar.jacoco.itReportPath}</destFile>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
This was inspired by the example found here.
However, when I run it with the command mvn clean install failsafe:integration-test sonar:sonar, it causes some of the unit tests which were previously being covered to not show up in the Sonarqube output. I believe that the prepare-agent and prepare-agent integrationgoals are using on-the-fly instrumentation. According to JaCoCo's docs, on-the-fly instrumentation is not possible while using PowerMock (which my project is utilizing), so we have to use the offline instrumentation for JaCoCo.
I looked at this example for using offline instrumentation and used the following pom.xml with the command mvn clean install test sonar:sonar:
parent pom.xml that fails to build due to NoClassDefFound errors
<build>
...
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>${jacoco.version}</version>
<executions>
<execution>
<id>default-instrument</id>
<goals>
<goal>instrument</goal>
</goals>
</execution>
<execution>
<id>default-restore-instrumented-classes</id>
<goals>
<goal>restore-instrumented-classes</goal>
</goals>
</execution>
</executions>
</plugin>
</build>
And here's the resulting error:
Any ideas for the proper pom.xml configuration to enable offline instrumentation to get integration and unit test coverage to show up in Sonarqube?
I know this question is 10 months old, but for anyone else coming across this, you need to add this to your dependencies in your pom.xml file.
<dependency>
<groupId>org.jacoco</groupId>
<artifactId>org.jacoco.agent</artifactId>
<classifier>runtime</classifier>
<version>${jacoco.version}</version>
<scope>test</scope>
</dependency>

How to include plugin in maven for test build only?

I want to add the plugin in the maven project. I want it to be added to build only when I build the project for testing purpose.
I found that <scope> can be used for dependency as shown below
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback</artifactId>
<version>0.5</version>
<scope>test</scope>
</dependency>
As you can see here <scope>test</scope>is used.
I want similar thing for plugin. For example this is my plugin code snipplet
<build>
<plugins>
<plugin>
<groupId>org.jibx</groupId>
<artifactId>jibx-maven-plugin</artifactId>
<version>1.2.4</version>
<executions>
<execution>
<goals>
<goal>bind</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
You can create a profile which you activate in your test builds:
<profiles>
<profile>
<id>testing</id>
<build>
<plugins>
<plugin>
<groupId>org.jibx</groupId>
<artifactId>jibx-maven-plugin</artifactId>
<version>1.2.4</version>
<executions>
<execution>
<goals>
<goal>bind</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profile>
Then you invoke mvn with the parameter -P testing to activate your profile:
mvn test -P testing
In addition to activating a profile manually, profiles can also be activated automatically based on conditions such as the existence of a environment variable or a specific file. You can find more information on this in the Maven introduction on profiles.
You can bind a plugin via executions to a phase:
<build>
<plugins>
<plugin>
<groupId>org.jibx</groupId>
<artifactId>jibx-maven-plugin</artifactId>
<version>1.2.4</version>
<executions>
<execution>
<phase>test</phase>
<goals>
<goal>bind</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
The problem I see that usually this plugin runs in process-classes phase which has been done on purpose by the plugin authors..So I don't the request to use it only in the test phase...

Auto deploy maven project war file in company's server

I have created a maven project in netbeans and there i manually build a war file and upload to server.
My pom file only contains:
<properties>
<endorsed.dir>${project.build.directory}/endorsed</endorsed.dir>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
...
<dependency>
<dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
<compilerArguments>
<endorseddirs>${endorsed.dir}</endorseddirs>
</compilerArguments>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.3</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.6</version>
<executions>
<execution>
<phase>validate</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<outputDirectory>${endorsed.dir}</outputDirectory>
<silent>true</silent>
<artifactItems>
<artifactItem>
<groupId>javax</groupId>
<artifactId>javaee-endorsed-api</artifactId>
<version>7.0</version>
<type>jar</type>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.datanucleus</groupId>
<artifactId>datanucleus-maven-plugin</artifactId>
<version>4.0.0-release</version>
<configuration>
<log4jConfiguration>${basedir}/log4j.properties</log4jConfiguration>
<verbose>true</verbose>
</configuration>
<executions>
<execution>
<phase>process-classes</phase>
<goals>
<goal>enhance</goal>
</goals>
</execution>
</executions>
</plugin>
<!--<plugin>
<groupId>com.mysema.querydsl</groupId>
<artifactId>querydsl-maven-plugin</artifactId>
<version>2.9.0</version>
<executions>
<execution>
<goals>
<goal>export</goal>
</goals>
</execution>
</executions>
<configuration>
<jdbcDriver>com.mysql.jdbc.Driver</jdbcDriver>
<jdbcUrl>jdbc:mysql://localhost:3306/login</jdbcUrl>
<jdbcUser>root</jdbcUser>
<packageName>com.titas.model</packageName>
<targetFolder>${project.basedir}/target/generated-sources/java</targetFolder>
</configuration>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
</dependencies>
</plugin>-->
<plugin>
<groupId>com.mysema.maven</groupId>
<artifactId>apt-maven-plugin</artifactId>
<version>1.1.3</version>
<executions>
<execution>
<goals>
<goal>process</goal>
</goals>
<configuration>
<outputDirectory>target/generated-sources/java</outputDirectory>
<processor>com.mysema.query.apt.jdo.JDOAnnotationProcessor</processor>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Now i want to auto deploy war file in company's server whenever i will build in netbeans.
Is there any tag to auto deploy in server in pom.xml? Like if i use any plugin where i will specify my server folder war file will auto deploy there and replace previous one.
Thanks in advance!!
I don't have experience deploying to Tomcat specifically, and apparently it's different based on the version.
Tomcat 6/7
For Tomcat 6 replace "tomcat7" with "tomcat6" in the following lines.
Use the tomcat7-maven-plugin by putting this in the <build><plugins> section of your pom.xml:
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.0</version>
<configuration>
<url>http://www.example.com:1234/mymanager</url>
</configuration>
</plugin>
Obviously change the url to match the URL of the server/manager you're trying to deploy to. If you need to specify credentials add a <server>servername</server> tag to the configuration block and put this in your maven settings.xml (under path <settings><servers>):
<server>
<id>servername</id>
<username>myusername</username>
<password>mypassword</password>
</server>
For other configuration changes see the plugin page linked above.
Once it's configured you should be able to run mvn package tomcat7:deploy to deploy to your server. Other maven goals are here.
Tomcat 8
The best I'm finding is this question: Tomcat 8 integration with Maven
The accepted answer uses the cargo-maven2-plugin, but looking at how it's configured I don't think that will go to a remote machine.
Alternately you can try the tomcat7 plugin as detailed above, I did see this blog post that suggests it works for 8 too.

maven-failsafe-plugin not seeing my tests (seleniumHQ)

i'm writing tests via selenium web driver here's my code :
Pom.xml
<project>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>2.24.1</version>
</dependency>
</dependencies>
<build>
<finalName>SeleniumebDriverProject</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.11</version>
<configuration>
<!-- Skip the normal tests, we'll run them in the integration-test phase-->
<skip>false</skip>
</configuration>
<executions>
<execution>
<phase>integration-test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<skip>false</skip>
<includes>
<include>**/*Test.java</include>
</includes>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
My test class named GoogleTest.java.
after reading this post : failsafe plugin won't run on one project but will run on another -- why?
I changed the name of my class so it's:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.11</version>
<configuration>
<!-- Skip the normal tests, we'll run them in the integration-test phase-->
<skip>false</skip>
</configuration>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
<executions>
</plugin>
But the problem persist.
The goal of the maven-failsafe-plugin is named integration-test instead of test. Furthermore if you changed your naming convention to the convention of maven-failsafe-plugin than you don't need any configuration which includes etc. files. Just use the defaults.
Furthermore i assume you have started running the integration tests via:
mvn verify

Resources