Maven include parent classes - java

I have a fairly simple maven-ized Java project, but am having trouble getting my head around it.
My parent module defines a lot of Java classes (and dependencies) that I expect to be useful for several child modules. One of the child modules is dedicated to deploying a web app, so it needs a few extra classes (the servlets) plus everything from the parent module.
The file structure looks like this
- parent
- src
- pom.xml
- child
- src
- pom.xml
My parent pom looks like this:
<project>
<groupId>my.group</groupId>
<artifactId>parent</artifactId>
<version>0.0.1</version>
<packaging>pom</packaging>
...
<modules>
<module>child</module>
</modules>
</project>
And the child looks like this:
<project>
<artifactId>child</artifactId>
<packaging>war</packaging>
<parent>
<artifactId>parent</artifactId>
<groupId>my.group</groupId>
<version>0.0.1</version>
</parent>
...
</project>
Is this all I need to have the child know about the classes and dependencies defined in parent? It doesn't seem to be: eclipse gives compile errors, and running mvn clean package from parent folder or child folder results "cannot find symbol" messages any time a class from parent is mentioned.
What am I doing wrong?

I'd change the structure of your project like this:
parent (pom)
core (jar, with all the classes that used to be in parent)
child (war, depends on core)
Parent:
<project>
<groupId>my.group</groupId>
<artifactId>parent</artifactId>
<version>0.0.1</version>
<packaging>pom</packaging>
<modules>
<module>core</module>
<module>child</module>
<!-- possibly more modules... -->
</modules>
</project>
Core:
<project>
<parent>
<groupId>my.group</groupId>
<artifactId>parent</artifactId>
<version>0.0.1</version>
</parent>
<artifactId>core</artifactId>
<packaging>jar</packaging>
</project>
Child:
<project>
<parent>
<groupId>my.group</groupId>
<artifactId>parent</artifactId>
<version>0.0.1</version>
</parent>
<artifactId>module1</artifactId>
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>my.group</groupId>
<artifactId>core</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>

Since your parent module's packaging is "pom", no jar file will be provided and no .class file from that will be accessible to other modules. Try changing it to "jar" and give it another try.
Although it's not a good practice to have a parent as "jar". I'd stick to the "pom" parent and probably create a new "core" or "common" child and make my "war" depend on it.

Try to add an internal dependency in child module pom, so it is familiar with its parent
<dependency>
<groupId>my.group</groupId>
<artifactId>parent</artifactId>
<version>0.0.1</version>
</dependency>

The first thing you should do is to define your dependencies within a dependencyManagmeent block in your parent like this:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>group-a</groupId>
<artifactId>artifact-a</artifactId>
<version>1.0</version>
</dependency>
...
</dependencies>
</dependencyManagement>
and furthermore in your child you should say which dependency your child would like to use as dependency:
<dependencies>
<dependency>
<groupId>group-a</groupId>
<artifactId>artifact-a</artifactId>
<!-- No version given. See dependencyManagement -->
</dependency>
...
</dependencies>

Related

Maven: Dependency to pom module is not include submodules from it

Project have next structure:
root
|
+--Module 1
| |
| +--Submodule_1
| |
| +--Submodule_2
| |
| +--Submodule_N
|
+--Module 2
Module 2 depend on Module 1 and expected access to classes from submodules 1..N
Root pom.xml:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>root</artifactId>
<version>master</version>
<packaging>pom</packaging>
<modules>
<module>Module_1</module>
<module>Module_2</module>
</modules>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
</project>
Module 1 pom.xml:
<project>
<parent>
<groupId>com.example</groupId>
<artifactId>root</artifactId>
<version>master</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>Module_1</artifactId>
<packaging>pom</packaging>
<modules>
<module>Submodule_1</module>
<module>Submodule_2</module>
...
<module>Submodule_N</module>
</modules>
</project>
Submodule_N pom.xml:
<project>
<parent>
<groupId>com.example</groupId>
<artifactId>Module_1</artifactId>
<version>master</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>Submodule_N</artifactId>
</project>
Module 2 pom.xml:
<project>
<parent>
<groupId>com.example</groupId>
<artifactId>root</artifactId>
<version>master</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>Module_2</artifactId>
<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>Module_1</artifactId>
<version>master</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>
So this configuration fail with error package com.example.submodule_n.x.y does not exist.
If add dependency from module 1 to submodule_n than package will be found but maven fail with error ...is referencing itself.
One working case if add dependency from module 2 to submodule_n. But expected way when module 2 will have only one dependency to module 1 for include all submodules from module 1.
It is can do gradle, but I don't have any ideas how it implement using maven.
One working case if add dependency from module 2 to submodule_n. But expected way when module 2 will have only one dependency to module 1 for include all submodules from module 1
That is your expectations that are actually not valid.
The purpose of configuration like:
<modules>
<module>Submodule_1</module>
<module>Submodule_2</module>
...
<module>Submodule_N</module>
</modules>
is to somehow organise project structure, it have nothing in common with dependencies between java libraries (though, it affects build lifecycle), moreover, the configuration like:
<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>Module_1</artifactId>
<version>master</version>
<scope>compile</scope>
</dependency>
</dependencies>
in general does not make sense because library may not depend on pom - actually that just tells maven to build Module_2 after Module_1.
Summarising statements above: if Module_2 depends on Submodule_N you must explicitly define that dependency in pom.xml

