Maven parent from dependencies - java

I have an acceptance test module that I would like to run on Docker. To get this working, I had to copy all its parent poms, until the very last one. I would like to find out if it is possible to use a parent pom from a dependency, as in having something like:
<dependency>
<groupId>group.id</groupId>
<artifactId>artifact.id.parent</artifactId>
<version>${project.version}</version>
<type>pom</type>
</dependency>
would make Maven find the parent
<parent>
<groupId>group.id</groupId>
<artifactId>artifact.id.parent</artifactId>
<version>x.x.x-SNAPSHOT</version>
</parent>
Assuming that the acceptance test module version is also x.x.x-SNAPSHOT

Related

Java/Gradle: Any tips on centralizing dependency version control for a multiple repository project?

I am tired of having to manually change the dependency version for every repository and run the build and tests.
Are there any good solutions/tools out there to centralize this, so that you only have to change the version in one file?
A requirement is that you still can override the desired version from the local repository.
In my Maven projects i use a parent pom for dependency management. I use the "dependencyManagement" tag in parent pom for declare al available dependencies and his versions for child modoules.
DIRECTORY HERARCHY
- project-name
- module-A
- pom.xml
- pom.xml
In parent pom.xml I specify the depencyManagement tag:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.test</groupId>
<artifactId>artifact</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
</dependencyManagement>
In module-A pom.xml there is something like:
<parent>
<artifactId>module-A</artifactId>
<groupId>com.test</groupId>
<version>1.0</version>
</parent>
<dependencies>
<!-- The version is inherited from parent pom -->
<dependency>
<groupId>com.test</groupId>
<artifactId>artifact</artifactId>
</dependency>
</dependencies>
This way permits change the version of dependencies only in parent pom.xml. Al child modules will use it.
You can find more details in Maven's official documentation: https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html

Exclude maven sub modules dependencies from top level module

I created a maven parent project with three modules :
data-layer-module
data-service-module (uses the data-layer-module)
web-module (uses the data-services-module)
Here is a snippet from the parent pom.xml :
<groupId>org.mygroup</groupId>
<artifactId>myArtifact</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<modules>
<module>data-layer-module</module>
<module>data-service-module</module>
<module>web-module</module>
</modules>
The data-layer-module pom.xml contains no dependencies to the other modules (it contains only its external dependencies).
The data-service-module has a dependency in its pom.xml to the data-layer-module :
<dependencies>
<dependency>
<groupId>org.mygroup</groupId>
<artifactId>data-layer-module</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
And the web-module has a dependency to the data-service-module :
<dependency>
<groupId>org.mygroup</groupId>
<artifactId>data-service-module</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
Everything is fine but I don't want the web-module to have access to the data-layer-module. I need to enforce the three layer web-service-data model. Which is not the case with this configuration.
I obviously tried manually excluding it from the web-module pom.xml :
<dependency>
<groupId>org.mygroup</groupId>
<artifactId>data-service-layer</artifactId>
<version>1.0-SNAPSHOT</version>
<exclusions>
<exclusion>
<groupId>org.mygroup</groupId>
<artifactId>data-layer-module</artifactId>
</exclusion>
</exclusions>
</dependency>
But this causes compilation error since the data-service-module can't find its data-layer-module dependency.
How could this configuration be done ?
If the web module is going to run in the same jvm as the data-service-layer, then a transient dependency to the data-layer-module is necessary - this is why the exclusion you added casuses the application to fail.
You could consider making a simple api, for example data-service-layer-api, which obviously does not depend on data-layer-module, and is implemented correctly by data-service-layer.
You can still use a multi-module maven project, but now you will have 2 artifacts - a web module, and a data-service, which must be deployed separated.
It's basically a tradeoff between strict dependency analysis and project complexity.

Maven - How to unit test a project dependent on another project?

