17

Import maven plugin configuration by composition rather than inheritance. Can it be done with build extensions?

I have used maven for more than 3 years and there's one shortcoming that has always bugged me. It's time to find a solution for that already.

The problem:

I have a "daddy" maven module with 3 children: "boy", "girl", and "kid". Each of these children must have its own distinct set of plugin configurations for a default "clean install" build. I don't want to put that configuration on the children's poms. I'd rather put it somewhere that I can reuse later.

I have tried using profiles for that, and it doesn't work - please see my comment and attached project on MNG-5127

I have found a better solution by making the following changes on the daddy.zip project:

1) On daddy's pom, Replaced the [profiles] with plugin executions having [phase]none[/phase]

<build>
    ...
    <plugins>
        <plugin>
            <artifactId>maven-antrun-plugin</artifactId>
            <executions>
                <execution>
                    <id>printboy</id>
                    <phase>none</phase>
                    <configuration>
                        <target>
                            <echo message="@@@@@@@@@@@@ HELLO! Iam a BOY project"/>
                        </target>
                    </configuration>
                    <goals>
                        <goal>run</goal>
                    </goals>
                </execution>
                <execution>
                    <id>printkid</id>
                    <phase>none</phase>
                    <configuration>
                        <target>
                            <echo message="@@@@@@@@@@@@ HELLO! Iam a KID project"/>
                        </target>
                    </configuration>
                    <goals>
                        <goal>run</goal>
                    </goals>
                </execution>
                <execution>
                    <id>printgirl</id>
                    <phase>none</phase>
                    <configuration>
                        <target>
                            <echo message="@@@@@@@@@@@@ HELLO! Iam a GIRL project"/>
                        </target>
                    </configuration>
                    <goals>
                        <goal>run</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
    ...
</build>

2) On the same pom, added a custom build extension

<build>
    <extensions>
        <extension>
            <groupId>br.com.touchtec.maven.plugins</groupId>
            <artifactId>execution-enabler-extension</artifactId>
            <version>1.0.0-SNAPSHOT</version>
        </extension>
    </extensions>
    ...
</build>

3) The extension will change the plugin execution phases based on the project's property values. Java code below.

@Component(role = AbstractMavenLifecycleParticipant.class, hint = "enableif")
public class EnableIfExtension extends AbstractMavenLifecycleParticipant {

    @Override
    public void afterProjectsRead(MavenSession session)
            throws MavenExecutionException {
        String phase = "validate";
        for(MavenProject project : session.getProjects()){
            Properties properties = project.getProperties();
            if(properties != null){
                if("boy".equals(properties.getProperty("project_type"))){
                    setExecutionPhase(project, "printboy", phase);
                    setExecutionPhase(project, "printkid", phase);
                }
                if("girl".equals(properties.getProperty("project_type"))){
                    setExecutionPhase(project, "printgirl", phase);
                    setExecutionPhase(project, "printkid", phase);
                }
                if("kid".equals(properties.getProperty("project_type"))){
                    setExecutionPhase(project, "printkid", phase);
                }
            }
        }
    }

    private void setExecutionPhase(MavenProject project, String executionId, String phase) {
        for(Plugin plugin : project.getBuild().getPlugins()){
            if(plugin.getExecutions() != null){
                for(PluginExecution execution : plugin.getExecutions()){
                    if(executionId.equals(execution.getId())){
                        execution.setPhase(phase);
                    }
                }
            }
        }
    }
}

4) The child module poms only need to define a property that will tell the build extension what to do, for example, the boy project:

<project>
    <properties>
        <project_type>boy</project_type>
    </properties>

    <modelVersion>4.0.0</modelVersion>
    <groupId>com.family</groupId>
    <artifactId>boy</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>

    <parent>
        <groupId>com.family</groupId>
        <artifactId>daddy</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <!-- No "build" section. Beautifull. -->
</project>

Invoking mvn clean install on the daddy project like thiss, will output the desired result: boys will be boys, girls will be girls and both will be kids.

The question is: can we do better?

In theory, a build extension could import the build configuration definitions for boy, girl, and kid from different poms... right? That would be the a clever and elegant way of importing [build] configuration into a pom.

There are a lot of available maven plugins, but I don't see a lot (actually any) of available build extensions that one can plug into a build. Does anyone know of a build extension that helps with this?


Update

This is not an actual answer, but it's an actual solution to my problem, so here goes.

Import maven plugin configuration by composition rather than inheritance. Can it be done with build extensions?

Probably

Does anyone know of a build extension that helps with this?

I'm pretty sure there isn't one

However, there is a solution using profiles.

The trick is that file-based profile activation is actually inherited (it only works with maven3 though)

Please see the daddy2.zip attached to MNG-5127

This is way better than using the build extension strategy, because using a profile provides more flexibility than just changing a few plugin execution phases.


Update 2

Does anyone know of a build extension that helps with this?

I'm pretty sure there isn't one

Actually there is something!

It's attached as project in MNG-5102 (by Maurizio Pillitu) I haven't tested it, but it seems it does something very close to the proposed build extension.

A_Di-Matteo
  • 26,902
  • 7
  • 94
  • 128
Tony Lâmpada
  • 5,301
  • 6
  • 38
  • 50
  • No answer so far, that's worrysome... At least it's good to know [I'm not alone](http://stackoverflow.com/questions/10245621/how-to-inherit-from-a-multimodule-maven-project-with-all-its-goodies). – Tony Lâmpada Aug 01 '12 at 04:43
  • A wish in [Maven 3.1](http://jira.codehaus.org/browse/MNG/fixforversion/15565#selectedTab=com.atlassian.jira.plugin.system.project%3Aversion-issues-panel) is to include "mixins" (http://jira.codehaus.org/browse/MNG-5102). Sounds a lot like what you're looking for. Unfortunately there doesn't seem to be much going on for Maven 3.1; the issues list looks about the same as it did when I looked over a year ago. :-( – user944849 Aug 01 '12 at 14:33
  • Yes indeed. I would love if [FreedomSponsors](http://www.freedomsponsors.org/) could help improve that :-) – Tony Lâmpada Aug 01 '12 at 15:06
  • 1
    I really had lost hope to get an actual answer on this question. But apparently, there is on in the making! THIS IS AWESOME! --> https://twitter.com/maoo/status/230704704668192768 – Tony Lâmpada Aug 01 '12 at 17:33

1 Answers1

10

I think that Maven Tiles can help you with your specific use-case. It is still work in progress, but it currently accomplishes what you're describing, I managed to "decompose" the wicket-quickstart and run Jetty successfully, even adding a multi-module structure.

Any comment or hint is more than welcome. Thanks, Maurizio

Paul Verest
  • 60,022
  • 51
  • 208
  • 332
maoo
  • 116
  • 1
  • 4
  • 2
    Now that 0.8-beta-6 is out, I added a [daddy3.zip](http://jira.codehaus.org/secure/attachment/61530/daddy3.zip) file to [MNG-5102](http://jira.codehaus.org/browse/MNG-5102?focusedCommentId=310175#comment-310175) that demonstrates how to use it. – Tony Lâmpada Oct 02 '12 at 20:08
  • Stable 2.8 as of April 2016 – Paul Verest Apr 18 '16 at 14:17
  • Why does `` can not be added to a tile and how to import dependency configuration? (The error says: Tile includes dependencies - this will prevent consumers from adding exclusions, use composites instead.) – fwonce Jun 30 '17 at 06:44