Parent project to include common maven dependencies - eclipse

I have reached a point where there are a few projects that include the same dependencies.
I want to create a parent project which only contains a pom file where the common dependencies will reside.
Is there any particular type of project I should choose in jBoss/Eclipse that will help me with this parent project creation.

When making such construction, you usually have 2 choices:
1) Using a common parent that defines these dependencies
2) Adding a Maven module of type "pom", that just lists the common dependencies
Integrating solution 1) is easy, just make a module a child of that project (can be a grandchild of course). Dependencies will be inherited.
<parent>
<groupId>com.mycompany</groupId>
<artifactId>my-company-parent-having-common-deps</artifactId>
<version>1.0.0</version>
</parent>
Integrating solution 2) is easy too. Just add a dependency on the pom module wherever it is needed, for instance:
<dependencies>
<dependency>
<groupId>com.mycompany</groupId>
<artifactId>mycompany-module-declaring-bunch-of-deps</artifactId>
<version>1.0.0</version>
<type>pom</type>
</dependency>
</dependencies>
Depending on your project, you'll have to see if solution 1) or 2) suits better.
I recently used a construction like solution 2) when using a JBoss EAP 6 sample: https://github.com/jboss-developer/jboss-eap-quickstarts/tree/6.3.x-develop/helloworld-jms. They created some poms projects to aggregate dependencies that should be used together, such as all dependencies needed for a JMS client.

Related

'parent.relativePath' of imported bill-of materials POM creating warning in Eclipse

