How to exclude tests maven dependency coming transitively - maven

I got following scenario:
Project A has dependency on Project B (and its test classes, test classes are provided to A via classifier tag - tests in maven dependency)
Project A pom is as follows:
<dependency>
<groupId>sample.project</groupId>
<artifactId>project-B</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>sample.project</groupId>
<artifactId>project-B</artifactId>
<version>1.0</version>
<classifier>tests</classifier>
</dependency>
Now, I have got another project C, which depends on A. The problem is when I add dependency of Project A to C, I got Project B s tests jar transitively in Project C.
Project C pom is as follows:
<dependency>
<groupId>sample.project</groupId>
<artifactId>A</artifactId>
<version>1.0</version>
</dependency>
How can I avoid just tests jar of Project B in C (not the normal jar of Project B in Project C)?
It is that I want to exclude tests jar of Project B from Project C.
Thanks

If a dependency is for tests only it should have the scope test:
<dependency>
<groupId>sample.project</groupId>
<artifactId>project-B</artifactId>
<version>1.0</version>
<classifier>tests</classifier>
<scope>test</scope>
</dependency>
Then it will not be transitively included into other projects.

Related

How should dependencies between modules be declared in a maven multi-module project?

Assume I have a maven multi-module project consisting of parent P and its modules A and B. How should a dependency of B to A be declared?
Until today I always used the following in B:
<dependency>
<groupId>org.example</groupId>
<artifactId>A</artifactId>
<version>${project.version}</version>
</dependency>
But a colleague just mentioned that it is also possible to create a dependency management entry for A in parent P
<depednencyManagement>
<dependency>
<groupId>org.example</groupId>
<artifactId>A</artifactId>
<version>${project.version}</version>
</dependency>
</dependencyManagement>
and then B only needs to specify:
<dependencies>
<dependency>
<groupId>org.example</groupId>
<artifactId>A</artifactId>
</dependency>
</dependencies>
Is there any downside to either of those methods? Does maven intend one to be actually used? Or is there actually another style I'm missing?
In the project I'm working all modules have the same version and we are having much more than 3 modules and also some deeper nesting than only 2 levels. Does this have an influence on which declaration style should be preferred?

Excluding some 3rd party jar in ear using maven

I am building an ear using maven <packaging>ear</packaging> tag.
One of the declared dependencies is adding it's transitive dependency to the generated ear. Is there any way to exclude this in the generated ear?
That is, my EAR pom has a dependency on module_A, this somewhere along the tree has a dependency on module_X which is getting packaged in the generated ear.
Is there any way not to include this(module_X) in the ear?
Directly adding an excludes tag for module_X in my pom did not work.
Everything is possible with maven. You just have to simly add a tag exclusions in the pom of your ear, something like that :
<dependency>
<groupId>my.group</groupId>
<artifactId>module_A</artifactId>
<exclusions>
<exclusion>
<groupId>my.group</groupId>
<artifactId>module_X</artifactId>
</exclusion>
</exclusions>
</dependency>
If the dependency is scoped as compile in the parent POM and you need it to be provided within your EAR, you can use dependency management within the child POM where you need to change its scope:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.group</groupId>
<artifactId>transitive-dependency</artifactId>
<version>1.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
</dependencyManagement>

Maven test dependencies: how to get dependencies from sibling project into test scope of dependent project

I have a multi-module maven project with the structure
main/
core/
interface/
where interface has a dependency on the artifact produced by core.
interface compiles, packages, and installs properly. However, when running tests in interface they fail due to not resolving dependencies found in core.
interface does not depend on the test classes themselves in core, simply compile scope maven dependencies defined in the core pom.xml file.
I did one painful attempt whereby I copied every single compile dependency declaration in core that was needed into the interface pom.xml and gave them all
<scope>test</scope>
. This helped with the tests but broke the install.
What is the best way to fix the dependency resolution of these tests in interface?
Here is an example of compile scope dependencies that are not resolved when running interface maven test goal.
core/pom.xml excerpt:
<dependency>
<groupId>com.sun.faces</groupId>
<artifactId>jsf-api</artifactId>
<version>${jsf-version}</version>
</dependency>
<dependency>
<groupId>com.sun.faces</groupId>
<artifactId>jsf-impl</artifactId>
<version>${jsf-version}</version>
</dependency>
interface/pom.xml excerpt:
<dependency>
<groupId>com.mycompany</groupId>
<artifactId>core</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>

Building project with maven containing other projects

I have a web-project A dependent on project B,
Project B dependent on JAR C
the problem:
When I package the web-project A, there is a jar for b (expected), but their is no reference to jar c
So, when I run my web-project A and access function the project B do I got class NotFoundException because jar C is not included
Any help how can I include jar C in parent project A without writing it myself in project A pom.xml
web-project pom.xml
<project ....>
..........
<dependencies>
<!--Local Projects -->
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>project B</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
</project>
project B pom.xml
<project ....>
<dependencies>
<dependency>
<groupId>jar_C</groupId>
<artifactId>jar_C</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
As your configuration, Maven is just responsible for the compilation, that is to say a jar won't take any of its dependencies with itself. If you need to wrap up the dependencies all together, you should use the Assembly plugin, see:here
Have a read at the Maven Dependency Mechanism
import (only available in Maven 2.0.9 or later)
This scope is only used on a dependency of type pom in the <dependencyManagement> section. It indicates that the specified POM should be replaced with the dependencies in that POM's <dependencyManagement> section. Since they are replaced, dependencies with a scope of import do not actually participate in limiting the transitivity of a dependency.
So Basically, try this
web-project pom.xml
<project ....>
..........
<dependencies>
<!--Local Projects -->
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>project B</artifactId>
<version>1.0.0</version>
<scope>import</scope>
</dependency>
</dependencies>
</project>