I know this question has been asked numerous times but the methods I've read just doesn't work for me. I tried this but it still won't work.
I have a subproject(A) that depends on another subproject(B).
Both subprojects are contained in a parent directory with a parent pom.xml (declares A and B as modules) within their respective subdirectories.
Compiling and installing the project works fine with the maven-assembly-plugin but when I try to test A, it doesn't recognize the classes from B.
I have tried installing it first and then testing but it still won't find the classes. What am I missing?
Error:
[ERROR] Failed to execute goal
org.apache.maven.plugins:maven-compiler-plugin:3.1:testCompile
(default-testCompile) on project (A)
[ERROR] TestService.java:[8,17] cannot find symbol
[ERROR] symbol: class **Model** (the class I'm referencing in B)
[ERROR] location: class **TestService**
(test in A that tests the class in ../service/src/main/java/Service.java)
Edit:
/project
--/service (this depends on model;this is also what I want to test)
---/src
----/main
-----/java
------/Service.java
----/test
-----/java
------/TestService.java
--/model (independent)
---/src
----/main
-----/java
------/Model.java
--/entry (this depends on service; entry point of the whole project)
--pom.xml (parent pom)
Each of the three projects have their own pom.xml inside.
/model/pom.xml contains no dependencies and no plugins
here's parent:
parent/pom.xml
...
<modules>
<module>entry</module>
<module>service</module>
<module>model</module>
</modules>
here's entry:
/service/pom.xml
...
<parent>
<groupId>com.some.project</groupId>
<artifactId>project</artifactId>
<version>xx</version>
</parent>
<artifactId>entry</artifactId>
<packaging>jar</packaging>
<version>xx</version>
<name>entry</name>
<build>
...
<!--assembly plugin is declared here-->
</build>
<dependencies>
<dependency>
<groupId>com.some.project</groupId>
<artifactId>service</artifactId>
<version>xx</version>
</dependency>
</dependencies>
here's service:
/service/pom.xml
...
<parent>
<groupId>com.some.project</groupId>
<artifactId>project</artifactId>
<version>xx</version>
</parent>
<artifactId>service</artifactId>
<packaging>jar</packaging>
<version>xx</version>
<name>service</name>
<dependencies>
<dependency>
<groupId>com.some.project</groupId>
<artifactId>model</artifactId>
<version>xx</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
Maven assembly plugin is used usually when you want to package the already compiled sources, so its kind of not related here.
If you have two projects, A and B and B has to depend on A, you have to define in B's pom.xml a dependency (trivial stuff):
<dependency>
<groupId>YOUR_GROUP_ID</groupId>
<artifactId>A</artifactId>
<version>YOUR_VERSION</version>
</dependency>
This will instruct maven to setup classpath during the build.
Now, Depending on artifact type of A and B maven can decide on some steps after the compilation, for example, if B is a WAR, A will be included in WEB-INF/lib folder of B because of such a dependency.
But in general, if A & B are jars, maven won't use this information only for the compilation/tests and not for packaging.
Now, maven has different classpaths for different phases: in particuler, one for compilation, and one for unit tests.
So if you want to specify that the dependency is required only for tests but should not be considered as a "compile" dependency, then define the scope:
<dependency>
<groupId>YOUR_GROUP_ID</groupId>
<artifactId>A</artifactId>
<version>YOUR_VERSION</version>
<scope>test</scope>
</dependency>
If you don't specify any scope, maven will conclude that the dependency is required both for compilation and for tests and maybe even for packaging as I've explained earlier.

How to bundle/package latest version of custom library in maven web project without updating pom.xml?

I have a custom library - Dao.jar which contains the database persistence logic.
I push this jar to artifactory with new version each time there is a change in code as shown below :
mvn install:install-file -Dfile=C:\*****\target\Dao.jar -DgroupId=non-public.com.karthik -DartifactId=dao -Dversion=2.0 -Dpackaging=jar
I have another maven web project which has a dependency on this jar. This jar is also packaged/bundled in the maven webapp project/war.
<dependency>
<groupId>non-public.com.karthik</groupId>
<artifactId>dao</artifactId>
<version>2.0</version>
</dependency>
Currently, I am changing the version of dao dependency in the pom.xml & re-building the maven webapp project each time a new version of Dao.jar is available in the artifactory.
Is there any option to build the maven project with the latest version of Dao.jar without manually changing the dependency version in the pom.xml?
When Maven searches for a dependency, it first checks the local repository (~/.m2/repository). If it's not found, it tries other resources, such as remote repositories defined in the POM file or in the settings file (~/.m2/settings.xml).
By that logic, if you try to use a version of a local project that's not yet installed to the local repository, Maven will never be able to find it to use in another project.
To avoid changing version numbers all the time and manually building both projects. You could create a parent POM for both projects. The parent would then be able to recognize that one of the child projects depends on the other and build them in the correct order.
Based on Luciano's inputs, I have created a multi-module maven project/parent POM with 2 modules(dao & web)
Parent
<groupId>com.karthik</groupId>
<artifactId>test</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>3.0.5.RELEASE</version>
</dependency>
<dependency>
<groupId>oracle</groupId>
<artifactId>ojdbc6</artifactId>
<version>11.2.0.3</version>
</dependency>
..........
</dependencies>
</dependencyManagement>
<modules>
<module>web</module>
<module>dao</module>
</modules>
Child module # 1 - dao
<parent>
<groupId>com.karthik</groupId>
<artifactId>test</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>dao</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>oracle</groupId>
<artifactId>ojdbc6</artifactId>
</dependency>
.........
</dependencies>
Child module # 2 - web(declared dao dependency in POM)
<parent>
<groupId>com.karthik</groupId>
<artifactId>test</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>web</artifactId>
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</dependency>
<dependency>
<groupId>com.karthik</groupId>
<artifactId>dao</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
.........
</dependencies>
When I run mvn package command at root path of parent pom, both modules - web.war and dao.jar are built. This method ensures always the latest version of dao.jar is packaged in web.war.

Maven: Re-use a POM file in every project

My goal is pretty simple actually but since there are multiple (and seemingly complex ways to do this) I wonder what I need to do... So I have certain runtime libraries (ADF libraries in particular) that are needed to be added to every project. This parent pom file will just have JAR dependencies in it. How can I use this pom file from a child pom file?
I don't think that using inheritance is a good solution here. Even if every project uses ADF artifacts, you don't want all poms to get these dependencies so declaring them in a corporate parent pom is not really an option.
So, instead, my recommendation would be to create a project with pom packaging to group the ADF dependencies together:
<project>
<groupId>com.mycompany</groupId>
<artifactId>adf-deps</artifactId>
<version>1.0</version>
<packaging>pom</packaging>
<dependencies>
<dependency>
<groupId>some.groupId</groupId>
<artifactId>adf-artifact-1</artifactId>
<version>${jdev.version}</version>
</dependency>
...
<dependency>
<groupId>some.groupId</groupId>
<artifactId>adf-artifact-n</artifactId>
<version>${jdev.version}</version>
</dependency>
</dependencies>
<properties>
<jdev.version>10.1.3</jdev.version>
</properties>
</project>
Then, install/deploy this project and declare it as dependency in any project that needs the ADF artifacts:
<project>
...
<dependencies>
...
<dependency>
<groupId>com.mycompany</groupId>
<artifactId>adf-deps</artifactId>
<version>1.0</version>
<type>pom</type>
</dependency>
</dependencies>
</project>
If the child POM file is actually a child (i.e. declares its parent), then it will inherit the dependencies and there is nothing left for you to do.

Categories

Resources