How to build a SVN project which depends on another SVN multi module project in Jenkins? - maven

My multi module project structure is:
Parent project - MyProj
|
|- ChildProj1
|
|- ChildProj2
Another project TestProj depends on child1 and child2.
So, what should be the POM dependencies in TestProj POM file for Jenkins to detect and include the child1 and child2 SVN projects while building and executing the test cases using Jenkins? I have created two projects in Jenkins. TestProj's build is triggered on build completion of MyProj. But, it doesn't seem to work. What should be the dependencies in TestProj POM? I have given the following dependencies:
<dependencies>
<dependency>
<groupId>proj1</groupId>
<artifactId>child1</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>test</scope>
<systemPath>https://subversion.assembla.com/svn/child1/pom.xml</systemPath>
</dependency>
<dependency>
<groupId>proj1</groupId>
<artifactId>child2</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>test</scope>
<systemPath>https://subversion.assembla.com/svn/child2/pom.xml</systemPath>
</dependency>

Dependencies can only be made on jar files which are located locally. if you need systemPath you can use this but it should be prevented...If you need them as it looks like you should create multi module build.
+ (root) pom.xml (modules)
!
+-- child1 (pom.xml)
!
+-- child1 (pom.xml)
which is checked in one into SVN where root is in the trunk of svn repository...

Related

In a multi-module build, why does a child module need to be told where to find the parent POM?