Multi-module maven build : different result from parent and from module

I am migrating an application from ant build to maven 3 build.
This app is composed by :
A parent project specifying all the modules to build
A project generating classes with jaxb and building a jar with them
A project building an ejb project
3 projects building war modules
1 project building an ear
Here is an extract from my parent pom :
<groupId>com.test</groupId>
<artifactId>P</artifactId>
<packaging>pom</packaging>
<version>04.01.00</version>
<modules>
<module>../PValidationJaxb</module> <-- jar
<module>../PValidation</module> <-- ejb
<module>../PImport</module> <-- war
<module>../PTerminal</module> <-- war
<module>../PWebService</module> <-- war
<module>../PEAR</module> <-- ear
</modules>
I have several problems which I think have the same origin, probably a dependency management issue that I cannot figure out :
The generated modules are different depending on if I build from the parent pom or a single module. Typically if I build PImport only, the generated war is similar to what I had with my ant build and if I build from the parent pom, my war took 20MB, a lot of dependencies from other modules had been added. Both wars are running well.
My project PWebService has unit tests to be executed during the build. It is using mock-ejb which has cglib as dependency. Having a problem of ClassNotFound with this one, I had to exclude it and add a dependency to cglib-nodep (see last pom extract). If I then build only this module, it is working well. But if I build from the parent project, it fails because other dependencies in other modules also had an implicit dependency on cglib. I had to exclude it in every modules pom and add the dependency to cglib-nodep everywhere to make it run.
Do I miss something important in my configuration ?
The PValidation pom extract :
It is creating a jar containing an ejb with interfaces generated by xdoclet, as well as a client jar.
<parent>
<groupId>com.test</groupId>
<artifactId>P</artifactId>
<version>04.01.00</version>
</parent>
<artifactId>P-validation</artifactId>
<packaging>ejb</packaging>
<dependencies>
<dependency>
<groupId>com.test</groupId>
<artifactId>P-jaxb</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate</artifactId>
<version>3.2.5.ga</version>
<exclusions>
<exclusion>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib-nodep</artifactId>
<version>2.2.2</version>
</dependency>
...
[other libs]
...
</dependencies>
<build>
...
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-ejb-plugin</artifactId>
<configuration>
<ejbVersion>2.0</ejbVersion>
<generateClient>true</generateClient>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>xdoclet-maven-plugin</artifactId>
...
The PImport pom extract :
It depends on both Jaxb generated jar and the ejb client jar.
<parent>
<groupId>com.test</groupId>
<artifactId>P</artifactId>
<version>04.01.00</version>
</parent>
<artifactId>P-import</artifactId>
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>com.test</groupId>
<artifactId>P-jaxb</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.test</groupId>
<artifactId>P-validation</artifactId>
<version>${project.version}</version>
<type>ejb-client</type>
</dependency>
...
[other libs]
...
</dependencies>
The PWebService pom extract :
<parent>
<groupId>com.test</groupId>
<artifactId>P</artifactId>
<version>04.01.00</version>
</parent>
<artifactId>P-webservice</artifactId>
<packaging>war</packaging>
<properties>
<jersey.version>1.14</jersey.version>
</properties>
<dependencies>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-servlet</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>com.rte.etso</groupId>
<artifactId>etso-validation</artifactId>
<version>${project.version}</version>
<type>ejb-client</type>
</dependency>
...
[other libs]
...
<dependency>
<groupId>org.mockejb</groupId>
<artifactId>mockejb</artifactId>
<version>0.6-beta2</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>cglib</groupId>
<artifactId>cglib-full</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib-nodep</artifactId>
<version>2.2.2</version>
<scope>test</scope>
</dependency>
</dependencies>
Many thanks
Solution after modification of the configuration :
When I got the projects already mavenized, it didnt respect the folder layout convention, but as it was declared in the pom where to find the sources, I thought it would be working.
Anyway, i changed it to match the recommended structure.
To build a single module I was executing mvn clean install directly at its level. It is this way I obtained a different result (which is in fact the one I wanted).
Anyway, my problem is solved, I put all the dependencies of the PValidation project as provided, as I am only including the generated client in other modules and they dont require all what is needed for the implementation.
But still I dont get why I had different result for the same configuration.
The first important thing is you should create the structure of your project appropriate to the modules structure which means having the following folder structure:
+-- parent
+-- PValidationJaxb
+-- PValidation
+-- PImport
+-- PTerminal
+-- PWebService
+-- PEAR
This means having a pom.xml which contains the modules definition in the parent folder.
if you follow the above recommendation you can simplify the modules list to the following:
<modules>
<module>PValidationJaxb</module> <-- jar
<module>PValidation</module> <-- ejb
<module>PImport</module> <-- war
<module>PTerminal</module> <-- war
<module>PWebService</module> <-- war
<module>PEAR</module> <-- ear
</modules>
Furthermore a best practice in Maven is to use lowercase artifacts which mean in your case pvalidationjaxb instead of PValidationJaxb.
An other important thing is your version which does NOT follow the Maven conventions. Furthermore your version will be from the Maven point of view a release which is not the case you are doing development on this. In Maven you should use a so called SNAPSHOT for such purposes like 1.0.0-SNAPSHOT.
I hope you have followed the folder layout recommendation of Maven which says to put production code (which will be packaged into the resulting jar) into src/main/java whereas test code into src/test/java.
The problem you described having different dependencies sounds weired. The question is how have you tried to build a single moduel? This can usualy be achieved by using the following from the parent location:
mvn -pl module clean package
The problem with your unit tests sounds like a missing dependencies etc. but here is the questions how have you tried to run the unit tests and have you configured maven-surefire-plugin ? Or do you have integration tests? This is only a guess cause i don't see any configuration of Maven plugins in your poms.

Resources