I have the following setup:
Master: has modules A and B
A: declares a dependency on B, Master as its parent
B: Master as its parent
So basically Master has a parent pom which builds A and B where A has a dependency on B.
My problem is that I want to put all of the 3rd party dependencies in B (things like JUnit etc.). But when I do this, A does have access to the dependencies declared by B. Why is this happening? I thought maven handles transitive dependencies.
Here are snippets of my poms just in case:
Master:
<modules>
<module>../A</module>
<module>../B</module>
</modules>
A:
<parent>
<groupId>com.project</groupId>
<artifactId>Master</artifactId>
<version>1</version>
<relativePath>../Master/pom.xml</relativePath>
</parent>
...
<dependency>
...
<artifactId>B</artifactId>
...
</dependency>
B:
<parent>
<groupId>com.project</groupId>
<artifactId>Master</artifactId>
<version>1</version>
<relativePath>../Master/pom.xml</relativePath>
</parent>
...
<dependency>
...
<artifactId>JUnit</artifactId>
...
</dependency>
Why doesn't A have access to JUnit?
If the JUnit dependency in Project B has scope 'test' then I don't believe it will be visibile as a transitive dependency in Project A. See the table in Maven Introduction to the Dependency Mechanism: Dependency Scope.
Related
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
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.
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.
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
I have 2 Maven projects, A and B. Project A is entirely independent, while B requires A as a dependency. Currently, B is getting A from the maven repository:
<dependency>
<groupId>com.myproject</groupId>
<artifactId>projectA</artifactId>
<version>2.0.0-SNAPSHOT</version>
</dependency>
What I would like to do is set up the dependency such that B can reference the local instance of A. I can do the following:
<dependency>
<groupId>com.myproject</groupId>
<artifactId>projectA</artifactId>
<version>2.0.0-SNAPSHOT</version>
<scope>system</scope>
<systemPath>${basedir}/../projectA/target/projectA-2.0.0-SNAPSHOT.jar</systemPath>
</dependency>
but this only works if A is already built (so projectA-2.0.0-SNAPSHOT.jar already exists).
Is there a way to force A to build before B in cases where I don't already have a build of A?
One way is you create a parent pom, and add these projects as child modules. So, the directory structure would look like this:
+ pom.xml
|
+-A
| \
| + pom.xml
+-B
\
+ pom.xml
The parent pom would have <modules> tag, adding A and B projects as child modules:
<groupId>com.myproject</groupId>
<artifactId>parent</artifactId>
<version>2.0.0-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>A</module>
<module>B</module>
<modules>
And then, add A module as dependency to B module. Just keep the group-id same for parent, A and B. And then refer the module using artifact-id.
pom.xml for B would be like:
<parent>
<groupId>com.myproject</groupId>
<artifactId>parent</artifactId>
<version>2.0.0-SNAPSHOT</version>
</parent>
<artifactId>projectB</artifactId>
<dependencies>
<dependency>
<groupId>com.myproject</groupId>
<artifactId>projectA</artifactId>
<version>2.0.0-SNAPSHOT</version>
</dependency>
</dependencies>
Now, build the parent pom. It will take care of build order.