Transitive dependency not included in war package - maven-2

A war project is dependent on com.mycompany:somejarname:1.0. It is dependent on slf4j-log4j12 (this is needed only at runtime by that jar).
The packaged war doesn't include slf4j-log4j12- my understanding is that it should be included since because of transitive dependency: war --> somejarname --> slf4j-log4j12. The dependency tree does show the dependency but it is not included in the final war package.
[INFO] +- com.mycompany:somejarname:jar:1.0:compile
[INFO] | +- common-crypt:common-crypt:jar:1.0:compile
[INFO] | +- org.apache.axis2:axis2-spring:jar:1.5.1:compile
[INFO] | +- org.objenesis:objenesis:jar:1.1:compile
[INFO] | +- org.mockito:mockito-all:jar:1.9.0:compile
[INFO] | +- org.slf4j:slf4j-log4j12:jar:1.5.6:compile
[INFO] | \- net.sf.json-lib:json-lib:jar:jdk15:2.4:compile
[INFO] | \- net.sf.ezmorph:ezmorph:jar:1.0.6:compile
Any suggestions? Using Maven 3
UPDATE: this works with Maven 2.2.1, but not with Maven 3.0.4. Dependency resolution in Maven 3 was changed from 2.2.1.
UPDATE: dependency tree functionality in Maven 3 is same as in Maven 2.2.1 so the tree above shows slf4j-log4j12.
Furthermore, not all parts of the Maven 2.x resolution API could be bridged onto Aether. Most notably the maven-dependency-tree shared component which is used for mvn dependency:tree still uses the legacy resolution code. As such, the output from mvn dependency:tree can differ from the actual dependency tree used by Maven itself to derive the classpaths of a project (see MSHARED-167 for an example of such a discrepancy)

Found the same issue using Maven 3.2.5 from Eclipse Mars (m2e plugin).
Solved it by using Maven 3.3.3 (needs Java 7 or 8) that comes packaged by default with Eclipse Mars.

Related

How to add project's name under "include" in installed location using CMake

I'm building PyTorch (which uses CMake) and it installs its header files and folders directly inside the include directory. I'd like it to install the headers in a subdirectory of the include directory, named pytorch (or for my needs, libtorch).
Actual:
+- include
+- torch
+- library.h
+- ...
Desired:
+- include
+- pytorch
+- torch
+- library.h
+- ...
Most other libraries I've built do this which is nice because it keeps the files organized.
How can I accomplish this with CMake?

Why does Gradle force a Kotlin version, and how to fix it?

I have a simple Gradle project that includes the following configuration:
plugins {
kotlin("jvm")
}
This does different things when running with different gradle versions:
$ ./gradlew wrapper --gradle-version=7.5
$ ./gradlew --version
Kotlin: 1.6.21
$ ./gradlew wrapper --gradle-version=7.4.2
$ ./gradlew --version
Kotlin: 1.5.31
$ ./gradlew wrapper --gradle-version=7.2
$ ./gradlew --version
Kotlin: 1.5.21
OK, so Gradle is determining the version of the Kotlin plugin. Bonus questions: Why does Gradle do this? Is this version link documented somewhere?
I'd like to specify the Kotlin version myself. So I change my config:
plugins {
kotlin("jvm") version "1.6.10"
}
Now Gradle complains:
Plugin request for plugin already on the classpath must not include a version
I've checked, and nowhere else in my project do I define a Gradle version explicitly.
Main question: How do I make Gradle use a Kotlin version of my choice?
From my experience the below configuration works fine for a single-project Gradle project with most gradle version.
plugins {
kotlin("jvm") version "1.6.10"
}
Example: https://github.com/jimmyiu/demo-spring-cache. I changed the kotlin version from 1.6.21 to 1.7.10 which works fine.
Are you working on a multi-project Gradle project with buildSrc folder? Since buildSrc is a special subproject which build your custom kotlin-dsl which can be used by Gradle.
This can answer your bonus question: for simplicity, buildSrc should be built to something that can be understood by your project specified Gradle version, hence it must have the same kotlin version as your selected Gradle.
If you root project set the Kotlin version to a version that not align with your Gradle, buildSrc project cannot be built.
To properly configure this, you can:
// root project’s build.gradle.kts
plugins {
kotlin("jvm") version "1.6.10" apply false
}
// in each subproject (except buildSrc):
plugins {
java
kotlin("jvm")
}
About the output of ./gradlew --version, the Kotlin version showing in the output is the build information of that Gradle version, but not your project.
$./gradlew --version
------------------------------------------------------------
Gradle 6.6.1
------------------------------------------------------------
Build time: 2020-08-25 16:29:12 UTC
Revision: f2d1fb54a951d8b11d25748e4711bec8d128d7e3
Kotlin: 1.3.72
Groovy: 2.5.12
Ant: Apache Ant(TM) version 1.10.8 compiled on May 10 2020
JVM: 11.0.15 (Private Build 11.0.15+10-Ubuntu-0ubuntu0.20.04.1)
OS: Linux 5.13.0-52-generic amd64
As an example, Gradle 6.6.1 is built by Kotlin 1.3.72 so that the buildSrc folder should use Kotlin 1.3.72, but the rest of your project can use another Kotlin version.
Reference:
detail explanation of buildSrc: Configure Kotlin extension for Gradle subprojects
suggested solution reference: https://discuss.kotlinlang.org/t/specifying-the-kotlin-version-in-gradle-multi-project-builds/23838
About apply false: https://docs.gradle.org/current/userguide/plugins.html#sec:subprojects_plugins_dsl

