Rebuild dependent projects automatically when building locally - java

I have several Maven projects which share a common parent as following:
project-parent
project-1
project-2: includes project-1
project-3: includes project-2
Here, project-3 has project-2 in its dependencies and project-2 has project-1 in its dependencies, as an example.
When I push a project to git, Jenkins automatically rebuilds to dependent projects. For example, when I push project-3, project-2 will be rebuilt. Because of that, project-1 will be rebuilt as well. This happens because Jenkins has knowledge about the dependency graph.
However, when I build project-3 locally on my development machine, I have to remember to rebuild project-2 (and project-1) as well.
I could add a <modules>...</modules> section to the parent project and simply rebuild the parent project. This will rebuild the whole project, all child projects included. However, I would rather not do that, as there are a lot of projects and some of them require a lot of time to build.
So I want to build one project (the one I'm working on) and somehow automatically (or conveniently) rebuild all dependent projects, similar to the Jenkins behavior. Basically, I want to achieve the Jenkins behavior locally on my development machine. Is this possible?

You can execute the following command from your parent project (assuming you have the my-child-module in the <module>...</module>:
mvn clean install -pl my-child-module -am
This command will build the project my-child-module and its dependencies.
-pl, --projects
Build specified reactor projects instead of all projects
-am, --also-make
If project list is specified, also build projects required by the list
-amd, --also-make-dependents
If project list is specified, also build projects that depend on projects on the list
Source

You can also create an aggregator completely independent of the rest: each <module> point to a path of a folder containing a pom.xml (it may also directly target a pom.xml).
<project>
...
<modules>
<module>project-parent</module>
<module>project-1</module>
<module>project-2</module>
<module>project-3</module>
</modules>
...
</project>
In this scenario, building from that aggregator will allow maven to take full knowledge of your dependency graph and build in order. You will only have to take care to update properly the version to ensure it match (if project-2 depends of version 2 of project-1 and project-1 is in version 3, then this won't work).
You need not put module you don't want, however be aware that if a module have children <module>, it will also build them.

Related

Maven release using multi-module pom

We have many, many different modules that make up different builds. I thought it may be a good idea to create a multi-module pom listing all the modules that would make up a specifc ear.
This post describes reasonably well what I am trying to achieve:
Maven 3 Multi Module build tries to run targets on the Multi Module POM itself
Essentially we have a master pom that defines all the common modules, spring etc.
I have created a separate multi module pom that creates all the modules for a specific build. I want to release all the modules in the modules section but dont want to release the actual multi-module pom itself.
I'm using a command line like:
mvn release:clean release:prepare -DdryRun=true release:update-versions -f My-Multi-Module-1.pom
but this is failing rtrying to release the My-Multi-Module-1.pom.
Can this be done?
Use this
-pl,--projects <arg> Comma-delimited list of specified
reactor projects to build instead
of all projects. A project can be
specified by [groupId]:artifactId
or by its relative path.

Maven how to automate installation of dependencies?

I have 3 projects, A->B->C in that dependency order. Currently everytime I make a change to B or C I have to go to the directory and do a mvn clean install in order to install it into the local repository. It is troublesome if I have to do this every time the projects updates.
How can I do it such that every time I do a mvn clean package on A, it will automatically build and install my dependent projects B and C into the local repository?
Create a parent project for all your projects A,B,C and then add all your child project on the parent pom.xml file something like this
<modules>
<module>A</module>
<module>B</module>
<module>C</module>
</modules>
Its called maven multi module project mentioned by #khmarbaise
Here are some example for this
How do I create a multi-module project in Eclipse?
Maven Multi module tutorial
Guide to Working with Multiple Modules
By use of multi module project you will get plenty of benefits like
Anytime you can add any new project with all of the current project
Separation of project is good for code cleanup
You can build Single project or You can build all project in one go.
Duplicacy of jar can be easily ignore .
Maven take care of the build order for you.
One single Jenkins job to build everything.
Plenty of other benefits.But remember if there will some pros then cons also there,its totally now what you want to use .
You can follow the solution I provided to the question Maven 2 Projects, since it is the pattern I usually use when building project with a certain complexity.
Summarizing you would have to create a main Maven project which has three submodules, say master, platform and parent.
The main project has simply the order in which the other projects will be evaluated by Maven
The master pom contains the list of project to be built and their order (aka Reactor order)
The platform pom contains all information about your platform, like JDK version, maven plugin versions, encoding and so on.
The parent pom has the platform pom as a parent and contains all global GAV information about the dependencies you are going to use in your project (Spring, CXF, junit, log4j etc.)

What is "pom" packaging in maven?

I was given a maven project to compile and get deployed on a tomcat server. I have never used maven before today, but I have been googling quite a bit. It seems like the top level pom.xml files in this project have the packaging type set as pom.
What am I supposed to do after mvn install to get this application deployed? I was expecting to be able to find a war file somewhere or something, but I guess I am looking in the wrong place or missing a step.
pom is basically a container of submodules, each submodule is represented by a subdirectory in the same directory as pom.xml with pom packaging.
Somewhere, nested within the project structure you will find artifacts (modules) with war packaging. Maven generally builds everything into /target subdirectories of each module. So after mvn install look into target subdirectory in a module with war packaging.
Of course:
$ find . -iname "*.war"
works equally well ;-).
pom packaging is simply a specification that states the primary artifact is not a war or jar, but the pom.xml itself.
Often it is used in conjunction with "modules" which are typically contained in sub-directories of the project in question; however, it may also be used in certain scenarios where no primary binary was meant to be built, all the other important artifacts have been declared as secondary artifacts
Think of a "documentation" project, the primary artifact might be a PDF, but it's already built, and the work to declare it as a secondary artifact might be desired over the configuration to tell maven how to build a PDF that doesn't need compiled.
Packaging of pom is used in projects that aggregate other projects, and in projects whose only useful output is an attached artifact from some plugin. In your case, I'd guess that your top-level pom includes <modules>...</modules> to aggregate other directories, and the actual output is the result of one of the other (probably sub-) directories. It will, if coded sensibly for this purpose, have a packaging of war.
To simply answer your question when you do a mvn:install, maven will create a packaged artifact based on (packaging attribute in pom.xml), After you run your maven install you can find the file with .package extension
In target directory of the project workspace
Also where your maven 2 local repository is search for (.m2/respository) on your box, Your artifact is listed in .m2 repository under (groupId/artifactId/artifactId-version.packaging) directory
If you look under the directory you will find packaged extension file and also pom extension (pom extension is basically the pom.xml used to generate this package)
If your maven project is multi-module each module will two files as described above except for the top level project that will only have a pom
Packaging an artifact as POM means that it has a very simple lifecycle
package -> install -> deploy
http://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html
This is useful if you are deploying a pom.xml file or a project that doesn't fit with the other packaging types.
We use pom packaging for many of our projects and bind extra phases and goals as appropriate.
For example some of our applications use:
prepare-package -> test -> package -> install -> deploy
When you mvn install the application it should add it to your locally .m2 repository. To publish elsewhere you will need to set up correct distribution management information. You may also need to use the maven builder helper plugin, if artifacts aren't automatically attached to by Maven.
I suggest to see the classic example at: http://maven.apache.org/guides/getting-started/index.html#How_do_I_build_more_than_one_project_at_once
Here my-webapp is web project, which depends on the code at my-app project. So to bundle two projects in one, we have top level pom.xml which mentions which are the projects (modules as per maven terminology) to be bundled finally. Such top level pom.xml can use pom packaging.
my-webapp can have war packaging and can have dependency on my-app. my-app can have jar packaging.
“pom” packaging is nothing but the container, which contains other packages/modules like jar, war, and ear.
if you perform any operation on outer package/container like mvn clean compile install. then inner packages/modules also get clean compile install.
no need to perform a separate operation for each package/module.
Real life use case
At a Java-heavy company we had a python project that needed to go into a Nexus artifact repository. Python doesn't really have binaries, so simply just wanted to .tar or .zip the python files and push. The repo already had maven integration, so we used <packaging>pom</packaging> designator with the maven assembly plugin to package the python project as a .zip and upload it.
The steps are outlined in this SO post
https://maven.apache.org/pom.html
The packaging type required to be pom for parent and aggregation (multi-module) projects. These types define the goals bound to a set of lifecycle stages. For example, if packaging is jar, then the package phase will execute the jar:jar goal. If the packaging is pom, the goal executed will be site:attach-descriptor
POM(Project Object Model) is nothing but the automation script for building the project,we can write the automation script in XML,
the building script files are named diffrenetly in different Automation tools
like we call build.xml in ANT,pom.xml in MAVEN
MAVEN can packages jars,wars, ears and POM which new thing to all of us
if you want check WHAT IS POM.XML

How do I implement maven source dependency among sibling projects?

I have a java project that is composed of 3 sub projects that generate a .jar artifact each (and have sub-dependencies among them).
In addition there is a web projects that depends on the first 3 projects and generate a war file. The war file is my final artifact, i.e. what I ship my customers.
Additionally I have a parent module that encompasses all the other projects:
<modules>
<module>../core</module>
<module>../commons</module>
<module>../api</module>
<module>../web</module>
</modules>
I generate eclipse files (mvn eclipse:eclipse) and work with eclipse. The problem is if I modify one of the non-web projects I must manually install it before deploying the web project to my web container. How can I make that the web project depends directly on the source code of the others and not on the version installed in the repository.
In your web application properties (right clic on the project in the Package explorer, then "properties"), add the three modules (core, commons and api) in the "J2EE Module Dependencies" (the others modules must be opened in the Eclipse workspace).
Do you want to add a dependency on the source jars deployed to the repository?
If so you can do it by adding the sources classifier to the dependency. See this answer for more details.
If not, can you clarify further please.
I think your problem is that you are just building just the war project. If you are building it from the command line, then what you have to build is the parent module. "mvn package" in the directory that contains the parent module should be enough. Of course this means that you have to build all the packages every time, but that is the way maven works.
The dependency:tree goal by itself will look things up in the repository rather than the reactor. You can work around this by mvn installing, as previously suggested, or doing something less onerous that invokes the reactor, such as
mvn compile dependency:tree
Works for me.
Edit: D'oh! Posted this answer to the wrong question. Was meant to be answering this

Migrating from ant to maven in Netbeans

Our software is written in Java and comprise many (7) projects.
These projects are Netbeans ant projects.
I'm considering to converting them to maven2.
Where can I find some hints for doing such thing?
Don't read that book. It will only make you confused. Read this book instead: "Maven - The definitive guide" http://www.sonatype.com/books/maven-book/reference/ .
Also, the maven site has a lot of information, but the structure is terrible so you'll need to use google to navigate in it.
Here is my suggestion:
Do this by hand, not with "automagic" "help" from the IDE. Maven integration doesn't work that good yet, not in any IDE.
Make sure you program project is divided into modules under a common umbrella module, so that each module produces a single binary artifact (jar, war,...) possibly accompanied by the javadoc of the source code behind that artifact, a zip with the source code etc. The basic principle is that each module produces a single artifact, containing all the non-test-code under that module. You can do this while the project is still built by ant.
Each module should conform to the standard maven directory layout. The build destination is under [module]/target/[output-type, e.g. "classes"]. The source code is under [module]/src/main/[src-type e.g. "java"] and [module]/test/[src-type]. The artifact consists of all the code under src/main, and none of the code under src/test, as it built to the target directories. You can do this while the is still built by ant.
Start by transforming the sub-module that has no dependencies on other modules in the project.
Now you can create the parent maven module pom.xml with artifact type "pom", consisting of one of the modules below. Make a child module for the first submodule (the one with only external dependencies), using the umbrella module as "parent". Remember that you need to specify version for the parent. Remember to add the child module as a "module" in the parent too. Always use ${project.version} as version in the child modules when you create multi-module projects like this. All modules under a parent must be released simultaneously in a single operation, and if you use this setting maven will make sure the version fields stay the same across all modules and gets updated everywhere during the release. This may make it difficult to re-use the existing numbering scheme, but that doesn't matter. You are never going to run out of version numbers anyway.
Add the necessary dependencies, and make sure you can build the parent and the child module together using the command "mvn clean install" from the parent module.
Proceed with the rest of the modules the same way. Dependencies to other modules under the same parent project should also use ${project.version} as the "version" they are depending on, meaning "the same version as this". NOTE THAT in order to build, the module you are depending on must be built using "mvn install", so that it gets deployed to you local (computer) repository. Otherwise the depending module will not be able to find the classes. There are NO source-code dependencies between modules in maven, only dependencies to built and packed versions installed in local and remote repositories. This can be very confusing if you come from ant-projects. Build from the root module until you get comfortable with this. It takes two days.
Don't use maven integration in IDEs. It is a bad idea. Use "mvn idea:idea" or "mvn eclipse:eclipse" to set up your workspace as a non-maven ordinary IDE project. The inter-module dependencies mechanisms in maven and the IDE aren't identical and will never be. Also, if you have several mavenized projects with dependencies in between, you want to have several of these in your workspace with dependencies set up between. You can do this with mvn idea:idea / eclipse:eclipse if you create a separate maven project file called "workspace.xml" (or whatever) in the same directory as parent module, set up as a multi-module project containing modules "." and "../otherproject" (only one-way reference here, no parent ref back). If you run "mvn idea:idea / eclipse:eclipse -f workspace.xml" you get a workspace with all these modules linked together. No IDE integration lets you do that. This sound like a lot of extra work, but the workspace.xml-file is really small. It doesn't have to contain all that dependency stuff and all that, only the reference to the modules you want to bind together in your IDE.
I did a succeful migration of NetBeans Ant project to Maven project using the instruccions by Joseph Mocker here: http://forums.netbeans.org/ptopic55953.html
I cite the important part:
close the project
rename the build.xml, nbproject files/folders to something so NB won't recognize them.
close and restart NB (so any memory cache knowledge of the project is gone)
copy in an empty pom from some other project.
open the project back up in NB (NB should now identify it as a maven project)
rearrange the files to follow the maven way (™)
This won't be an easy task since Maven2 expects the files to be organized in a specific way. Anyway Better Builds with Maven is a free book that should get you started. It will help you understand Maven and it also has a chapter on migration.
I discovered that the migration is not necessary. The real requirements that I need was automatic download of dependencies (libraries).
This is also achieved by Ivy which nonetheless uses maven repositories.
I solved converting project from ant to ant+ivy with IvyBeans.
I have built a script to migrate Ant builds to Maven. You can find more information here:
https://github.com/ewhauser/ant2maven
It won't help you with fixing your directory structure and or any additional Ant tasks, but it removes a lot of the tedious steps to get started.

Categories

Resources