Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I setup maven sub-projects with inter-dependencies?

Tags:

maven-2

maven

I'm having a hard time setting up a set of related maven projects with interdependencies between them.

Here's my simplified case:

pom.xml     -- parent pom \base\     pom.xml     src\main\java\Base.java     -- this is just a simple class \derived\     pom.xml     src\main\java\Derived.java  -- this is a simple class that needs Base class to compile successfully, and has a main function 

My goals are:

  1. be able to compile, on my machine, all projects:
    • i.e. mnv clean compile is successful in \
  2. be able to compile, on my machine, just one project:
    • i.e. mnv clean compile is successful in \base\ and \derived\ (though this may not work by design: Inter Project Dependencies in Maven)
      [edit: found the answer for this one: base needs to be published locally before derived in compiled: i.e. in \base, do mvn clean compile install instead of doing just doing mvn clean compile. Once this is done, doing mvn clean compile in \derived works fine. Still, it would be great to do this without touching global state, i.e. without having to install base -- so if anyone knows a way of achieving this, please add it as an answer]
  3. be able to run derived project on my machine (mvn exec:run or equivalent) direcly from the source tree:
    • i.e. mvn exec:run in \derived\ should compile (if needed) and run the derived.jar
  4. the "shared component" use case: push the base artifact to the shared repository, where other people can consume it as a maven dependency (i.e. compile time dependency):
    • i.e. mvn clean compile ??? will push this to the shared repository specified in ~/.m2/config.xml
  5. the "image directory" use case: push the derived artifact and its depedencies to a local directory, where it can be run via "java -jar ..." or it can exposed as an ftp/http share for other people to get it. I.e., use cases like those:
    • mvn clean compile ??? will push derived.jar and dependencies (like base.jar) to ~/.m2/maven.repo/.../derived or equivalent, and then I can cd ~/.m2/maven.repo/.../derived and run java -jar derived.jar to run it.
    • mvn clean compile ??? will push base.jar to ~/.m2/maven.repo/.../base (or derived.jar to its corresponding dir), which is already exposed as a download point via local web or ftp server.

How do I do the goals above?

Here's the relevant section from parent pom:

... <modelVersion>4.0.0</modelVersion> <groupId>com.foo</groupId> <artifactId>parentpom</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>pom</packaging>  <name>parentpom</name>  <modules>     <module>base</module>     <module>derived</module> </modules> ... 

Here's the relevant section from base pom.xml:

... <parent>     <groupId>com.foo</groupId>     <artifactId>parentpom</artifactId>     <version>0.0.1-SNAPSHOT</version> </parent>  <modelVersion>4.0.0</modelVersion> <groupId>com.foo.base</groupId> <artifactId>base</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging>  <name>base</name> ... 

Here's the relevant section from derived pom.xml:

... <parent>     <groupId>com.foo</groupId>     <artifactId>parentpom</artifactId>     <version>0.0.1-SNAPSHOT</version> </parent>  <modelVersion>4.0.0</modelVersion> <groupId>com.foo.derived</groupId> <artifactId>derived</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging>  <name>derived</name>  <dependencies>     <dependency>         <groupId>com.foo</groupId>         <artifactId>base</artifactId>         <version>0.0.1-SNAPSHOT</version>     </dependency> </dependencies>  ... 

Thank you in advance for your help.

like image 762
daniel Avatar asked Aug 31 '12 23:08

daniel


People also ask

Can two Maven modules depend on each other?

Because modules within a multi-module build can depend on each other, it is important that the reactor sorts all the projects in a way that guarantees any project is built before it is required. The following relationships are honoured when sorting projects: a project dependency on another module in the build.

How do I add a project as a dependency of another project Maven?

Right-click the utility project, and select Maven>Add Dependency. Type a dependency name in the Enter groupID… field (e.g., commons-logging) to search for a dependency. Select the dependency, and click OK.

How do I merge two Maven projects?

let's assume that you have two maven projects A and B. Now create a new project C in your intllij-idea. In project C, create a new module A1. Copy the dependencies and build, properties (if present) from pom.

How do you create a multi-module project?

POM Aggregator (Parent POM) Let's understand the structure of the multi-module application that we have created. Step 1: Create a Maven Project with the name spring-boot-multimodule. Step 2: Open the pom. xml (parent pom) file and change the packaging type jar to pom.


1 Answers

Your parent pom looks good but your module/derived poms don't: There are several issues which will produce some problems etc.

First you are using different groupId's for the derived/base module. If you have a multi-module build you shouldn't do this. Furthermore, the version of derived/base is inherited by the parent and shouldn't be set explicit which means you should have something like the following:

<modelVersion>...</...> ... <parent>     <groupId>com.foo</groupId>     <artifactId>parentpom</artifactId>     <version>0.0.1-SNAPSHOT</version> </parent>  <artifactId>base</artifactId> <packaging>jar</packaging>  <name>base</name> 

The groupId is usually inherited. But sometimes you have a larger number of modules that may be sub-modules of sub-modules which results in a structure like this:

+--- parent (pom.xml)        +--- mod1 (pom.xml)               +--- mod11 (pom.xml)               +--- mod12 (pom.xml)        +--- mod2 (pom.xml) 

In Such cases, the mod1 itself is a a pom packaging module:

<modelVersion>...</...> ... <groupId>com.company.project<groupId>   <artifactId>parent</artifactId> <packaging>pom</packaging> <modules>   <module>mod1</module>   <module>mod2</module> </modules> 

mod1:

<parent>     <groupId>com.company.project<groupId>       <artifactId>parent</artifactId>     <version>0.0.1-SNAPSHOT</version> </parent>  <groupId>com.company.project.mod1</groupId> <artifactId>mod1</artifactId> <packaging>pom</packaging>  <modules>   <module>mod11</module>   <module>mod12</module> </modules> 

mod11:

<parent>     <groupId>com.company.project.mod1</groupId>     <artifactId>mod1</artifactId>     <version>0.0.1-SNAPSHOT</version> </parent>  <artifactId>mod11</artifactId> <packaging>pom</packaging>  <modules>   <module>mod11</module>   <module>mod12</module> </modules> 

If you need to make a dependency between modules the solution is:

<parent>     <groupId>com.company.project.mod1</groupId>     <artifactId>mod1</artifactId>     <version>0.0.1-SNAPSHOT</version> </parent>  <artifactId>mod11</artifactId> <packaging>jar</packaging>  <dependencies>   <dependency>     <!-- This shouldn't be a dep which is packaging: pom -->     <groupId>${project.groupId}</groupId>     <artifactId>mod2</artifactId>     <version>${project.version}</version>   </dependency>  </dependencies>     

To compile the whole project with all sub modules in one just go to parent folder and:

mvn clean package

will compile etc. If you like to compile only a single project you can do this by (from parent):

mvn -pl mod1 

which will work only if you have installed the whole project once before. Another solution is:

mvn -am -pl mod1 

To make the artifacts acessible for others the simplest solution is to install a repository manager and do:

mvn deploy

All others can use and artifact as a SNAPSHOT dependency.

like image 56
khmarbaise Avatar answered Sep 21 '22 15:09

khmarbaise