In Maven, do modules get effected by the repository's updatePolicy? - java

This is just like this other question I asked, but instead of dependencies, this is about modules. Let me give a scenario. You've got a multi-module project and a continuous integration server that deploys the project. This deploys to a repository that your local settings.xml has an updatePolicy of always. Now imagine you run mvn compile right after the CI deploys the project.
Will you end up compiling against the remote server's modules, or your local modules?
In other words, does the updatePolicy of a repository have any effect on the module tags?

modules tag is an aggregation. It is not treated the same as dependencies. Notice that the value that you specify in dependency and module is different. When you declare a dependency, you specify maven coordinates. Whilst for module, you specify relative directories.
Will you end up compiling against the remote server's modules, or your local modules?
You will always end up compiling against your local module if you run the mvn compile in the aggregator module (NOT in the child module!) and the child module dependency is a sibling dependency. When you mvn compile in an aggregator module, the dependency lookup when it is compiling the child module will be special. It will look from the sibling modules target folder ONLY. I can't find documentation on this, but you can try it out.
Imagine that you have these aggregator pom
...
<modules>
<module>child-a</module>
<module>child-b</module>
</modules>
....
child-b pom is declaring a dependency against child-a. (Make sure you have a real output classes)
Next, when you mvn compile the aggregator pom, child-b will be able to compile even if you have NOT mvn install child-a before. That means, child-a is not even in your local repository. This is possible because maven will look into child-a's target folder for the classes. To confirm this, you can try to run mvn compile clean (yes, clean after compile).
Again, do note that this behavior only applies when you run it from the aggregator pom. If your current working directory is child-b (which is dependent on child-a), it will respect the updatePolicy when it tries to look for child-a.

Related

How to work on different interdependent maven modules in IntelliJ [duplicate]

Let's say I have a maven project which has some maven modules inside.
My main module depends on the other modules, so when I compile the main module they should be compiled together.
The question is, how to add these modules as dependencies to the main module?
I know if I have a custom lib that I want to use with maven, let's say a utilities project, I have to compile the jar of the project, do a mvn install:install-file on it to install it on the local repository and then add it to the pom.xml.
Do I have to do this with all my modules and add the dependency to the pom.xml on my main module? Because if it should be done like this, there will be a lot of work to do when changing code on the other modules.
What is the best practice to use avoid the trouble of compiling/installing the modules to local repository?
The question is, how to add these modules as dependencies to the main module?
The same way you add any other dependency to your maven project. By adding group id, artifact id and version to <dependency> element
Do I have to do this with all my modules and add the dependency to the pom.xml on my main module?
If your main module depends on some module A then only the pom of the main module should contain dependency declaration towards module A. You do that for all the dependencies of your module.
I don't know what you mean by "a lot of work when changing the code on other modules". Maven has nothing to do with code changes, it just builds the projects whatever they look like at the given moment...
What is the best practice to use avoid the trouble of compiling/installing the modules to local repository?
Any project that you invoke mvn install on gets built and it's jar copied to local repository. That's all you need to do to get the jar into the repo. This will also put all the dependent jars, if available, into the local repo.
As for best practices for multi module projects:
If your parent project (the one that has modules inside) has <modules> section that lists the modules of your application, and modules are in subdirectories of your parent project, then you simply mvn install (or whatever you want to do) the parent project and that will cause all the modules to be built in order defined by declared dependencies between them. That means that if your main module has dependency on module A, then module A will be built before the main module. This way you can build and install all your modules with one command. On the other hand this approach makes more tight coupling between modules which is not desired in some cases, so it depends on your use case whether it is a good approach or not.

Rebuild dependent projects automatically when building locally

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.

how to define path to superpom?

Any maven experts out there? I inherited a huge maven project and am trying to get it to compile. Not getting very far. I go to the highest level pom.xml I can find, located in trunk directory, one level down from the main project. Then I issue command "mvn validate". Get the following error:
[INFO] Scanning for projects...
Downloading: http://repo1.maven.org/maven2/com/mycompany/neto/vsd/vsd-superpom/1.1.0/vsd-superpom-1.1.0.pom
[INFO] Unable to find resource 'com.mycompany.neto.vsd:vsd-superpom:pom:1.1.0' in repository central (http://repo1.maven.org/maven2)
I noticed a vsd-superpom folder at the same level as the main project so I'm guessing the main project needs to point to it somewhere? Looking at the pom.xml I see
<parent>
<groupId>com.mycompany.neto.vsd</groupId>
<artifactId>vsd-superpom</artifactId>
<version>1.1.0</version>
</parent>
Where do I put the vsd-superpom folder so that it will be found? I don't understand why it tries to download it. I don't see anything in pom.xml that tells it to do that.
Apache Maven has a two level strategy to resolve and distribute files, which we call artifacts. The first level is called the local repository, which is the artifact cache on your system, by default located at ${user.home}/.m2/repository. When executing Maven, it'll first look in this local cache for artifacts. If the artifact cannot be found here, Maven will access the remote repositories to find the artifact. Once found it will be stored into the local repository, so it's be available for current and future usage.
see Apache Maven Install Plugin Documentation
So if your super pom is independent of the rest of the project you can simply invoke mvn install from the super pom folder so that it will be placed into your local repository. That will solve your problem.
Usually the top-level project pom defines the project dependencies and it should be enough to invoke mvn verify | compile | ...
If the top-level pom depends on the super pom that you have to install the super pom first (or define a pom that contains the submodules super pom and rest of the project)
Common project structure what I have seen (and used) is:
foo-parent
pom.xml - parent POM for my modules with parent ../pom.xml
foo-module
pom.xml - module POM with parent ../foo-parent/pom.xml
...other modules...
pom.xml - multimodule POM without a parent
Now if I want to build foo-module I need to be in the top-level folder and run:
mvn -pl foo-module -am package
In other words you are always building the multi-module project. However you can specify that you are interested only in some submodules (-pl) and their dependencies (-am).

make jetty:run auto load dependences during running

I have a maven project which own the following structure:
api(with packaging pom)
pom.xml
api-common(with packaging jar)
pom.xml
api-webapp(with packaging war)
pom.xml
The api is the parent of api-common and api-webapp.
api-webapp have a dependency of api-common.
Now when I run mvn jetty:run inside the api/api-webapp,jetty can not auto load the change of the module api-common.
Any idea?
BTW,I use maven3
Since api-webapp depends on api-common and they are separate projects, api-webapp will look for it's dependencies in the maven repository: your .m2 directory, then the remote repo. You'll need to compile and install your changes in api-common first before api-webapp can see them.
api-webapp has no knowledge of the location of the source of api-common so it can not detect changes. The fact that they share a common parent does not give them the ability to see each other.
That's the general maven answer, but the jetty plugin does provide a workaround to this issue by letting you provide additional classpath for the container. See this defect

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

Categories

Resources