Malaz Albawarshi
Malaz Albawarshi

Reputation: 49

How to execute maven Plugins multiple times

I am using Properties Maven Plugin to read some Properties, after execute this plugin I execute another Plugin, after that I want to execute this plugin again with different configuration

<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>properties-maven-plugin</artifactId>
    <version>1.0.0</version>
    <executions>
        <execution>
            <phase>initialize</phase>
            <goals>
                <goal>read-project-properties</goal>
            </goals>
            <configuration>
                <files>
                    <file>src/Args.properties</file>
                </files>
            </configuration>
        </execution>
  </executions>
</plugin>

execute maven-antrun-plugin and then recall this plugin with configuration "src/Args2.properties", because with last plugin i declared a new properties, and it's used in file "Args2.properties

<plugin>
    <artifactId>maven-antrun-plugin</artifactId>
    <version>1.3</version>
    <executions>
        <execution>
            <phase>package</phase>
            <goals>
                <goal>run</goal>
            </goals>
            <configuration>
                <tasks>
                    <taskdef resource="net/sf/antcontrib/antcontrib.properties"
                             classpathref="maven.plugin.classpath"/>

                    <if>
                        <equals arg1="${serviceType}" arg2="none"/>
                        <then>
                            <property name="prop" value="x"/>
                        </then>
                        <else>
                           <property name="prop"value="y"/>
                        </else>
                    </if>
                </tasks>
            </configuration>
        </execution>
    </executions>
</plugin>

and Args2.properties :

prop2=${prop}/anotherValue

i want after giving a value to prop in Antrun plugin to read prop2 later from the file Args2

Upvotes: 0

Views: 2899

Answers (1)

Tunaki
Tunaki

Reputation: 137064

Having another execution of a Maven plugin in the build is simply done by specifying another <execution> block, and not by specifying the plugin twice in the POM:

<plugin>
  <groupId>my.groupid</groupId>
  <artifactId>my-plugin</artifactId>
  <version>version</version>
  <executions>
    <execution>
      <id>execution-1</id>
      <phase>initialize</phase>
      <!-- goals and configuration for this execution -->
    </execution>
    <execution>
      <id>execution-2</id>
      <phase>test</phase>
      <!-- goals and configuration for this execution -->
    </execution>
  </executions>
</plugin>

For example, the configuration above would define two execution of a plugin, where the first is bound to the initialize phase, while the other is bound to the test phase. When 2 executions are bound to the same phase, they will be executed in their declaration order in the POM: this means that even if execution-2 would be bound to the initialize phase, just like execution-1, it would be executed after execution-1.

In your case, you have something not really conventional of reading multiple properties file in the build but somehow interleaving an execution of the maven-antrun-plugin plugin in between. This is troublesome, because, since you cannot declare the plugin twice in the POM, it isn't possible to insert an execution of a plugin A between two executions of another plugin B, all at the same phase. This is normal, since executions at a given phase are executed in the declaration order in the POM, and plugins have to be declared once; so either A is before B in the POM, and it'll be executed before, which isn't wanted (since one execution of B needed to be run before), or B is before A, and the 2 executions of B will be executed before the one of A, which isn't wanted either (since the execution of A needed to happen in between).

One way to solve this is to bind the executions to different phases: e.g. make sure that the execution of B we want to run first is bound to a certain phase, and that the execution of A we want to run after is bound to a phase that happens later in the build, and finally that the last execution of B is also bound to a later phase. This isn't a clean solution though, because you end-up abusing certain phases to do things that shouldn't be done at this time.

A better solution is to accept the fact that what we really want to do in a single step with a single execution: i.e. load a properties, do things, load another properties, in the same execution. They are so tied together that it makes sense to integrate them together as well. This cannot always be done easily -- typically, you would need to create your own Maven plugin to do this, so that all thoses tasks are encapsulated by it.

However, in this specific case, you could just reuse the maven-antrun-plugin and do everything inside an execution of this plugin. Ant has a task loadproperties that can be used to load the properties file, before and after setting the prop property.

<plugin>
  <artifactId>maven-antrun-plugin</artifactId>
  <version>1.8</version>
  <executions>
    <execution>
      <id>load-properties</id>
      <phase>initialize</phase>
      <goals>
        <goal>run</goal>
      </goals>
      <configuration>
        <target>
          <loadproperties srcFile="${project.basedir}/src/Args.properties" />
          <taskdef resource="net/sf/antcontrib/antcontrib.properties"
            classpathref="maven.plugin.classpath" />
          <if>
            <equals arg1="${serviceType}" arg2="none" />
            <then>
              <property name="prop" value="x" />
            </then>
            <else>
              <property name="prop" value="y" />
            </else>
          </if>
          <loadproperties srcFile="${project.basedir}/src/Args2.properties" />
        </target>
        <exportAntProperties>true</exportAntProperties>
      </configuration>
    </execution>
  </executions>
  <dependencies>
    <dependency>
      <groupId>ant-contrib</groupId>
      <artifactId>ant-contrib</artifactId>
      <version>1.0b3</version>
      <exclusions>
        <exclusion>
          <groupId>ant</groupId>
          <artifactId>ant</artifactId>
        </exclusion>
      </exclusions>
    </dependency>
  </dependencies>
</plugin>

A couple of notes with the declaration above: the plugin was updated to the latest version of 1.8 and the dependency to ant-contrib is needed to resolve the antcontrib.properties file. ant needs to be excluded from the dependency to ant-contrib because the AntRun plugin uses Ant 1.9, but that dependency would make the plugin inherit an older version. Note also the <exportAntProperties> which will enable your build to use the properties created in the Ant task, and the use of <target> instead of the deprecated <tasks>.

Upvotes: 5

Related Questions