maven - build once to generate separate war files for separate environment - maven

My pom.xml -
<?xml version="1.0" encoding="UTF-8"?>
<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.example</groupId>
<artifactId>test-application</artifactId>
<packaging>war</packaging>
<version>0.2.0</version>
<profiles>
<profile>
<id>local</id>
<activation>
<property>
<name>envType</name>
<value>local</value>
</property>
</activation>
<properties>
<envType>local</envType>
</properties>
</profile>
<profile>
<id>local2</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<envType>local2</envType>
</properties>
</profile>
<profile>
<id>dev</id>
<activation>
<property>
<name>envType</name>
<value>dev</value>
</property>
</activation>
<properties>
<envType>dev</envType>
</properties>
</profile>
<profile>
<id>sit</id>
<activation>
<property>
<name>envType</name>
<value>sit</value>
</property>
</activation>
<properties>
<envType>sit</envType>
</properties>
</profile>
<profile>
<id>uat</id>
<activation>
<property>
<name>envType</name>
<value>uat</value>
</property>
</activation>
<properties>
<envType>uat</envType>
</properties>
</profile>
</profiles>
<build>
<finalName>my-application</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>com.github.eirslett</groupId>
<artifactId>frontend-maven-plugin</artifactId>
<version>1.4</version>
<executions>
<execution>
<id>install node and npm</id>
<goals>
<goal>install-node-and-npm</goal>
</goals>
<phase>generate-resources</phase>
<configuration>
<nodeVersion>v6.10.0</nodeVersion>
<npmVersion>3.10.10</npmVersion>
</configuration>
</execution>
<execution>
<id>npm install</id>
<goals>
<goal>npm</goal>
</goals>
<phase>generate-resources</phase>
<configuration>
<arguments>install</arguments>
</configuration>
</execution>
<execution>
<id>bower install</id>
<goals>
<goal>bower</goal>
</goals>
<configuration>
<arguments>install</arguments>
</configuration>
</execution>
<execution>
<id>gulp build</id>
<goals>
<goal>gulp</goal>
</goals>
<phase>generate-resources</phase>
<configuration>
<arguments>optimize --env ${envType}</arguments>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Front end maven plugin installs node, all required npm and bower packages and initiates the gulp task for optimizing all the front end code. Gulp places all the front end code into the below -
/src/main/webapp/index.html
/src/main/webapp/js/
etc
web.xml is at -
/src/main/webapp/WEB-INF/web.xml
Command to build the war package for local,SIT,DEV, etc environment -
mvn clean install -DenvType=local
mvn clean install -DenvType=sit
mvn clean install -DenvType=uat
This builds the war file - my-application.war in /target directory.
I need to run the maven command separately each time in order to build the war package for each environment. (because the front-end code uses separate environment variables for each environment).
How can I change the build process so that I need to build only once and maven takes care of running the gulp tasks for each environment (gulp optimize --env ${envType}) one after the other and produces separate war files in the target directory -
my-application-local.war
my-application-sit.war
my-application-uat.war
etc
I need maven to run the gulp task in sequence. I can make each run of gulp to output the front-end code to separate directories. The maven should pick from these separate directories and create separate war files. Not sure whether this is the right approach. Please let me know on this.

Related

Maven - pom file - Artifact not being created

I have a pom file that is triggered by jenkins and is being used twice, every time on a different machine(docker container) with different compilers(to be built for different linux distributions).
In order to get those 2 different builds as artifacts, and with different names, I'm trying to use profiles and set the classifier of the artifact with different values.
It seems though that the artifacts are not being created for some reason, and I don't know why.
I'm not sure I configured the profiles correctly and I also have the 'attach-to-artifact' in an execution block of its own and I don't know if it's right.
Any help would be much appreciated.
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>
<parent>
<groupId>XXXX</groupId>
<artifactId>XXXXX</artifactId>
<version>1-SNAPSHOT</version>
</parent>
<groupId>XXXXX</groupId>
<artifactId>XXXXXXX</artifactId>
<version>${revision}</version>
<packaging>pom</packaging>
<scm>
<developerConnection>scm:git:ssh://XXXXXX</developerConnection>
</scm>
<properties>
<revision>1.0.0-1-SNAPSHOT</revision>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>flatten-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>build</id>
<phase>compile</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<target>
<exec executable="sh" failonerror="true">
<arg line="build.sh"/>
</exec>
</target>
</configuration>
</execution>
<execution>
<id>prepare-test-package</id>
<phase>prepare-test</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<skip>${env.ESX_COMPILATION}</skip>
<target>
<exec executable="sh" failonerror="true">
<arg line="tests.sh"/>
</exec>
<attachartifact file="${project.build.directory}/archive.tar.gz" type="tar.gz"/>
</target>
</configuration>
</execution>
<execution>
<id>attach-to-artifact</id>
<phase>attach-artifact</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<classifier>${envClassifier}</classifier>
<target>
<attachartifact file="${project.build.directory}/archive.tar.gz" type="tar.gz"/>
</target>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>esx</id>
<activation>
<property>
<name>env.ESX_COMPILATION</name>
<value>true</value>
</property>
</activation>
<properties>
<envClassifier>esx</envClassifier>
</properties>
</profile>
<profile>
<id>linux</id>
<activation>
<property>
<name>env.ESX_COMPILATION</name>
<value>false</value>
</property>
</activation>
<properties>
<envClassifier>linux</envClassifier>
</properties>
</profile>
</profiles>
As can be seen I'm using the 'env.ESX_COMPILATION' variable to set the profile choice which sets the 'envClassifier' variable and in the final execution block, under and before i set the 'classifier'. and inside target i call 'attachtoartifact'
What am I doing wrong here?
Any help is much appreciated!
Thanks!

