You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@maven.apache.org by Edwin Park <es...@cornell.edu> on 2005/12/08 06:50:57 UTC

composite artifacts

Hi,

I have a non-trivial application component (let's call it ComponentA) which
is itself divided into subcomponent modules (let's call these ComponentX,
ComponentY, ComponentZ):

ComponentA
     ComponentX
     ComponentY
     ComponentZ

The relationship between ComponentA and components X, Y and Z is not really
a dependency relationship - it is a structural composition relationship.
What I am finding is that although Maven handles dependency relationships
very nicely, it does not handle composition relationships particularly well.

I have made ComponentA a multi-module project with no code of its own - just
module references to ComponentX, Y and Z:

<modules>
     <module>ComponentX</module>
     <module>ComponentY</module>
     <module>ComponentZ</module>
</modules>

This allows me to maintain the useful separation of X, Y, Z subcomponents,
while at the same time allowing me to build all of them at once from the
ComponentA project. Maven's multi-module support works nicely for this, but
the problem comes when you decide you want to deal with a modularized
component such as ComponentA as a *single entity* rather than a collection
of individual modules. Separating my application component into subcomponent
modules is a good thing from a *development* point of view, but I do not
want to *distribute* the component as a lot of little jar files: I want to
distribute it as a single jar.

Presumably the way to compose my modularized component into a single jar is
by using the Maven assembly plugin. But the assembly plugin merely packages
things together into a single archive. It does not take the important
additional step of treating the assembled archive as a first-class maven
artifact. This means that the assembled archive can not be treated as a
dependency. If another component, e.g. ComponentB, wishes to use the
aggregated ComponentA, it can not express a dependency on it directly since
the aggregation is not a Maven artifact and has no pom. Instead, it must
express individual dependencies on components X, Y and Z.

Now let me tell you about some of the hoops I've been jumping through in
order to get my 'single jar' and the issues I've encountered along the way.
Keep one thought in the back of your mind as you read the rest of this: how
much simpler would things be if Maven had first-class support for
composition relationships? What if Maven had a nice way to construct
composite artifacts?

In order for the assembly plugin to work, I had to convert my module
references to components X, Y and Z to dependency references instead,
because the assembly plugin can only refer to fileSets or dependencySets:

<dependencies>
     <dependency>
          <groupId>mygroup</groupId>
          <artifactId>ComponentX</artifactId>
          <version>1.0-SNAPSHOT</version>
     </dependency>
     <dependency>
          <groupId>mygroup</groupId>
          <artifactId>ComponentZ</artifactId>
          <version>1.0-SNAPSHOT</version>
     </dependency>
     <dependency>
          <groupId>mygroup</groupId>
          <artifactId>ComponentZ</artifactId>
          <version>1.0-SNAPSHOT</version>
     </dependency>
</dependencies>

Also, because I didn't want to include all of the transitive dependencies of
components X, Y and Z, I had to list explicit includes in the assembly.xml:

<dependencySet>
     ...
     <includes>
          <include>mygroup:ComponentX</include>
          <include>mygroup:ComponentY</include>
          <include>mygroup:ComponentZ</include>
     </includes>
</dependencySet>

At this point, i can run assembly:assembly and I get my nice composite jar
file, but:
1. The mutli-project build doesn't work anymore, because I don't have a
<modules> section. I could put the <modules> section back, but then I would
be specifying my composition relationship in 3 different places: <modules>,
<dependencies> in pom.xml and <includes> in assembly.xml. This works, but
this is ridiculous.
2. As noted above, I can't refer to the composite ComponentA in a dependency
relationship. Aside from the previously mentioned consequences, this also
means that if I want to create a higher-level assembly of ComponentA
together with ComponentB and ComponentC in a single distribution archive
(and I do), I can't do it since the assembly plugin can only assemble
dependencies (well, the assembly plugin can also assemble files, but you
don't want to refer to file resources outside of the current project).

The upshot is that composition is a different concept from dependency, and
deserves recognition and support in the build system. I have more thoughts
on how composition might be handled in Maven and on potential pitfalls, but
this post is long enough for now. I'd love to know if this is already a
known problem and work is already going on to address composition issues, or
if I'm totally off base and there are already ways of doing what I want to
do here, or not.

Thanks,
Edwin