Which standard library to use in Kotlin

In Kotlin, when working with the JVM, it seems there is multiple choices for standard library, namely kotlin-stdlib, kotlin-stdlib-jdk7 and kotlin-stdlib-jdk8.
I cannot, however, find anything telling me the difference between these.
The only visible difference I have found is that I cannot use com.fasterxml.jackson.databind.exc.MismatchedInputException with kotlin-stdlib, but I can with kotlin-stdlib-jdk8.
Is there anywhere I can read about the advantages using one over the others, or can anyone explain this in layman terms?
Most of the stdlib is in the plain kotlin-stdlib artifact.
kotlin-stdlib-jdk7 adds suppressed exceptions and a few extension methods.
kotlin-stdlib-jdk8 adds ThreadLocalRandom as well as a few other extension methods and retrieving groups by name in Regexes.
The code is there: https://github.com/JetBrains/kotlin/blob/55c8b35eee2ee8a93ccaffeaac6f9c3e4fd4ff18/libraries/stdlib/jvm/src/kotlin/internal/PlatformImplementations.kt#L27
EDIT: I got curious so wrote an article about this: https://medium.com/#mbonnin/the-different-kotlin-stdlibs-explained-83d7c6bf293.
Bottom line: Android declares a weird JVM version so almost nothing from -jdk7 and -jdk8 is used.
As the name indicates, -jdk8 is supposed to be used when using the JDK8. It contains code used to integrate the changes made in the JDK 8 into the Kotlin standard lib.
As its pom indicates, it depends on -jdk7, which contains the code needed to integrate the changes made in the JDK 7 into the Kotlin standard lib.
And as the pom of -jdk7 indicates, it depends on the stdlib.
So, in short, use the one matching your JDK. Adding it to the dependencies will also, transitively, add all the ones for the previous versions of the JDK.
As of Kotlin 1.8, the different standard libraries have been merged, and you can just use kotlin-stdlib. JVM targets 1.6 and 1.7 are not supported anymore.
Updated JVM compilation target
In Kotlin 1.8.0, the standard libraries (kotlin-stdlib,
kotlin-reflect, and kotlin-script-*) are compiled with JVM target 1.8.
Previously, the standard libraries were compiled with JVM target 1.6.
Kotlin 1.8.0 no longer supports JVM targets 1.6 and 1.7. As a result,
you no longer need to declare kotlin-stdlib-jdk7 and
kotlin-stdlib-jdk8 separately in build scripts because the contents of
these artifacts have been merged into kotlin-stdlib.
note
If you have explicitly declared kotlin-stdlib-jdk7 and kotlin-stdlib-jdk8 as dependencies in your build scripts, then you
should replace them with kotlin-stdlib.
Note that mixing different versions of stdlib artifacts could lead to
class duplication or to missing classes. To avoid that, the Kotlin
Gradle plugin can help you align stdlib versions.
What's new in Kotlin 1.8 - Updated JVM compilation target
By running Gradle dependencies task in your Kotlin project, you can find some useful information. This is a part of output in a sample project:
$ ./gradlew dependencies
...
kotlinCompilerClasspath
\--- org.jetbrains.kotlin:kotlin-compiler-embeddable:1.3.20
+--- org.jetbrains.kotlin:kotlin-stdlib:1.3.20
| +--- org.jetbrains.kotlin:kotlin-stdlib-common:1.3.20
| \--- org.jetbrains:annotations:13.0
+--- org.jetbrains.kotlin:kotlin-script-runtime:1.3.20
+--- org.jetbrains.kotlin:kotlin-reflect:1.3.20
| \--- org.jetbrains.kotlin:kotlin-stdlib:1.3.20 (*)
\--- org.jetbrains.intellij.deps:trove4j:1.0.20181211
...

Create an AAR with multiple AARs/JARs

