1

I have the following project structure in Maven:

./
├─ app1/
│  ├─ pom.xml
├─ app2/
│  ├─ pom.xml
├─ core/
│  ├─ pom.xml
├─ pom.xml

My parent pom.xml contains the following:

    <packaging>pom</packaging>
    <modules>
        <module>core</module>
        <module>app1</module>
        <module>app2</module>
    </modules>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.6.9</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.acme</groupId>
    <artifactId>parent</artifactId>
    <version>1.0.0-SNAPSHOT</version>

    <repositories>
        <repository>
            <id>Maven central</id>
            <url>https://repo1.maven.org/maven2/</url>
        </repository>
        <repository>
            <id>Confluent</id>
            <url>https://packages.confluent.io/maven/</url>
        </repository>
        <repository>
            <id>Local Maven</id>
            <name>Local Maven Repository</name>
            <url>file://${user.home}/.m2/repository/</url>
        </repository>
    </repositories>

My core pom.xml contains the following:

    <parent>
        <groupId>com.acme</groupId>
        <artifactId>parent</artifactId>
        <version>1.0.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <packaging>jar</packaging>

    <artifactId>core</artifactId>
    <version>1.0.0-SNAPSHOT</version>

My app1 pom.xml contains the following:

    <parent>
        <groupId>com.acme</groupId>
        <artifactId>parent</artifactId>
        <version>1.0.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>app1</artifactId>

    <dependencies>
        <dependency>
            <groupId>com.acme</groupId>
            <artifactId>core</artifactId>
            <version>1.0.0-SNAPSHOT</version>
        </dependency>
        <!-- ... -->
    </dependencies>

If I try to build in the root project directory, via:

mvn package

it correctly builds all my modules.

If I try to build the core package (which does not have additional intra-project dependencies) via mvn package, it correctly builds.

But if I try to build the app1 package (which does contain a dependency on my core module), even while forcing updates:

user@dev:~/parent/app1$ mvn package -U
[INFO] Scanning for projects...
[INFO] 
[INFO] ---------------< com.acme:app1 >----------------
[INFO] Building app1 1.0.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
Downloading from Local Maven: file:///home/user/.m2/repository/com/acme/core/1.0.0-SNAPSHOT/maven-metadata.xml
Downloading from Maven central: https://repo1.maven.org/maven2/com/acme/core/1.0.0-SNAPSHOT/maven-metadata.xml
Downloading from Confluent: https://packages.confluent.io/maven/com/acme/core/1.0.0-SNAPSHOT/maven-metadata.xml
Downloading from Confluent: https://packages.confluent.io/maven/com/acme/parent/1.0.0-SNAPSHOT/maven-metadata.xml
Downloading from Maven central: https://repo1.maven.org/maven2/com/acme/parent/1.0.0-SNAPSHOT/maven-metadata.xml
Downloading from Local Maven: file:///home/user/.m2/repository/com/acme/parent/1.0.0-SNAPSHOT/maven-metadata.xml
Downloading from Maven central: https://repo1.maven.org/maven2/com/acme/parent/1.0.0-SNAPSHOT/event-processor-1.0.0-SNAPSHOT.pom
Downloading from Confluent: https://packages.confluent.io/maven/com/acme/parent/1.0.0-SNAPSHOT/event-processor-1.0.0-SNAPSHOT.pom
Downloading from Local Maven: file:///home/user/.m2/repository/com/acme/parent/1.0.0-SNAPSHOT/event-processor-1.0.0-SNAPSHOT.pom
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  2.324 s
[INFO] Finished at: 2023-01-06T11:54:58+01:00
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal on project app1: Could not resolve
dependencies for project com.acme:app1:jar:1.0.0-SNAPSHOT: Failed to 
collect dependencies at com.acme:core:jar:1.0.0-SNAPSHOT: Failed to 
read artifact descriptor for com.acme:core:jar:1.0.0-SNAPSHOT: Could 
not find artifact com.acme:parent:pom:1.0.0-SNAPSHOT in Maven central  
(https://repo1.maven.org/maven2/) -> [Help 1]
[ERROR] 
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR] 
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/DependencyResolutionException

