How to get only required dependency from parent dependency maven pom file - java

Can I include only the required dependencies from parent pom(like we have exclude)?
I need this to achieve one scenario
Project A with hibernate and spring as my dependencies(there are
many other)
Project B with only hibernate and spring
Project C with A and B as dependencies
Problem statement : when I run maven install in project C, hibernate and spring are again downloaded separately. This I observed because of the increase in final jar size.
As a work around I included project A as dependency in project C so that I don't need to mention hibernate and spring explicitly.
To avoid this is there a way to include only spring and hibernate from project A?

It sounds like you are guessing what's in the project C jar just based on size. Unzip the final jar (rename to .zip) and look inside to see what jars are actually being packaged to figure that out.
Jars, wars, ears are just zip files with a manifest (more or less).

So, your all dependencies should be defined in parent pom and all your projects here in case A, B and C should be child projects of the parent pom.
In all child poms, you can define all dependencies needed without versions, so that they will be resolved from parent pom.
Interdependency of child projects should be defined only in case of needed. This, to get just dependencies from project A, C should not depends on A.
| - - A
| - - | - - pom.xml
| - - B
| - - | - - pom.xml
| - - C
| - - | - - pom.xml
| - - pom.xml (parent pom)
If you could get this structure as github project, then I can create a pull request with the changes.

To Get Spring Hibernate from you need to make Child Parent relationship A(Parent) and B, C as Child.
Jar file increment mustn't be the case. POM.xml does provide reference of dependencies downloaded in .m2 repo.
For further investigation we need POM.xml

Related

Maven Plugin: accessing resources accross multiple modules

I'm currently writing a custom maven plugin for generating a XML file in a multi-module maven project.
My maven structure is pretty standard: one parent project and a module by project components in the parent project folder:
-- Parent
-- module A
-- module B
-- module C
I need to list, by module, a set of classes flagged by a custom annotation.
I already wrote a set of custom annotations and an annocation processor to create a XML file at compile time in the corresponding module output directory (${project.build.outputDirectory}) .
Now i need to merge each module XML into one file, but i don't know how to access each modules from within my maven plugin except having each path set as parameters (i don't like this method).
Any idea on how to do this ?
Does maven plugins can traverse project modules ?
Thank you in advance.
To get the list list of all projects you can use:
List<MavenProject> projectList = MavenSession.getProjectDependencyGraph().getSortedProjects()
If one of your goals is correctly executed you will get everything you need. Every MavenProject contains a getBaseDir() etc.
After some researches, it seems that MavenProject.getCollectedProjects() will return the list of projects beeing manipulated by a goal execution in a multi-module project.

Spring Boot application with part of JSP files from other Maven module

Let's assume that we have Spring Boot based web application using JSP templates. It can be even as simple as in the following example (from official Spring Projects repository)
Project structure:
|-src/main/java/
| |-sample.tomcat.jsp
| |-SampleTomcatJspApplication.java
| |-WelcomeController.java
|-src/main/resources/
| |-application.properties
|-src/test/java/
| |-...
|-src/main/webapp/
| |-WEB-INF
| |-jsp
| |-welcome.jsp
|-pom.xml
Properties file contains view prefix /WEB-INF/jsp/ and suffix .jsp and when requesting / we see properly rendered content of welcome.jsp.
WelcomeController.java
application.properties
Changes
Now let's make the following changes
Duplicate WelcomeController.java as WelcomeController2.java and change a bit request mapping, model attributes and returned view name, e.g.:
#RequestMapping("/2")
public String welcome2(Map<String, Object> model) {
model.put("message", "Hi from Welcome2");
return "welcome2";
}
Duplicate welcome.jsp as welcome2.jsp so that src/main/webapp will be like this:
|-src/main/java/
| |-sample.tomcat.jsp
| |-SampleTomcatJspApplication.java
| |-WelcomeController.java
| |-WelcomeController2.java
...
|-src/main/webapp/
| |-WEB-INF
| |-jsp
| |-welcome.jsp
| |-welcome2.jsp
Then when requesting /2 we can see properly rendered content of welcome2.jsp.
The question
What is the way of splitting such project into two maven projects, so that both WelcomeController2.java and welcome2.jsp could be moved to other project (maven dependency) and still be successfully resolved when /2 URL is requested?
Note that with Spring Boot web-fragment.xml (that could be placed in META-INF directory of dependency) is ignored.
Unfortunately, I don't know of an easy way to do this but one approach I've used is to create a Maven artifact just like normal for the main project, in your case probably a WAR artifact. This project will need to have a dependency upon your second project. Then your second project would consist of two components:
A standard Maven JAR artifact containing the compiled class files.
A Maven assembly ZIP consisting of the JSP files that need to be included in the WAR archive as well. This will be generated from the second project during the package phase, but will need to be included as a separate dependency on the main project using a zip classifier.
When the first project is built, you'll need to unpack the assembly dependency as part of the packaging process for the WAR archive. If you want this to work in an IDE, you'll probably need to unpack it in a fairly early phase, such as process-resources or generate-sources.

