I have been battling dependencies on a Java Maven multi-module project for a couple of days.
With too little oversight developers managed to create a situation where modules each can be compiled on their own but not as a single whole together. This results in all kinds of errors. Classes that cannot be found, casting errors etc etc. The cause of these problems seems impossible to determine.
My suspicion is that Maven puts conflicting dependencies on the class path. I think we made a mess of the Maven dependencies but regardless I don't understand how Maven can be such a poor performing framework for multi-module projects.
Now I can understand that Maven tries to do very smart useful things when compiling multiple modules as a whole but shouldn't there be an option in Maven to just configure a module to be isolated from other modules? Is there such an option? To avoid this dependency hell?
Or is the Maven best practice to create other scripts, bash scripts for example to be able to compile multiple modules in isolation, with one command?
But that is also poort workaround some tools for example SonarQube require ability to run Maven on the whole code base in order to create a single project in SonarQube.
This results in all kinds of errors. Classes that cannot be found, casting errors etc etc. The cause of these problems seems impossible to determine.
Could you post the error messages? it would make analyzing your issues easier. This may be caused by dependency conflicts, but it is hard to say without more information.
Now I can understand that Maven tries to do very smart useful things when compiling multiple modules as a whole but shouldn't there be an option in Maven to just configure a module to be isolated from other modules? Is there such an option? To avoid this dependency hell?
I do not get this. If two modules do not depend on each other, their builds will be independent. If one module depends on another module and its build fails because of version conflicts, this build will fail regardless of whether it is built together with the other modules or in isolation.
Or is the Maven best practice to create other scripts, bash scripts for example to be able to compile multiple modules in isolation, with one command?
Maven follows the philosophy "convention over configuration", meaning the more you follow the convention, the less configuration you will have and the less maintenance work. Creating all kinds of scripts goes against this philosophy and is not Maven's best practice.
To manage dependency conflicts in a multi module project, you would typically have a parent module with a pom.xml that looks like
<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>...</groupId>
<artifactId>...</artifactId>
<version>...</version>
<packaging>pom</packaging>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-web-api</artifactId>
<version>6.0</version>
<scope>provided</scope>
</dependency>
...
</dependencies>
</dependencyManagement>
<modules>
...
</modules>
</project>
In the dependendencyManagement element you define the version of libraries used. This way you force each module to use the same version of libraries.
For Maven, I often recommend the Java EE NetBeans IDE, because among other things it has a good visualisation tool for dependencies, which is useful in detecting and removing version conflicts. (I am not aware of a similar tool in Eclipse or IntelliJ). If you open a Maven project in NetBeans, click on the pom.xml (in the Projects window) and then select Graph > Show Graph.
I use this tool for 2 things:
remove the transitive dependencies in Maven, otherwise you have to manage more dependencies than required. To remove transitive dependencies, right click in the graph and select the Hierarchical layout. Every dependency that is not on the first line is a transitive dependency and can be removed from the pom.xml.
identifying conflicts between transitive dependencies. (Conflicts are coloured red in the graph.) I resolve these conflicts by explicitly setting the version for the dependencies in the dependencyManagement element in the root pom.xml
Related
I have two Maven projects, A and B, where A depends on B at compile time, but at runtime B needs some classes of A.
What I did is:
A's pom.xml
<dependency>
<groupId>B</groupId>
<artifactId>B</artifactId>
<version>${B.version}</version>
</dependency>
B's pom.xml
<dependency>
<groupId>A</groupId>
<artifactId>A</artifactId>
<version>${A.version}</version>
<scope>runtime</scope>
</dependency>
When letting Jenkins compile the projects it fails to compile each other as a downstream project because it finds the circular dependency and avoid the infinite build loop.
So, what I thought is a way to add the A's runtime dependency only when packaging B (when Jenkins executes mvn package) so that Jenkins does not find the circular dependencies in the pom.xml files and configures the downstream compilation.
Is there any way to accomplish this with an existing Maven plugin or other way?
Thank you
I wrote this Maven plugin for the same reason.
It adds any listed JAR artifact to the WAR file where this plugin is used. JAR dependencies are resolved and added to the WAR file if not artifact with the same version is found.
The important thing is to define dependencies only inside the <dependency> POM section because that's the only configuration used by the Maven reactor.
If you fiddle with custom plugins to introduce your own dependency management ideas you will most likely break the reactor. Even if your custom approach works with regular mvn clean install it will usually explode when -T4 or similar option is used to enable multi threaded builds. There is simply no way to explicitly define the module build order in POM as it's governed by the reactor.
The usual way of sharing code between modules is to create a new module C which is depended on by both A and B.
I have a Maven project with 2 modules. I want the modules to inherit the version of that project, without defining it as a parent in the POM file of any submodules (the reason behind that is that the modules already have parents). What would be the best way to achieve that?
Importing the version from a properties file doesn't work because maven expects a constant value as a project version, not an expression. Maven plugins such as the version maven plugin or the maven release plugin are not solutions to my problem because I need something that would work in an IDE (I have to use Eclipse for packaging the projects, not my call).
Edit
To clarify things (apologies if my original post was not clear enough)
Main Project POM file
...
<groupId>org.mygroup</groupId>
<artifactId>parentproject</artifactId>
<version>1.1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>module1</module>
<module>module2</module>
</modules>
...
Module POM file example
...
<groupId>org.mygroup</groupId>
<artifactId>module1</artifactId>
<version>1.1.0-SNAPSHOT</version>
<packaging>war</packaging>
<parent>
<!-- Some parent that's NOT the main project, e.g. Spring Boot -->
</parent>
...
What I want is a solution that would allow me to set the version only ONCE (e.g. in the main project POM file) and having every module of that project to "inherit" that version.
You should probably set the parent back to your actual parent project. Version numbers between modules can be simultanuously updated using mvn versions:set. If you need the version number for cross-module dependencies, use ${project.version}. If you want to embed another Maven configuration file for its dependencies, consider using a Bill-of-material (BOM): https://stackoverflow.com/a/14876651 . Hope things brings you to your answer!
I really can't think of any Maven facility that fit 100% your necessities. Event if you could set the parentproject as an actual parent on each submodule, you'd need to specify its version in the parent declaration, so...
But I think of a trick to do the job through an authomatism, so that every time the parent version is changed, it will be automatically propagated to each submodule. It can be done like this:
Program a plugin in the parent project that writes the version id on each of its modules' pom files (for example, through an XSL transformation with the xml-maven-plugin).
Then, link this plugin to the package phase, so that every time the parent is build, the versions gets propagated to the submodules.
You only will have to refresh the submodules projects in Eclipse to make Eclipse be aware of the changes.
But if you don't want to refresh manually, there is still another alternative - fully based on Eclipse:
Make an Ant script to perform the copy-version-to-all-module-poms task. And, instead of calling it from a Maven phase, program an Eclipse builder to call it and, within this builder, program also a refresh of the specific modules. So, every time you execute a build of your project, it will copy its version to the submodules and make Eclipse be aware of this change.
I'm developing on an java application that consists on a main-application that is loading extensions (jars) at runtime. Each extension is a java project.
all jars have the main application in class path and other libraries. The manifest of the main application also has dependencies in the manifest classpath, e.g. sqldriver, poi,log4j etc.
Everytime I change on of the lib, i have to set all classpaths of the projects. Also if i want to build all the jars, i have to export each project once.
So I thought maybe is Maven a good solution for me. So I've installed m2eclipse and converted the projects to maven projects.
But for now i have for each projekt an own pom.xml and i also have to build all projects once.
I'm new to Maven and searching for best practises for my problem. So I'll thank you for your help and advice
Make all your projects modules of one parent pom project. This way you can build them all at the same time.
You can use a hierarchy for your pom files. Here's an older question (similar to yours) that has a great example in the answers:
Maven: POM modules and submodules hierarchy
Basically this structure:
<project>
<parent>...
</parent>
<artifactId>module</artifactId>
<packaging>pom</packaging>
<name>Module</name>
<modules>
<module>submodule</module>
</modules>
(...)
</project>
in a 'root' pom.xml file, besides the actual submodule pom.xml files.
Unless you really, really need OSGi , Maven is great. If you're doing OSGi maven is less great.
M2eclipse however is less helpful, and in my experience only leads to confusing headaches.
How you should build your projects depends on a few things. I agree that the submodule approach described in the other answers is best-practice, and if all your sub-module candidates are related (for instance, each represents a tier in a n-tiered application), in the same SCM repository, and the interfaces change often, and the versions are co-dependant then by all means, you should do that.
If however your submodules are stand-alone and don't have a lot of transitive dependencies, particularly if they are in separate SCM repositories, they are independently versioned, and you have a little spare hardware for a build server (like say Hudson) and a Maven2 artifactory (like Sonatype Nexus), you could just keep them as seperate projects, and let maven handle the rest. This way you avoid having to re-build everything because you made a small change in one of the submodules. You can just build that one.
I am using maven 3 for building my huge multi module project. I have nearly 80 projects and many dependencies are used by many project thus makes me to add the same dependency entry in all my projects. In case if i am updating/moving any of my dependency to its latter or earlier version I need to update in all other projects which uses that dependency which is quite impossible.More over it is not possible to create a parent pom for set of projects which has same dependency.
Is there any plugin just to map as below in a pom of parent project
<dependency>somegroup:somefact:anyV<dependency>
<projects>
<project>somegroup:somefact:anyV</project>
</projects>
or is it possible to implement a plugin on my own </br>
or whether maven provide any other way to do this in its style.
Maven has a concept of importing dependencies. The documentation says that this feature is for cases where extending a base POM is not possible. I have not used this feature so I'm not sure how it works, might be what you are looking for though.
If this is answered somewhere else, kindly smack me and point me in the right direction.
I'm brand new to Maven and trying to wrap my head around how to use it with my projects. I've got two top level projects, one a Swing app, the other is a set of Web Services. They both depend on the same in-house jar. What are good ways to set up the poms for this?
If the jar was only used by one of the projects, then it looks like I'd move it down inside and make it a module. But I don't want two (and later more) copies of that jar's source code.
One way it looks like I could do this is to have a master pom for the Swing app that has the Swing app and the library jar as a modules. Then have another master pom for the Web app set up the same way. Would that make sense? Are there better ways?
The directory structure is currently very straightforward:
Development/
----SwingApp/
----WebServices/
----CoreLibrary/
Way too much info and side questions follow:
I've inherited a "build system" (using the term loosely) which is 100% Netbeans autogenerated ant scripts. I started trying to put it into Continuous Integration, TeamCity, which I really like. I've run into serious problems trying to build the WebServices project with it. There are things in the generated ant (build-impl.xml) that cannot be overridden in the CI environment as far as I can tell. Combine this with some serious classpath hell in day to day development and you're starting to see why I want to go to maven.
One of the issues wrapped up in this question is a habit developers on my team all seem to have. Right now the various projects in Netbeans have project references to the "CoreLibrary" project. What this means is that when source is changed in "CoreLibrary" and the developer does a build on a top level app, it will also build the CoreLibrary as necessary. Can that be simulated in Maven? It would go a ways to ease the transition. So far I'm seeing that Netbeans (6.7) doesn't do that with maven builds, and I don't think I can sell (yet) doing the day-to-day build work outside of Netbeans.
Within your Development directory you would have a pom which would look something like the following:
<project>
<groupId>yourGroup</groupId>
<artifactId>project</artifactId>
<packaging>pom</packaging>
<modules>
<module>coreLibrary</module>
<module>swingApp</module>
<module>webServices</module>
</modules>
</project>
yeah, I've left out some of the other elements, so fill in whatever else you need for a complete pom.
Then, your coreLibrary, swingApp, and webServices modules would each have a pom with a parent element, and any dependencies, as follows
<project>
<parent>
<groupId>yourGroup</groupId>
<artifactId>project</artifactId>
<version>yourVersion</version>
</parent>
<artifactId>webServices</artifactId>
<packaging>war</packaging>
<version>yourVersion</version>
<dependencies>
<dependency>
<groupId>yourGroup</groupId>
<artifactId>coreLibrary</artifactId>
<version>yourVersion</version>
</dependency>
</dependencies>
</project>
If you build at the root level, then it will build all 3 modules, or, even better, you could use the --also-make option to build only webServices and its dependencies (in this case coreLibrary)
mvn -am --projects webServices clean install
You shouldn't be adding the .jars into your projects. You should be adding JAR dependencies to your .pom files. Maven will download the .jars for you. You will have to create .pom files for each in-house .jar and add them to your maven repository (or proxy if you have one.)
Technically, there are several solutions to implement this build but, depending on the coupling between these project and their life cycles, you might end up choosing one option or the other. Some questions may help to decide:
Who is building all these projects? A unique team? Separated teams?
Is there any relations between the SwingApp and the WebServices? When you build the SwingApp, does it make sense to build the WebServices? When you release the SwingApp, do you release the WebServices too? Do the SwingApp and WebServices projects always use the same version of the CoreLibrary?
Does it make sense to build the 3 projects together?
Does it make sense to build the CoreLibrary separately and have both projects depend on the produced jar?
Based on the provided informations, my understanding (which may be wrong, it's just an interpretation) is that all 3 projects are actually tightly coupled and developed in the same time, by the same people. When the core library is modified, the dependent project are rebuilt. So, I'd suggest the following multi-modules project:
my-app/ // this is the parent module, it aggregates the child modules
|-- pom.xml
|-- core-library
| `-- pom.xml
|-- swing-app // this module has a dependency on core-library
| `-- pom.xml
`-- web-services // this module has a dependency on core-library
`-- pom.xml
The idea is to put all projects under a parent module and to use both project aggregation and project inheritance:
The parent project will be used to aggregate the child modules. It has a packaging of type pom and declare a <modules> element containing all 3 child modules. By doing so, the parent project now knows its modules, and if a Maven command is invoked against the parent project, that Maven command will then be executed to the parent's modules as well.
Each child module will declare the parent project as <parent>. This is useful to inherit common part from the parent pom
The swing-app and the web-services modules will have a <dependency> on core-library declared in their pom. During a multi-modules build, dependencies are use by maven to calculate the build order.
With this setup, the core-library will be build before swing-app and web-services when running Maven from the top project (this is called a multi modules build or reactor build) which seems to be the desired behavior. This seems thus equivalent to the actual situation without the messy local JARs management (with maven, dependencies are managed through a "local repository" and this is a built-in feature).
Note: If NetBeans doesn't like nested modules, it's possible to use a flat layout like this (but this is more a detail for now):
my-app/
|-- parent
| `-- pom.xml
|-- core-library
| `-- pom.xml
|-- swing-app
| `-- pom.xml
`-- web-services
`-- pom.xml
For implementation details, the Multi Module Project with Eclipse might help you to get started very fast, just skip the Eclipse specific steps. Or check out the Chapter 6. A Multi-module Project of Sonatype's Maven book for a "real" reference.
Let each of the application and the jar library be a module inside a trivial parent. Let both applications depend on the core, and maven will figure out the order in which to build things.
I've got two top level projects, one a Swing app, the other is a set of Web Services. They both depend on the same in-house jar.
Are you using your own Maven repository? If so, the simplest option is to simply deploy the common in-house JAR and have both projects depend on the JAR, using the <dependency> element in the POM.
Nexus is a really great and easy to use repository, if you are going to use Maven in-house then you will no doubt want to run your own repository so you can actually "release" versions of each project, library JARs, etc. Repository Management with Nexus is a free book from Sonatype that details how to use it, best practices, etc.