Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using maven to build multiple resources assemblies that are very similar

I'm having a problem with this very redundant maven configuration.

The application I'm working on sometimes gets built for environments that need alternate resource bundles. The current way the resources are prepared for deployment is that they are added to a single .zip file. The build master then deploys the zipped resources to the server. For some environments, alternate versions of some of the resources need to be used. The folder structure in the project looks like this:

src/main/resources
  - resource1
  - resource2
  - resource2
  ENV1/
    -resource1 (environment-specific)
  ENV2/
    -resource1 (environment-specific)
    -resource3 (environment-specific)

For most environments, the resource zip file needs to contain the files resource1, resource2, resource3. For ENV1, the zip file needs to contain ENV1/resource1, resource2, resource3. For ENV3, the zip file needs ENV2/resource1, resource2, ENV2/resource3.

I am currently doing this with an assembly descriptor for each environment, and a separate execution in my POM file:

        <plugin>
            <artifactId>maven-assembly-plugin</artifactId>
            <version>2.4</version>
            <executions>
                <execution>
                    <id>zip-normal-resources</id>
                    <phase>package</phase>
                    <goals>
                        <goal>single</goal>
                    </goals>
                    <configuration>
                        <descriptor>assembly-descriptor.xml</descriptor>
                    </configuration>
                </execution>
                <execution>
                    <id>zip-ENV1-resources</id>
                    <phase>package</phase>
                    <goals>
                        <goal>single</goal>
                    </goals>
                    <configuration>
                        <descriptor>assembly-descriptor-ENV1.xml</descriptor>
                    </configuration>
                </execution>

And each descriptor looks very similar. The "normal" assembly desrciptor:

<assembly
    xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 "
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance "
    xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2
                         http://maven.apache.org/xsd/assembly-1.1.2.xsd ">
    <id>Resources</id>
    <includeBaseDirectory>false</includeBaseDirectory>
    <formats>
        <format>zip</format>
    </formats>
    <fileSets>
        <fileSet>
            <directory>src/main/resources</directory>
            <includes>
                <include>*.properties</include>
                <include>*.xml</include>
            </includes>
            <outputDirectory>/</outputDirectory>
            <filtered>true</filtered>
        </fileSet>

        <fileSet>
            <directory>${project.build.outputDirectory}/resources</directory>
            <outputDirectory>/</outputDirectory>
            <includes>
                <include>**/*</include>
            </includes>
        </fileSet>
    </fileSets>
</assembly>

An environment-specific descriptor:

<assembly
    xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 "
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance "
    xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2
                         http://maven.apache.org/xsd/assembly-1.1.2.xsd ">
    <id>Resources-ENV1</id>
    <includeBaseDirectory>false</includeBaseDirectory>
    <formats>
        <format>zip</format>
    </formats>
    <fileSets>
        <fileSet>
            <directory>src/main/resources</directory>
            <includes>
                <include>*.properties</include>
                <include>*.xml</include>
            </includes>
                    <!-- exclude environment-specific files -->
                    <excludes>
                        <exclude>resource1</exclude>
                    </excludes>
            <outputDirectory>/</outputDirectory>
            <filtered>true</filtered>
        </fileSet>
        <fileSet>
            <directory>src/main/resources/ENV1</directory>
            <includes>
                <include>*.properties</include>
                <include>*.xml</include>
            </includes>
            <outputDirectory>/</outputDirectory>
            <filtered>true</filtered>
        </fileSet>
        <fileSet>
            <directory>${project.build.outputDirectory}/resources</directory>
            <outputDirectory>/</outputDirectory>
            <includes>
                <include>**/*</include>
            </includes>
        </fileSet>
    </fileSets>
</assembly>

This solution works but it feels very inefficient. I don't like having multiple assemblies for each environment that are almost identical, except for the environment names. Is there any way to streamline this?

like image 974
FrustratedWithFormsDesigner Avatar asked Oct 28 '13 14:10

FrustratedWithFormsDesigner


1 Answers

Assuming the following structure:

src/
└── main
    ├── assembly
    │   └── iterator.xml
    └── environment
        ├── dev
        │   └── server.properties
        ├── pretest
        │   └── server.properties
        ├── production
        │   └── server.properties
        ├── qa
        │   └── server.properties
        └── test
            └── server.properties

where you can use the following assembly-descriptor like this:

<assembly>
  <id>${item}</id>
  <formats>
    <format>war</format>
  </formats>
  <includeBaseDirectory>false</includeBaseDirectory>
  <dependencySets>
    <dependencySet>
      <unpack>true</unpack>
      <useProjectArtifact>false</useProjectArtifact>
    </dependencySet>
  </dependencySets>
  <fileSets>
    <fileSet>
      <outputDirectory>WEB-INF</outputDirectory>
      <directory>${basedir}/src/main/environment/${item}/</directory>
      <includes>
        <include>**</include>
      </includes>
    </fileSet>
  <fileSet>
      <outputDirectory>WEB-INF</outputDirectory>
      <directory>${project.build.directory}/environment/${item}</directory>
      <includes>
        <include>**</include>
      </includes>
  </fileSet>
  </fileSets>
</assembly>

using the iterator-maven-plugin will solve the problem:

  <build>
    <plugins>
      <plugin>
        <groupId>com.soebes.maven.plugins</groupId>
        <artifactId>iterator-maven-plugin</artifactId>
        <version>0.2</version>
        <executions>
          <execution>
            <phase>package</phase>
            <goals>
              <goal>executor</goal>
            </goals>
            <configuration>
              <items>
                <item>dev</item>
                <item>test</item>
                <item>qa</item>
                <item>production</item>
                <item>pretest</item>
              </items>
              <pluginExecutors>
                <pluginExecutor>
                  <goal>single</goal>
                  <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-assembly-plugin</artifactId>
                  </plugin>
                  <configuration>
                    <descriptors>
                      <descriptor>${project.basedir}/src/main/assembly/iterator.xml</descriptor>
                    </descriptors>
                  </configuration>
                </pluginExecutor>
              </pluginExecutors>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>

The iterator-maven-plugin is available via maven central. I think you can adapt the above configuration/structure to your problem.

like image 177
khmarbaise Avatar answered Oct 04 '22 18:10

khmarbaise