Multimodule maven project - exclusions in depenedency

I want my ModuleTypeA war to include ModuleBase as a dependency with 'src/main/java/typeA' package Excluded and similarly ModuleTypeB war to include ModuleBase as a dependency with 'src/main/java/typeB' package Excluded.
Here is my project structure:
ModuleBase
|
|----> src/main/java/base
|----> src/main/java/typeA
|----> src/main/java/typeB
|----> pom.xml
ModuleTypeA
|
|----> src/main/java/..
|----> pom.xml
ModuleTypeB
|
|----> src/main/java/..
|----> pom.xml
I am new to Maven and not sure how to achieve that. ModuleBase cannot be a parent project as I need to build a jar for that (can't have packaging type pom) so I can create a top level parent project.
Any suggestions are welcome.
Thanks
Normally it should look something like this:
proj
+ proj-base
+ src/main/java/ // containing base code
+ pom.xml
+ proj-mod-type-a
+ src/main/java/ // containing module a code
+ pom.xml // dependency to proj-base
+ proj-mod-type-b
+ src/main/java/ // containing module b code
+ pom.xml // dependency to proj-base
+ proj-a-web
+ src/main/java // war A source
+ pom.xml // dependency to proj-base and proj-mod-type-b
+ proj-b-web
+ src/main/java // war B source
+ pom.xml // dependency to proj-base and proj-mod-type-a
In brief, split your project into meaningful modules, each being a unit for dependency. Construct your WAR base on the dependency you need.
If proj-base is in fact a WAR that you want to reuse its content in other WAR, then you may look closer to behavior of WAR overlay in Maven. However, I believe the basic idea is still the same: better modularize your project and have appropriate dependencies when constructing your WAR/EAR
First, read this article about dependency exclusions:
Optional Dependencies and Dependency Exclusions
If you are building a .war file from ModuleBase, you can make not a dependency but an overlay for ModuleTypeA from ModuleBase and similarly ModuleTypeB war as overlay of ModuleBase. For this, you can use Maven War Plugin:
Maven War Plugin
This way, for exclusion of a package use this in you pom.xml:
<excludes>
<exclude>src/main/java/typeA</exclude>
</excludes>
UPDATE:
I haven't try this yet, but there are two ways possible to exclude a package from .jar.
1) Use Maven Assembly Plugin. Here is an example you can refer to:
Exclude files with maven assembly does not work
2) Use Maven Jar Plugin, check this answer as an example:
maven-jar-plugin Exclusions Failing
You could create different assemblies in the ModuleBase and refer to those as system dependecies in ModuleTypeA/B.
You can set the path to a dependency with <systemPath>../module-base/target/rt.jar</systemPath>
Maybe Multiple assemblies from one maven project will help you with the assembly topic.

How do I compile a single module in a scenario of two multi-module Maven projects

