How to share project dependencies among multiple projects in Maven? - java

I have the below project structure
Main Project
--Sub Project 1
- child 1
* pom-child1
- child 2
* pom-child2
* pom-sub-project1
--Sub Project 2
* pom-sub-project2
* main project pom
I had defined few project dependencies in main project pom and referred it in child and sub project poms. But I am finding issues if the pom is not a direct child of the main project pom. Is there a way to resolve it?
Example,
Main Project pom
<packaging>pom</packaging>
<version>dev</version>
<name>parent-project</name>
..
<properties><spring-version>3.1.0.RELEASE</spring-version></properties>
child POM
<parent>
<groupId>com.test.pkg</groupId>
<artifactId>test-proj</artifactId>
<version>${project.version}</version>
</parent>
The ${project.version} isn't resolved if it is not a direct child of a parent pom due to which none of the project dependencies are resolved.
Also, I read about properties-maven-plugin which is used to read properties from external properties file. Can this be used for reading dependency version or is there any other plugin/approach that could be used in this case?

You cannot use
${project.version}
to define your parents version, because the child by default inherits the parents version.
Set the parents version with the valid value and not with a property.
If you do so, it should work and you do not have to specify the childs version, as it will be inherited from the parent.

Related

How to override maven property at runtime for a specific module?

Lets say my project has multiple sub-modules and the structure is something like this:
Parent
- Submodule-A
- Submodlue-B
- Submodule-C
Now both parent and child poms have the same maven property defined in their pom.xml
<properties>
<custom.property>some-value</custom.property>
</properties>
If I run the below command, this would override the value for both parent and its child module
mvn <phase|goals> -Dcustom.property=some-other-value
But How do I override this property only for a specific sub-module's pom?

Java how to use methods from another module in Intellij

I have added two projects as modules in empty intellij project.
Then I added in pom of module B following dependency to first project(module A):
<dependency>
<groupId>Tests</groupId>
<artifactId>Group</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
This allows me to import classes from module A into module B.
But I can't see any method from that module (it looks like classes are empty or they have only private fields/methods).
What am I missing? What should I do to see all public methods/fields from A module?
Thanks
Kamil
If you are adding one of them as a dependency, you can avoid to join them as modules. For local purposes, you can build(mvn clean package) one of them and add that as a dependency to another one. You can check relevant .class file to see the access levels of the class members.
For multi-module projects, please, see: https://www.jetbrains.com/help/idea/creating-and-managing-modules.html

Third party API can't see class in multi module Maven project

I have a multi module maven project, and in the dao module, I added the JSON-IO dependency. When I try to deserialize my object, it gives me:
Exception in thread "main" com.cedarsoftware.util.io.JsonIoException: Class listed in #type [hu.kleatech.projekt.model.Employee] is not found
The class name is correct, the Employee is public, and the dao has the module as dependency. What could have gone wrong?
Edit: Since this is an old question and have been answered long ago, I'm deleting the github repository that I made specifically for this question. The solution to the problem is in the accepted answer, the exact code is not relevant.
Please try adding an empty constructor to Employee class.
Edit: Actually, while adding an empty constructor solves the problem, it is not necessarily required. Json-IO "will make a valiant effort to instantiate passed in Class, including calling all of its constructors until successful. The order they tried are public with the fewest arguments first to private with the most arguments."
(copied from MetaUtils.java javadoc)
Also, when calling a multi-argument constructor, the library fills the arguments with nulls and defaults for primitives. Then any exceptions thrown during the constructor call is ignored. In your case, a NullPointerException was thrown, because the constructor is not null-safe. So either modify the constructor so that it can handle nulls, or add an empty constructor.
Maven dependency configuration is hierarchical from <parent> element not from <modules> element.
It means that in the project's pom.xml file where you have dependency on "JSON-IO dependency" you do not have dependency on your dao project or where that class is.
<modules> stands only to define what projects to build. Order of modules definition does not matter, since Maven detects order by required dependencies
So, you can define dependency in <parent> pom.xml either in
<dependencies> element. then all children will have it.
or in <dependencyManagement> - then children who need it can include it in their <dependencies> without common configurations like version, scope etc...
look at quite similar answer here:
How to minimize maven pom.xml
As per your project and modules Pom your main Pom should have modules in following order ....
<modules>
<module>core</module>
<module>controller</module>
<module>service</module>
<module>dao</module>
</modules>
service depends on core so core should be build before service
dao depends on service and core both so dao should be after core and service.
Employee class is available in core and it should be available in core jar.
You should add depencyManagent in main Pom and then add all the module as dependencies in dependencyManagement so whoever adds your main Pom as dependency will be able to access all your jars.
Once you change order build your project again and then update your maven project.
If this code is being used in another project then make sure that you have uploaded jars to repository (mvn deploy) so whoever uses it can download it when they are building their project.
One way to verify whether this jar is downloaded in the main project where it is used or not is check in project explorer there would be a Maven Dependencies section where you can see all dependency jars and check if core is present or not.
I am not sure what controller module is doing in main Pom as I couldn’t find a module by that name in your project so you should either remove it or add a module (folder) for it.

Maven Cyclic reference when root pom has plugin which is common to two or more child modules

So i have a project with the structure as follows-:
pom.xml
\
---Module A (Child)
---Module B (Maven child plugin with Dependency on A)
---Module C (Child Dependency on A)
---Plugin B
the parent pom looks like the following
<modules>
<module>A</module>
<module>B</module>
<module>C</module>
</modules>
<plugins>
<plugin>
B
</plugin>
</plugins>
POM for A has no dependencies and has just the parent-:
parent
POM for B has
<parent>parent</parent>
<dependencies>
<dependency>A</dependency>
</dependencies>
POM for C also has
<parent>parent</parent>
<dependencies>
<dependency>A</dependency>
</dependencies>
With the above,maven gives me the following error-:
org.apache.maven.ProjectCycleException: The projects in the reactor contain a cyclic reference:
Edge between 'B' and 'A' introduces to cycle in the graph A->parent->B->A
What am i doing wrong and how should i structure the project?I want to keep everything in one place.
You should move your plugin declaration inside of the parent into the pluginManagement tag so that you can set the version (but not actually use it), and then in individual projects that need the plugin, simply name the plugin in your plugins tag.
Additionally, A cannot use plugin B if B depends upon A. Sorry, can't be done; You'll need to find a way to make one do without the other. Additionally I don't think B can use itself as a plugin, since that has to resolve before it can even begin to build B. C and any other modules (D, E, etc.) can use B though.

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