Compiling classes with dependent jar files in maven - maven

I want to compile some java files which have multiple dependent jars and make a jar file. I have kept all dependent jars under src/main/lib. after running mvn clean install, i get compilation failure of the classes. Dependent jars are not being copied to class path it seems. Anyone can tell whats going wrong her.
<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>test</groupId>
<artifactId>test</artifactId>
<version>1.0</version>
<repositories>
<repository>
<id>external-jars</id>
<name>external-jars</name>
<url>file://${project.basedir}\src\main\lib\</url>
</repository>
</repositories>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>jars</groupId>
<artifactId>jars</artifactId>
<version>1.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/src/main/lib/*</systemPath>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<finalName>finaljar</finalName>
<sourceDirectory></sourceDirectory>
</build>
</project>

You construction
<dependency>
<groupId>jars</groupId>
<artifactId>jars</artifactId>
<version>1.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/src/main/lib/*</systemPath>
</dependency>
does not work. In Maven, each artifact is addressed through groupId, artifactId and version. You cannot add a directory, but only separate jars.
While it is possible to add jars through system paths, it is much better to use a repository. Look at the possibilities in
How to add local jar files to a Maven project?

Related

including test-jar in the runtime scope

i got a war-project and in the test-jar of it, we have aside of the jUnit testcases also the mocks to the neighbor systems (for instance, the roles and users management system).
and we have a maven profile called mocking that adds the test-jar dependency to the war-project, at runtime, so that the mocks are available for the developer, but do not end up by error in production.
<profile>
<id>mocking</id>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>${project.artifactId}</artifactId>
<version>${project.version}</version>
<type>test-jar</type>
<scope>runtime</scope>
</dependency>
...
not very clean, i know, but we did not want to have just another artifact for only a hand full of mock clases, and it worked so far well with Maven 3.3.9.
now we need a feature of Maven 3.5.0, so i updated to the latest Maven 3.6.2 and get following error:
The project com.my-project:web:0.0.1-SNAPSHOT has 1 error:
'dependencies.dependency.[com.my-project:web:0.0.1-SNAPSHOT]' for com.my-project:web:0.0.1-SNAPSHOT is referencing itself.
which is kind of borderline case.
imho, and since the dependency is of scope runtime, it should be allowed.
is this a bug?
can anyone figure out a better way to achieve this?
many thanks
Michael
UPDATE 20191125:
Without full pom files or at least an example which looks very like your original projects it's hard to guess....
Here a small pom-file to reproduce the problem:
<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>my.project</groupId>
<artifactId>test</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>test</name>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>${project.artifactId}</artifactId>
<version>${project.version}</version>
<type>test-jar</type>
<scope>runtime</scope>
</dependency>
</dependencies>
</project>
with that file, and nothing else, mvn compile works fine with v3.3.9 but breaks with v3.6.2
If you use the normal setup for creating a test-jar this implies the test-jar is created as supplemental artifact to your usual artifacts which needed to be distinguished from each other which has to be achieved by using the <classifier>tests</classifier>.

Transitive dependency jars are not resolved from maven nexus repository

I created my own maven project (project 1) where I have added dependencies like junit, spring, etc. and deployed the jar (name it as jar1 ) in my nexus maven repository.
Now when I add jar1 as dependency to my new project 2, only jar1 is getting downloaded from the maven repository and the transitive dependencies such as junit ,spring are not downloaded.
pom - project1
<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>Project1</groupId>
<artifactId>Project1</artifactId>
<version>Dev.0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
pom - project2
<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>Project2</groupId>
<artifactId>Project2</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>Project1</groupId>
<artifactId>Project1</artifactId>
<version>Dev.0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
As per above pom configuration, project2 should automatically resolve junit jar right?.
But project2 only resolves Project1.jar and not the junit jar. Please let know what am I missing.
Not all scopes are transitive, especially test and provided dependencies are not.
Look at the table in https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html

How does Maven handle transitive dependencies inherited from parent?

Given the parent and child pom below and lib1 and lib2 both include the class foo.bar.Test.
parent pom
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>foo</groupId>
<artifactId>foo-parent</artifactId>
<version>1.0</version>
<dependencies>
<dependency>
<groupId>my.transitive</groupId>
<artifactId>lib1</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
</project>
child pom
<project>
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>foo</groupId>
<artifactId>foo-parent</artifactId>
<version>1.0</version>
</parent>
<artifactId>foo-child</artifactId>
<dependencies>
<dependency>
<groupId>my.transitive</groupId>
<artifactId>lib2</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
</project>
If I include foo-child as a dependency in myApp and instantiate foo.bar.Test, which version of the class would Maven resolve to? And why?
my app pom
<project>
<modelVersion>4.0.0</modelVersion>
<artifactId>myApp</artifactId>
<groupId>myApp</groupId>
<version>1.0</version>
<dependencies>
<dependency>
<groupId>foo</groupId>
<artifactId>foo-child</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
</project>
The short answer would be: it depends on which one is found on the classpath first.
Having 2 of the same classes packaged with an application is not ideal as it can lead to many difficult to debug errors... If your myApp project is just going to be a jar then it would be best to compile it using the same library as what is going to be available to it at runtime.
I believe maven uses the order it is written to the pom to build. One way of looking at this would be to run the following command for myApp:
mvn dependency:tree -Dverbose
This will print the dependencies in the order that they should appear on the classpath per spec. You can always use exclusions to exclude any inherited library you might not want. Hope this helps.

Maven and dependencies

I have a simply POM like this :
<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>com.sim</groupId>
<artifactId>log4j</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<parent>
<groupId>com.sim</groupId>
<artifactId>sim-java</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../sim-java/pom.xml</relativePath>
</parent>
<name>log4j</name>
<dependencies>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
<scope>compile</scope>
</dependency>
</dependencies>
I run mvn clean package on this project and a JAR is created as expected.
When I navigate into this JAR, I thought that I would see a JAR named log4j-1.2.17.jar inside it but it's not the case.
Using dependency with compile scope does not include JAR into packaging version of project ?
Thank you for clarification
The jar:jar plugin of maven just compiles your source and bundles it into a jar. Just like building a jar out of ant or bare hands, no dependency jars will be bundled in the jar. Jars cannot have dependent jars bundled inside them and even if they did, they cannot be loaded by the default class loader.
If you are looking to build a ejb-jar, then you might want to consider a EJB plugin
Check this link for various plugins that you can exploit.

Maven 3 regression: Profile dependencies lost?

I observed a change behavior between Maven 2 and Maven 3. Is this a bug or a feature? I couldn't find anything in the Maven 3.x Compatibility Notes
I use two different profiles to add dependencies for different environment in a multi-module project.
parent-pom:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>group</groupId>
<artifactId>main</artifactId>
<packaging>pom</packaging>
<version>1.0.0-SNAPSHOT</version>
<modules>
<module>common</module>
<module>portal</module>
</modules>
</project>
The common-pom has the profile in it:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>group</groupId>
<artifactId>common</artifactId>
<packaging>jar</packaging>
<version>1.0.0-SNAPSHOT</version>
<parent>
<groupId>group</groupId>
<artifactId>main</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<profiles>
<profile>
<id>development</id>
<dependencies>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.14</version>
</dependency>
</dependencies>
</profile>
<profile>
<id>production</id>
<dependencies>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.1</version>
</dependency>
</dependencies>
</profile>
</profiles>
</project>
The portal-pom has only the common dependency and should include the transitive dependency from the common module:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>group</groupId>
<artifactId>portal</artifactId>
<packaging>war</packaging>
<version>1.0.0-SNAPSHOT</version>
<parent>
<groupId>group</groupId>
<artifactId>main</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<dependencies>
<dependency>
<groupId>group</groupId>
<artifactId>common</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
Building this project (from the parent) via Maven2 mvn -P production package results in a WAR which includes the transitive dependency. (I used those simple dependencies for easy reproduction)
Executing via Maven3, I get only the common.jar in the WAR, but not the transitive dependency.
Is this a desired behavior?
To make things even "interesting": If one of the profiles is activated by default (explicit in the common-pom as the activation is not derived from the parent to the child modules) these transitive dependencies are always add to the portal.
But filtering or property-setting via profiles works as expected.
This comment solves it the one way:
the situation described above does work when profile activation using properties is used
With property activation (and not via -P) it works in Maven2 and 3
But the real solution was "caused" by the release plugin:
The profile must be submitted to release-plugin via
-Darguments=-Pproduction
Not a solution, but your use case looks similar to this open maven bug. Interestingly, according to the bug details, it happens on earlier maven versions as well.

Resources