injecting new argument/property value to maven profile in module

i have main pom.xml
i like to change from the main mvn command line cli which I'm using and change the :
<argument>${docker.image}</argument>
argument in only in the submodule :
module_y profile NOT module_x
this is the command I'm executing now :
mvn clean install -Ddocker_build=build
<artifactId>foo</artifactId>
<version>b1</version>
<packaging>pom</packaging>
<properties>
<docker.image>www.repo.org:8000/${project.artifactId}:${project.version}</docker.image>
</properties>
<modules>
<module>module_x</module>
<module>module_y</module>
</modules>
this is the section in the module_x and module_y
<profiles>
<profile>
<activation>
<property>
<name>docker_build</name>
<value>build</value>
</property>
<file>
<exists>Dockerfile</exists>
</file>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.6.0</version>
<executions>
<execution>
<phase>install</phase>
<configuration>
<executable>docker</executable>
<arguments>
<argument>build</argument>
<argument>-f</argument>
<argument>${project.basedir}/Dockerfile</argument>
<argument>-t</argument>
<argument>${docker.image}</argument>
<argument>.</argument>
</arguments>
</configuration>
<goals>
<goal>exec</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
in short, how do i change only the property value ${docker.image} in profile docker_build in module_y from main mvn run?
If you cannot change the POMs, this cannot be done.
The only possible approach would be to build the modules separately (by using -pl module_x -am or something like that) and use different command line parameters in both cases.

Skip exec-maven-plugin from Command Line Argument in Maven

By default in my project POM, exec-maven-plugin, rpm-maven-plugin will be executed,
which is not required in local compilation/build.
I want to skip these plugin execution by passing Command Line Arguments
I tried below command to skip them like normal plugins, but didn't work though!
mvn install -Dmaven.test.skip=true -Dmaven.exec.skip=true
-Dmaven.rpm.skip=true
This page should tell you that the name of the argument to be passed by cmdline (i.e. the user property) is called skip, which is a poorly chosen name. To fix this do the following:
<properties>
<maven.exec.skip>false</maven.exec.skip> <!-- default -->
</properties>
...
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.3.2</version>
<configuration>
<skip>${maven.exec.skip}</skip>
</configuration>
</plugin>
Try -Dexec.skip from specification:
http://www.mojohaus.org/exec-maven-plugin/java-mojo.html#skip
Using profiles (as little as possible) and execution phase you may achieve what you want for plugins that do not handle the skip property:
Plugin configuration:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>rpm-maven-plugin</artifactId>
<executions>
<execution>
<phase>${rpmPackagePhase}</phase>
<id>generate-rpm</id>
<goals>
<goal>rpm</goal>
</goals>
</execution>
</executions>
<configuration>
...
</configuration>
</plugin>
Profile configuration:
<profiles>
<profile>
<id>default</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<rpmPackagePhase>none</rpmPackagePhase>
</properties>
</profile>
<profile>
<id>rpmPackage</id>
<activation>
<property>
<name>rpm.package</name>
<value>true</value>
</property>
</activation>
<properties>
<rpmPackagePhase>package</rpmPackagePhase>
</properties>
</profile>
</profiles>
Invocation:
mvn package -Drpm.package=true [...]

Heroku: managing different properties files in with maven

