8

I am looking for a way to include all the modules in a project from another pom.xml. So in my case I have a parent pom with packaging set to pom. It contains 3 child modules that implement my interfaces in another api module. I want to dynamically include all the child modules in my project in maven.

In this case I want to include the connector1, connector2, connector3 in another module without having to specifiy the connector1,2,3 implicitly.

connectors - packaging: pom
   connector1 - packaging: jar
   connector2 - packaging: jar
   connector3 - packaging: jar

I tried including the connectors pom in my project but this did not work. I was hoping that specifying the parent package with pom would include the child modules but this did not work. Are there any workarounds for how to do this?

Update

This was more of peeve of mine because I wanted to simply add a single connector and have all the child module dependency jars for the project be included. This would make the pom a little simpler to read.

Instead of having to register all the child dependencies like so

<dependencies>
        <dependency>
            <groupId>com.foo</groupId>
            <artifactId>connector1</artifactId>
            <version>0.0.1</version>
        </dependency>

        <dependency>
            <groupId>com.foo</groupId>
            <artifactId>connector1-api</artifactId>
            <version>0.0.1</version>
        </dependency>

        <dependency>
            <groupId>com.foo</groupId>
            <artifactId>connector1-etl</artifactId>
            <version>0.0.1</version>
        </dependency>

        <dependency>
            <groupId>com.foo</groupId>
            <artifactId>connector1-persistence</artifactId>
            <version>0.0.1</version>
        </dependency>

         <dependency>
            <groupId>com.foo</groupId>
            <artifactId>connector2</artifactId>
            <version>0.0.1</version>
        </dependency>

        <dependency>
            <groupId>com.foo</groupId>
            <artifactId>connector2-api</artifactId>
            <version>0.0.1</version>
        </dependency>

        <dependency>
            <groupId>com.foo</groupId>
            <artifactId>connector2-etl</artifactId>
            <version>0.0.1</version>
        </dependency>

        <dependency>
            <groupId>com.foo</groupId>
            <artifactId>connector2-persistence</artifactId>
            <version>0.0.1</version>
        </dependency>

       <dependency>
            <groupId>com.foo</groupId>
            <artifactId>connector2-other</artifactId>
            <version>0.0.1</version>
        </dependency>
       ...
</dependencies>

This is just an example to clarify the original question. It does not exist and would probably have reprocussions if it did work.

<dependencies>
        <dependency>
            <groupId>com.foo</groupId>
            <artifactId>connector1</artifactId>
            <version>0.0.1</version>
            <type>pom</type>
            <include>submodules</include>
        </dependency>

        <dependency>
            <groupId>com.foo</groupId>
            <artifactId>connector2</artifactId>
            <version>0.0.1</version>
            <type>pom</type>
            <include>submodules</include>
        </dependency>

</dependencies>

If I remember correctly I was creating a modular project for an ordering system where I had a common api that our internal system would use (REST). I was creating a routing system where I could route an order to a single fulfillment center based on a criteria of the order (country, priority taxes etc). Each of the fulfillment centers had their own api (connectors).

The example is greatly simplified in the original question to make it more the problem more concise. In the real project each connector (1,2,3) would have been a separate pom with multiple dependency jars. One for their client api, then some etl code to match with my original api.

I don't remember how I solved this. I think I just had to include the all the child dependencies.

