Run a multi-module Maven project - java

This is a basic question, I'm just not really familiar with maven multi-module structures. Say, I have a web application. And I want to connect some modules to it (some services). Do I need to make a web app just one of the modules, dependent from some others, and then run it? At first I thought I could run the whole project, but this option turns out to be inactive in my IDE (I'm using NetBeans now), which made me think I should run something like a main module (a web app in this case). Is it so? Thanks in advance.

If you have a multi-module project you need a structure like the following which will also be represented by the folder structure as well.
+-- root (pom.xml)
+--- module-1
+--- module-2
+--- module-war
Whereas the root module contains a thing like this:
<project ..>
<groupId>com.test.project</groupId>
<artifactId>parent</artifactId>
<version>1.0-SNAPSHOT</version>
<modules>
<module>module-1</module>
<module>module-2</module>
<module>module-war</module>
</modules>
</project>
In the module-1 your pom should look like this:
<project ..>
<parent>
<groupId>com.test.project</groupId>
<artifactId>parent</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>module-1</artifactId>
dependencies for the module
</project>
in module-2 it look more or less the same..and in the war module it looks like:
<project ..>
<parent>
<groupId>com.test.project</groupId>
<artifactId>parent</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<packaging>war</packaging>
<artifactId>module-war</artifactId>
dependencies for the module
</project>
If you have dependencies between the modules for example module-1 depends on module-2 it looks like the following in module-1:
<project ..>
<parent>
<groupId>com.test.project</groupId>
<artifactId>parent</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>module-1</artifactId>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>module-2</artifactId>
<version>{project.version}</version>
</dependency>
..other dependencies..
</dependencies>
</project>
To build and package your project you will go to parent folder and do simply a
mvn clean package

Related

.getResource("/filename") returns null when maven packaging is pom

I have a Maven project with a submodule, developed in IntelliJ, using Java 11.
Unless the pom.xml file contains <packaging>pom</packaging>, there is a warning that
'packaging' with value 'jar' is invalid. Aggregator projects require 'pom' as packaging.
But when packaging is set to "pom", the resource file that I need can't be loaded; a null value is returned, and an exception is thrown. From the main() method:
URL resource = getClass().getResource("/fx/gui.fxml");
Objects.requireNonNull(resource);
On the other hand, sometimes the submodule is not found, unless I ask for pom packaging. What I do then is: Request pom packaging, start the program and watch it fail, remove the pom packaging statement from pom.xml, start again and the program works.
My resource file is in the standard location src/main/resources/fx/gui.fxml. This location is also given in the pom file:
<build>
<sourceDirectory>${project.basedir}/src/main/java</sourceDirectory>
<testSourceDirectory>${project.basedir}/src/test/java</testSourceDirectory>
<resources>
<resource>
<directory>${project.basedir}/src/main/resources</directory>
</resource>
</resources>
</build>
Please help me understand what's going on. Do I need pom packaging, and how can resources be loaded with it?
Looks like you have your source code in your parent pom.
A parent pom (with sub-modules) must have packaging as pom and cannot have java source code. See this question
You should move your code in a new sub-module.
The project or module which contains the source code, has to have the packaging as jar/war as per your requirement. It can not be packaging as pom. Generally pom packaging is used with parent module when you have multimodule project structure and the submodules would have packaging as jar/war. So in your case, if you have multimodule project structure, your parent packaging would be "pom" and all submodules(contain source code) must have jar/war. Note : Your parent module should not have source code, if it is then move your source code to submodule. Multimodule project structure is basically used where there are common dependencies and artifacts can be used in multiple submodules so that duplication can be removed.
Like below.
parent pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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>org.abc.test</groupId>
<artifactId>testartifact</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>pom</packaging>
<properties>
<java.version>1.8</java.version>
</properties>
<modules>
<module>rest-services</module>
</modules>
</project>
Submodule pom.xml
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.abc.test</groupId>
<artifactId>testartifact</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>rest-services</artifactId>
<name>rest-services</name>
<dependencies>
<dependency>
</dependency>
</dependencies>
</project>

How do I manage version numbers with modularized Maven projects?

I have a fairly typical plugin architecture that looks something like this (just larger):
project
core
data
main
ui
The parent project has a version number defined, is packaged as a pom and defines modules in it's pom.xml:
<groupId>group</groupId>
<artifactId>project</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
...
<modules>
<module>core</module>
<module>data</module>
<module>main</module>
<module>ui</module>
</modules>
All of the sub-modules have many references to the parent's version number everywhere. Here is the an example of what the main module looks like to give you an idea:
<parent>
<groupId>group</groupId>
<artifactId>project</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<groupId>group</groupId>
<artifactId>project.main</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>group</groupId>
<artifactId>group.core</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>group</groupId>
<artifactId>group.data</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>group</groupId>
<artifactId>group.ui</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
We're getting tired of having to change the version number over, and over, and over with each release in every parent block, in every artifact block, and in every dependency block for each and every module. On a few occasions, someone used search/replace which hit other files and messed up the build. We tried using properties, but that doesn't work inside the parent definitions for some nonsensical reason.
The version number defined in the parent is the only place we care to manage. We don't even need the sub-modules to even HAVE versions (or artifacts, for that matter). We can do this in our other Ant projects. We can do this in our other Gradle projects. I can't imagine this being impossible in Maven, so I am guessing we are missing something.
How can we define the project's version number in one place, and have that used in all of the parent, artifact, and dependency sections in our modules?
Version maven plugin offers the possibility of changing the subprojects version in one shot. After including the plugin:
mvn versions:set -DnewVersion=<your version>
And if everything is correct:
mvn versions:commit