Maybe someone can help me. I have searched the web but haven't been able to find a solution yet.
I have a java application running on Heroku. I want to be able to have different properties files loaded for different Heroku instances (dev, test, prod), but I get java.io.FileNotFoundException. This is what I have in my pom.xml.
<profiles>
<profile>
<id>dev</id>
<activation>
<property>
<name>env.APP_ENVIRONMENT</name>
<value>dev</value>
</property>
</activation>
<properties>
<profile.name>dev</profile.name>
</properties>
</profile>
<profile>
<id>test</id>
<activation>
<property>
<name>env.APP_ENVIRONMENT</name>
<value>test</value>
</property>
</activation>
<properties>
<profile.name>test</profile.name>
</properties>
</profile>
<profile>
<id>prod</id>
<activation>
<property>
<name>env.APP_ENVIRONMENT</name>
<value>prod</value>
</property>
</activation>
<properties>
<profile.name>prod</profile.name>
</properties>
</profile>
</profiles>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.2</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.4</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>com.github.jsimone</groupId>
<artifactId>webapp-runner</artifactId>
<version>7.0.34.0</version>
<destFileName>webapp-runner.jar</destFileName>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/profiles/${profile.name}</directory>
<includes>
<include>*.xml</include>
<include>*.properties</include>
</includes>
</resource>
</resources>
</build>
How to customize the Maven build is described here:
https://devcenter.heroku.com/articles/using-a-custom-maven-settings-xml
You can create a settings file for each build type:
settings.xml <-- Default
settings-dev.xml
settings-test.xml
settings-prod.xml
A production build could then be performed as follows:
heroku config:set MAVEN_SETTINGS_PATH=settings-prod.xml
git push heroku master
Details
The Java buildpack supports a way to specify a custom Maven settings file.
By default it uses a settings file located in the build directory, this can be overridden by setting one of the following variables:
MAVEN_SETTINGS_PATH
MAVEN_SETTINGS_URL

Maven Wagon plugin: Can wagon:upload upload to multiple locations?

I'm looking into the Maven Wagon Plugin to attempt uploading some artifacts to remote UNC Server shares (\\servername\share\directory\to\put\to), and I have gotten it configured to work like so in the POM:
<build>
<extensions>
<extension>
<groupId>org.apache.maven.wagon</groupId>
<artifactId>wagon-file</artifactId>
<version>1.0-beta-7</version>
</extension>
</extensions>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>wagon-maven-plugin</artifactId>
<version>1.0-beta-3</version>
<executions>
<execution>
<id>upload-jar-to-folder</id>
<phase>deploy</phase>
<goals>
<goal>upload</goal>
</goals>
</execution>
</executions>
<configuration>
<fromDir>${project.build.directory}</fromDir>
<includes>*</includes>
<url>file://localhost///${servername}/${sharename}</url>
<toDir>directory/to/put/artifact</toDir>
</configuration>
</plugin>
...
</build>
This works great for one server when I pass in -Dservername=x -Dsharename=y, but how can I scale it out so I can run a deploy for QA or Prod where I have multiple servers to deploy to?
I've considered (and written) a script to run mvn wagon:upload -Penvironment# multiple times--once for each server--but this seems flawed to me. If I'm shelling out to a script to handle this process, I could just as well script out the entire deploy, too. However, this takes away from the usefulness of Wagon (and Maven)...
Is there a way to run multiple <executions> for one goal? For instance, running multiple profile configured wagon:upload tasks when I just run mvn deploy -Pqa?
If you want to use multiple profiles you could just use: mvn deploy -Denv=qa and trigger some profiles on this property and define the configuration for your severs in the profiles. For this kind of profile activation look at
http://maven.apache.org/guides/introduction/introduction-to-profiles.html
and search for
-Denvironment=test
Here's an example POM which does two executions of the maven-antrun-plugin in one build:
<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>org.stackoverflow</groupId>
<artifactId>q5328617</artifactId>
<version>0.0.1-SNAPSHOT</version>
<profiles>
<profile>
<activation>
<property>
<name>env</name>
<value>qa</value>
</property>
</activation>
<id>qa1</id>
<build>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>qa1</id>
<phase>test</phase>
<configuration>
<tasks>
<echo level="info">Executing qa1</echo>
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
<dependencies>
</dependencies>
</plugin>
</plugins>
</build>
</profile>
<profile>
<activation>
<property>
<name>env</name>
<value>qa</value>
</property>
</activation>
<id>qa2</id>
<build>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>qa2</id>
<phase>test</phase>
<configuration>
<tasks>
<echo level="info">Executing qa2</echo>
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
<dependencies>
</dependencies>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>

Resources