Chris Hinshaw
  • 6,967
  • 2
  • 39
  • 65
  • Do you have an example project somewhere (github?) where we can get a better impression what exactly you are trying to do? – khmarbaise Oct 21 '14 at 16:41
  • 1
    @RobinJonsson The question is unclear. What exactly does *include* mean here? What end-result do you want? Do you mean you want to automatically fill in the `` section in `connectors` POM? Or somewhere else? Could you please expand a little? – Tunaki Apr 06 '16 at 21:32
  • 1
    @Tunaki The outcome I want is to be able to add new "connectorX" packages without having to specify them as dependencies somewhere else. Say for instance I have another module that is packaged as a WAR. I'd like to add a dependency from the WAR to "connectors", and whenever i add a new "child-module" (perhaps connector4) to connectors, it's automatically packaged with the WAR file. I don't have a desired packaging format for my connectors. It doesn't matter if the connectors are packaged as separate JARs, or an uber-jar. As long as they are included in my WAR. – Robin Jonsson Apr 07 '16 at 06:19
  • @Tunaki I think the underlaying issue here is that I cant add`jar – Robin Jonsson Apr 07 '16 at 06:21

3 Answers3

10

One way is to create a fourth module which "wraps" the 3 modules as dependencies. This way you could depend on this wrapper module which would.

connectors - packaging: pom
   connector1 - packaging: jar
   connector2 - packaging: jar
   connector3 - packaging: jar
   connectorWrapper - packaging: pom (depends on the above three)

Although it would make more sense to explicitly declare a dependency for each connector especially that they are only three.

Alternative solution:

A more dynamic approach (although very much an overkill IMO) is to have this fourth module package the implementation modules in an assembly using a custom assembly descriptor. For example, inside connectorWrapper, you could write an assembly.xml:

<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 http://maven.apache.org/xsd/assembly-1.1.3.xsd">

    <id>impl-modules</id>
    <formats>
        <format>jar</format>
    </formats>
    <includeBaseDirectory>false</includeBaseDirectory>
    <fileSets>
        <fileSet>
            <directory>${project.basedir}</directory>
            <includes>
                <include>pom.xml</include>
            </includes>
            <useDefaultExcludes>true</useDefaultExcludes>
        </fileSet>
    </fileSets>
    <moduleSets>
        <moduleSet>
            <useAllReactorProjects>true</useAllReactorProjects>
            <includes>
                <include>*:connector*</include>
            </includes>
            <binaries>
                <includeDependencies>false</includeDependencies>
            </binaries>
        </moduleSet>
    </moduleSets>
</assembly>

Note that the descriptor tells the assembly plugin to:

  1. include all modules in the current project reactor, so when you run mvn clean package in the root project, it will include all modules

  2. include only implementation modules (the connector modules), as specified in the include element having *:connector*.

Of course you'll need to configure the assembly plugin to use this descriptor in the connectorWrapper (or whatever other name you choose for this wrapper):

<plugins>
    <plugin>
        <artifactId>maven-assembly-plugin</artifactId>
        <configuration>
            <descriptors>
                <descriptor>assembly.xml</descriptor>
            </descriptors>
        </configuration>
        <executions>
            <execution>
                <id>make-assembly</id>
                <phase>package</phase>
                <goals>
                    <goal>single</goal>
                </goals>
            </execution>
        </executions>
    </plugin>
</plugins>

Then you can run mvn install on the root project to install the assembly artifact, after which you can depend on it from the other project:

<dependencies>
    <dependency>
        <groupId>groupId</groupId>
        <artifactId>connectorWrapper</artifactId>
        <version>...</version>
        <classifier>impl-modules</classifier> <!-- note the classifier -->
    </dependency>
</dependencies>
M A
  • 71,713
  • 13
  • 134
  • 174
  • 2
    Thanks but my goals is for others to be able to create implementations without having to manually add them as another dependency to a project. It is a good idea though but this would kind of be equivalent to adding it to the list of dependencies in the other project. I think there may be a way to do this with the assembly plugin but I am looking into that now. – Chris Hinshaw Oct 20 '14 at 17:33
  • Not accepting this as the answer since this includes another project which just moves the dependency management to itself. The original problem where it would be nice to not actively have to specify dependency on new "connectors" is still open. – Robin Jonsson Apr 06 '16 at 09:07
  • 1
    @RobinJonsson In fact as the OP mentioned, it may be feasible with the assembly plugin. Updated my answer. – M A Apr 06 '16 at 15:01
  • @AR.3 I'll try it out – Robin Jonsson Apr 07 '16 at 06:21
1

Not entirely sure whether it exactly does what you need but within the latest maven releases you can use the scope import on your dependencies.

The first step would be to create a pom containing all the dependencies you would like to include in other projects:

<project>

    <groupId>com.foo</groupId>
    <artifactId>connectors</artifactId>
    <version>0.0.1</version>
    <packaging>pom</packaging>

    <dependencies>
        <dependency>
            <groupId>com.foo</groupId>
            <artifactId>connector1</artifactId>
            <version>0.0.1</version>
        </dependency>

        <dependency>
            <groupId>com.foo</groupId>
            <artifactId>connector1-api</artifactId>
            <version>0.0.1</version>
        </dependency>

        <dependency>
            <groupId>com.foo</groupId>
            <artifactId>connector1-etl</artifactId>
            <version>0.0.1</version>
        </dependency>

        ...
    </dependencies>    
</project>

In the projects you would like to include the connectors you have:

<dependency>
    <groupId>com.foo</groupId>
    <artifactId>connectors</artifactId>
    <version>0.0.1</version>
    <type>pom</type>
    <scope>import</scope>
</dependency>

See Importing Dependencies for more information.

An alternative approach could be to use the maven assembly plugin and create a single (huge) jar containing all the classes you would like to include (single jar packaging); (for that you also need to create once a pom with all the dependencies and the assembly plugin).

uniknow
  • 938
  • 6
  • 5
  • Doesn't this still mean I have to explicitly specify dependency in `connectors` on all child-modules? – Robin Jonsson Apr 08 '16 at 06:54
  • Yes within the parent pom you still need to define the modules/dependencies that need to be part. I thought your goal was to have a connectors dependency you could include in other projects instead of including each sub connector separately. Might have misunderstood you. – uniknow Apr 08 '16 at 07:09
  • That's okay, take a look at the comment I made on the original question. Regards – Robin Jonsson Apr 08 '16 at 08:43
  • Still not entirely getting it (sorry) but would, given your last update, this not work to include all dependencies of connector 1 and 2: ` com.foo connector1 0.0.1 pom import ... ` – uniknow Apr 08 '16 at 09:19
0

I would write my own maven plugin for this. Judging from your reputation and the question, you could probably have something ready within the hour. Most probably sooner than researching and trying out solutions to do what you want.

chrisl08
  • 1,658
  • 1
  • 15
  • 24