Maven multimodule build. I want to deploy the ear to our Repository, but not the other modules - maven

We have multi-module project that consists of 17 modules. There'a base jar module. There are 15 filter jar modules that depend upon that base jar. Then, there's the Ear that we build that contains the 16 other jars.
We have the build working just fine, but we'd like to deploy our Ear to our Maven repository -- mainly because it'll make it easy for our deployment tools to get to it. Plus, we can easily do that via mvn deploy without having to put together another tool.
The problem is that when we say mvn deploy, we deploy the Ear and the 16 other jars. Those jars are not used in any other project, and we simply don't want them clogging up our Maven repository.
Is there a way to specify that a particular module doesn't get put into the Maven repository when I say mvn deploy?

Looking through the documentation, I found the ${maven.skip.deploy} property. I actually set this to true in the parent project, then set it to false in the EAR build. That does what I want, deploys only the EAR. This way, if another module is added, it will by default not be deployed.
steve c recommended mvn -pl core-ear clean deploy which doesn't work in my circumstance. The module I want to deploy is actually a module of a module, so the main level build doesn't see it.
Our structure is like this:
parent --|
|-engine
|-filter1
|-filter2
.
.
|-distribution --|
|--jar
|--sar
|--ear <-Deploying this one only
khmarbaise mentioned setting <skip>true</skip> in all of the modules except for the one I want to deploy. khmarbaise recommends against this, and I don't blame him. However, there are several issues here. First, we're doing continuous delivery which means that we will have a new version in our repository for each build. I also want to make sure no one tries to depend upon these jars.
I set the property ${maven.deploy.skip} to false in my parent module. This means it's that way in all of my modules and none of them will deploy. I don't need to configure my maven-deploy-plugin in order to set this.
I then set ${maven.deploy.skip} to true in the only module I actually want to deploy (which is the ear module of the distribution submodule). Running mvn clean deploy from the parent now only deploys the ear distribution module I actually want to deploy.

Related

maven pack too many jars to WEB-INF/lib, clear the local repository and re-execut mvn can make things right

In our company, thousands projects are build on 3 servers, with mvn commands.
A few projects occasionally pack too many jars to its WEB-INF/lib folder, the unwanted jars looks like another projects business code and its dependencies.
This is
the diff in WEB-INF/lib between right one(left) and too many jars one(right)
The jar in red frame looks like another project' jars, project name is "jd-common", and the other green jar on right is another project's dependencies.
This situation always reappeared until I clear local repository.
I guess the another project uses "mvn install" to install jars into local repository on build server, and our project is actually depend on jd-common-cached and jd-common-util only.
How can I avoid this?! Thanks for help.
First of all if the jars are there - you depend on them. You may depend on them implicitly (transitive dependencies). Run mvn dependency:tree to list all the dependencies (including transitive). You may find out that you depend on another project that in turn depends on those red/green jars.
Second, on the Build Server you don't want to share local repo with other projects. That's why, at least in Jenkins, there is an option Use Private Repository - this way all the project are going to be separated. This protects you from the situation when the artifact is not in remote repo anymore but the build is still green since that artifact is in local repo. But this has nothing to do with the problem you described.
It's finally be resolved!
The project A depend on a jar which deployed by another project B, the depend jar is a sub-module in B. (A->B)
Unfortunately:
1. A and B are packaged on the same build server
2. B's sub-module jar has the parent config in its pom.xml.
3. B use "mvn clean install -DskipTests" as the build command, so all the B's modules are installed in local repository.
Maven always package the local installed jar, and use the installed jar's pom file to find the sub dependencies, so when maven is executed, project A found that:"one of my depended jar has a parent, it's B, and all the B's sub-modules are found in local repository because of B installed all of them, I should package them all!".

Maven deploy multi module project only if all modules build successfully

