The whole project dependencies are looking like this:
- parent
- child-a
- pom.xml
- child-b
- src.main.java.resources
- mybatis-generator.xml
- pom.xml
- pom.xml
parent, pom.xml
<project>
<packaging>pom</packaging>
<modules>
<module>child-a</module>
<module>child-b</module>
</modules>
</project>
child-b, pom.xml
<project>
<packaging>jar</packaging>
<parent>
<artifactId>parent</artifactId>
<relativePath>../</relativePath>
</parent>
<dependencies>
<dependency>
<artifactId>child-a</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<!-- other configs -->
</plugin>
</plugins>
</build>
</project>
When packaging child-b project/module solely,all dependencies were handled properly(child-a was imported as expected).
Problem:
When I'm trying to run mvn mybatis-generator:generate in the directory of child-b:
Error: Failed to execute goal on project service_a: Could not resolve dependencies for project xx.xx.child-b:jar:1.0-SNAPSHOT: Could not find artifact xx.xx.child-a:jar:1.0-SNAPSHOT -> [Help 1]
When you run maven from a nested project, it will only succeed if all the dependencies are available in your local repo. I can reproduce this if I delete a dependency from my local repo and try it on one of my projects.
Snapshot dependencies add another level of complexity in that they expire - meaning maven will look for a newer version if the version in your local repo is not considered current. They may be why a package ran at some point, but later on another maven commend like running the generator failed.
Bottom line...when snapshot dependencies are involved with nested projects, the only reliable way to run maven is to run the entire project (run maven from the parent directory).
Related
I have a multi-module Maven project structure with several layers, something like this:
root-module
module-group
war-module
pom.xml
jar-module1
pom.xml
jar-module2
pom.xml
pom.xml
another-module
pom.xml
etc
pom.xml
pom.xml
module-group, another-module and etc have root-module as their parent.
So root-module/pom.xml has this:
<packaging>pom</packaging>
<modules>
<module>module-group</module>
<module>another-module</module>
<module>etc</module>
</modules>
and each of those modules has this:
<parent>
<!-- artifact coordinates etc -->
<artifactId>root-module</artifactId>
</parent>
Then, war-module, jar-module1 and jar-module2 have module-group as their parent. Thus, module-group/pom.xml also includes:
<modules>
<module>war-module</module>
<module>jar-module1</module>
<module>jar-module2</module>
</modules>
war-module has jar-module1 in its <dependecies>, and jar-module1 depends on jar-module2. War-module has <packaging>war</packaging>, jar-* modules have jar.
So dependency chain is like war-module -> jar-module1 -> jar-module2. Versions for each artifact are defined using ${revision} (I'm using Maven3).
I was trying to introduce the dependency chain from war-module in the profiles in war-module/pom.xml:
<profiles>
<!-- this profile is for building with jar-module1 (jar-module2 is resolved transitively) -->
<profile>
<id>profile1</id>
<dependencies>
<dependency>
<artifactId>jar-module1</artifactId>
</dependency>
</dependencies>
</profile>
<!-- this profile is for building without jar-module1 (straight dependency to jar-module2) -->
<profile>
<id>profile2</id>
<dependencies>
<dependency>
<artifactId>jar-module2</artifactId>
</dependency>
</dependencies>
</profile>
</profiles>
However, when I try to build my project (or just module-group or even jar-module1) the process exits with error while packaging jar-module1:
package org.example.package.from.jarmodule2 doesn't exist.
(that package has the only Java class from jar-module2 referenced in jar-module1). However, I have the target folder in my jar-module2 with correct .jar in it. IntelliJ IDEA resolves the classes correctly, only Maven cannot build it right. What might be the problem?
Also, if I introduce the dependency without using profiles, it seems to package correctly. But I need to build different configurations all the time and would really love to not have to change pom.xml every time.
I have multiple spring boot projects, every project is independent and has its own CICD pipeline.
These projects need some common classes, I have created a separate project with common classes.
Parent
pom.xml (with packaging)
lib-project
pom.xml
project-1
pom.xml
project-2
pom.xml
I can build project easily from the parent directory, it builds all the projects
parent$ mvn clean package
it generates all the jar files and put them in their respective target folder of projects
My problem is I can't initiate this at the parent level, this has to be initiated from within each project from its own pipeline.
and
I cannot use any local or remote repository, to put the dependent jar in m2 using mvn clean install and then refer to it as dependency
I want to build it from the relavent project directory
parent/project-1$ mvn clean package
it shows following error:
Could not resolve dependencies for project com.test.multiple:project-1:jar:0.0.1-SNAPSHOT: Could not find artifact com.test.multiple:lib-project:jar:0.0.1-SNAPSHOT
My expectation stepwise on compilation of project-1
Check if there is a dependency for project-1
Go to ../lib-project
Compile and build it in target folder (or anywhere relative to our project)
Add this generated jar to "project-1" dependency
Compile and build the "project-1" jar file.
Parent Pom Configurations
<project ...>
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.test.multiple</groupId>
<artifactId>parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>lib-project</module>
<module>project-1</module>
</modules>
</project>
** Lib project pom **
<project ...>
<parent>
<groupId>com.test.multiple</groupId>
<artifactId>parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<groupId>com.test.multiple</groupId>
<artifactId>lib-project</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>lib-project</name>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Project-1 pom
<project ...>
<parent>
<groupId>com.test.multiple</groupId>
<artifactId>parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<groupId>com.test.multiple</groupId>
<artifactId>project-1</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>project-1</name>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.test.multiple</groupId>
<artifactId>lib-project</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
I have multiple spring boot projects, every project is independent and has its own CICD pipeline.
These projects need some common classes, I have created a separate project with common classes.
Congratulations, your projects are not independent any more!
Given the definitions above, here are the dependencies:
lib-project depends on parent;
project-1 depends on parent;
project-1 depends on lib-project.
Please check Introduction to the POM and Guide to Working with Multiple Modules for the discussion on the dependencies in Maven projects.
I cannot use any local or remote repository, to put the dependent jar in m2 using mvn clean install and then refer to it as dependency
Given this limitation, and dependencies listed above, the POMs and source files of all the projects have to be present on the disk for build purposes. The build process has to start from the parent folder. The build process has to build all modules at once.
Also, please consider using mvn clean verify instead of mvn clean install to avoid populating the local repository with the artifacts you are building.
A maven project isn't designed to build its dependencies on demand. However, jenkins can be configured to build downstream projects when changes are pushed to an upstream dependency.
I have also worked around this by using the -pl option on a parent pom in the relevant jenkinsfile to build a subset of the child projects
Jenkinsfile
clone parent project
mvn clean package -pl core,deployable
In my maven project I need to use some local jar libraries as a dependency.
I'm trying to use this method to configure them in pom.xml:
<repositories>
<repository>
<id>projectName.local</id>
<url>file://${project.basedir}/libs</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.myproject</groupId>
<artifactId>ProjectName</artifactId>
<version>1.0</version>
</dependency>
<!-- other dependencies... -->
</dependencies>
I defined a local repository that points to a libs folder into the project root. Then I placed the jars in this folder:
/libs/org/myproject/ProjectName/1.0/ProjectName-1.0.jar
But, building the project I'm getting this warning:
The POM for org.myproject:ProjectName:jar:1.0 is missing, no dependency information available
And this build failure result:
Failed to execute goal on project my_project: Could not resolve dependencies for project *** : The following artifacts could not be resolved: org.myproject:ProjectName:jar:1.0: Failure to find org.myproject:ProjectName:jar:1.0 in file://C:\Users\David\Documents\NetBeansProjects\my_project/libs was cached in the local repository, resolution will not be reattempted until the update interval of projectName.local has elapsed or updates are forced -> [Help 1]
What am I missing?
I think just copying the jar file will not solve your problem. You will need to install the dependency using Maven itself in that repository using a command like this one:
mvn org.apache.maven.plugins:maven-install-plugin:2.5.2:install-file -Dfile=path-to-your-artifact-jar \
-DgroupId=your.groupId \
-DartifactId=your-artifactId \
-Dversion=version \
-Dpackaging=jar \
-DlocalRepositoryPath=path-to-specific-local-repo
path-to-specific-local-repo should be the path to your local repository (file://${project.basedir}/libs).
Define the pom.xml like dependency.
<dependency>
<groupId>org.myproject</groupId>
<artifactId>ProjectName</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>system</scope>
<systemPath>${project.basedir}/src/main/resources/jarfile</systemPath>
</dependency>
Put the all the files in the folder
You can add your local jar as:
<dependency>
<groupId>com.sample</groupId>
<artifactId>sample</artifactId>
<version>1.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/src/main/resources/Name_Your_JAR.jar</systemPath>
</dependency>
Local works for you by doing above.If you want to pack this local jar in your fat jar then include following line in maven plugin configuration:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<includeSystemScope>true</includeSystemScope>
</configuration>
</plugin>
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
I'm turning a single Eclipse Maven-managed webapp project in a multi-module Maven project (this is a test project to experiment with Maven, so feel free to provide any kind of suggestion).
The single project webapp doean't have any error, succesfully compiles and behaves correctly when deployed, so I'm starting with a working application.
The application has a web part and a console part, meaning that there are some classes with a main() method that when run from within Eclipse (with Run as -> Java Application) work as expected. Both parts show data from a database, queried either directly through JDBC or through jOOQ.
So, this is how I split the project:
core (holds everything common to the other two parts);
runnable (contains the classes that have a main() method);
webapp (the web application part).
Inside Eclipse, I have now 4 separate projects:
shaker-multi holds the aggregator (and parent) POM, plus each module in a subdirectory;
shaker-multi-core;
shaker-multi-runnable;
shaker-multi-webapp.
Inside Eclipse, core and webapp compile, and the latter can be deployed to a Tomcat instance and I can see it in the browser.
The problem arises with runnable. That project relies on jOOQ classes, so the relevant source code must be generated. The jOOQ dependencies and configuration are in core/pom.xml (since they may be used there too).
When I do Project -> Run As -> Maven build... -> clean generate-sources, on shaker-multi-core I get:
Non-resolvable parent POM: Failure to find sunshine.web:shaker-multi:pom:0.0.1
which sounds reasonable, since I didn't install any of those artifacts, even in my local repository.
But when I call Maven build... -> 'clean install' on shaker-multi, it breaks because it can't find the web.xml file for shaker-multi-webapp (although it correctly resides in shaker-multi-webapp/src/main/webapp/WEB-INF/web.xml).
What should I do?
Is my project configuration / splitting totally wrong?
Should I add another module with the parent POM? This sounds wrong, since the POM Reference states:
Inheritance and aggregation create a nice dynamic to control builds through a single, high-level POM. You will often see projects that are both parents and aggregators.
I'm totally lost here.
My expectations:
run Maven package on shaker-multi-webapp and obtain a deployable war;
run Maven package on shaker-multi-runnable and obtain a command line runnable jar (I still need to configure its POM to generate a jar-with-dependencies, though, I know);
run Maven package on shaker-multi and obtain some kind of bundle that I can move around and that will contain the war or the jar of each module.
EDIT
I added
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<webXml>src/main/webapp/WEB-INF/web.xml</webXml>
</configuration>
</plugin>
to shaker-multi-webapp POM, as seen in this answer, but with no difference.
EDIT-2
I cleared my whole local repository (as suggested here), and when I reopened Eclipse, in the Maven console I saw
[...]
05/09/14 07:58:19 CEST: [INFO] Adding source folder /shaker-multi-webapp/src/main/java
05/09/14 07:58:19 CEST: [INFO] Adding source folder /shaker-multi-webapp/src/test/java
**05/09/14 07:58:19 CEST: [ERROR] Could not read web.xml**
[...]
Any hint? From where does it come from? I can't reproduce it though (without removing again my whole local repo).
This is shaker-multi POM:
<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>sunshine.web</groupId>
<artifactId>shaker-multi</artifactId>
<version>0.0.1</version>
<packaging>pom</packaging>
<modules>
<module>shaker-multi-core</module>
<module>shaker-multi-runnable</module>
<module>shaker-multi-webapp</module>
</modules>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
</project>
This is shaker-multi-core POM:
<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>sunshine.web</groupId>
<artifactId>shaker-multi</artifactId>
<version>0.0.1</version>
</parent>
<artifactId>shaker-multi-core</artifactId>
<packaging>jar</packaging>
<build>
<plugins>
<plugin><!-- jOOQ plugin--></plugin>
</plugins>
</build>
<dependencies>
<dependency><!-- jOOQ dependency --></dependency>
</dependencies>
</project>
This is shaker-multi-webapp POM:
<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>sunshine.web</groupId>
<artifactId>shaker-multi</artifactId>
<version>0.0.1</version>
</parent>
<artifactId>shaker-multi-webapp</artifactId>
<packaging>war</packaging>
<build>
<plugins>
<plugin><!-- Tomcat local -->
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>sunshine.web</groupId>
<artifactId>shaker-multi-core</artifactId>
<version>0.0.1</version>
</dependency>
<dependency>
<!-- JSP & Servlet dependencies -->
</dependency>
</dependencies>
</project>
I assume you folder structure is like this:
+-- shaker-multi
+--- pom.xml
+--- shaker-multi-core
+-- pom.xml
+--- shaker-multi-runnable
+-- pom.xml
+--- shaker-multi-webapp
+-- pom.xml
Furthermore you should check if your project works correctly on command and
NOT in Eclipse. So you should go to the root of your project
(shaker-multi folder) and
mvn clean package
This should produce no error etc.
One thing which comes into my mind is why do you use a release version instead of
a SNAPSHOT version for your project. So 0.0.1 instead of 0.0.1-SNAPSHOT?
A thing which you should improve is the definintion of maven-compiler plugin
in your parent:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
I would suggest to do it this way:
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
The encoding can be solved in a better way just define the following in your pom:
<project>
...
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
...
</project>
The above will define the default value for many plugin like maven-compiler-plugin,
maven-resources-plugin etc.
part from that your structure looks good ...one small improvement i would
suggest is if you define dependencies between your module:
<dependencies>
<dependency>
<groupId>sunshine.web</groupId>
<artifactId>shaker-multi-core</artifactId>
<version>0.0.1</version>
</dependency>
<dependency>
<!-- JSP & Servlet dependencies -->
</dependency>
</dependencies>
I would suggest to define inter module dependencies like this:
<dependencies>
<dependency>
<groupId>sunshine.web</groupId>
<artifactId>shaker-multi-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<!-- JSP & Servlet dependencies -->
</dependency>
</dependencies>
The whole problem here was really simple, and I feel a bit ashamed about it: but being the first time I did a multi–module project, I guess that could happen.
Of course, the details here hold when you work with all the project and modules sources by yourself: if you're in a team, working on only a part of the project and / or with a centralized private repository, then YMMV.
First of all, after I splitted the single–project into several modules, this was the situation in my Eclipse Project Explorer:
+-- shaker-multi
^--- pom.xml
^--- shaker-multi-core
^-- pom.xml
^-- (other content)
^--- shaker-multi-runnable
^-- pom.xml
^-- (other content)
^--- shaker-multi-webapp
^-- pom.xml
^-- (other content)
+-- shaker-multi-core
^-- pom.xml
+-- shaker-multi-runnable
^-- pom.xml
+-- shaker-multi-webapp
^-- pom.xml
Each +-- is a single, separated, Eclipse project. Each one of them has been singularly checked out from SVN (so they were, in fact, detached from one another).
I was, then, editing something in +-- shaker-multi-runnable and expecting that to work when I was running Maven on +-- shaker-multi, without svn–committing the former and svn–updating the latter.
That's why I kept getting the error in this question!
The proper way to handle such projects, if they come from an originally monolithic project is:
to split the code, resources, etc in subfolders;
to commit every change to the repository;
to erase every involved project in Eclipse.
Next, you go in the SVN Repositories tab of the IDE, expand the repository with the now splitted project and do Check out as Maven project of the parent–project (the one that has modules as subfolders).
If you, like me, are working with a recent version of Subclipse, you'll need the Maven Eclipse (m2e) SCM connector for subclipse 1.10 (svn 1.8) - update site (thanks go to buluschek development, see the last comments on that post), so that you can choose the repository path from the Check out as Maven Project dialog.
With it, you tell Eclipse to checkout the whole project from the parent folder, and the Eclipse automatically:
fetches all the Maven project modules;
creates a project corresponding to the parent–project, where modules are subfolders;
creates a separate project for every single module
links together each module project with the parent project, so that each edit in a module source code, resource, POM, etc is instantly reflected inside the folders of the parent-project.
That point (4) is the key here: although there are several projects, they have been linked together (I guess the same can be done when manually checking out each module folder, although I do not know how).
After having done this, all the Maven problems I had disappeared.