Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Maven 3 profile with extensions

My question had been addressed in this thread, but the explanation is not clear.

I have this build definition in one of my pom.xml files:

<build>
    <finalName>${my.project}</finalName>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>2.0</version>
            <configuration>
                <source>1.6</source>
                <target>1.6</target>
            </configuration>
        </plugin>
    </plugins>
    <extensions>
        <extension>
            <groupId>org.kuali.maven.wagons</groupId>
            <artifactId>maven-s3-wagon</artifactId>
            <version>1.1.19</version>
        </extension>
    </extensions>
    <resources>
        <resource>
            <directory>src/main/resources</directory>
            <filtering>true</filtering>
            <includes>
                <include>**/settings.properties</include>
            </includes>
        </resource>
    </resources>
</build>

Notice that I'm using the maven-s3-wagon extension. Next, I would like to have 2 different profiles, each with it's own settings, plugins and extensions but maven does not allow the extensions tag under a profile.

When I try using a profile:

<profiles>
    <profile>
        <id>local-build</id>
        <activation>
            <activeByDefault>true</activeByDefault>
        </activation>
        <build>
            <finalName>${my.project}</finalName>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>2.0</version>
                    <configuration>
                        <source>1.6</source>
                        <target>1.6</target>
                    </configuration>
                </plugin>
            </plugins>
            <extensions>
                <extension>
                    <groupId>org.kuali.maven.wagons</groupId>
                    <artifactId>maven-s3-wagon</artifactId>
                    <version>1.1.19</version>
                </extension>
            </extensions>
            <resources>
                <resource>
                    <directory>src/main/resources</directory>
                    <filtering>true</filtering>
                    <includes>
                        <include>**/settings.properties</include>
                    </includes>
                </resource>
            </resources>
        </build>
    </profile>
</profiles>

I get a an error in my pom:

cvc-complex-type.2.4.a: Invalid content was found starting with element 'extensions'. One of '{"http://maven.apache.org/POM/4.0.0":defaultGoal, "http://maven.apache.org/POM/
 4.0.0":resources, "http://maven.apache.org/POM/4.0.0":testResources, "http://maven.apache.org/POM/4.0.0":directory, "http://maven.apache.org/POM/4.0.0":filters, "http://
 maven.apache.org/POM/4.0.0":pluginManagement}' is expected.

Question So using the extension tag means I can't use profiles? How can I use or change build extensions via profile?

like image 470
forhas Avatar asked Jul 14 '13 13:07

forhas


People also ask

How do I run a specific profile in Maven?

Profiles can be activated in the Maven settings, via the <activeProfiles> section. This section takes a list of <activeProfile> elements, each containing a profile-id inside. Profiles listed in the <activeProfiles> tag would be activated by default every time a project use it.

Is it possible to add library dependencies inside a profile in Maven?

Within each profile element, we can configure many elements such as dependencies, plugins, resources, finalName. So, for the example above, we could add plugins and their dependencies separately for integration-tests and mutation-tests.

Can Maven profile be defined in POM xml?

Using a build profile, you can customize build for different environments such as Production v/s Development environments. Profiles are specified in pom. xml file using its activeProfiles/profiles elements and are triggered in variety of ways.


1 Answers

Indeed, the official Maven POM reference is not clear about the possible usage of extensions as part of a Maven profile, since it states you can have a build element within it, but not what of the build section.

However, the official Maven model effectively filters and provides what of the build section you can actually use within a profile section. And indeed extensions is not there.

However, what are Maven extensions? Build/Lifecycle enhancement, but also (and essentially): a library added to the runtime classpath of the Maven build, which participates to the build, but it is not packaged with the final artifact.

Hence, in such a scenario (if you need to have extensions in profile or have a profile to change/add an extension) you could use the following trick:

  • Have an harmless extension as default extension of your build (where harmless means whatever library which could be part of your build classpath and essentially not affect it at all)
  • Have properties defining the GAV coordinates (GroupId, ArtifactId, Version) of this extension
  • Have a profile which overrides these properties with the desired (useful) extension

As an example, given the following sample POM:

<project>
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.sample</groupId>
    <artifactId>project</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <properties>
        <extension.groupId>junit</extension.groupId>
        <extension.artifactId>junit</extension.artifactId>
        <extension.version>4.11</extension.version>
    </properties>

    <build>
        <extensions>
            <extension>
                <groupId>${extension.groupId}</groupId>
                <artifactId>${extension.artifactId}</artifactId>
                <version>${extension.version}</version>
            </extension>
        </extensions>
    </build>

    <profiles>
        <profile>
            <id>customize-extension</id>
            <properties>
                <extension.groupId>junit</extension.groupId>
                <extension.artifactId>junit</extension.artifactId>
                <extension.version>4.12</extension.version>
            </properties>
        </profile>
    </profiles>

</project>

The default build (without the customize-extension profile activated), would use the default defined properties and as such add junit as build extension: this is harmless (although it may create conflicts with another junit version of your build, so make sure you use the same version of use an even more harmless library for that).

You can check Maven will pick it up by running a really first build phase, just to check information in our case, and enable the debug flag:

mvn initialize -X

And checking as part of the build log:

[DEBUG] Populating class realm extension>junit:junit:4.11   
[DEBUG]   Included: junit:junit:jar:4.11   

Now let's use our trick: let's add (change) a build extension via profile:

mvn initialize -X -Pcustomize-extension

And as part of our build log we would have:

[DEBUG] Populating class realm extension>junit:junit:4.12   
[DEBUG]   Included: junit:junit:jar:4.12   

Bingo. Maven picked up a different extension (in this case, a different version, the 4.12) and we succeeded on changing (or actually adding a meaningful) build extension via profile.

like image 147
A_Di-Matteo Avatar answered Sep 21 '22 04:09

A_Di-Matteo