Modifying resources inside a war overlay in maven

M1EK picture M1EK · May 31, 2012 · Viewed 8k times · Source

I have this setup currently:

Project A outputs a war file - has a configuration file (WEB-INF/web.xml). We've been delivering this with a commented out section of configuration which gets uncommented manually when the project is deployed in a particular environment.

Needs of the project have changed - and I need Project A to be built without that section of configuration entirely; and I need another project (Project B) to be built WITH that section of configuration (enabled, not commented out).

Rather than having the file exist in both projects (dual maintenance), I had hoped I could have Project B depend on Project A (via war overlay), and then use the maven-config-processor-plugin to add my special config to WEB-INF/web.xml, then re-package the war file.

This doesn't seem to work - though - the config modification can work if the target already exists (i.e. after the previous run), but when I run everything together, the overlay and repackaging into the new war happens together - and I can't figure out any way to make the config-processor plugin operate in the middle. Basically, the default order ends up being "config-processor" (which fails because the overlay hasn't happened yet), then "war" (all as one unit). I can't make the config-processor happen after the overlay but before the war is fully packaged.

Multiple people on the internets have asked over the last few years if there is a way to inject a plugin in between the "unpack the overlay" and "repack the war file" steps, but nobody has seemingly answered this definitively either way. Any ideas?

Answer

matts picture matts · May 31, 2012

Since war overlays and war packaging all seems to happen as part of a single goal, I don't think there's a way to get in the middle of it. As a workaround, you could extract web.xml in an earlier phase and process it. The maven-dependency-plugin can be used in Project B to extract web.xml from Project A into a work directory, then run maven-config-processor-plugin on web.xml and place the result somewhere else, then instruct maven-war-plugin to include that processed web.xml before overlays. In Project B's POM:

<plugins>
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-dependency-plugin</artifactId>
        <version>2.4</version>
        <executions>
            <!-- Extract web.xml from Project A -->
            <execution>
                <id>unpack-webxml</id>
                <phase>generate-resources</phase>
                <goals>
                    <goal>unpack</goal>
                </goals>
                <configuration>
                    <artifactItems>
                        <artifactItem>
                            <groupId>your.group</groupId>
                            <artifactId>project.a</artifactId>
                            <version>...</version>
                            <type>war</type>
                            <overWrite>true</overWrite>
                            <outputDirectory>${project.build.directory}/myconfig/work</outputDirectory>
                            <includes>WEB-INF/web.xml</includes>
                        </artifactItem>
                    </artifactItems>
                </configuration>
            </execution>
        </executions>
    </plugin>
    <plugin>
        <groupId>com.google.code.maven-config-processor-plugin</groupId>
        <artifactId>maven-config-processor-plugin</artifactId>
        <version>2.0</version>
        <executions>
            <!-- Process extracted web.xml and place in temp build directory -->
            <execution>
                <id>process-webxml</id>
                <goals>
                    <goal>process</goal>
                </goals>
                <configuration>
                    <outputDirectory>${project.build.directory}/myconfig/build</outputDirectory>
                    <transformations>
                        <transformation>
                            <input>${project.build.directory}/myconfig/work/WEB-INF/web.xml</input>
                            <output>WEB-INF/web.xml</output>
                            <!-- your transformation config -->
                        </transformation>
                    </transformations>
                </configuration>
            </execution>
        </executions>
    </plugin>
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-war-plugin</artifactId>
        <version>2.1.1</version>
        <configuration>
            <webResources>
                <!-- Instruct war plugin to include temp build directory in webapp -->
                <resource>
                    <directory>${project.build.directory}/myconfig/build</directory>
                    <includes>
                        <include>**</include>
                    </includes>
                </resource>
            </webResources>
            <overlays>
                <!-- Overlay customization if needed -->
            </overlays>
        </configuration>
    </plugin>
</plugins>

As far as I can tell, the war plugin includes webResources first, followed by src/main/webapp, followed by overlays.

I'm not familiar with maven-config-processor-plugin, so I apologize if my configuration there is not correct.