Calling foreach in maven-antrun-plugin

Brian Nickel picture Brian Nickel · May 24, 2012 · Viewed 7.5k times · Source

I'm trying to set up maven to execute the LESS CSS preprocessor on a directory in my web project. The basic flow is:

  1. Maven calls maven-antrun-plugin.
  2. Ant-contrib <foreach/> loops through a directory and finds all the .less files and calls a target.
  3. The target executes Rhino, which executes LESS which converts the file.

To do this, I have the following XML:

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-antrun-plugin</artifactId>
            <version>1.7</version>
            <executions>
                <execution>
                    <phase>compile</phase>
                    <configuration>
                        <target name="processLessFile">
                            <!-- ... -->
                        </target>
                        <target name="main">
                            <taskdef resource="net/sf/antcontrib/antcontrib.properties" classpathref="maven.plugin.classpath"/>
                            <property name="css.dir" location="src/main/webapp/css"/>
                            <foreach param="file" target="processLessFile">
                                <fileset dir="${css.dir}">
                                    <filename name="**/*.less" />
                                </fileset>
                            </foreach>
                        </target>
                    </configuration>
                    <goals>
                        <goal>run</goal>
                    </goals>
                </execution>
            </executions>
            <dependencies>
                <dependency>
                    <groupId>ant</groupId>
                    <artifactId>ant-contrib</artifactId>
                    <version>1.0b2</version>
                </dependency>
            </dependencies>
        </plugin>

The problem I'm encountering is that the "main" target starts to execute but then fails in <foreach>:

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-antrun-plugin:1.7:run (default) on project model-web-project: An Ant BuildException has occured: The following error occurred while executing this line:
[ERROR] /Users/.../pom.xml:4: Unexpected element "{http://maven.apache.org/POM/4.0.0}project" {antlib:org.apache.tools.ant}project
[ERROR] around Ant part ...<foreach param="file" target="processLessFile">... @ 6:50 in /Users/.../target/antrun/build-main.xml
[ERROR] -> [Help 1]

It appears that something in Ant is causing it to try read the POM file, possibly looking for the target. I see that both targets were generated into files target/antrun/build-main.xml and target/antrun/build-processLessFile.xml so that is the directory it should be looking in.

Answer

Mark O&#39;Connor picture Mark O'Connor · May 24, 2012

The ant plugin does not appear to support the declaration of more than one target section. You can check the generated ANT script to see what I'm talking about:

target/antrun/build-main.xml

Digging deeper the plug-in documentation states the following:

It is not the intention of this plugin to provide a means of polluting the POM, so it's encouraged to move all your Ant tasks to a build.xml file and just call it from the POM using Ant's task.

Harsh words, but the advice is sound. I'd recommend moving your ANT logic into a dedicated file and invoke it as follows:

        <plugin>
            <artifactId>maven-antrun-plugin</artifactId>
            <version>1.7</version>
            <executions>
                <execution>
                    <phase>compile</phase>
                    <configuration>
                        <target>
                            <ant antfile="${basedir}/src/main/ant/build.xml"/>
                        </target>
                    </configuration>
                    <goals>
                        <goal>run</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>