In this specific case, the archetype could always create all the required modules and move the different flavors (set of modules) into profiles. Only one profile will be active by default as specified during the archetype:generate
step.
As such, if I want to have the set of modules for flavorA, I will run the archetype as
mvn archetype:generate -DarchetypeGroupId=.. -DflavorA=true
And the archetype will pass this variable to the activeByDefault
element of the flavorA profile re-defining the modules
element for the set of modules required by the flavorA users.
The same could be done for flavorB and flavorB (for example), each defining a different set of modules.
An example of such an aggregator/parent POM as part of the archetype would be:
<profiles>
<profile>
<id>flavourA</id>
<activation>
<activeByDefault>${flavourA}</activeByDefault>
</activation>
<modules>
<module>profiled-module2</module>
<module>profiled-module3</module>
</modules>
</profile>
<profile>
<id>flavourB</id>
<activation>
<activeByDefault>${flavourB}</activeByDefault>
</activation>
<modules>
<module>profiled-module3</module>
</modules>
</profile>
<profile>
<id>flavourC</id>
<activation>
<activeByDefault>${flavourC}</activeByDefault>
</activation>
<modules>
<module>profiles-module1</module>
<module>profiled-module2</module>
<module>profiled-module3</module>
</modules>
</profile>
</profiles>
The archetype-metadata.xml
file could then specify:
<requiredProperties>
<requiredProperty key="flavourA">
<defaultValue>false</defaultValue>
</requiredProperty>
<requiredProperty key="flavourB">
<defaultValue>false</defaultValue>
</requiredProperty>
<requiredProperty key="flavourC">
<defaultValue>false</defaultValue>
</requiredProperty>
</requiredProperties>
And the archetype invoked with the -DflavorB=true
option would then generate a pom as following:
<profiles>
<profile>
<id>flavourA</id>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<modules>
<module>profiled-module2</module>
<module>profiled-module3</module>
</modules>
</profile>
<profile>
<id>flavourB</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<modules>
<module>profiled-module3</module>
</modules>
</profile>
<profile>
<id>flavourC</id>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<modules>
<module>profiles-module1</module>
<module>profiled-module2</module>
<module>profiled-module3</module>
</modules>
</profile>
</profiles>
Such an approach has the following advantages and disadvantages:
Advantages
- You keep the common modules and the archetype maintenance in one centralized place, while leaving the choice of flavors to the user of the archetype
- Users of the archetype could, if desired and with zero-cost, switch from one flavor to another just activating/deactivating profiles
- The approach uses standard Maven features
Disadvantages
- Each archetype will generate the whole set of modules, even though not all of them will be required
- If really a "noise", the user could manually delete the undesired modules, but still it would be a manual action
Moreover, on top of the approach above, we could also configure the Maven Clean Plugin in each profile to delete the modules not concerned by its flavor, so that at its first build (a maven clean
), any non required module would be deleted. Such an approach would leave the POM with inconsistent profiles though, but it might be considered as well (not recommended).
Something like:
<profile>
<id>flavourA</id>
<activation>
<activeByDefault>${flavorA}</activeByDefault>
</activation>
<modules>
<module>profiled-module2</module>
<module>profiled-module3</module>
</modules>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-clean-plugin</artifactId>
<version>3.0.0</version>
<configuration>
<filesets>
<fileset>
<directory>${basedir}/profiled-module1</directory>
</fileset>
</filesets>
</configuration>
</plugin>
</plugins>
</build>
</profile>