I have seen questions (Android Studio combine 2 .aar into one and others) posted by various developers but I haven't seen a definitive response that enables me to create an AAR that includes 1 or more AARs or JARs (I can do with JARs since I don't need to share any resources; only classes). Here is the app.gradle for my library project:
apply plugin: 'com.android.library'
android {
compileSdkVersion 19
buildToolsVersion "19.1.0"
defaultConfig {
minSdkVersion 16
targetSdkVersion 21
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
}
}
}
dependencies {
compile 'com.google.code.gson:gson:2.1'
compile ('libs/eventbus.jar')
compile project(':core-release')
compile project(':midware-release')
}
Again, this app is a library project which needs two other library projects ('core-release', 'midware-release') and while I was able to generate one AAR file that I can use in my application, the application was unable to find the dependent library projects' classes so, I had to add the two library projects' AARs into my application.
Here is the app.gradle application project (without adding the JARs manually) which is unable to find the dependent projects' classes:
apply plugin: 'com.android.application'
android {
compileSdkVersion 23
buildToolsVersion "23.0.1"
defaultConfig {
applicationId "com.app.sample"
minSdkVersion 19
targetSdkVersion 23
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.1.1'
compile 'com.android.support:design:23.1.1'
compile files('libs/eventbus.jar')
compile project(':sdk3-debug')
}
I don't think the library project's AAR file is pulling in the dependent projects (AAR or JAR) and hence the application is unable to find the classes.
I read about transitive dependency, but I was unable to find an example implementation which may help with my situation.
I haven't seen a definitive response that enables me to create an AAR that includes 1 or more AARs or JARs.
Yes, I think because this topic is not limited to AAR or JAR, but how Maven manage dependency.
https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html
while I was able to generate one AAR file that I can use in my application, the application was unable to find the dependent library projects' classes so, I had to add the two library projects' AARs into my application.
It's not your AAR responsibility to include your dependencies, your POM file should include information about dependencies.
https://maven.apache.org/pom.html
I don't think the library project's AAR file is pulling in the dependent projects (AAR or JAR) and hence the application is unable to find the classes.
Correct, you still need to include libraries dependency in your Application.
I assume you want your library can be used by Application, without specifying your library dependencies core-release and midware-release. I made a full explanation here android studio generate aar with dependency but here is what you need to do:
Upload core-release and midware-release to your Maven repository
Create a POM file for your library that include your dependencies
<project>
<modelVersion>4.0.0</modelVersion>
<parent>...</parent>
<artifactId>okhttp</artifactId>
<name>OkHttp</name>
<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>core-release</artifactId>
</dependency>
<dependency>
<groupId>com.example</groupId>
<artifactId>midware-release</artifactId>
</dependency>
</dependencies>
<build>...</build>
</project>
Publish your AAR with that POM file
mvn deploy:deploy-file \
-DgroupId=com.example \
-DartifactId=your-library \
-Dversion=1.0.1 \
-Dpackaging=aar \
-Dfile=your-library.aar \
-DpomFile=path-to-your-pom.xml \
-DgeneratePom=true \
-DupdateReleaseInfo=true \
-Durl="https://mavenUserName:mavenPassword#nexus.example.com/repository/maven-releases/"
And then your Application can use your library. Gradle will download your library transitive dependencies automatically.
I was able to address the issue by following Stan Kurdziel 's suggestion: stackoverflow.com/questions/30052058/multiple-aar-files and here are steps I took to arrive at a solution:
I created an AAR which I published to the local maven repository
Now this AAR was accessible in the application project
This AAR also had reference to the classes in the core and midware libraries. I followed Stan Kurdziel's approach #2:
Manually add the dependency on Library Project 2 to the Application Project - so that your Application has a dependency line for both Libraries. Depending on your specific situation this may or may not be a workable solution.
Hope this helps others that might run into similar issue.
This should fix your issue:
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.1.1'
compile 'com.android.support:design:23.1.1'
compile files('libs/eventbus.jar')
compile project(':sdk3-debug') { transitive = true }
}
Include the transitive flag at true.

How to limit version of a 3rd party package dependency reference?

I have a 3rd party dependency in my project, which refer to its dependencies with open-ended version reference:
<version>[4.0,)</version>
How I can override this in my project so my dependency doesn't use versions of its dependency later than specific version, 6.0 for example? ( versions later than 6.0 require some other packages I do not want at all )
If you specify the transitive dependency explicitly in your project, the version you specify will take precedence.
For example. In your POM add the dependency on com.foo:bar with a version range with an exclusive upper limit like this:
<dependencies>
<dependency>
<groupId>com.foo</groupId>
<artifactId>bar</artifactId>
<version>[4.0,6.0)</version>
</dependency>
</dependencies>
Update(2): I just tested this and it does work (I just had a typo in my test project). Here's my test explanation.
I have 3 test projects: test-base, test-dependency, and test-transitive.
The test-base project has a direct dependency on test-dependency, test-dependency has an open-ended dependency on test-transitive.
I have 3 versions of test-transitive installed, 0.0.1, 1.0.1, and 2.0.1
If I do dependency:tree on test-base I see this:
name.seller.rich:test-base:jar:0.0.1
\- name.seller.rich:test-dependency:jar:0.0.1:compile
\- name.seller.rich:test-transitive:jar:2.0.1:compile
If I add an explicit dependency on test-transitive in test-base with the dependency range set to [0.0.1,2.0.0), I get this tree instead:
name.seller.rich:test-base:jar:0.0.1
+- name.seller.rich:test-dependency:jar:0.0.1:compile
\- name.seller.rich:test-transitive:jar:1.0.1:compile