Note that this question is about a parent.relativePath warning in an imported bill-of-materials (BOM), not in the hierarchy of my own POM as with 'parent.relativePath' points at my com.mycompany:MyProject instead of org.apache:apache - Why?.
In Eclipse EE 2022-09 using Java 17 I have a a project with a main POM that extends from our own root POM:
<parent>
<groupId>com.globalmentor</groupId>
<artifactId>globalmentor-root</artifactId>
<version>0.8.13</version>
</parent>
The main POM also brings in dependencies from a bill of materials POM (which we also published):
<dependency>
<groupId>io.clogr</groupId>
<artifactId>clogr-bom</artifactId>
<version>0.8.3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
When viewing the POM as source, Eclipse shows this warning:
'parent.relativePath' of POM io.clogr:clogr-bom:0.8.3 points at io.clogr:clogr-bom instead of com.globalmentor:globalmentor-base, please verify your project structure pom.xml /foo-bar
(In case it is relevant, note that I also have the actual source of io.clogr:clogr-bom imported into Eclipse as a separate project.)
I am aware of the purpose of relativePath as used in my own POM and parent POM. But this warning seems to be saying that the it doesn't like the relativePath designation of the imported BOM! Nevertheless the warning references line 5 of my main POM, which is the designation of the parent POM (com.globalmentor:globalmentor-root). Moreover look closely at the error message: it says that the relative path of io.clogr:clogr-bom points to itself! This cannot be the case, as io.clogr:clogr-bom has no relative path designation, and the default I understand is ../pom.xml. There is no way I can think of that io.clogr:clogr-bom could have its relative path pointing at io.clogr:clogr-bom itself.
Why is there a warning for the relativePath of an imported BOM, yet the warning references the line for the parent POM coordinates?
How do I fix this: by publishing a new io.clog:clogr-bom using <relativePath />?
But if I publish a new a new io.clog:clogr-bom using <relativePath />, does that mean the children of io.clog:clogr-bom need to add an explicit <relativePath>../pom.xml</relativePath> on the aggregated children of io.clog:clogr-bom because they are now inheriting a relative path from io.clog:clogr-bom, or will they stil get a default of <relativePath>../pom.xml</relativePath> because the relative path does not inherit?
Eclipse is right: your bom is incorrect, let's elaborate that...
in order to build module pom (project object model, do not confuse with pom.xml) maven needs to know where the parent pom.xml is located (if parent is specified), and here we may raise a question: why do we need to specify both parent GAV coordinates (group-artifact-version) and relativePath? And the rationale is following:
maven may locate artifact using GAV coordinates only when that artifact was installed/published in local/remote repository, if that didn't happen maven obviously fails (example: we are bootstrapping new multi-module project)
technically, there is no strict requirement to publish parent pom files (for example, parent/aggregator pom files may contain some information about our build process and we do not want to expose such information), moreover, there is no requirement for parent modules to be a part of reactor, however in that case you must use flatten-maven-plugin when installing/publishing such artifacts
maven resolves parent's pom.xml using following algorithm:
if relativePath is "specified" maven uses it, please note, the absence of relativePath element means that relativePath is ../pom.xml (that is your case) - to nullify the value of relativePath you need to place <relativePath/> element into parent configuration
otherwise maven tries to locate parent pom.xml using GAV coordinates in local repository and in case of failure in remote repositories
so, the general recommendations when dealing with parents are following:
if parent module is a part of multi-module project set the correct value of relativePath (relying on default ../pom.xml is not good idea though)
if parent module is a not part of multi-module project nullify relativePath via specifying <relativePath/>
take advantage of flatten-maven-plugin
In regard to your clogr-bom - that is definitely not a Bill Of Materials, it is just a published aggregator module, in order to be a bom it's content should be following:
<groupId>io.clogr</groupId>
<artifactId>clogr-bom</artifactId>
<version>0.8.3</version>
<packaging>pom</packaging>
<name>Clogr BOM</name>
<description>Parent POM and bill of materials of all Clogr projects.</description>
<url>https://clogr.io/</url>
<inceptionYear>2016</inceptionYear>
<licenses>
<license>
<name>Apache-2.0</name>
<url>https://www.apache.org/licenses/LICENSE-2.0</url>
<distribution>repo</distribution>
</license>
</licenses>
<organization>
<name>GlobalMentor, Inc.</name>
<url>https://www.globalmentor.com/</url>
</organization>
<developers>
…
</developers>
<scm>
<connection>scm:git:https://bitbucket.org/globalmentor/clogr.git</connection>
<developerConnection>scm:git:https://bitbucket.org/globalmentor/clogr.git</developerConnection>
<url>https://bitbucket.org/globalmentor/clogr</url>
</scm>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.clogr</groupId>
<artifactId>clogr</artifactId>
<version>0.8.3</version>
</dependency>
<dependency>
<groupId>io.clogr</groupId>
<artifactId>clogr-logback</artifactId>
<version>0.8.3</version>
</dependency>
<dependency>
<groupId>io.clogr</groupId>
<artifactId>clogr-logback-provider</artifactId>
<version>0.8.3</version>
</dependency>
<dependency>
<groupId>io.clogr</groupId>
<artifactId>slf4j1-shim</artifactId>
<version>0.8.3</version>
</dependency>
</dependencies>
</dependencyManagement>
UPD.
Q: Thus any POM that will be published as a parent POM or to be imported needs <relativePath/>
A: My opinion on that is following: any published artifact, which is not intended to be parent in any project must strip-off information about parent (that is not just about relativePath element, but about the entire parent element), the rationale is following:
when we consume external dependency, the only information which makes sense for us is it's transitive dependencies, on the other hand specifying parent in external dependency forces maven to resolve that parent as well, and, unfortunately, that process is error-prone because parent may reside in unreachable repository, may contain mistakes, etc - such glitches are pretty common for projects, which we are considering now as "legacy", however, anything what we are doing now will eventually turn into "legacy" as well.
Q: Who says an aggregate POM cannot also serve as a bill of materials by being imported into another project?
A: I do :) Well, actually there is no common opinion about "what is BoM" even across maven team, however I would prefer to share my opinion with Robert Scholte and consider "BoM" as a "Table Of Contents":
To me a BOM represents only the set of modules of a multimodule, that contain the versions that work together. This should prevent issues with dependency depth/distance which could pull in an unexpected version.
Ideally all multimodules also provide a BOM.
Other dependencies don't belong here, as they should be upgradable/downgradable independent of the BOM.

How to do a modular project architecture with Maven in Eclipse?

