{{announcement.body}}
{{announcement.title}}

Managing Environments and Plugins in Maven

DZone 's Guide to

Managing Environments and Plugins in Maven

Even in 2019, there are still no proper plugins for managing environments in Maven.

· Java Zone ·
Free Resource

It is amazing that in 2019, there are still no proper plugins for managing environments in Maven. The only one that makes an attempt at solving environment management issues is multienv-maven-plugin  (https://github.com/khmarbaise/multienv-maven-plugin) by Khmarbaise. In this article, we discuss details about using the environments-maven-pluginassess what multienv-maven-plugin is lacking, and look at potential solutions to this problem. Let's get into it!

Doesn't Allow the Exclusion of Environments

For almost all of the projects I have worked on, they have resource files both for various environments and for running the code on the developer's machine but pointing to various environments. For example:dev,  dev_localci,  ci_localqa,  qa_local, etc. — these QA resources files are used to run the application in the QA environment. qa_local resource files are used to run the application on the developer machine pointing to the QA environment. When a release build is run, war files for dev_local, ci_local, and qa_local should not be generated. Otherwise, it slows down the build and clutters bamboo build pages, potentially causing confusion to the party performing the actual deployment.

multienv-maven-plugin is built on the philosophy that each directory under src/main/environments represents an environment, and all directories under src/main/environments are environments. Additionally, a war file is generated for each environment. This philosophy appears to provide simplicity but does so at the expense of proper functionality.

environments-maven-plugin allows for the exclusion of environments for which generation of war files is undesirable. This can be done using the excludeEnvironments tag in the plugin configuration.

Example Configuration

<plugin>
   <groupId>net.sf.environments-maven-plugin</groupId>
   <artifactId>environments-maven-plugin</artifactId>
   <version>1.1.0-SNAPSHOT</version>
   <configuration>
      <excludeEnvironments>dev01, qa01 ,qa02,</excludeEnvironments>
      <parallel>true</parallel>
   </configuration>
   <executions>
      <execution>
         <goals>
            <goal>configuration</goal>
         </goals>
      </execution>
   </executions>
</plugin>


Doesn't Allow Manifest Customization

When war files are generated for different environments, there may be cases where it is necessary to add environment-specific manifest entries. multienv-maven-plugin doesn't provide this. One can do this easily with environments-maven-plugin using the environmentArchiveConfiguration tag in the plugin configuration.

You can have one configuration for all environments or have a configuration for each of the individual environments, as shown below.

For ease, the environment is already added to each war file. The manifest entry looks like this.

Environment: ci_local 

Example Configuration

<project>
  ...
<build>
   <plugins>
      <plugin>
         <groupId>net.sf.environments-maven-plugin</groupId>
         <artifactId>environments-maven-plugin</artifactId>
         <version>1.1.0-SNAPSHOT</version>
         <configuration>
            <excludeEnvironments>dev01, qa01</excludeEnvironments>
            <parallel>true</parallel>
            <archives>
               <environmentArchiveConfiguration>
                  <environment>dev02</environment>
                  <archive>
                     <manifestEntries>
                        <mode>development</mode>
                        <key>value</key>
                     </manifestEntries>
                  </archive>
               </environmentArchiveConfiguration>
               <environmentArchiveConfiguration>
                  <environment>prod01, prod02</environment>
                  <archive>
                     <manifestEntries>
                        <mode>development1</mode>
                        <key>value1</key>
                     </manifestEntries>
                  </archive>
               </environmentArchiveConfiguration>
            </archives>
         </configuration>
         <executions>
            <execution>
               <goals>
                  <goal>configuration</goal>
               </goals>
            </execution>
         </executions>
      </plugin>
   </plugins>
</build>
  ...
</project>


Doesn't Have Environment-Specific Filtering

environments-maven-plugin introduces the commonDir and filters tags. commonDir tag takes the path of a directory inside src/main/environnments. The common directory contains templates that are common to all environments. These templates can have variables that are enclosed by  @(@variable@).

The filters tag can have multiple filter tags. Each filter tag takes the name of a file.

When the wars are built, the plugin does the following.

  • Takes the template files from the common directory.
  • Retrieves the files with the names declared in filter tags from the environment directory. For example, if dev war is currently being built, the plugin tries to find the files from filter tags in the src/main/environments/dev directory.  
  • Merges all the key-value pairs from all the files in filter tags into a HashMap.  
  • Uses those key-value pairs from the HashMap to substitute variables in the template.  
  • Packages the files from the previous step in the dev war file.  
  • Also packages all the files from src/main/environments/${env} directory.

Example Configuration

<plugin>
   <groupId>net.sf.environments-maven-plugin</groupId>
   <artifactId>environments-maven-plugin</artifactId>
   <version>1.3.0-SNAPSHOT</version>
   <configuration>
      <commonDir>common</commonDir>
      <filters>
         <filter>ec.properties</filter>
      </filters>
   </configuration>
   <executions>
      <execution>
         <goals>
            <goal>environment</goal>
         </goals>
      </execution>
   </executions>
</plugin>


The image below illustrates the file/directory naming/structure.

Image title

For filtering to work, both commonDir and filters tags should be declared.

Doesn't Provide the Facility to Place the Resource Files in a Specific Directory Inside the War File

 Resource files usually belong in WEB-INF/classes directory inside the war file. To achieve this in multimaven-maven-plugin, one would have to create WEB-INF/classes directory in each of the environments inside src/main/environments and then place the resource files inside them.  As shown below this is redundant and ugly.


  • src
    • main
      • environments
        • dev
          • WEB-INF
            • classes
              • files
        • dev_local
          • WEB-INF
            • classes
              • files
        • ci
          • WEB-INF
            • classes
              • files
        • ci_local
          • WEB-INF
            • classes
              • files


To solve this, environments-maven-plugin introduces a new tag called targetPath. If this tag is declared with a directory path for value, the resources files packaged in the war are placed inside the directory. So. it looks like this.

  • app_dev.jar  
    • WEB-INF
      • classes
        • files
  • app_dev_local.jar
    • WEB-INF
      • classes
        • files
  • app_ci.jar
    • WEB-INF
      • classes
        • files
  • app_ci_local.jar
    • WEB-INF
      • classes
        • files

So the directory structure looks like this in that case.

  • src
    • main
      • environments
        • dev
          • files
        • dev_local
          • files
        • ci
          • files
        • ci_local
          • files


Example Configuration

<plugin>
   <groupId>net.sf.environments-maven-plugin</groupId>
   <artifactId>environments-maven-plugin</artifactId>
   <version>1.1.0-SNAPSHOT</version>
   <configuration>
      <targetPath>WEB-INF/classes</targetPath>
   </configuration>
   <executions>
      <execution>
         <goals>
            <goal>environment</goal>
         </goals>
      </execution>
   </executions>
</plugin>


Doesn't Allow Building a Single Environment

multienv-maven-plugin doesn't provide the facility to build a single environment. The result is that one will have to maintain an entirely separate set-up just for individual environments. environments-maven-plugin solves this problem with a command line option -Dem.env. The value of the option is the directory name of the environment of interest in src/main/environment.

 mvn clean install -Dem.env=dev_local 

Conclusion

environments-maven-plugin is a fork of mutlienv-maven-plugin. I did submit pull requests to multienv-maven-plugin, but either I said something the kind gentleman didn't want to hear or he heard something I didn't say. The net result is the pull requests didn't get approved. So I had to fork it.

There are issues with 1.0, 1.1, and 1.2. Please use the latest version: 1.3.

Project Page: https://sourceforge.net/projects/environments-maven-plugin/
Source Code: https://sourceforge.net/p/environments-maven-plugin/code/ci/master/tree/
Overview page: https://environments-maven-plugin.sourceforge.io/index.html

Lastly, the plugin is in Maven Central.

If you feel like asking why not GitHub, the answer is pretty simple— that bandwagon is already too crowded.

Topics:
maven ,java ,plugins

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}