Maven inheritance aggregation
Challenge
The challenge is to create a build system (based on maven of
course) that will be delivered to the next layer of development. The difficulty
here is that the core team will continue to change the delivery system, and
release new versions. We do not want (or would like to limit) the adoption teams
to always have to merge when there is a new version.
Solution
The solution needs to be implemented in more than one single
solution and way. The standard way of
maven is inheritance. Any dependency or plugin that you want to add you put it
in the parent pom and everyone can inherit this. The problem is that we do not
always want to inherit, and we don’t always want the same functionality for all
children. To solve this issue you can put any dependencies or plugins in
profiles and then activate them in a child module. This solution is not clean
since it is very cumbersome and makes the parent pom very big and hard to
manage with all the profiles.
BOM (Bill Of Materials)
Since our project consists of multiple jars and versions we
do not want the adoption team to have to update all versions for every new
release. In addition if we add a new jar we do not want the adoption team to
have to add the new jar to their parent pom.
By creating a bom file (more a less a parent pom), the
adoption parent pom does not have to inherit your pom, but can import it (http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html).
This will allow the adoption to manager the core product with one import on the
dependency.
For example (this is put in the dependencyManagement section):
<dependency>
<groupId>com.xxx.wsf.buildtools</groupId>
<artifactId>wsf-bom</artifactId>
<version>${wsf.tools.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
This will import all the dependency managements from the
wsf-bom file.
Just a reminder in the BOM you only have dependencyManagement
and not the dependencies themselves. In addition BOM’s are only for dependency management
and not plugin management.
Note: When you have a multi module project,
you parent pom needs to be the bom so that it is installed first, else no one
is installing it since it is imported in the dependencyManagment and not
dependencies.
DepChain
A BOM file is a good start, but what do I do if I have
multiple projects that need the actual dependencies and not just the versions
(dependency management). If it is only one dependency then we can manually add
it to the module, but if it is more than one, or even one but in the future it
will grow we would like to import the dependencies themselves and not just the
dependency management.
A depchain is a pom file that has the actual dependency list
and not just the management. Once you have an artifact that is a depchain you
can then import it into any module (this is put in the dependencies section:
<dependency>
<groupId>com.xxx.wsf.buildtools</groupId>
<artifactId>wsf-depchain-design</artifactId>
<type>pom</type>
<scope>provided</scope>
</dependency>
This will bring in the actual dependency list into your
module, notice that the scope is provided.
For more information see: http://books.sonatype.com/mvnref-book/reference/pom-relationships-sect-pom-best-practice.html.
Mixins
Mixin is an object oriented paradigm to add functionality to
a class but not by inheritance (http://en.wikipedia.org/wiki/Mixin).
Maven has toyed with the idea of adding mixins, currently it is on the roadmap
for maven 4 (https://cwiki.apache.org/confluence/display/MAVEN/Roadmap).
All thought it is not released by maven, maven allows you to create plugins
that are extensions to maven. So a developer by the name of ohad david has
written a mixin extension for maven (https://github.com/odavid/maven-plugins).
What this extension allows you to do is to create an external
pom that will be merged into your pom. So with this you can write a set of
plugins that will give you added value, and then you import it into any module
you need this functionality (you also have the option to move the content of
the pom to a mixin.xml so that when you install the mixin it does not run the
plugins).
For example we would like to write a set of plugins that
depending on the OS it will change the permissions of a file in a folder. The
pom that does this is fairly simple. What we would like is the option to move this
functionality from the parent pom into anther pom that other projects can use.
Just like the BOM allows you to import all dependencies version of a project, a
dep chain will allow you import the dependencies them self’s.
Example of mixin: permission per os (the value of the
properties will be defined in the calling pom).
The pom of the mixin might look something like:
<properties>
<folder.location/>
<windows.permissions>-r
/s</windows.permissions>
<linux.permissions>777</linux.permissions>
</properties>
<profiles>
<profile>
<id>windows</id>
<activation>
<os>
<family>windows</family>
</os>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>run app maven</id>
<phase>validate</phase>
<configuration>
<target>
<exec
dir="${folder.location}" executable="attrib"
failonerror="true">
<arg line="${windows.permissions}
*.*"/>
</exec>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>linux</id>
<activation>
<os>
<family>unix</family>
</os>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>set permission</id>
<phase>process-test-resources</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<target>
<chmod
dir="${folder.location}" perm="${linux.permissions}"/>
</target>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
The usage of this plugin in another pom would then be:
<properties>
<folder.location>${basedir}/src/test/resources/asm</folder.location>
</properties>
<plugin>
<groupId>com.github.odavid.maven.plugins</groupId>
<artifactId>mixin-maven-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<phase>process-classes</phase>
<mixins
combine.children="append">
<mixin>
<groupId>com.abc</groupId>
<artifactId>wsf-mixin-files-permission</artifactId>
<type>mixin</type>
</mixin>
</mixins>
</configuration>
</plugin>
Why mixins still don’t make it:
Although mixins do give us a lot of functionality, they do
not really wrap a full set of functionality to be used in other poms. For
example is you write an assembly mixin, all the extra files for the assembly
cannot be put in the mixin but need to be put into the calling pom. So we don’t
actually have a full encapsulation solution, but a step in the right direction.
For more information on this see:
No comments:
Post a Comment