First of all im a little newbie in Maven+Eclipse world, so please excuse me if im not explaining myself good.
Im trying to implement Maven to existing Java old projects, the architecture im trying to achive is something like this (i put an image to explain myself a little better):
The project Utils have the most of the libs, that genericlly will be used for the other projects, and some classes that will be useful for the others (like date comparison method and mathematic method etc...), this project is working well with mvn install, generating the respective .war file.
The questions are:
The N Web Modules projects must have the project Utils as a
depedency and the most of dependencies too. I
don't know how to achive this in the pom.xml of N Web Modules
projects.
I don't know if it is posible in
Eclipse+Maven: Try to do some Parent Web Project that
implements the other projects and in one single mvn install the
parent project build and install the rest of the childs
(including Utils and N Web Modules).
I hope you can orientate and help me with this.
I think you are looking for Multi-Module projects
http://books.sonatype.com/mvnex-book/reference/multimodule.html
You can put various subprojects in one larger project and build them all at once. Furthermore, modules can depend on other modules (as long as this is not circular) and they are build in the correct order.
The project Utils have the most of the libs, that genericlly will be
used for the other projects, and some classes that will be useful for
the others (like date comparison method and mathematic method etc...),
this project is working well with mvn install, generating the
respective .war file.
One advise, you should extract classes used by other projects in a maven project with a JAR packaging and not leave them in a WAR packaging.
In Maven, generally, dependencies are provided as JAR.
It may also be provided as WAR by configuring the maven-war-plugin with some specific properties such as attachClasses but it looks like a trick and it also may create side effects.
Here are some information on how to do it.
But the documentation doesn't advise this way :
If you need to re-use this JAR/WAR in another project, the recommended
approach is to move the classes to a separate module that builds a
JAR, and then declare a dependency on that JAR from your webapp as
well as from any other projects that need it.
About your two questions.
The N Web Modules projects must have the project Utils as a dependency
and the most of dependencies too. I don't know how to achive this in
the pom.xml of N Web Modules projects.
Just include it as a dependency in the dependencies element of the consumer project :
<?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>mygroup</groupId>
<artifactId>project1-consumer</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
...
<dependencies>
<dependency>
<groupId>mygroup</groupId>
<artifactId>util</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
...
</dependencies>
</project>
I don't know if it is posible in Eclipse+Maven: Try to do some Parent
Web Project that implements the other projects and in one single mvn
install the parent project build and install the rest of the childs
(including Utils and N Web Modules).
What you are looking for is designing a multi-module project.
It relies on a aggregator pom that declares each module.
Note that this module has to be specified with a pom packaging as it doesn't produce a consumable artifact.
You could define something like that :
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>mygroup</groupId>
<artifactId>myaggregatorpom</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<modules>
<module>util</module>
<module>project1-consumer</module>
<module>project2-consumer</module>
</modules>
</project>

Maven - how to add a module in parent project's pom as dependency

I have a situation mentioned in this question.
I have a multi-module Maven project with a parent project P and two sub-modules A and B. When I only had A as a sub module it worked fine. I added a new source folder in the main project, created a package and added a class (am i doing something wrong here?), lets call it module B. Now i import the class in package B in a class in package A, but A's pom doesnt get updated to include B as dependency and thus when I try to mvn compile the parent project it gives the error undefined symbol B.
Am I adding project B wrongly? coz it doesnt have any pom in it?
How do I add B as dependency in main project's pom file as mentioned in the referenced question?
Edit: Adding poms and code
here is project A's pom
<dependencies>
<dependency>
<groupId>javax.slee</groupId>
<artifactId>jain-slee</artifactId>
</dependency>
<dependency>
<groupId>org.mobicents.servers.jainslee.core</groupId>
<artifactId>fault-tolerant-ra-api</artifactId>
<version>2.6.0.FINAL</version>
</dependency>
<dependency>
<groupId>org.mobicents</groupId>
<artifactId>hello-slee-world-sbb</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
nowwhere it has B's dependency mentioned. Here is the reference of B in project A.
import BPackage.*;
this is how I have used B in A.
there is only one class in BPackage named BClass. Now I am asking if I am adding the package wrongly i.e. do I need to maven add some thing? so that its pom gets created and its dependency is added in A.
Furthermore I want to build both B and A when I compile the parent so in that case I guess I need to add A in parents pom as well. Here is the parent's pom
<modules>
<module>sbb</module>
<module>customRAType-ratype</module>
<module>customAdaptor-ra</module>
<module>du</module>
</modules>
customAdaptor-ra is project A
Each of your projects needs to have a pom.xml. The top-level project needs to have
<modules>
<module>project1</module>
<module>project2</module>
</modules>
If project2 depends on project1, you need to define a <dependency/> to it inside project2's pom.xml.

Missing Maven dependencies in Eclipse multi-module project

