Search code examples
mavenoverlaymaven-war-plugin

Modifying resources inside a war overlay in maven


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?


Solution

  • 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.