How do I compile a single module in the following scenario of two multi-module Maven projects A and B.
Both projects are located in the same directory so that the directory structure looks like this:
root
|-- A
| |-- A1
| |-- A2
| `-- A3
`-- B
|-- B1
`-- B2
All directories except root have their own pom.xml files and each submodule is referencing its parent module (A1 has parent A, etc.) and the parent is referencing its submodules (A has modules A1-A3). The problem I have is that A1 depends also on B1, since project B is a collection of utilities that I want to use in other projects.
My question is how do I reference B1 correctly so that I can build A1 without having to install B1 first. I mean I want to build A1 with all its dependencies using one maven command.
My current solution is to make B1 a module of A (via module reference ../B/B1). Then I can call mvn package from directory A and it works fine. But building the whole project A is sometimes very time consuming. Therefore I would like to build only A1 + deps. How can I do that? When I call mvn reactor:make -Dmake.folders=A1 from directory A I get the following build error:
Reason: Cannot find parent: B:B for project: B:B1:jar:1.0-SNAPSHOT for project B:B1:jar:1.0-SNAPSHOT
So it seems that maven suddenly cannot find B1's parent module anymore when using the reactor plugin. Does anybody know a solution for that or an alternative approach for referencing a submodule from another project that allows building A1 in the way described above?
Note, I don't want to set up a super module in root that includes modules A and B, because this pom file, because every user that checks out A and B might have also other projects in his root directory and therefore would have to write his own pom file for root.
Simple create a root pom which has modules in there and do referencing the parent in A and B then it would work. Otherwise it does not work.

Can maven projects have multiple parents?

We have Java and Flex projects. We currently have 1 base pom that contains the configurations we want to use for both projects. Problem with this is: Flex projects inherit configuration, for example, for javadoc and pmd plugins, which is not desirable.
I want to clean it up and have a real base pom, and then a java-base-pom and a flex-base-pom. But how does this work in a multi-module that has both a Flex part and a Java part?
We have plugins to our own application where we use the following structure:
my-plugin
my-plugin-client (flex)
my-plugin-server (java)
my-plugin just contains a pom.xml with <modules/> section. I would use my-plugin pom.xml as a parent for both, but then I cannot also use the java base-pom or the flex base-pom as parent. What would be the best approach for this?
Even though maven projects have single parent, they can import any number of other pom's like this:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.example</groupId>
<artifactId>my-shared-dependencies</artifactId>
<version>0.0.1-SNAPSHOT</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
This has two important differences compared to a parent:
Plugins defined in the imported pom won't be imported
Dependencies defined in the imported pom won't be added to the current pom, it will only import dependencies into the dependency management section
However, if your parent pom has a <dependencies> section and you want to include those into your dependencies, then you can add the parent to your <dependencies> section just like a regular dependency:
<dependency>
<groupId>org.example</groupId>
<artifactId>my-shared-dependencies</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
Even though the same dependency is already imported, the version tag has to be specified again. To reduce duplication, it can be stored in a property
A project can have only one parent (unlike multiple inheritance in C++) but this parent can be part of a bigger parent hierarchy. As pointed out by others, you could thus have something like this:
base-pom/
|-- flex-base-pom
| |-- my-plugin-client
| | `-- pom.xml
| `-- pom.xml
|-- java-base-pom
| |-- my-plugin-server
| | `-- pom.xml
| `-- pom.xml
`-- pom.xml
That said, I noticed you wrote that your actual problem is that:
flex projects inherit configuration for javadoc and pmd for example, which they do not want.
You should use the pluginManagement element to avoid this situation:
pluginManagement is an element that is seen along side plugins. Plugin Management contains plugin elements in much the same way, except that rather than configuring plugin information for this particular project build, it is intended to configure project builds that inherit from this one. However, this only configures plugins that are actually referenced within the plugins element in the children. The children have every right to override pluginManagement definitions.
So, in the parent pom, configure your plugins in pluginManagement (javadoc and pmd for example), and reference them within the plugins element in the desired children (only in my-plugin-server here). This would solve your current issue.
The only way is to have base-pom as parent of java-base-pom and flex-base-pom.
I have similar structure for my spring projects:
base-pom (basic configuration - eclipse, reports, repositories, etc)
|
+ spring-base-pom (spring definitions)
|
+ spring-jar-base-pom (jar specific definitions)
|
+ spring-war-base-pom (spring web and servlet dependencies)
|
+ spring-webapp-base_pom (spring web mvc dependencies)
I've cross this exact proble also, and the best solution I found was to use Inheritance and Aggregation as suggest in this question : does maven support multiple parents (multiple inheritance) ?
You can have an aggregator pom that is not the parent of the projects it
aggregates.
and explain in the Maven Documentation
Inheritance and aggregation create a nice dynamic to control builds through a single, high-level POM (...) Conversely, a POM project may aggregate projects that do not inherit from it.
From this I had my POMs inheritance (pom-master contains communes configurations, and each children the specifics ones) :
pom-master
|-- pom-java
|-- pom-flex
and so my project can get the specifics for each modules configurations as wished :
project (aggregate project-flex & project-java)
|-- project-java
| `-- pom.xml => parent = pom-java
|-- project-flex
| `-- pom.xml ==> parent = pom-flex
`-- pom.xml => parent = pom-master
Hope it will help others as well :)
Just image that pom.xml are in fact Java classes: you can have only one parent (or extends a class), but this parent can also have another parent, and so on.
As I explained here, you must distinguish the parent and aggregation principles in Maven, which means that my-plugin would be considered as an aggregation project, not necessarily a parent project for both my-plugin-client and my-plugin-parent.
So to summarize:
my-plugin will define the base pom for all your projects. Then, you create two new pom projects: java-base-pom and flex-base-pom. They have both my-plugin as parent. Now, my-plugin-client will have java-base-pom as parent, while my-plugin-server will use flex-base-pom for his parent.
This way, my-plugin-client will inherit all properties defined in the my-plugin pom.xml, and also from java-base-pom project.
You can achieve multiple inheritance with profiles:
You create (multiple) profiles in the root pom, and auto activate any variation of these profiles achieves multiple inheritance of maven configuration.

Categories