Add dependency according to the given condition in Maven - java

Is there a way I can set up dependancies according to a given condition when I buid the maven project.
mvn package someCondition
So if I say mvn install A it should add one dependancy and if a say mvn install B it should add another type of dependancy.
Please help. Thank You
P.S. Is there a way I can do this by creating multiple profiles?

Using profile is the most straight-forward way.
in brief, consider having something like this:
<project>
...
<profiles>
<profile>
<id>profile-a</id>
<dependencies>
<dependency>
// dependency 1
</dependency>
</dependencies>
</profile>
<profile>
<id>profile-b</id>
<dependencies>
<dependency>
// dependency 2
</dependency>
</dependencies>
</profile>
<profiles>
</project>
Then you can simply do mvn install -P profile-a which will do what you ask for.

Related

Maven cannot resolve package from another module dependency

I have a multi-module Maven project structure with several layers, something like this:
root-module
module-group
war-module
pom.xml
jar-module1
pom.xml
jar-module2
pom.xml
pom.xml
another-module
pom.xml
etc
pom.xml
pom.xml
module-group, another-module and etc have root-module as their parent.
So root-module/pom.xml has this:
<packaging>pom</packaging>
<modules>
<module>module-group</module>
<module>another-module</module>
<module>etc</module>
</modules>
and each of those modules has this:
<parent>
<!-- artifact coordinates etc -->
<artifactId>root-module</artifactId>
</parent>
Then, war-module, jar-module1 and jar-module2 have module-group as their parent. Thus, module-group/pom.xml also includes:
<modules>
<module>war-module</module>
<module>jar-module1</module>
<module>jar-module2</module>
</modules>
war-module has jar-module1 in its <dependecies>, and jar-module1 depends on jar-module2. War-module has <packaging>war</packaging>, jar-* modules have jar.
So dependency chain is like war-module -> jar-module1 -> jar-module2. Versions for each artifact are defined using ${revision} (I'm using Maven3).
I was trying to introduce the dependency chain from war-module in the profiles in war-module/pom.xml:
<profiles>
<!-- this profile is for building with jar-module1 (jar-module2 is resolved transitively) -->
<profile>
<id>profile1</id>
<dependencies>
<dependency>
<artifactId>jar-module1</artifactId>
</dependency>
</dependencies>
</profile>
<!-- this profile is for building without jar-module1 (straight dependency to jar-module2) -->
<profile>
<id>profile2</id>
<dependencies>
<dependency>
<artifactId>jar-module2</artifactId>
</dependency>
</dependencies>
</profile>
</profiles>
However, when I try to build my project (or just module-group or even jar-module1) the process exits with error while packaging jar-module1:
package org.example.package.from.jarmodule2 doesn't exist.
(that package has the only Java class from jar-module2 referenced in jar-module1). However, I have the target folder in my jar-module2 with correct .jar in it. IntelliJ IDEA resolves the classes correctly, only Maven cannot build it right. What might be the problem?
Also, if I introduce the dependency without using profiles, it seems to package correctly. But I need to build different configurations all the time and would really love to not have to change pom.xml every time.

How to have maven resolve a dependency of a dependency which was created by a non-default profile for some classifier?

Given a library which has different dependencies depending on a profile, say for example
<profile>
<id>default</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<envClassifier>cuda-10.1</envClassifier>
</properties>
<dependencies>
<dependency>
<groupId>org.jcuda</groupId>
<artifactId>jcuda</artifactId>
<version>10.1.0</version>
</dependency>
</dependencies>
</profile>
<profile>
<id>cuda-10.0</id>
<properties>
<envClassifier>cuda-10.0</envClassifier>
</properties>
<dependencies>
<dependency>
<groupId>org.jcuda</groupId>
<artifactId>jcuda</artifactId>
<version>10.0.0</version>
</dependency>
</dependencies>
</profile>
I am creating artefacts with different classifiers, say for example
library-1.0.0-cuda-10.0
and
library-1.0.0-cuda-10.1
(here cuda-10.0 and cuda-10.1 are the classifiers for the artefact library-1.0.0).
If another project references this library, say for example as
<dependency>
<groupId>net.finmath</groupId>
<artifactId>library</artifactId>
<version>1.0.0</version>
<classifier>cuda-10.0</classifier>
</dependency>
then the correct artefact is pulled (here library-1.0.0-cuda-10.0.jar) but the dependency tree (via mvn dependency:tree) shows the wrong dependencies of the dependency. In this example it shows jcuda-10.1.0 and not juda-10.0.0.
This issue is due to an artefact having a single pom.xml for all classifiers (and the default profile kicks in).
Question 1: Can you have dedicated pom.xml in the repositories for different classifiers, to reflect the correct dependencies?
Apparently the issue cannot be resolved by setting a profile (-P parameter) on the outer project, because profile selectors are not passed to the poms of the dependencies. It looks as if profiles do not walk down the dependency tree.
Question 2: Is there a way to pass a profile selector to a pom of a dependency to select the right dependencies of the dependency?
I found two options to resolve the problem, but I am not very happy with them.
The first one would be to not have a default profile with a dependency in the pom of the library. In that case the user of the library (here library-1.0.0) has to specify the correct classifier and the correct downstream dependencies. This appears to be cumbersome. Also note that in this case the build of the library would fail without specification of the profile.
It is possible to use the profile to alter the name (or version) of the artefact. Since each version or artefact comes with its own pom, this allows to specify profile specific dependencies to be resolved.
However, I believe there should be a better solution, because otherwise it looks as if the specification of dependencies in profiles makes no sense for artefacts which are libraries, that is, which are themselves dependencies of another projects.
Question 3: What is the Maven way to resolve this issue?
PS: The question arose in this project: http://finmath.net/finmath-lib-cuda-extensions/
I found a lightweight solution for the problem.
You may activate a profile though a property.
Properties may not be passed from a pom to the poms of it's dependencies, but a property which is set on the command line acts on both poms.
Hence, instead of using a profile on the command line, use a property and activate the corresponding profiles in your project's pom and the library's pom.
So in the above example, the (outer) project (which references the library) has a profile
<profile>
<id>cudaversion</id>
<activation>
<property>
<name>cuda.version</name>
</property>
</activation>
<properties>
<finmath-cuda.classifier>cuda-${cuda.version}</finmath-cuda.classifier>
</properties>
</profile>
which sets the classifier of its dependency, that is this project has a dependency to library-1.0.0
<dependency>
<groupId>net.finmath</groupId>
<artifactId>library</artifactId>
<version>1.0.0</version>
<classifier>${finmath-cuda.classifier}</classifier>
</dependency>
And the pom of library-1.0.0 has a profile which is activated by the same property as in
<profile>
<id>cuda-10.0</id>
<activation>
<property>
<name>cuda.version</name>
<value>10.0</value>
</property>
</activation>
<properties>
<envClassifier>cuda-10.0</envClassifier>
</properties>
<dependencies>
<dependency>
<groupId>org.jcuda</groupId>
<artifactId>jcuda</artifactId>
<version>10.0.0</version>
</dependency>
</dependencies>
</profile>
The outer project is then build with mvn -Dcuda.version=10.0 to activate both profiles.

Make Eclipse default to JUnit4 rather than JUnit5 when the class only contains JUnit4 annotations

A recent upgrade of groovy which brought with it JUnit5 has resulting in Eclipse wanting to run every test under JUnit5. I can sort of work around this by going to run configurations and tell Eclipse to use JUnit4, however this gets tedious.
Is it possible to tell Eclipse to always use JUnit4 for a particular project, including new tests?
You can specify a profile and activate it in Eclipse only.
Example (assuming your problem arose by having a dependency to groovy-all):
<profiles>
<profile>
<id>eclipse-groovy-no-junit5</id>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>${groovy.groupId}</groupId>
<artifactId>groovy-all</artifactId>
<version>${groovy.version}</version>
<type>pom</type>
<exclusions>
<exclusion>
<groupId>${groovy.groupId}</groupId>
<artifactId>groovy-test-junit5</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</dependencyManagement>
</profile>
</profiles>
Then go to
Project -> Properties -> Maven -> Active Maven Profiles
and specify the profile name eclipse-groovy-no-junit5.
Remark: groovy.groupId is set to org.codehaus.groovy (it's a variable, because it will be replaced by org.apache.groovy in 4.x) and groovy.version is set to 3.0.8.
If you want to be a bit more verbose, you can add...
<activation>
<activeByDefault>false</activeByDefault>
</activation>
...but it's the default anyway.

Need Multiple versions for same dependency for Maven

I know its a repetitive question on Site , but I didn't find solution to my problem.
I have project specific dependency with multiple versions and I want all of them :
<dependency>
<groupId>com.abc.textile</groupId>
<artifactId>textile-client</artifactId>
<version>431</version>
</dependency>
<dependency>
<groupId>com.abc.textile</groupId>
<artifactId>textile-client</artifactId>
<version>441</version>
</dependency>
<dependency>
<groupId>com.abc.textile</groupId>
<artifactId>textile-client</artifactId>
<version>451</version>
</dependency>
PS : Doing migration from ANT to MAVEN. Thus ANT can support multiple versions for the same jar in lib folder.(textile-client-431.jar,textile-client-441.jar,textile-client-451.jar) But when migrating to MAVEN, it takes only the latest version(textile-client-451.jar). Is there any way to include all versions.
As far as I know, Maven does not allow that. Maven will only resolve one dependency and will avoid the other ones.
I do not test it, but I remember to read about two possibilities:
First, you can specify different profiles, and in each profile you can specify a dependency with a version. Something like this:
<profiles>
<profile>
<id>431</id>
<activation>
...
</activation>
<dependencies>
<dependency>
<groupId>com.abc.textile</groupId>
<artifactId>textile-client</artifactId>
<version>431</version>
</dependency>
</dependencies>
</profile>
<profile>
<id>431</id>
<activation>
...
</activation>
<dependencies>
<dependency>
<groupId>com.abc.textile</groupId>
<artifactId>textile-client</artifactId>
<version>431</version>
</dependency>
</dependencies>
</profile>
<profiles>
Second, I read something some time ago about OSGI, maybe it could help you to take a look. http://felix.apache.org/documentation/subprojects/apache-felix-maven-bundle-plugin-bnd.html

Maven Profile in different dependencies

I have a Maven module with two different database profiles.
<profile>
<id>db-localhost-oracle</id>
<dependencies>
<dependency>
<groupId>ojdbc6</groupId>
<artifactId>ojdbc6</artifactId>
</dependency>
</dependencies>
<properties>
<db.driver>oracle.jdbc.driver.OracleDriver</db.driver>
<db.dialect>no.jbv.sergej.util.FixedOracle10gDialect</db.dialect>
<db.url>jdbc:oracle:thin:#//localhost:1521/xe</db.url>
<db.hbm2ddl>update</db.hbm2ddl>
</properties>
</profile>
<profile>
<id>db-localhost-mysql</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependencies>
<properties>
<db.driver>com.mysql.jdbc.Driver</db.driver>
<db.dialect>org.hibernate.dialect.MySQL5Dialect</db.dialect>
<db.url>jdbc:mysql://localhost/${mysql.schema}</db.url>
<db.hbm2ddl>update</db.hbm2ddl>
</properties>
</profile>
When is run maven install with "db-localhost-mysql" it includes the "mysql-connector-java" jar file in lib directory. Now I do clean install with "db-localhost-oracle" and it includes the both "mysql-connector-java" and "ojdbc6" jars in the lib directory.
How can I make it like, if I build with one profile maven automatically remove the jars for other profile?
Your problem does not match what should happen in practice. Your profile definition sounds about right to me:
mvn clean install will enable the db-localhost-mysql (as it is marked as to be activated by default) and it will add mysql-connector-java. The same will happen if you run mvn clean install -Pdb-localhost-mysql
mvn clean install -Pdb-localhost-oracle will add the ojdbc6 driver. The mysql profile will not be enabled (as it is triggered only if no profile is explicitly active).
That does not mean your current dependency hierarchy hasn't already one of those jars. It might come as a transitive dependency. To isolate this case and know which project needs to be fixed run mvn dependency:tree -Pdb-localhost-oracle to look at your dependencies hierarchy when the mysql profile is not enabled.
I assume you download your downloaded dependencies using maven-dependency-plugin somewhere outside your target dir (${basedir}/lib).
If that is the case, you would need to include your lib dir inside your clean definition (see http://maven.apache.org/plugins/maven-clean-plugin/examples/delete_additional_files.html):
<build>
[...]
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>2.5</version>
<configuration>
<filesets>
<fileset>
<directory>lib</directory>
</fileset>
</filesets>
</configuration>
</plugin>
[...]
</build>
However: Please consider doing it differently:
do not have your regular build change anything outside the target directory, if possible (which would have prevented your problem in first place), instead download to something like target/lib
Please do not use profiles to change the outcome of your build. This is dangerous. (see http://www.blackbuild.com/how-to-really-use-maven-profiles-without-endangering-your-karma/ for an extended explanation)
If you want different outcame consider Maven Assemblies.

Categories