Need Multiple versions for same dependency for Maven - java

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

Related

How to build and test AWS Lambda code with layers

I'm new to AWS Lambdas. Running Java 11 and using IntelliJ.
We currently have a layer which contains a lot of dependencies so our lambdas don't have to include all of them. We now need to write a new set of lambdas which will have some additional common functionality, so I want to write another set of Common code, which also depends are our existing dependency layer. Then, all our new lambdas will include the Common code, which also includes the existing layer
In my new Common code, I reference the dependency layer like this
<dependency>
<groupId>com.xxx</groupId>
<artifactId>my-layer</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
scope=provided is specified so that the layer is not included in the Common jar, but instead will be provided by AWS at runtime.
The problem is that when I write another lambda that tries to include my Common codes as a dependency, all of the dependencies in the dependency layer are not included. I just want to be able to build and test locally. Is there a way I can specify scope=provided only when building for actual deployment, but scope=compile when testing locally? Or maybe a totally different way of doing it?
You can use Maven profiles, creating something like this
<profiles>
<profile>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<id>local</id>
<dependencies>
<dependency>
<groupId>com.xxx</groupId>
<artifactId>my-layer</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</profile>
<profile>
<id>deployment</id>
<dependencies>
<dependency>
<groupId>com.xxx</groupId>
<artifactId>my-layer</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
</dependencies>
</profile>
</profiles>
So you will have default profile for local development and to use the other dependency definition you call maven in that way
mvn -P deployment

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.

Add dependency according to the given condition in Maven

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.

Setting custom runtime classpath for a maven project in netbeans

I want to add a custom classpath when I'm running my maven project from within netbeans. So far I've tried adding the following to the Run Project action in the project properties:
exec.args=-classpath %classpath;c:/QUASR/duplicateRemoval.jar;c:/QUASR/lib/QUASR.jar ${packageClassName}
exec.args=-cp %classpath;c:/QUASR/duplicateRemoval.jar;c:/QUASR/lib/QUASR.jar ${packageClassName}
exec.args=-cp c:/QUASR/duplicateRemoval.jar;c:/QUASR/lib/QUASR.jar ${packageClassName}
but no luck, the custom runtime classpath is not set.
You should add a new profile run-with-netbeans in your pom that declares the additional dependencies (use the provided scope to not include them in the release).
Then you'll have to add the new profile to your IDE to run the pom with the -P run-with-netbeans option in the command line.
<properties>
<!-- provided by default -->
<my-dynamic-scope>provided</my-dynamic-scope>
</properties>
<profiles>
<profile>
<id>run-with-netbeans</id>
<properties>
<!-- compile when running in IDE -->
<my-dynamic-scope>compile</my-dynamic-scope>
</properties>
<dependencies>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
</dependencies>
</profile>
</profiles>
<dependencies>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>${commons-lang.version}</version>
<scope>${my-dynamic-scope}</scope>
</dependency>
</dependencies>
The snippet above add log4j only when running with the run-with-netbeans profile. It also sets a property my-dynamic-scope that can be used in your dependency block to change the scope.
HIH
M.

Categories