Search code examples
mavenmaven-3pom.xmlmaven-war-pluginmaven-antrun-plugin

Run ant task in maven build phase before war is packaged?


When deploying a webapp I need to concat some files, currently this is achieved via an ant task. I'm trying to run this task in the maven build process using something like the following:

<plugin>
    <artifactId>maven-antrun-plugin</artifactId>
    <version>1.7</version>
    <executions>
        <execution>
            <phase>package</phase>
            <configuration>
                <target>
                    <move file="${project.build.directory}/${project.name}-${project.version}/WEB-INF/classes/log4j.dev.properties"
                        tofile="${project.build.directory}/${project.name}-${project.version}/WEB-INF/classes/log4j.properties" />

                    <move file="${project.build.directory}/${project.name}-${project.version}/WEB-INF/classes/hibernate.cfg.dev.xml"
                        tofile="${project.build.directory}/${project.name}-${project.version}/WEB-INF/classes/hibernate.cfg.xml" />
                    <delete>
                        <fileset dir="${project.build.directory}/${project.name}-${project.version}/WEB-INF/classes/"
                            includes="**/hibernate.cfg.*.xml" />
                        <fileset dir="${project.build.directory}/${project.name}-${project.version}/WEB-INF/classes/"
                            includes="**/log4j.*.properties" />     
                    </delete>
                </target>
            </configuration>
            <goals>
                <goal>run</goal>
            </goals>
        </execution>
    </executions>
</plugin>

The above fails because the files have not yet been copied/deleted into target directory. If I set the phase to "package" the ant task runs fine and all the files are copied/deleted, but it's no help as the .war has already been built before the ant target is run.

Basically, I need to run my ant target near the end of the prepare-package phase.

Having looked though the Lifecycle Reference I can't workout how to expose the more granular Goals to the antrun plugin.

Question: How to achieve this scenario?


Solution

  • Rather then executing it at the end of the prepare-package phase, you probably want to execute it within the package phase but before the war packaging (via the Maven War Plugin).

    A possible solution is as possible:

    • Disable the default Maven War Plugin
    • Add your execution within the package phase
    • Add a new Maven War Plugin execution for the package phase

    Since Maven will execute plugins within the same phase by the declaration order, you would then have your ant execution first, then the war packaging.

    Executing the following:

    mvn help:effective-pom
    

    You can check that by default the war packaging already configures a Maven War Plugin execution for us:

    <plugin>
        <artifactId>maven-war-plugin</artifactId>
        <version>2.2</version>
        <executions>
            <execution>
                <id>default-war</id>
                <phase>package</phase>
                <goals>
                    <goal>war</goal>
                </goals>
            </execution>
        </executions>
    </plugin>
    

    We could then add to our POM the following after the maven-antrun-plugin declaration:

    <plugin>
        <artifactId>maven-war-plugin</artifactId>
        <version>2.2</version>
        <executions>
            <execution>
                <id>default-war</id>
                <phase>none</phase>
                <goals>
                    <goal>war</goal>
                </goals>
            </execution>
            <execution>
                <id>package-war</id>
                <phase>package</phase>
                <goals>
                    <goal>war</goal>
                </goals>
            </execution>
        </executions>
    </plugin>
    

    Note: we are actually using the same default execution id and binding it to a non existing phase (none) and as such disabling it; then we are adding a new execution (the package-war id), which will be executed by Maven after your maven-antrun-plugin execution but still within the package phase.

    Note that the declaration order is really important to achieve your goal, so better to also add a comment (for colleagues, if any, and for the future yourself).


    Further note: it seems you are swapping dev files with prod-like files, you could probably achieve the same via Maven profiles and Maven resource filtering delegating to properties values the differences between environments and as such avoid swapping files.

    Check this SO post for some hints if interested in this alternative approach.