Maven 3 profile with extensions
Asked Answered
D

3

11

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?

Deina answered 14/7, 2013 at 13:23 Comment(0)
M
8

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.

Mornay answered 27/3, 2016 at 21:41 Comment(0)
S
1

Just a crazy idea: use modules

Define a parent pom like this:

<groupId>org.example</groupId>
<artifactId>my-parent</artifactId>
<version>1.0</version>
<packaging>pom</packaging>
<profiles>
    <profile>
        <id>use-pom1</id>
        <modules>
            <module>pom1</module>
        </modules>
    </profile>
    <profile>
        <id>use-pom2</id>
        <modules>
            <module>pom2</module>
        </modules>
    </profile>
</profiles>

Define the desired extensions on pom1 and pom2.

Safekeeping answered 24/7, 2013 at 3:29 Comment(2)
Indeed an interesting idea but it could complicate stuff. Since this is a production system on stake I'm trying to find a more simple\stable\official\tested solution. Thanks thougthDeina
Well, you could try to use maven-assembly-plugin, using a descriptor.xml. But I doubt it would do what your extensions do.Safekeeping
F
0

I think the solution is here http://maven.apache.org/guides/mini/guide-using-extensions.html

Define a build section where extensions are defined and then into the profile set the attribute true ( like in the second profile shown below )

<build>
    <extensions>
        <extension>
            <groupId>org.apache.maven.wagon</groupId>
            <artifactId>wagon-ssh</artifactId>
            <version>2.9</version>
        </extension>
    </extensions>
</build>

<profiles>
    <profile>
        <id>create-default</id>
        <activation>
            <activeByDefault>true</activeByDefault>
            <property>
                <name>build</name>
                <value>full</value>
            </property>
        </activation>
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                    <executions>
                        <execution>
                            <goals>
                                <goal>repackage</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </build>
    </profile>

    <profile>
        <id>create-core</id>
        <activation>
            <property>
                <name>build</name>
                <value>full</value>
            </property>
        </activation>
        <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-jar-plugin</artifactId>
                    <extensions>true</extensions>
                    <version>2.6</version>
                    <configuration>
                        <finalName>import-station-core-${project.version}</finalName>
                    </configuration>
                    <executions>
                        <execution>
                            <id>make-jar</id>
                            <phase>package</phase>
                            <goals>
                                <goal>jar</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </build>
    </profile>
</profiles>
Felucca answered 9/12, 2016 at 13:12 Comment(1)
Here what do you mean by "and then into the profile set the attribute true ( like in the second profile shown below )" can you specify the tag name you are talking about here in the second profile? It will be helpful. Or else, if i simply keep a build outside the profiles and dont add anything specific in the profiles (not setting any attributes as such) will it work? ThanksUnyoke

© 2022 - 2024 — McMap. All rights reserved.