Maven nested dependency is not accessible

I have a maven project and in the parent POM and I have declared some dependencies inside this parent POM. This POM is used within the child POM as shown in the code snippet. When compiling the Child project, IntelliJ complains that it cannot find an interface used within the parent project.This interface is declared within the dependency "anotherApp" in the parent POM.
My understanding about Maven dependencies is that, since I have declared the dependency in Parent POM, it should get inherited in the child POM as well and child should be able to access these dependencies and their classes / interfaces without an issue.
I tried adding the dependency inside dependencyManagement tag in parent POM. But cannot achieve what I expect to get. I also looked into the dependency trees of both parent and child projects. In parent, dependency tree shows anotherApp as its dependency, but in child, only parent is shown as a dependency, anotherApp is not shown as a dependency came through parent.
This is how my parent POM looks like
<project>
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>it.app</groupId>
<artifactId>commonParent</artifactId>
<version>1.0-SNAPSHOT</version>
<relativePath>../CommonParent/pom.xml</relativePath>
</parent>
<groupId>com.app</groupId>
<artifactId>parent</artifactId>
<version>0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>com.myapp</groupId>
<artifactId>anotherApp</artifactId>
<version>2.0-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
This is how my child POM looks like
<project>
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>it.app</groupId>
<artifactId>commonParent</artifactId>
<version>1.0-SNAPSHOT</version>
<relativePath>../CommonParent/pom.xml</relativePath>
</parent>
<groupId>com.app</groupId>
<artifactId>child</artifactId>
<version>0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>com.app</groupId>
<artifactId>parent</artifactId>
</dependency>
</dependencies>
</project>
There is an interface Foo declared inside "anotherApp". This interface is accessible by the parent project. But child project cannot access this interface. IntelliJ complains that it cannot access this interface.
Two things that need to be corrected:
The parent POM should have <packaging>pom</packaging>.
The child project should not use the parent POM as dependency, but add it in the <parent> tag.

Build War with multi module project

I have a multi module maven project with three different modules Module-Data, Module-Domain, Module-Web. All three projects are spring boot projects, however Module-Web is the web component of the project that handles everything web oriented which I want to build a war file for. I have a parent project with the following pom file which contains no code.
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.somename</groupId>
<artifactId>My-Project</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>module-data</module>
<module>module-domain</module>
<module>modele-web</module>
</modules>
Module-Domain depends on Module-Data and Module-Web depends on both Module-Data and Module-Domain. The problem I'm having is that when I try to build the project using maven it fails when building the Module-Domain with the following erros:
package com.somename.data.model does not exist // class file with this error
Module-Domain class files that imports from the Module-Data project fails with this error. I suspect this is because maven is not adding the Module-Data jar to the Module-Domain when building although its referenced in its pom file. How can I solve this problem and generate a war file with all dependencies?
Module-Domain pom.xml:
<dependency>
<groupId>com.somename.data</groupId>
<artifactId>module-data</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
Module-Web pom.xml
<dependency>
<groupId>com.somename.data</groupId>
<artifactId>module-data</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.somename.domain</groupId>
<artifactId>module-domain</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
This is a simple straight-forward approach that you are using. Should not cause a problem.
Module-Domain pom.xml:
<parent>
<groupId>com.somename</groupId>
<artifactId>My-Project</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>
<groupId>com.somename.data</groupId>
<artifactId>module-data</artifactId>
<version>0.0.1-SNAPSHOT</version> <!-- Make sure this version is correct -->
</dependency>
</dependencies>
Module-Web pom.xml:
<parent>
<groupId>com.somename</groupId>
<artifactId>My-Project</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>
<groupId>com.somename.domain</groupId>
<artifactId>module-domain</artifactId> <!-- pulls "module-data" as well : transitive dependency -->
<version>0.0.1-SNAPSHOT</version> <!-- Make sure this version is correct -->
</dependency>
</dependencies>
Do maven clean compile on the parent project that would build all the modules.
If you still see any compilation issues, you would need fix the source code.

