maven-replacer-plugin to replace tokens in build and not source

10,818

You can use the exploded goal of the maven-war-plugin to get to a temporary folder (like whatever created under target actually) the exploded version of what would later on be part of the final war file, then execute the replacer plugin on this file (a safe copy, not in conflict with other plugins consuming the file).

This approach is actually also documented by the official replacer plugin doc

That is, having a similar configuration:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-war-plugin</artifactId>
    <version>2.6</version>
    <configuration>
        <useCache>true</useCache>
    </configuration>
    <executions>
        <execution>
            <id>prepare-war</id>
            <phase>prepare-package</phase>
            <goals>
                <goal>exploded</goal>
            </goals>
        </execution>
    </executions>
</plugin>

<plugin>
    <groupId>com.google.code.maven-replacer-plugin</groupId>
    <artifactId>replacer</artifactId>
    <version>1.5.2</version>
    <executions>
        <execution>
            <phase>prepare-package</phase>
            <goals>
                <goal>replace</goal>
            </goals> 
        </execution>
    </executions>
    <configuration>
        <file>${project.build.directory}/${project.build.finalName}/WEB-INF/web.xml</file>
        <token>@@sec.level@@</token>
        <value>local</value>
    </configuration>
</plugin>

Note: the replacer documentation also suggests to use the useCache option which should prevent the plugin to override what the exploded goal previously created. However, the option doesn't really suit this purpose.


Similarly, the following approach would instead work according to my tests:

  • Use the exploded goal of the maven-war-plugin to create a temporary copy of the future war file in a <war_name>-tmp directory under target: that's not an issue, whatever is under target is supposed to be discarded via a clean command anyway
  • Configure the replacer plugin to replace that copy of the web.xml file
  • Configure the default war goal using its webXml option to point to that web.xml file for its final war file

The following would apply the approach described above:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-war-plugin</artifactId>
    <version>2.6</version>
    <executions>
        <execution>
            <!-- explode the future war content for pre-package processing -->
            <id>prepare-war</id>
            <phase>prepare-package</phase>
            <goals>
                <goal>exploded</goal>
            </goals>
            <configuration>
                <webappDirectory>${project.build.directory}/${project.build.finalName}-tmp</webappDirectory>
            </configuration>
        </execution>
        <execution>
            <!-- use the same execution id to further configure the default binding and execution -->
            <id>default-war</id>
            <phase>package</phase>
            <goals>
                <goal>war</goal>
            </goals>
            <configuration>
                <!-- during the package phase, use the processed web.xml file -->
                <webXml>${project.build.directory}/${project.build.finalName}-tmp/WEB-INF/web.xml</webXml>
            </configuration>
        </execution>
    </executions>
</plugin>

<plugin>
    <groupId>com.google.code.maven-replacer-plugin</groupId>
    <artifactId>replacer</artifactId>
    <version>1.5.2</version>
    <executions>
        <execution>
            <!-- apply pre-package processing on web resources -->
            <id>process-web-resources</id>
            <phase>prepare-package</phase>
            <goals>
                <goal>replace</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <file>${project.build.directory}/${project.build.finalName}-tmp/WEB-INF/web.xml</file>
        <token>@@test@@</token>
        <value>local</value>
    </configuration>
</plugin>
Share:
10,818
amphibient
Author by

amphibient

Software Engineer with table manners

Updated on June 04, 2022

Comments

  • amphibient
    amphibient almost 2 years

    I am trying to use the maven-replacer-plugin to replace tokens in my web.xml when it is built in the WAR file but not in the source, which would remove the tokens for subsequent builds and show the file as changed relative to the version control repository.

    Currently, I am only able to change the file in the source, which does not meet my requirement:

    <plugin>
        <groupId>com.google.code.maven-replacer-plugin</groupId>
        <artifactId>replacer</artifactId>
        <version>1.5.2</version>
        <executions>
            <execution>
                <phase>prepare-package</phase>
                <goals>
                    <goal>replace</goal>
                </goals>
            </execution>
        </executions>
        <configuration>
            <file>${project.basedir}/src/main/webapp/WEB-INF/web.xml</file>
            <replacements>
                <replacement>
                    <token>@@sec.level@@</token>
                    <value>local</value>
                </replacement>
            </replacements>
        </configuration>
    </plugin>
    

    Question: How can I run the replacer to only change the file in the WAR package while leaving the source unchanged for subsequent builds?

  • amphibient
    amphibient over 7 years
    I already have a plugin declaration for maven-war-plugin in my build declaration. Should i just modify the existing one to add the executions or do I need a whole new declaration ?
  • A_Di-Matteo
    A_Di-Matteo over 7 years
    you can add additional executios to the same plugin declaration, also note the global configuration I just added with my latest update
  • amphibient
    amphibient over 7 years
    my ${project.build.directory}/${project.build.finalName}/WEB-IN‌​F/web.xml does not exist. my target dir contains only classes, generated-sources, and test-classes. IOW, I can't find the web.xml in the target
  • A_Di-Matteo
    A_Di-Matteo over 7 years
    @amphibient I updated my answer with a working (tested) approach, hope it helps