I have a maven multi module project with several modules. I want to deploy them (mvn deploy) only if they all pass a full mvn install (which includes the tests).
Currently, I run a mvn install on the project. If all modules pass, I run mvn deploy to do the deployment. The problem I see is the waste of time calling mvn twice (even if I skip tests on the second run).
Does anyone have an idea on this?
EDIT: I have learned that using Artifactory as a repository manager and the maven-artifactory-plugin with your maven setup will add the atomic deploy behaviour to the mvn deploy command. See the Build Integration section in the Artifactory documentation.
[DISCLOSURE - I'm associated with JFrog. Artifactory creator.]
Take a look at the deployAtEnd parameter of Maven Deployment plugin: http://maven.apache.org/plugins/maven-deploy-plugin/deploy-mojo.html
This is a bit tricky. Maven is not atomic when it executes the build life-cycle. So a broken set of artifacts may end up in a repository.
One solution I know is Nexus Pro: http://www.sonatype.com/Products/Nexus-Professional/Features - it allows you to promote builds or define certain repos as staging. So only verified versions get promoted to be used. Maybe artifactory has something similar - I just don't know.
If that solution is too expensive you probably need to create a cleanup build or profile to remove artifacts that where already uploaded. My first guess would be to write a Maven plugin to use the the proxy remote API or maybe the maven features are already sufficient. But since deploy means update the meta-data xml files too I dont think there is a delete - not sure on this either.

Maven: Change the "test" phase directory from local .m2 to target?

Forgive me if this is remedial, but I am still new to Maven and it's functionality.
In my project, when it "builds" and gets to the compile phase, it will create a target directory with just compiled libraries and update (or create if not there) the local .m2 directory.
When I get to the "test" phase, I want it to build against the target directory's library files, and not the local .m2 directory.
Any hints, recommendations, or suggests would be greatly appreciated. Thanks!
Maven has this concept of “the reactor”, which is just a fancy term for the list of projects being built. At the start of a Maven build, and at the end, Maven prints out this list of projects (using /project/name if defined or groupId:artifactId otherwise).
For each project in the reactor, Maven maintains a list of artifacts that have been attached. By default, each module's pom.xml is attached, and as each plugin runs, they have the option of attaching additional artifacts. Most plugins do not attach artifacts, here are some plugins that do:
jar:jar creates a .jar and attaches it
war:war creates a .war and attaches it
source:jar creates a .jar of the source Java code and attaches it with a classifier of source
java doc:jar creates a .jar of the JavaDocs ad attaches it with a classifier of javadoc
There is also a default primary artifact (this is the one that gets replaced by jar:jar) which is actually a directory and not a file, as such it will not get installed or deployed to the local repository cache or a remote repository.
So when in the reactor, and a plugin that attaches the primary artifact has not run yet, and another plugin asks for the primary artifact, it will be given the directory ${project.build.outputDirectory}. If after the primary artifact as been attached, then that primary artifact will be provided.
The test phase happens before the package phase, so will use the directory and not the .jar. The integation-test phase happens after, so will always use the .jar.
Things get more complex in a multi-module project (which is where my long intro should help you out)
Maven has to build the test classpath. If one of the dependencies is within the reactor, Maven will use the artifact attached to the reactor. Otherwise it will use the local cache (populating from the remote repositories if necessary).
When you run
mvn test
In a multimdule project from the root, there is no replacement of the default (directory-based) artifact, so intra-module classpath will be to the target/classes directories.
When you run
mvn package
In the same project, however, because each module completes its life cycle sequentially, all the dependent modules will have swapped in their .jar files as their attached artifact.
All of this should show you that Maven is doing the sensible thing. Hope this has helped.
The test phase is going to execute tests on your project. The project won't reference itself via the dependency mechanism. Only dependencies will be referenced via your local repository, i.e. .m2/repository
Also, it's not the compile phase that installs the artifact to the local repository, it's the install phase. And, then, there's a later phase, called deploy, that will deploy the artifact to a remote repository, provided you have a remote repository configured as the deploy target. Note, install and deploy are nearly identical phases except install is a local only thing; thus, it's the common build phase to hit when doing dev environment work. Normally the build server will do the deploy stuff.

How to rebuild dependencies before running jetty from maven

I have a multi module maven project. One of the modules is a reusable part which is packaged into a jar, and the other is a war web-app which depends on the first module. When I use jetty:run-exploded on the second module, the packaged jar is taken from local maven repository whereas I want the first module to be rebuild and packaged into the resulting war. Is there any way to force such behavior instead of the default one?
From everything I can tell from reading documents about Maven's design and using Maven myself this cannot be done in the projects own directory.
Maven will not follow module paths UP a hierarchy. Using -amd (also make dependencies) will only work at the top level module that ties all the other multi-module pom's together. So what you can do is this:
At the TOP level directory
mvn -amd -pl jetty_module jetty:run-exploded
I think you can use maven Advanced Reactor Options to archive this.
http://www.sonatype.com/people/2009/10/maven-tips-and-tricks-advanced-reactor-options/
The -pl or –projects option allows you to select a list of projects from a multimodule project. This option can be useful if you are working on a specific set of projects, and you’d rather not wait through a full build of a multi-module project during a development cycle.
Maven -amd(also-make-dependents ) also help to build multi module project once. Using that you can build a project and any project that depends on that project.

Best practice wrt. `mvn install`, multi-module projects, and running one submodule

I tend to avoid using mvn install in my multi-module projects because I feel like I then don't know which exact version of a submodule is then used when building / launching other submodules (particularly when switching between branches very often).
I tend to use mvn package a lot and then mvn verify.
I'm now facing the issue in a FOSS project (a Maven archetype moreover) where I'd like to use Maven's best practices.
It's a multi-module project with a webapp submodule depending on the other modules, and what worries me is the ease of development along with mvn jetty:run (or jetty:start).
Currently, I defined 2 profiles:
prod, the default one, declares dependencies on the other submodules;
dev on the other hand does not depend on the other modules, and configures the jetty-maven-plugin by adding the other modules' output directories as extraClasspath and resourcesAsCSV.
That way, I can mvn package once and then cd webapp && mvn jetty:start -Pdev and quickly iterate, reloading the webapp without the need to even stop the server.
AFAICT, extraClasspath was added for that exact purpose (JETTY-1206).
I've been pointed at the tomcat7-maven-plugin which can resolve modules from the reactor build when using Maven 3 (and I raised an issue to bring the same to Jetty: JETTY-1517), but that hardly solve my
If I hadn't removed the dependency on the other submodules from in dev profile, I'd have had to do an mvn install first so that validating the POM doesn't fail, even if jetty:start doesn't use those dependencies afterwards.
So here's my question: is mvn install really that common? or my approach of putting the intra-reactor dependencies only in the prod profile OK?
(note that I have the exact same problem with the gwt-maven-plugin, so please don't tell me to simply switch to Tomcat; that wouldn't even work actually, details here)
The mvn install is common in particular in relationship with multi-module builds, cause it will give you the chance to run a single module from your multi-module build.
This can be achieved by using:
mvn -pl submodule LifeCycle
I just found a workaround (which seems logical as an afterthought): https://jira.codehaus.org/browse/JETTY-1517?focusedCommentId=306630&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-306630
In brief: skip the plugin by default in the parent module then re-enable it where needed.
This however only works if the plugin can be skipped (i.e. has a skip configuration) and is only used in one specific submodule, and it has to be selectively done for each plugin you need/want to run that way (in my case, jetty:run and gwt:run).
I do most of my development on my laptop. For the projects I'm currently working on, my local repository is really more of a temporary holding area. I run mvn install all the time. Putting artifacts in one's local repo is the only way I know of to share built artifacts between projects, especially if you are working on projects which are related but are not (and should not be) part of the same multi-module build.
When I'm done developing I commit changes to the shared SCM and let Jenkins build & deploy the code to the shared remote repo. Then I either blow away the changed projects in my local repository so the next build brings down the freshly built artifacts, or I run Maven with -U to force updates.
This works well for me, YMMV.

Resources