Maven - dependency management in parent and import scope

The setup is the following:
I am using Maven and I would like to use as a parent POM some artifact that has a number of dependencies in the dependencyManagement section. But I would also like to have a dependencyManagement section in my POM as well, because my artifact will be the parent pom of some other submodules.
Example:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.mycompany</groupId>
<artifactId>parent-pom</artifactId>
<version>1.0</version>
</parent>
<groupId>com.mycompany</groupId>
<artifactId>my-artifact</artifactId>
<version>1.0-SNAPSHOT</version>
<modules>
<module>sub-module-01</module>
<module>sub-module-02</module>
</modules>
<packaging>pom</packaging>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>1.2.3.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
Let's say that both these parent poms define a version for some dependency (let's say the version for jackson), but each has a different version.
When I define that dependency in one of my submodules, which version will be resolved?
I am not sure how to search for this situation on google.
Typically, Maven resolves using the closest version declaration.
My best guess would be that the one from the import in the dependency management section would be preferred, since it is closer to the location where the dependency is used:
dependency -> imported dependency in parent pom = 2 hops
dependency -> parent pom -> dependencyManagement in parent pom = 3 hops
But really, just try it ;)
Let us according to the different case:
Firstly, The simplest case is NO pom dependency import tag in any pom's dependencyManagement section, everything is clear and the dependency declaration will make a really affect with the closest dependency and properties such as exclude will inherit from parent pom and the exclusion with be merged .
Secondly, if the there is a direct declaration in any of each pom's DM section, this declaration will be used for this jar . if not, the closest import dependency declaration if exists will be used to the jar/pom's version. Here the closest mean is the distance to the pom and super pom or ,super super pom. But Not The transitivity distance!
I think it will be the version from import. Because the import
DependencyManagement Just do a replace of dependencies. so Parent dependency will be overwritten by the import dependency. I do not verify this. Just a guess.
I Just do an experiment to check this situation.
Firstly. I define a dependency of netty-handler.
In my maven repository netty-handler version contain:
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-handler</artifactId>
<version>4.1.8.Final</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-handler</artifactId>
<version>4.1.9.Final</version>
</dependency>
I create one test_parent pom project with this content in pom.xml
<groupId>dm-test</groupId>
<artifactId>parent-test-pom</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<dependencyManagement>
<dependencies>
<!-- define a dependency in super parent pom with version 4.1.8.Final -->
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-handler</artifactId>
<version>4.1.8.Final</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
and then create a pom project for import:
<groupId>dm-test</groupId>
<artifactId>import-pom</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<dependencyManagement>
<dependencies>
<!-- define a dependency in super parent pom with version 4.1.9.Final -->
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-handler</artifactId>
<version>4.1.9.Final</version>
</dependency>
</dependencies>
</dependencyManagement>
Finally, I create a war project with the parent_pom and import_pom, like this:
<groupId>dm-test</groupId>
<artifactId>test-project</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<parent>
<groupId>dm-test</groupId>
<artifactId>parent-test-pom</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>dm-test</groupId>
<artifactId>import-pom</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>import</scope>
<type>pom</type>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-handler</artifactId>
</dependency>
</dependencies>
finally, We can see the dependency jar version is 4.1.8.Final
So, My guess is wrong. sorry about that.

Cyclic reference error in maven

Good day,
I am getting an error saying: 'The projects in the reactor contain a cyclic reference'.
Parent pom.xml:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.solveit.cmr</groupId>
<artifactId>cmr-parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>cmr-parent</name>
<modules>
<module>cmr-core</module>
</modules>
<dependencies>
<dependency>
<groupId>com.solveit.cmr.core</groupId>
<artifactId>cmr-core</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>
child pom:
<modelVersion>4.0.0</modelVersion>
<artifactId>cmr-core</artifactId>
<name>cmr-core</name>
<groupId>com.solveit.cmr.core</groupId>
<parent>
<groupId>com.solveit.cmr</groupId>
<artifactId>cmr-parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
How can I fix this problem?
Thank you
The <modules> section tell maven the hierarchy between the parent pom and childs pom.
The parent should contain all the common section to all the modules.
such as <dependencyManagement>, <plugins> and <properties>

Categories