I have a multi module project having the following structure:
Project:
- module1
- module2
- integration-test
- parent pom
What is the correct way of achieving the following:
run unit tests from all modules(except integration-test) using mvn clean install
run integration tests on demand(may be by using maven-failsafe plugin or via a maven profile? )
fail the build when integration tests fail.
By Default integration tests should not be run using mvn clean install
integration-test module has only the integration tests.
I have tried multiple hacks using maven-failsafe plugin and maven-sunfire-plugin(for unit tests) but not able to achieve the above in standard way.
Following is how the relevant portion of integration-test pom looks like:
<dependencies>
<!-- dependencies required for this module-->
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.12</version>
<executions>
<execution>
<id>add-integration-test-sources</id>
<phase>generate-test-sources</phase>
<goals>
<goal>add-test-source</goal>
</goals>
<configuration>
<sources>
<source>src/test/java</source>
</sources>
</configuration>
</execution>
<execution>
<id>add-integration-test-resources</id>
<phase>generate-test-resources</phase>
<goals>
<goal>add-test-resource</goal>
</goals>
<configuration>
<resources>
<resource>
<filtering>true</filtering>
<directory>src/test/resources</directory>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>run-its</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
currently when i run mvn clean install it runs integration tests too. When i run mvn -Prun-its clean verify, it is running unit tests from other modules too. what am i missing?
You can skip execution of the Integration tests simply by setting -DskipITs=true when running your build like so:
mvn clean install -DskipITs=true
this will run all other tests but your ITs (see here for doc).
If you only want to run
mvn clean install
you can set the default for skipITs in your pom.xml
<properties>
<skipITs>true</skipITs>
</properties>
This way you can override it on demand with
mvn clean install -DskipITs=false
To run only ITs without Unittests you can configure the -Property of the maven-surefire-plugin like so
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.12.4</version>
<configuration>
<skip>${skipUnitTests}</skip>
</configuration>
</plugin>
so if you run
mvn clean install -DskipITs=false -DskipUnitTests=true
Note that skipUnitTests will be false by default so no need to declare a property for that.
If you'd rather use a Profile it should work like that
<profile>
<id>ITs</id>
<properties>
<skipUnitTests>true</skipUnitTests>
<skipITs>false</skipITs>
</properties>
</profile>
and run the build like so
mvn clean install -PITs
Of course you could also use the plugin-configuration for maven-surefire-plugin with true directly in the profile so there'd be no need for the extra property, like
<profile>
<id>ITs</id>
<properties>
<skipITs>false</skipITs>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.12.4</version>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>
</profile>
I don't know if that's the best solution but you can achieve that using profiles. For example in the main pom.xml you add just the other modules in the <modules> section and then add another profile:
<modules>
... standard modules ...
</modules>
<profiles>
<profile>
<id>tests</id>
<modules>
<module>module1</module>
... standard modules repeated (it might not be needed>...
<module>module2</module>
<module>module-integration-test</module>
</modules>
</profile>
</profiles>
Then you run maven with that profile if you wnat to run tests.
maven -P tests clean install
That would work if you want to run integration tests AND the other modules. If you want to run just the integration tests you can do it like that:
<modules>
<!-- EMPTY -->
</modules>
<profiles>
<profile>
<id>defaultModule</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<modules>
<module>module1</module>
... standard modules repeated (it might not be needed>...
<module>module2</module>
</modules>
</profile>
<profile>
<id>tests</id>
<modules>
<module>module-integration-test</module>
</modules>
</profile>
</profiles>
This way with mvn clean install you will run with defaultModule (which is activeByDefault) and if you specify -P tests you will run just tests
The best is to make a separate module which contains the integration tests which looks like already shown in your own question. Now how to handle the integration tests being running or not ...
The integration-test module looks like this:
<?xml version="1.0"?>
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>groupOfYourParant</groupId>
<artifactId>integration-test</artifactId>
<version>0.1.0-SNAPSHOT</version>
</parent>
<artifactId>integration-test</artifactId>
<packaging>jar</packaging>
<name>Mod-IT</name>
<dependencies>
<dependency>
<groupId>groupId</groupId>
<artifactId>TheArtifact</artifactId>
<version>${project.version}</version>
</dependency>
<!-- Supplemental deps only needed in this module -->
<dependency>
<groupId>....</groupId>
<artifactId>....</artifactId>
<version>...</version>
<scope>test</scope>
</dependency>
</dependencies>
<profiles>
<profile>
<id>run-its</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>
By using this you can simply control to run the integration tests via:
mvn -Prun-its clean verify
It's important that you have define the dependencies to other modules which are needed by the integration tests module or where it made be sure that those modules have to be built before this integration test module.
Furthermore you can now configure here supplemental things which are needed for integration tests and which should be run for example in the pre-integration-test and/or in post-integration-test phase.
If you put the test code into src/test/java plus optional resources into src/test/resources you can now define dependencies within your integration test module separately from any other module.
You should of course define the versions for your plugins in a pluginManagement in your parent pom to define all plugins which are being used during a build.
I need to know how to instruct maven to deploy a ROOT.war into /deployments folder while keeping the standard /src/main/webapp deployement directory.
Here is the profile that I need to deal with:
<profile>
<id>sdk</id>
<build>
<plugins>
<plugin>
<groupId>com.google.appengine</groupId>
<artifactId>appengine-maven-plugin</artifactId>
<version>${gae.version}</version>
<configuration>
<enableJarClasses>false</enableJarClasses>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>gwt-maven-plugin</artifactId>
<version>${version.gwt}</version>
<executions>
<execution>
<!-- gwt:compile happens just before package phase -->
<phase>prepare-package</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
<configuration>
<modules>
<!-- gwt module inherits Core gwt module therefore both will be gwt:compiled -->
<module>org.example.App</module>
</modules>
<logLevel>DEBUG</logLevel>
<!--<logLevel>WARN</logLevel>-->
<runTarget>index.html</runTarget>
<appEngineVersion>${gae.version}</appEngineVersion>
<!-- tell the gwt plugin that the webapp source resides in src/main/webapp -->
<webappDirectory>${webappDirectory}</webappDirectory>
<!-- tell the gwt plugin that dev mode should be run using the webapp that resides in target/${webappDirectory} -->
<hostedWebapp>${webappDirectory}</hostedWebapp>
<!-- Normally the gwt maven plugin executes dev mode using a builtin jetty server.
This config property instructs the gwt maven plugin to execute dev mode using the
jetty server supplied by the appengine sdk. -->
<server>com.google.appengine.tools.development.gwt.AppEngineLauncher</server>
</configuration>
</plugin>
</plugins>
</build>
</profile>
Now, my app being deployed in Openshift I need to have this profile also:
<profiles>
<profile>
<id>openshift</id>
<build>
<finalName>OpenShift template</finalName>
<plugins>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.1.1</version>
<configuration>
<outputDirectory>deployments</outputDirectory>
<warName>ROOT</warName>
</configuration>
</plugin>
</plugins>
</build>
</profile>
Just putting the maven-war-plugin alonside with the gwt-maven-plugin doesn't work and web.xml is not being copied and so forth. So I need to modify the gwt-maven-plugin settings instead.
The question here now is
How to make the gwt-maven-plugin to also deploy similar to this
openshift profile? To deploy ROOT.war into the /deployments folder
Im trying to get the properties-maven-plugin to read from my .properties file. Flyway (which im trying to use the properties for) just keeps throwing errors about the db url being malformed, but works if i set the values within the pom.xml itself, rather than using the properties read from file.
Im using eclipse with the m2e plugin.
plugin config to read from .properties
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>properties-maven-plugin</artifactId>
<version>1.0-alpha-2</version>
<executions>
<execution>
<phase>initialize</phase>
<goals>
<goal>read-project-properties</goal>
</goals>
<configuration>
<files>
<file>src/main/resources/config.properties</file>
</files>
</configuration>
</execution>
</executions>
</plugin>
Flyway config where the properties are being used
<plugin>
<groupId>com.googlecode.flyway</groupId>
<artifactId>flyway-maven-plugin</artifactId>
<version>2.2.1</version>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>flyway:migrate</goal>
</goals>
</execution>
</executions>
<configuration>
<driver>${db.driver}</driver>
<url>${db.url}</url>
<user>${db.user}</user>
<password>${db.password}</password>
</configuration>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.26</version>
</dependency>
</dependencies>
</plugin>
config.properties located in /src/main/resources/
# Database details
db.driver=com.mysql.jdbc.Driver
db.url=jdbc:mysql://localhost:3306/dbname
db.user=username
db.pass=password
Ive tried looking through several other stackoverflow threads but none of the solutions seem to work. I'm new to maven and the whole thing seems to be throwing me, anyone got a light to shed?
There are basically two ways you can execute the Flyway migrate goal:
As part of a lifecycle phase: You have configured the Flyway plugin to be executed during the compile phase. That means you can just enter mvn compile and Flyway will be executed along with all other goals that are part of that lifecycle phase and all previous phases. Everything works fine, except you have a slight misconfiguration: The goal must not be prefixed. In order to fix this you have to provide the goal without prefix:
<goals>
<goal>migrate</goal>
</goals>
Now the execution works. Flyway gets all parameters from the properties-maven-plugin because it is executed in a previous phase.
Direct invocation: If you execute Flyway with mvn flyway:migrate, the plugin is invoked independent of any lifecycle phases. Since no phase is executed, the properties-maven-plugin is also not executed because it relies on the initialize phase - which effectively doesn't set any parameters. That's why Flyway complains about missing parameters.
Solution:
If you want the properties-maven-plugin to work together with Flyway you have to execute Flyway as part of a lifecycle. If you don't want to invoke it with every compile phase, you could create a separate profile and only run this profile whenever you need a Flyway migration with mvn compile -PflywayMigration:
<profiles>
<profile>
<id>flywayMigration</id>
<build>
<plugins>
<plugin>
<groupId>com.googlecode.flyway</groupId>
<artifactId>flyway-maven-plugin</artifactId>
<version>2.2.1</version>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>migrate</goal>
</goals>
</execution>
</executions>
<configuration>
<driver>${db.driver}</driver>
<url>${db.url}</url>
<user>${db.user}</user>
<password>${db.password}</password>
</configuration>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.26</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</profile>
</profiles>
Specifically, I run the launch4j-maven-plugin plugin to generate me an .exe file. This only works on Windows, so I was wondering if I could 'opt-out' of this step on other platforms?
The plugin is tied to the execution phase like this
<plugin>
...
<execution>
<id>l4j-clui</id>
<phase>package</phase>
<goals>
<goal>launch4j</goal>
</goals>
</execution>
...
You can wrap that plugin under separate build profile and just enable that profile on the build that you want
For example:
<project>
...
<profile>
<id>generate-exe</id>
<build>
<plugins>
<plugin>
<!_- your plugin configuration -->
</plugin>
...
</plugins>
</build>
</profile>
...
</project>
Now pass parameter while launching maven to specify profile
For example:
mvn clean install -Pgenerate-exe
I'm trying to execute grunt tasks from within maven without needing to install Node.js or anything. This is because I wan't my artifact to be packaged by Jenkins and I can't install Node.js on that machine.
I know that it's easy with npm and a few commands to get it working, but I also think that it should be easy to integrate with maven, the problem is that I don't know where to start since I'm new to npm.
Yes, using the frontend-maven-plugin, you can compile Grunt projects via Maven (found via the NodeJS mailing list).
As the documentation points out, the plugin has the following features:
Let you keep your frontend and backend builds as separate as possible, by reducing the amount of interaction between them to the bare minimum; using only 1 plugin.
Let you use Node.js and its libraries in your build process without installing Node/NPM globally for your build system
Let you ensure that the version of Node and NPM being run is the same in every build environment
I've walked through the code and it's fairly simple. Thank goodness someone finally put this together; it's an elegant solution. The repository includes an example that uses a regular Gruntfile.js to invoke jshint analysis.
UPDATE 2014-09-19: This is no longer the most accurate answer - please take a look at some of the other answers below. It was accurate at the time when I answered the question, but there seems to have been a good deal of progress in this area since then.
I'm afraid you're out of luck. Grunt is built using node and needs to be installed using npm. You might be able to copy an existing installation of Grunt from another machine if you don't want to use npm, but will still use the grunt executable and all of its dependencies on your build server.
In addition to that, many of the Grunt tasks are implemented as Node.js modules, and you will have to install them as well. Again, you might be able to copy them from another server, where you've done the Node.js/Grunt installation, but at one point, you have to do it.
For running Grunt from Maven, your best bet is to use the Maven exec plugin and then execute the grunt executable from there.
As an alternative, there are several Maven plugins that allow you to do things similar to Grunt in a Java-based fashion. They require additional configuration not compatible with Grunt, so YMMV. One that I've used in the past is http://code.google.com/p/wro4j/, which comes with a Maven plugin as well: http://code.google.com/p/wro4j/wiki/MavenPlugin
Any particular reason why you can't install Node.js on your build server?
You can use grunt-maven-plugin. It allows you to easily integrate Grunt tasks into Maven build process. No dirty hacks.
This is what I use in my current project and it works just perfect.
Finally I ended up with this (which is close enough but doesn't solve the problem):
<plugin>
<groupId>org.mule.tools.javascript</groupId>
<artifactId>npm-maven-plugin</artifactId>
<version>1.0</version>
<executions>
<execution>
<phase>generate-resources</phase>
<goals>
<goal>fetch-modules</goal>
</goals>
<configuration>
<packages>
<package>grunt-cli:0.1.6</package>
</packages>
</configuration>
</execution>
</executions>
</plugin>
that installs locally the grunt-cli, but if I don't have installed node.js it's worthless. Although I try to install node.js locally there's the need to have installed python, g++ and make. So I'll go with the KISS solution: install grunt in the build server.
References:
https://github.com/mulesoft/npm-maven-plugin
https://github.com/joyent/node/wiki/Installing-Node.js-via-package-manager
https://github.com/mcheely/requirejs-maven-plugin
You might want to checkout http://jhipster.github.io/ : it's a Yeoman generator, that generates an application which has Maven, Grunt and Bower all working together.
It's a bit like your third option, but everything is configured for you, which isn't that easy. It's also generating the basic AngularJS and Java REST services for you
This is a full copy/paste solution which work in 2017 using frontend-maven-plugin for front build, and maven-war-plugin to build the war.
What it does ? install npm, bower grunt,and everything you need, then run npm install, bower install and finally grunt build.
You can remove/add replace the steps you want, for me it's a full 30 sec install/build library and project.
<dependencies>
...
</dependencies>
<dependencyManagement>
<dependencies>
<!-- https://mvnrepository.com/artifact/com.github.eirslett/frontend-maven-plugin -->
<dependency>
<groupId>com.github.eirslett</groupId>
<artifactId>frontend-maven-plugin</artifactId>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.4</version>
<configuration>
<warSourceDirectory>src/main/webapp/YourFrontJsFolder/dist</warSourceDirectory>
<warName>YouWarName</warName>
<failOnMissingWebXml>false</failOnMissingWebXml>
<warSourceExcludes>node_modules/**</warSourceExcludes>
<includeScope>system</includeScope>
<webResources>
<resource>
<directory>WebContent/WEB-INF</directory>
<targetPath>WEB-INF</targetPath>
<includes>
<include>**/*.jar</include>
<include>**/*.jsp</include>
</includes>
</resource>
</webResources>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
<encoding>Cp1252</encoding>
</configuration>
</plugin>
</plugins>
</pluginManagement>
<finalName>YourAppName</finalName>
</build>
<profiles>
<profile>
<id>release</id>
<build>
<plugins>
<plugin>
<groupId>com.github.eirslett</groupId>
<artifactId>frontend-maven-plugin</artifactId>
<executions>
<execution>
<!-- optional: you don't really need execution ids, but it looks
nice in your build log. -->
<id>install node and npm</id>
<goals>
<goal>install-node-and-npm</goal>
</goals>
<!-- optional: default phase is "generate-resources" -->
<phase>generate-resources</phase>
<configuration>
<nodeVersion>v7.6.0</nodeVersion>
</configuration>
</execution>
<execution>
<id>npm install</id>
<goals>
<goal>npm</goal>
</goals>
<!-- optional: default phase is "generate-resources" -->
<phase>generate-resources</phase>
<configuration>
<arguments>install</arguments>
</configuration>
</execution>
<execution>
<id>bower install</id>
<goals>
<goal>bower</goal>
</goals>
<configuration>
<!-- optional: The default argument is actually "install", so unless
you need to run some other bower command, you can remove this whole <configuration>
section. -->
<arguments>install</arguments>
</configuration>
</execution>
<execution>
<id>grunt build</id>
<goals>
<goal>grunt</goal>
</goals>
<!-- optional: the default phase is "generate-resources" -->
<phase>generate-resources</phase>
<configuration>
<!-- optional: if not specified, it will run Grunt's default task
(and you can remove this whole <configuration> section.) -->
<arguments>build</arguments>
</configuration>
</execution>
</executions>
<configuration>
<installDirectory>target</installDirectory>
<workingDirectory>src/main/webapp/YourFrontJsFolder</workingDirectory>
</configuration>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>debug</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<profile>
<id>IDE</id>
<activation>
<property>
<name>m2e.version</name>
</property>
</activation>
<build>
<!-- Put the IDE's build output in a folder other than target, so that
IDE builds don't interact with Maven builds -->
<directory>target-ide</directory>
</build>
</profile>
</profiles>
Then you can Run as -> Maven build ..., with goal clean install and profile release
The first problem is that Maven is Java, but Grunt.js runs on the Node.js runtime. The easiest integration I ever achieved between the two involved the maven-exec-plugin. The maven-exec-plugin is capable of executing .sh/.bat/.cmd scripts, whichever are native to the OS you are using. So during a Maven build I would have the maven-exec-plugin execute a script named optimize-js.sh, for example, which would simply do something like “grunt release –force”, or whatever. The scripts can be made to do whatever. The important thing is to configure the maven-exec-plugin to execute them in the correct working directory. Of course, “grunt” and “node” need to be executable from the command-line.
If the problem is installing NodeJS on the Jenkins machine then you can use the NodeJS Jenkins plugin.
https://wiki.jenkins-ci.org/display/JENKINS/NodeJS+Plugin
We're not using it with Maven (yet) but we've got grunt running.
Can be done with exec-maven-plugin.
Define a script and dependency to grunt-cli in your package.json:
...
"scripts": {
"build": "./node_modules/.bin/grunt install"
},
"devDependencies": {
"grunt-cli": "^1.2.0",
...
In your pom, add the commands to run:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>X.Y.Z</version>
<executions>
<execution>
<id>exec-npm-install</id>
<phase>generate-sources</phase>
<configuration>
<workingDirectory>${project.basedir}</workingDirectory>
<executable>npm</executable>
<arguments>
<argument>install</argument>
</arguments>
</configuration>
<goals>
<goal>exec</goal>
</goals>
</execution>
<execution>
<id>exec-grunt-install</id>
<phase>generate-sources</phase>
<configuration>
<workingDirectory>${project.basedir}</workingDirectory>
<executable>npm</executable>
<arguments>
<argument>run</argument>
<argument>build</argument>
</arguments>
</configuration>
<goals>
<goal>exec</goal>
</goals>
</execution>
</executions>
</plugin>
It will now run on mvn package