I’m using STS 2.9.1 (build on Eclipse 3.7.2) with m2e plugin bundled with STS (v1.0.200.20111228-1245).
I have a problem regarding missing dependencies in Eclipse project that contains several modules, or maybe I don’t fully understand how it should work.
It’s a maven project.
In my Project > Properties > Java Build Path > Libraries I have “Maven Dependencies” library, but it's empty (and that’s the problem).
The main POM doesn’t have any dependencies, but it has several modules declared in it.
Adding a dependency to module’s POM doesn’t add it to the “Maven Dependencies” library (what was my expectation) and leads to Eclipse showing errors in source files.
Adding a dependency to the main POM adds it to the “MD” lib, but of course I don’t want to add all of my modules’ dependencies to the main POM just to have it in “MD” lib and adding every single dependency to the Build Path doesn’t seem right nor practical.
I’ve tried:
Project > Clean,
Maven > Update dependencies,
Maven > Update project configuration,
Unchecking the checkbox: Project > Properties > Maven > Resolve dependencies from Workspace projects.
None of the above seems to do the trick.
Example:
Simplified project structure:
simple.project
...
sample-module
...
pom.xml
pom.xml
simple.project/pom.xml:
<project ...>
<modelVersion>4.0.0</modelVersion>
<groupId>test</groupId>
<artifactId>simple.project</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>sample-module</module>
</modules>
<dependencies>
<dependency><!-- This dependency is present in "MD" lib. -->
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
simple.project/sample-module/pom.xml:
<project ...>
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>simple.project</artifactId>
<groupId>test</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<groupId>test</groupId>
<artifactId>sample-module</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency><!-- I've expected this dependency also to appear in "MD" lib. -->
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
It is not supposed to work. A project only imports a dependency from another one if it depends on that project (using dependency) or if it inherits from it (using parent). The module element only represents an aggregation.
The question is from time ago, but I solved this creating a Maven Project and adding Maven Modules: right click on project and "New > Project... > Maven > Maven Module".
After that, no more errors were shown in code.
First thing that I see is that you're defining dependencies in a pom parent. There I would expect to see a <dependencyManagement> (see here the doc) structure. In this way the submodules will inherit properly those common dependencies.
Aside from that lets start for the most simple test. Try to compile your project from the maven utility in the command line. If it works then you have a problem in your Eclipse configuration, otherwise the problem is in the way you have defined your project.
If your project compiles properly from the command line, lets see what else can be happening.
The fact that the Maven Dependencies Library is empty means that the Eclipse Maven plugin is not resolving properly your poms. I had quite bad experiences with the embedded STS maven plugin. Try to downgrade it to the m2e 0.10 version. You only need to open the STS DashBoard / Find Updates / Install m2e 0.10
I hope some of these tips can help you.

Maven and Eclipse code organization

I'm new to Maven, and after having read the docs on the maven site and Sonatype's online Maven book, I'm still not clear on how to best organize things.
I have two apps, A and B which share code from mylib. Different developers work on apps A and app B, they are released independently. Before we started with maven, in Eclipse, I'd have a workspace with apps A and B and mylib. The classpath for app A contained mylib. If I made a change in mylib, pressing run within Eclipse, contained my latest changes.
In Maven, I can create a parent pom.xml, which references app A and mylib. But this makes mylib a subdirectory of app A. How can I keep one instance of mylib and not link the building of apps A and B?
We use SVN for our SCM
Thanks
You have multiple options, however, potentially the simplest approach would be to separate out mylib into its own Maven project with its own life-cycle. The benefit of this approach is that you can support having multiple versions of mylib and your apps A and B can reference different versions of mylib as needed. If mylib and appA are open in Eclipse (and mylib references the version of mylib you have open), you can build the application in the same manner as you did prior to using Maven.
This approach does not mandate any dependencies between the directory structures of the applications, so you could go with something similar to the following:
/myapps/mylib
/myapps/appA
/myapps/appB
The downside to this approach is that maven will not automatically build both appA and mylib (or appB and mylib) as they are treated as separate applications. However, this may not be much of an issue if your applications are using pre-defined and built versions of mylib (that have been uploaded to your local maven repository using "mvn install").
Here is an example of the POMs for these projects:
mylib:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.test</groupId>
<artifactId>myLib</artifactId>
<versioning>0.0.1</versioning>
<packaging>jar</packaging>
<name>mylib</name>
...
</project>
appA:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.test</groupId>
<artifactId>appA</artifactId>
<packaging>jar</packaging>
<name>appA</name>
...
<dependencies>
<groupId>com.text</groupId>
<artifactId>mylib</artifactId</artifactId>
<version>0.0.1</version>
</dependencies>
...
</project>
appB:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.test</groupId>
<artifactId>appB</artifactId>
<packaging>jar</packaging>
<name>appB</name>
...
<dependencies>
<groupId>com.text</groupId>
<artifactId>mylib</artifactId</artifactId>
<version>0.0.1</version>
</dependencies>
...
</project>
If you still want the convenience of a parent POM (one mvn package comment), then you could create a master pom in the /myapps folder similar to the following:
<project>
<groupId>com.test</groupId>
<version>0.0.1</version>
<artifactId>myapps</artifactId>
<packaging>pom</packaging>
<name>myapps</name>
<modules>
<module>shared</modules>
<module>appA</modules>
<module>appB</modules>
</modules>
</project>
This POM will automatically build myapp, appA and appB. If desired you could also create an appA and appB specific POM (pom-appA.xml). This is not the cleanest approach from a Maven perspective, but it will function. The only issue you would run into is if the version of mylib is not the version on which appA or appB is dependent. In that case your appA or appB code would be compiling against the version in your maven repository (if that version exists).
There are many other options you can use as well and I have seen plenty of discussions on Blogs and Wikis as to which is the best for various scenarios. However, it usually comes down to what works best for you and your organization. As long as it works and you are not going off building a custom, non-portable maven solution, then you are probably doing ok.
Hopefully this gives you some thoughts that you can use.