Consider the following scenario of a flat multi-module layout:
| parent-pom
| - pom.xml
| module1
| - pom.xml
Where parent-pom/pom.xml is the parent POM of all modules:
<groupId>my-group</groupId>
<artifactId>parent-pom</artifactId>
<version>1.0.0</version>
...
...
<module>../module1</module>
Now, the pom.xml of module1 contains the following parent section:
<parent>
<groupId>my-group</groupId>
<artifactId>parent-pom</artifactId>
<version>1.0.0</version>
</parent>
I'm starting with a clean local repository; none of the artifacts is pre-built, everything done from scratch. Trying to execute mvn install on parent-pom will result in an error, because the Maven reactor will look for my-group:base-pom in the local repository, fail (because it's not there) and then look for ../pom.xml.
Fine. My question is this: if the build of module1 is invoked through the build of parent-pom, why does Maven even have to look for the parent's pom.xml anywhere? when Maven comes to build module1, it already knows the following things:
The physical location, of the file system, of my-group:parent-pom:1.0.0.
The fact that module1 is rooted in my-group:parent-pom:1.0.0.
Why look elsewhere?
The Introduction to the POM:Project Inheritance:Example 2 told us as the following: -
The Scenario
However, that would work if the parent project was already installed in our local repository or was in that specific directory structure (parent pom.xml is one directory higher than that of the module's pom.xml).
But what if the parent is not yet installed and if the directory structure is
.
|-- my-module
| `-- pom.xml
`-- parent
`-- pom.xml
The Solution
To address this directory structure (or any other directory structure), we would have to add the <relativePath> element to our parent section.
<project>
<parent>
<groupId>com.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<version>1</version>
<relativePath>../parent/pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>my-module</artifactId>
</project>
As the name suggests, it's the relative path from the module's pom.xml to the parent's pom.xml.
EDITED:
The getRelativePath told us as the following
Get the relative path of the parent pom.xml file within the check out. The default value is ../pom.xml. Maven looks for the parent pom first in the reactor of currently building projects, then in this location on the filesystem, then the local repository, and lastly in the remote repo. relativePath allows you to select a different location, for example when your structure is flat, or deeper without an intermediate parent pom. However, the group ID, artifact ID and version are still required, and must match the file in the location given or it will revert to the repository for the POM. This feature is only for enhancing the development in a local checkout of that project.
I hope this may help.

Fully automate release procedure with release+versions plugins

Would be great if Maven guru community can help me with the following task.
I would like to automate the release process of Maven module in Hudson in a way that release process runs in batch mode (does not need anything to be asked from console). Currently I use common steps release:prepare (with <preparationGoals>versions:update-parent clean verify</preparationGoals> to update parent to latest version before commit) + release:perform. However I would like Maven to do the following:
Somewhen during preparation step:
For all dependencies which match the groupId of the current module and parent, replace -SNAPSHOT with released version (e.g. versions:use-releases -Dincludes=???).
Somewhen after release:
For all dependencies which match the groupId of the current module and parent, replace release version with -SNAPSHOT version (e.g. versions:use-latest-snapshots ...).
Example:
<parent>
<groupId>org.mycompany.myproject</groupId>
<artifactId>myproject-parent</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>myproject-api</artifactId>
<version>1.1-SNAPSHOT</version>
</dependency>
before module is tagged is transformed into:
<parent>
<groupId>org.mycompany.myproject</groupId>
<artifactId>myproject-parent</artifactId>
<version>1.0</version>
</parent>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>myproject-api</artifactId>
<version>1.1</version>
</dependency>
and after release is succeeded is transformed into:
<parent>
<groupId>org.mycompany.myproject</groupId>
<artifactId>myproject-parent</artifactId>
<version>1.1-SNAPSHOT</version>
</parent>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>myproject-api</artifactId>
<version>1.2-SNAPSHOT</version>
</dependency>
I feel like it needs a mixture of
versions:use-releases scm:commit release:prepare release:perform versions:use-latest-snapshots scm:commit
but I am not sure what is the best way of doing this. Especially it would be nice to have as less commits as possible: the difficulty is that reparationGoals are run after -SNAPSHOT version check.
The described project is not a multi-module project in a sense that parent POM is not referring it's children via <modules>. SCM structure is the following:
.
|
+-- myproject-parent
| +-- pom.xml
+-- myproject-api
| +-- pom.xml
+-- myproject-impl
+-- pom.xml
Dependencies are:
myproject-api → myproject-parent
myproject-impl → myproject-parent
myproject-impl → myproject-api
The project's parent POM (myproject-parent) will be released rarely and thus will be released first. Then myproject-api (if necessary) and then myproject-impl.
The simple problem you have is that your parent has a different version number than your childs which is the wrong way for a mulit-module build. A multi-module build is intended to have a number of modules related which have the same release process from which follows to have the same version number. If you follow that guideline you don't need the versions plugin you only do the release via release:prepare and release:perform That's it.
Update:
After the further discussion I would suggest to setup a new set of Hudson jobs which contain the dependencies between the modules (downstream/upstream deps.) and do a release on each hudson job which triggers the next in the string of the jobs and so on. This prerequisites to have separate modules and separate areas in the version control as well. Otherwise this fight will be lost with Maven and complicate the life.

Jenkins and maven multi module Projects missing artifacts

This is a simplified example of an ear project, the parent pom aggregates the EAR, the EJBs, and the jars.
I have this structure in a Maven project, stored in SVN:
parent/
|- pom.xml
|- modulA/
| |- pom.xml
|- modulB/
| |- pom.xml
modulB has a Dependency of modulA
The pom.xml have the modules section
<modules>
<module>modulA</module>
<module>modulB</module>
</modules>
And a Dependency Management section
<dependencyManagement>
<dependencies>
<dependency>
<groupId>group</groupId>
<artifactId>modulA</artifactId>
<version>0.0.2-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>group</groupId>
<artifactId>modulB</artifactId>
<version>0.0.2-SNAPSHOT</version>
</dependency>
</dependencies>
</dependencyManagement>
The sub-modules reference the parent
<parent>
<groupId>group</groupId>
<artifactId>parent</artifactId>
<version>0.0.2-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
in my PC when I compile for the first time with maven 2.2.1 (windows)
mvn clean compile
I don't have any problems
but.... when Jenkins try to compile for first time (Maven 2.2.1 Linux RedHat)
Missing:
----------
1) modulA:jar:0.0.2-SNAPSHOT
Try downloading the file manually from the project website.
Then, install it using the command:
mvn install:install-file -DgroupId=group -DartifactId=modulA -Dversion=0.0.2- SNAPSHOT -Dpackaging=jar -Dfile=/path/to/file
Alternatively, if you host your own repository you can deploy the file there:
mvn deploy:deploy-file -DgroupId=group -DartifactId=modulA -Dversion=0.0.2-SNAPSHOT -Dpackaging=jar -Dfile=/path/to/file -Durl=[url] -DrepositoryId=[id]
Path to dependency:
1) modulB:ejb:0.0.2-SNAPSHOT
2) modulA:jar:0.0.2-SNAPSHOT
----------
1 required artifacts are missing.
Why????????
After that if I deploy the project from my pc to Artifactory, Jenkins doesn't have problems, because Jenkins downloads the artifact from the repository... but why does Jenkins depend on the artifacts in the repository?
:(
Thanks in Advance
EDIT:
I thought the dependencyManagement section only "defines" the dependencies, but if a submodule doesn't use the dependency, the dependency isn't added to the submodule.
I drop the dependencyManagement section and the problem in Jenkins still occurs.
It works on my PC without problems.
I hope above dependency management section is inside the parent pom. According to your requirement modulB has a Dependency of modulA. So I suggest you to include dependency in moduleB instead of having it in the parent pom. I think when it runs in first time maven is looking for both dependencies since you have mentioned in in the parent pom.Look at your project build order. First it builds module A and then B. In your case I hope you have include all other dependencies in moduleA's pom file and once it built it will deploy a jar file in to m2 repository. And then moduleB start to build and since your dependency is already in the m2 repository it wont shout and project will build successfully.
The first time you build parent project, your Jenkins user's maven repository won't have modulA installed. clean compile is then run successfully in modulA, but nothing is installed. When it is run in modulB, the dependency on modulA can't be resolved.
If your Jenkins job's goal was clean install instead of clean compile, then modulA's artifacts would be installed to the Jenkins user's repository before the modulB build begins, and all would work.
Presumably this worked on your own machine because either you had run mvn install at least once in modulA, or because your IDE's classpath resolved the problem for you.

Where placed the scm tag?

I have a little probleme with the scm tag in my pom.xml file.
My project architecture is like this:
Parent
Submodule1
Submodule2
reactor
Parent is the project which hold all maven plugins configuration, librairies version ect. It's the parent of reactor project which is the parent of all submodules.
Reactor is a pom.xml which contains tags to compile all submodules.
I would like put the scm tag on the parent pom.xml because it's the higher pom.xml. But I get an error when I want to do a "mvn release:prepare".
So I put the scm tag in the reactor pom.xml and it works.
It's good for me, it works :) but I don't understand why I need to put the scm tag in the reactor pom.
Someone can explain me this behavior ?
Thanks.
Edit:
Here is the folder structure:
root
parent
pom.xml (parent)
submodule1
pom.xml
submodule2
pom.xml
pom.xml (reactor)
Here is the interesting part of pom reactor:
<parent>
<groupId>groupId</groupId>
<artifactId>parent</artifactId>
<relativePath>./parent/pom.xml</relativePath>
<version>1.0.2-SNAPSHOT</version>
</parent>
<modules>
<module>parent</module>
<module>submodule1</module>
<module>submodule2</module>
</modules>
Finally, here is the error for the release:prepare:
[INFO] Unable to tag SCM
Provider message:
The svn tag command failed.
Command output:
svn: Path 'http://10.211.55.4/svn/trunk/reactor' does not exist in revision 112
First requirement is that trunk, tags and branches folder in SVN exist which i assuem but
you have to define the scm part only in the reactor and not in the parent.
root
+-- pom.xml (reactor)
+-- parent
! +-- pom.xml (parent)
+-- submodule1
! +-- pom.xml
+-- submodule2
+-- pom.xml
Furthermore you should define the maven-release-plugin (reactor) as well with true.
The default handling of such situation is that Maven will do relative changing of the SVN paths. This will produces trouble like you have. So you have to put the information into the reactor pom NOT into the parent pom. Very important is to have only a single configuration.
Furthermore i would recommend to remove the parent and put the information into the reactor, cause you would get trouble during site generation phase.
root
+-- pom.xml (parent)
+-- submodule1
! +-- pom.xml
+-- submodule2
+-- pom.xml

Maven - Sharing libraries between projects

I'm working on a multi-project, and right now I have a structure that resembles this (actually there are a couple of jar projects and a couple of war projects)
/myProj
|_______projA (jar)
| |____pom.xml
| |____target/jar files
|_______projB (war)
| |___pom.xml
| |___web-inf/lib/jarfiles
|_______projEar
| |___pom.xml
|___pom.xml
What I want to achieve, is to make projA and projB to read their dependences from a common shared folder, instead of keeping their own copy.
Actually, I don't really care where they read them from at compile time, but when I package my EAR file, I want each jar/war to appear just once, hence reducing the EAR size.
I've tried declaring the dependencies on the parent pom, declaring the dependencies as and some other things, but so far I haven't achieved this.
Is there an easy way to achieve this? Any simple maven plugin?
Thanks in advance.
You should be able to do this by adding the JAR as a dependency to your EAR's pom.xml:
<dependencies>
<dependency>
<groupId>com.mycompany</groupId>
<artifactId>myapp-web</artifactId>
<version>1.0-SNAPSHOT</version>
<type>war</type>
</dependency>
<dependency>
<groupId>com.mycompany</groupId>
<artifactId>myapp-utils</artifactId>
<version>0.0.1-SNAPSHOT</version>
<type>jar</type>
</dependency>
</dependencies>
...and specifying the dependency as provided in your WARs' pom.xml:
<dependency>
<groupId>com.mycompany</groupId>
<artifactId>myapp-utils</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
If Maven/other tooling has already copied the JAR to your WEB-INF/lib directory, you may need to delete the file manually prior to rebuilding.
This should result in an EAR of the form:
META-INF/MANIFEST.MF
lib/myapp-utils-0.0.1-SNAPSHOT.jar
META-INF/application.xml
myapp-web.war
When you are moving to Maven, you should not store the dependency JAR's in your code base. I would suggest you to create a central Maven repository which will contain all the dependencies.
Refer mvn install to first install these artifacts into the local repository. Also, you can refer to the maven central repository to get artifacts while building.
What you need to do is: remove all the dependency jar's from the source code, and all their dependency in the pom.xml. These would be downloaded and packaged from the maven central repository as and when required. Set the Dependency Scope of the artifacts accordingly.

Resources