How to make existing maven parent project, child of newly created maven project

I have existing maven Project(named as projectB) that is parent of other Projects(projectC and projectD), and I want to make projectB as child of newly created maven Project(named as projectA). This is Directory structure:
projectA
-> pom.xml
projectB
-> pom.xml
projectC
-> pom.xml
projectD
-> pom.xml
This is how my pom.xml of projectA looks:
<modules>
<module>projectB</module>
</modules>
And this is my pom.xml of projectB Looks:
<parent>
<groupId>(groupId of projectA)</groupId>
<artifactId>projectA</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modules>
<module>../projectC</module>
<module>../projectD</module>
</modules>
But when I perform make clean on projectA it gives me error:
Child module C:\Users\projectB of C:\Users\projectA\pom.xml does not exist
I have searched existing solutions, but none has helped me in solving the problem.
Since your all projects are all in the same level, you should have:
In Project A:
<modules>
<module>../projectB</module>
</modules>
And in Project B:
<parent>
...
<relativePath>../projectA/pom.xml</relativePath>
</parent>
Below Configuration in pom.xml of Project B is incorrect
<parent>
<groupId>(groupId of projectB)</groupId>
<artifactId>projectB</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
In parent section, you have to specify Project A not B. Something like below should help
<parent>
<groupId>(groupId of projectA)</groupId>
<artifactId>projectA</artifactId>
<version>(Project A version)</version>
</parent>

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 issue to build one module using revision property

Recently we tried to deploy files using jenkins providing ${revision} property for the build ( Maven 3.3.9 ).
It worked OK on json creating 0.0.1-SNAPSHOT for dev builds and 0.0.1-RC for releases, but we have an issue using maven on developer machines.
We have multi-module maven project with version defined in parent and some modules uses others as dependencies. Both build it from jenkins and use maven locally, to integrate with IDEs and run tests before pushing it into repository.
When we try to build a single module, maven does not recognize ${revision}, although it works fine when we mention all modules e.g. mvn clean install -pl appserver, we see
Failed to execute goal on project appserver: Could not resolve dependencies for project com.org:appserver:war:0.0.1-local: Failed to collect dependencies at com.org:my-kinesis-events:jar:0.0.1-local: Failed to read artifact descriptor for com.org:my-kinesis-events:jar:0.0.1-local: Could not transfer artifact com.org:my-parent:pom:${revision} from/to central: Failed to transfer .../repository/maven-central/com/org/my-parent/${revision}/my-parent-${revision}.pom. Error code 500, Server Error -> [Help 1]
We tried to use:
-Drevision=0.0.1-local
<profile>
<id>default-version</id>
<activation>
<property>
<name>!revision</name>
</property>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<revision>0.0.1-local</revision>
<project.version>0.0.1-local</project.version>
</properties>
</profile>
but the only thing that works is a build for parent that that builds the module and all modules it depends on:
mvn clean install -pl appserver,my-kinesis-events,module1,module2,...
Although the above works it requires from the team to define custom run configuration in IDE, each time they need something.
Did somebody also experienced this issue and found the solution?
Parent pom snippet:
<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.org</groupId>
<artifactId>my-parent</artifactId>
<version>${revision}</version>
<packaging>pom</packaging>
<name>My Parent module</name>
<modules>
<module>../my-tools</module>
<module>my-kinesis-events</module>
....
</modules>
.....
</project>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>my.org</groupId>
<artifactId>my-kinesis-events<</artifactId>
<version>${project.version}</version>
<dependency>
<dependencies>
</dependencyManagement>
Module pom snippet:
<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>
<artifactId>appServer</artifactId>
<parent>
<groupId>com.org</groupId>
<artifactId>my-dsp</artifactId>
<version>${revision}</version>
<relativePath>..</relativePath>
</parent>
<packaging>war</packaging>
<name>AppServerAPI</name>
<description>Application Server</description>
<dependencies>
<dependency>
<groupId>com.org</groupId>
<artifactId>my-openrtb</artifactId>
</dependency>
.....
</dependencies>
....
</project>
These issues have been fixed since Maven 3.5, you need however to use the maven flatten plugin to ensure that all variables are removed from your POM before publishing. Otherwise you end up having POM containing ${revision} has version.
This is neatly explained in the official maven documentation:
https://maven.apache.org/maven-ci-friendly.html#install-deploy

Categories