I've read various docs (https://maven.apache.org/guides/introduction/introduction-to-the-pom.html) and some other questions and answers which seem a little dated.

These all state that if I run something like:

# In root project dir
mvn --projects app1 package --also-make

it correctly builds my single module and also any local dependencies, and it does.

However, I want to be able to use my IDE's (IntelliJ, in this case) Maven support and simply be able to run the module's Maven lifecycle task package from my IDE's Maven tool integration window.

Alternatively, at the very least, I'd like to just be able to go into the child module directory and do a mvn package and have it work. I expect that I can have a team member check out the repository and build a single module that they're working on instead of having to build everything (which may take a long time, especially if a core dependency or parent is changed).

How can I do this? Do I have to build from the parent context (i.e. from the root project dir)? If so, why doesn't Maven just tell me that instead of complaining that it can't find a pom.xml that is quite obviously there (and it knows where it is!)?

I know that dependency resolution is a hard problem, but I'm quite annoyed that such a common functionality such as building a child module is seemingly super hard to do with Maven...

filpa
  • 3,651
  • 8
  • 52
  • 91
  • Simple question: did you mvn install the core package firts, then try to mvn package app1 ? It then should work as the core package would be deployed in your local .m2 repo – greg Jan 06 '23 at 11:28
  • I believe I've found the main issue: the parent `pom.xml` is not implicitly installed when installing any of the child modules, hence I have to do a `mvn install` of the parent (in the root project dir) to install (i.e. put in `~/.m2`) it first. This is exactly what I wanted to avoid. It seems that I have to structure my project like the [example 2](https://maven.apache.org/guides/introduction/introduction-to-the-pom.html#example-2) in the documentation for what I want to do to work somewhat.. – filpa Jan 06 '23 at 13:23
  • 1
    What you have to do is to mvn deploy your parent pom into your nexus or whatever jar server. Then your teammates will be able to work on a single module without having to check out everything – greg Jan 06 '23 at 13:33

1 Answers1

1

All dependent packages need to be deployed in the local or distant repo before being resolved as dependencies in any of your module.

To deploy a module on which you depend (e.g core module) in the local repo use the mvn install command.

Then the mvn packages command should work in the app1 module.

Furthermore in your case you used

<relativePath/> <!-- lookup parent from repository --> 

Which means that to be able to resolve the parent pom from any child module the parent-pom shall also be deployed in a local or distant repository. In your case you also have to mvn install the parent pom.

mvn package does not make your module "visible" to others, it just package everything by default in the target folder of the module. To make it visible locally use mvn install.

Finally for your team to be able to work as you wish you must deploy your jars including the parent pom in a remote / shared jar repository like Nexus for instance. For that you use the mvn deploy command. But naturally, you need to set up all the deploy configuration and server beforehand... Then it would work as you expect

greg
  • 306
  • 1
  • 13
  • Unfortunately that leads to the same error message as before. What I did exactly: `cd core/; mvn install; cd ../app1; mvn package`. – filpa Jan 06 '23 at 12:17
  • Can you try with cd core, then mvn clean install. then cd../app1 and mvn clean package ? – greg Jan 06 '23 at 12:32
  • That unfortunately has the same result as before. What's weird is that it is complaining that it cannot find the parent `pom.xml`... – filpa Jan 06 '23 at 13:14
  • 1
    Ah ok :) You have to install the parent pom as well so mvn install in the parent pom folder should fix the issue. This is because you set wich forces maven to look up the parent pom in the repo – greg Jan 06 '23 at 13:24
  • 1
    Thanks. I'll accept this since it helped me find out the root cause. To be specific: what I ended up doing is `mvn install -N` in the parent, which installs the `pom.xml` locally (later `deploy` instead of `install`). After that, other components can be built locally using `mvn package`. It's not perfect, but it beats having to install everything as long as it's documented behaviour. – filpa Jan 06 '23 at 13:37
  • 1
    Ok tx, you'll need to deploy into your own jar repository server if you want to achieve your goal. And then it will work as you expect – greg Jan 06 '23 at 13:38