Project structure:
src
- pom.xml (parent POM)
- core (lot of folders, sub-folders, source files)
- deploy
- DTO
- pom.xml
The DTO folder:
uses shade plugin to collect a few classes from core and create a new jar
this new jar has simple POJOs and does not need any dependencies
hence the deployed POM for this jar should not have any parent or dependencies as this jar is used by many other clients (android is one)
however, since the POM in DTO folder is inherited from the parent pom, this parent inheritence is an issue
Question: how can we deploy this jar with a simplified custom POM without any parent?
Possible solution: DTO POM can be without parent. However, we lose many inheritences, such as version, properties, repository etc., which need to be redefined in the DTO POM if it does not have any parent.
Is there a better way of doing this?
Related
I am wondering if there is a way to run a Maven subproject alone. I mean, in several code samples you can find a group of maven projects with a common parent. There is a way to replace parent in order to be able to run just a subproject.
Lets suppose this repository https://github.com/in28minutes/spring-boot-examples
There is way to run just spring-boot-tutorial-soap-web-services/ project?
Thanks in advance.
maven projects are identified by pom.xml and you can run any maven project individually. (Any maven goal).
cd into_a_maven_project(identified by pom.xml).
mvn install(this will run install phase for the project).
There are several relationships among maven projects.
Parent-child
Submodule
Dependency
Parent-child: This relationship is used in defining a pom. For instance, When a set of pom shares a lot, you can define a parent pom(parent maven project) and reference from the child project. (reference is done from child to parent)
When you run child project, the parent project is used only to inherit the pom(copy the content of parent pom). Child pom overrides the configuration in parent pom.(child pom contains little because of the fact that required configurations copied from the parent pom)
Submodule: This relationship is used when it makes sense to build multiple projects together. In this case, you run build in the project referencing submodules. (This is not a parent child relationships, the pom is not inherited if the project is not also a parent). The result is that the submodule projects become part of the build. (The order of the build is determined by dependencies between them)
Dependency: This relationship is used when the code in a project depended by your project. The build order is calculated using this relationship.
I have created a maven goal that outputs a dependency tree for a given maven project to a YAML file. Using the m2eclipse plugin for Eclipse Photon.
Currently when I run the goal against a parent project (using type pom when setting up dependency), the only dependency returned is on the pom for the specific parent. Is there any way to prevent me needing to run this goal against all of the projects underneath the parent?
Might need a little more information on this, but are your children poms of the parent specified as modules within the parent pom?
Example:
<parentPom>
<modules>
<module>/path/to/childA</module>
</modules>
</parentPom>
I'm just curious, what happens if there are used both inheritance and aggregation in the same maven application?
This is the application structure:
my-project-app
my-project-jar
my-project-war
Now, in app's pom.xml, I declare jar and war projects as modules, and in the same time the the poms from both modules declare the app pom as their parent. It is create some kind of redundancy here, isn't it?
What is the best solution for this case?
It's not redundant. They both do different things.
If you use aggregation (define <modules>), you just say which projects have to be built, and its package type is pom.
If you inherit (define <parent>), you'll inherit the parent pom's preferences.
See:
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. For example, the entire maven core runs through a single base POM org.apache.maven:maven, so building the Maven project can be executed by a single command: mvn compile. However, although both POM projects, an aggregator project and a parent project are not one in the same and should not be confused. A POM project may be inherited from - but does not necessarily have - any modules that it aggregates. Conversely, a POM project may aggregate projects that do not inherit from it.
More infos here.
I have a maven project
Parent Project (with the following modules) (package type pom)
API Project (package type jar)
Packaging Project (has a dependency on API Project) (package type custom)
I want to be able to deploy the API project to Nexus repositories so others can leverage that code. The Packaging Project is more of a supporting utility project for a smaller set of deployment use-cases. The Parent Project wraps it all together for me.
When I deploy the API project to the nexus repo, it deploys fine. If i try to make a brand new project that has a depdency on API, it finds the API dependency in nexus but then also wants the Parent project as well. Is there any way to get around publishing the parent project as its really isnt necessary for use of the API lib when used via the nexus repo?
Any tips on how to organize my maven proj to support this?
When you add a <parent> reference to a Maven project what you are doing is saying: "Take all the configuration from that parent and inject it into my model, then override with the following"
Therefore, in order for Maven to build the model of your project, it is necessary for Maven to retrieve the parent itself. In other words, adding a <parent> tag creates an explicit hard dependency between the parent and the child.
The good news is that Inheritance does not have to follow Aggregation. What does that exactly mean?
Aggregation is when you list <modules> in your pom. It tells Maven that the reactor (i.e. the set of projects that Maven builds) should also include the following (sub)projects.
Inheritance is when you set a project's <parent>.
Nowhere does Maven enforce that a project's <parent> has to list its children as <modules> and nowhere does Maven enforce that a projects <modules> must list the project as a <parent>.
Some people will set up their project like so
ROOT/
+- pom.xml
+- parent/
| \- pom.xml
+- api/
| \- pom.xml
\- packaging/
\- pom.xml
where the parent of ROOT, api and packaging is actually a child of ROOT. Or sometimes ROOT will be a standalone project with no parent [In fact this is a pattern I use a lot myself. When I am working on several related project I will throw together an aggregating pom.xml on my local disk and open that with my IDE and that way all the related code is available as one single "project", even though the actual modules may come from different sources]
So in your case the solution would be to remove the <parent> tag from your "API" module.
Now! There is a downside. When you remove the <parent> tag from your "API" module you have removed all the defaults that your parent project is providing, so you will need to copy those defaults that are relevant to the "API" project or else you may find subtle changes in behaviour. For example, you should definately copy over the pinning of plugin versions, and any <dependencyManagement> that is relevant to the "API" dependencies. There are other bits you may have to copy, but you should use the Maven command mvn help:effective-pom before and after removing the <parent> tag as an aid to seeing the effective differences
for my developments I use uber-pom maven plugin which merges information in maven project hierarchy and provides independent pom as result and I publish artifacts in maven central without any extra links to parents
I appologize for the length of this post, but I had trouble making it more concise without presenting the picture. I've recently inherited the job of build-master for a maven 3.0 multi-module project. The problem is that the structure of the project/modules is a disaster. From the way things are currently stored in Source Control (we use RTC) to the pom structure of the modules, I'm tearing my hair out trying to get a full build cycle completed each time.
As a project hierarchy goes, all the modules are stored "flat"; ie: everything is at the same level. I have a parent pom, and all modules depend on the parent. However, the parent is at the same level as all my other modules.
Ex:
c:\dev\MyEarProject
+ parent-pom
- pom.xml
+ module1
- pom.xml (depends on parent-pom)
- src
- main
- ...
+ module2
- pom.xml (depends on parent-pom)
- src
- main
- ...
+ module3
- pom.xml (depends on parent-pom)
- src
- main
- ...
The parent pom defines all the modules required to build the project, as well as a bunch of properties for artifact version numbers used throughout the different submodules:
<modules>
<module>../module1</module>
<module>../module2</module>
<module>../module3</module>
</modules>
<properties>
<org.springframework.version>3.0.5.RELEASE</org.springframework.version>
<slf4j.version>1.6.4</slf4j.version>
<repositoryAddress>${snapshots.repo.url}</repositoryAddress>
<my.hibernate-module.dao.impl>1.2.3</my.hibernate-module.dao.impl>
<my.hibernate-module.dao.api>1.2.3</my.hibernate-module.dao.api>
</properties>
Each module's pom, in turn, depends on the parent pom via the pom's artifact number:
<parent>
<groupId>com.cws.cs.lendingsimulationservice</groupId>
<artifactId>parent-pom</artifactId>
<version>1.0.6</version>
</parent>
To make things even more confusing, the actual artifact name may, or may not (depending on the module), match the module path. For example, module1 may be located in path c:\dev\MyEarProject\module1 but have artifact name hibernate-module. However, due to the way it is stored in RTC, the directory is called module1 when it is checked-out.
The easiest way to build everything, of course, is to go into c:\dev\MyEarProject\parent-pom\ and run mvn clean deploy. This works fine when in SNAPSHOT mode as the SNAPSHOT repo allows for multiple deployments of the same artifact version. But in release mode, this fails.
This structure is causing 2 problems for me.
Everytime I need to make a version change to a property in the parent, I have to update the parent-pom version number, and all the child modules parent pom's version, and all the child modules version themselves (since the parent changed).
Whenever I need to deploy a release cycle, mvn will throw an error if one of the modules has not changed since the last cycle and consequently cannot be redeployed to the same repo (the repo does not allow overwriting existing artifacts)
So I'm looking for the best way to restructure this project to avoid these problems. For the parent pom, I know I can use a relative path to point to the parent instead. However, given the "flat" structure of the modules, is this a recommended approach (ie: the parent pom relative path would be ../parent-pom/pom.xml - seems a little odd to me)? Additionally, given that the versioning control of the parent is independent of the modules, would using a relative path not just open the door to additional confusion (ie: there would be no way to know which version of the parent pom is associated with which version of the submodule).
Secondly, how can I build the entire ear without encountering the deploy errors I am having? Since the artifact already exists in the repo, I don't need to rebuild and redeploy it. I tried using --projects but with the number of modules involved, it gets extremely difficult to manage.
The first thing I really recommend is to restructure the projects folders ...which means to have the projects folder represent the structure which means NOT flatten the structure.
+-- parent-pom (pom.xml)
+--- module1 (pom.xml)
+--- module2 (pom.xml)
+--- module3 (pom.xml)
As a result of that the modules section your parent will be simplified like this:
<modules>
<module>module1</module>
<module>module2</module>
<module>module3</module>
</modules>
Furthermore the parent entries in your modules can be simplified as well like this:
<parent>
<groupId>com.cws.cs.lendingsimulationservice</groupId>
<artifactId>parent-pom</artifactId>
<version>1.0.6</version>
</parent>
...which brings me to the next point:
If all your current project define their parent as above this is simply wrong, cause will try to find the parent within the repository and not in a upper level folder. In other words this is causing of much of your problems with releasing etc.
If we would fix this problem it has to look like this which I can't recommend:
<parent>
<groupId>com.cws.cs.lendingsimulationservice</groupId>
<artifactId>parent-pom</artifactId>
<version>1.0.6</version>
<relativePath>../parent-pom/pom.xml</relativePath>
</parent>
An other thing which I observe is that you don't use SNAPTSHOT's which will be replaced by the release plugin during the release phase. And in relationship to that it will automatically change all versions in the appropriate parents etc.
In ideal case your modules should look like this:
<parent>
<groupId>com.cws.cs.lendingsimulationservice</groupId>
<artifactId>parent-pom</artifactId>
<version>1.0.6</version>
</parent>
<artifactId>module-1</artifactId>
<!-- No Version or groupId -->
Cause all modules will inherit the version and groupId from their parent. Sometimes it's useful or needed to change a modules groupId but it's an exception.
On thing I reread is about the separate versioning of the parent. This simply does not make sense, cause it's the parent of their modules so put it into the same structure and of course the same VCS.
If you want to make some configuration/plugins versions, dependencies which should be used for other projects as well than make a separate corporate pom.xml which is a separate project and will be separately released etc.
After you finished your structure changes you can simply go into the parent-pom directory and do mvn clean package or mvn release:prepare release:perform from that folder and everything will simpler.
If you're publishing your POM, you'll have to release any updates but you don't need to modify POM versions by hand - you can update versions automatically using the versions plugin or the release plugin. I tend to prefer the release plugin as it'll commit to SCM for you too.
mvn versions:set
http://mojo.codehaus.org/versions-maven-plugin/
mvn release:prepare release:perform
http://maven.apache.org/plugins/maven-release-plugin/
Your repository manager may also allow overwriting an existing version but it's better practice to just release a new version.
I tend to prefer the flat module structure as it allows use of the parent folder to store common files e.g. checkstyle configuration. I also find it useful to share the group id across modules then name the module directory the same as the artifactId.
You are presenting contradicting requirements. You want to restructure your project but can't move things around. You want to simplify your deployment and release cycles but do not want to use a single version.
Given that changes in one module will inevitably affect all of the dependent modules, I would use a simple version'ing scheme where all the sub-modules inherit their parent's version. maven release:prepare and release cycles become simple. Use a release notes to track your changes and justify skipping unnecessary testing of unchanged modules (changes to a version do not change the build/binary output of the build process so you can use that as your primary argument).
Good luck with your project.