Building project with maven containing other projects - maven

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>

Related

Maven POM packaging with dependencies

I'm trying to construct a codebase where subsystems can be developed as maven modules, without the importing POM needing to concern itself with the internal structure of the maven module.
The "importing" pom
<project>
<artifactId>application</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
<artifactId>submodule-1</artifactId>
</dependency>
</dependencies>
</project>
The "imported" pom
<project>
<artifactId>submodule-1</artifactId>
<packaging>pom</packaging>
<modules>
<module>api</module>
<module>implementation</module>
</modules>
<dependencies>
<dependency>
<artifactId>api</artifactId>
</dependency>
<dependency>
<artifactId>implementation</artifactId>
</dependency>
</dependencies>
</project>
This does seem to work, at least partially; the generated JARs appear to be on the classpath during mvn package. IntelliJ shows the application has a dependency on submodule-1 and transitively on api and implementation. However, mvn dependency:tree fails while building submodule-1 saying
Could not resolve dependencies for project submodule-1:pom:1.0.0-SNAPSHOT: Could not find artifact api:jar:1.0.0-SNAPSHOT
I'm trying to determine if this is a valid pattern, that of having packaging of pom, with defined dependencies which are also defined modules in the POM.
Have I stumbled upon a working-but-not-supported edge case, or is the dependency plugin broken in some way, or I'm breaking it in some way, or something else?

Maven projects - how to read a property that is defined in the pom file of a project that is added as a dependency

I am working on a large project that contains many maven projects. We are using Maven 3.3.9.
I want to use a property that is defined in one maven project in another project, but i can't access the property.
The situation is: there is one maven project called "product-packaging", that has a pom file that includes some properties. This maven project only contains a pom file. It is used for generating a package that contains a set of components that are compatible with each other.
There is another maven project called "projectX" that has a dependency on "product-packaging". In "projectX" we want to use a property that is defined in "product-packaging".
I want to add xx-ws-rest as a dependency in projectX, and i want to set the version as xx-ws-rest.version, which is a property that is defined in "product-packaging"
The pom of "product-packaging" looks like:
<project ...>
...
<properties>
<xx-ws-rest.version>1.6.0</xx-ws-rest.version>
</properties>
...
</project>
The pom of "projectX" looks like:
<project ...>
...
<properties>
<product-packaging.version>1.6.0</product-packaging.version>
</properties>
...
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.company.product</groupId>
<artifactId>product-packaging</artifactId>
<version>${product-packaging.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.company.product.xx</groupId>
<artifactId>xx-ws-rest</artifactId>
<version>${xx-ws-rest.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>com.company.product.xx</groupId>
<artifactId>xx-ws-rest</artifactId>
<type>war</type>
</dependency>
....
</dependencies>
</project>
AFAIK this is not possible. The usual way to define common properties for different projects is to use a parent POM. There, you can define properties and let the different projects inherit from that parent POM - that way, the properties are visible for all child projects.

Maven: How to import dependency of type pom?

I am trying to migrate a java application to maven. There are some dependencies which have been provided as jar files so far. One of these dependencies is jung2, which is available from the maven repository: mvnrepository.com
I need all of the provided modules and I do not understand how to declare this dependecy correctly in my pom.xml such that all corresponding jar files are downloaded and the classes are available at compile time.
This is what my pom.xml file looks like right now:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>groupId</groupId>
<artifactId>myProject</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencyManagement>
<dependencies>
<!-- https://mvnrepository.com/artifact/net.sf.jung/jung2 -->
<dependency>
<groupId>net.sf.jung</groupId>
<artifactId>jung2</artifactId>
<version>2.0.1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
I also tried leaving out <scope>import</scope> and put the dependency into the dependencies section. When executing mvn compile or mvn package, error message occur that the corresponding packages do not exist.
If I additionally add a dependency inside dependencies but outside of dependencyManagement, e.g.
<dependencies>
<dependency>
<groupId>net.sf.jung</groupId>
<artifactId>jung2</artifactId>
</dependency>
I receive an error about missing version. But as far as I understood, this should not be necessary due to dependencyManagement? If I also add <version>2.0.1</version>, then I get the following error message:
Failure to find net.sf.jung:jung2:jar:2.0.1
The dependencyManagement tag is used generally when you have a multi module project in maven (where you will have parent-child relationship).
If you specify any dependencies within the dependencyManagement tag, it would NOT actually download the dependencies.
Putting the dependency within this tag simply means that this dependency is available (to download / to use) for the child pom. The child pom will have to explicitly provide the groupId and the artifactId co-ordinates to download and use the jar to compile its classes.
If you just have a single module project (looks like yours is a single module project) then you can fix this issue by not using the dependencyManagement tag.
Simply put your jars in the dependencies tag.
For ex:
<dependencies>
<dependency>
<groupId>com.abc</groupId>
<artifactId>def</artifactId>
<version>1.0.0</version>
<type>pom</type> // This will now download the pom and its associated transitive dependent jars
</dependency>
<dependency>
<groupId>com.pqr</groupId>
<artifactId>xyz</artifactId>
<version>1.0.0</version>
<type>pom</type> // This will now download the pom and its associated transitive dependent jars
</dependency>
</dependencies>
Like I said before, the dependencyManagement tag will mostly make sense to use if you have a multi-module project, which isn't your case.

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.

Dependeny Management using POM import

I am creating a project 'test-jar' in my local and i am using pom file which I don't have write access as Parent of 'test-jar' project. The parent project has already defined depedencyManagement with old versions.
As I have to update dependency versions in my project and planning to override parent's dependency Management. So, I have created another POM file with my own dependency Management and imported into 'test-jar' project.
My Project :
<project>
<artifactid>test-jar</artifactid>
<parent>
<artifactId> test-parent </artifactId>
</parent>
<dependencies>
<dependency>
<artifactId>jar/artifactId>
</dependency>
<dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<artifactId>custom-pom</artifactId>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencyManagement>
</project>
My Parent Project:
<project>
<artifactid>test-parent</artifactid>
<dependencyManagement>
<dependencies>
<dependency>
<artifactId>jar/artifactId>
<version>1.0</version>
</dependency>
</dependencyManagement>
</project>
My Custom POM for updated dependencyManagement:
<project>
<artifactid>custom-pom</artifactid>
<dependencyManagement>
<dependencies>
<dependency>
<artifactId>jar</artifactId>
<version>3.0</version>
</dependency>
</dependencyManagement>
</project>
The problem is, I am always getting dependency version from parent pom, though i have imported new dependency management in project.
I am using Maven 2.2.1 version here.
Is there any solution how to overwrite Dependency Management from Parent POM ?
Based on the documentation:
This scope is only used on a dependency of type pom in the
section. It indicates that the specified POM
should be replaced with the dependencies in that POM's
section. Since they are replaced, dependencies
with a scope of import do not actually participate in limiting the
transitivity of a dependency.
Apart from your problem you can simply use differerent version which are different of the onses defined in the parent pom's dependencyManagement. Furthermore you could create a separate pom wich defines the dependencies with new version (dependencyManagement) and inherits from the given parent.

Resources