Finding unwanted code dependencies on transitive dependencies - gradle

I want to find all my Java code dependencies on libraries that I have not included as top level dependencies in Gradle.
My first though as to how to accomplish this is to turn off all transitive dependencies in Gradle and see what compilation errors I get.
From my research the way to do this seems to be:
configurations.all { transitive = false }
Is there a better way, or does this do it?

I'm not sure I understand the question, but the command line "gradle dependencies" might help.
For example, consider this (from this modest project):
dependencies {
groovy 'org.codehaus.groovy:groovy-all:1.6.4'
groovy 'com.google.guava:guava-collections:r03'
releaseJars 'org.codehaus.groovy:groovy-all:1.6.4'
releaseJars 'com.google.guava:guava-collections:r03'
}
Using gradle dependencies gives output such as:
compile - Classpath for compiling the main sources.
+--- org.codehaus.groovy:groovy-all:1.6.4
| +--- junit:junit:3.8.2
| +--- org.apache.ant:ant:1.7.1
| | \--- org.apache.ant:ant-launcher:1.7.1
| +--- org.apache.ant:ant-launcher:1.7.1
| \--- jline:jline:0.9.94
| \--- junit:junit:3.8.1 -> 3.8.2
\--- com.google.guava:guava-collections:r03
+--- com.google.guava:guava-annotations:r03
\--- com.google.guava:guava-primitives:r03
....

Related

In gradle dependencies, why API configurations discards all transitive dependencies?

I have a gradle project that contains 2 subprojects: common & demo.
The common project depends on a published library:
dependencies {
implementation("eu.timepit:singleton-ops_${vs.scalaBinaryV}:0.5.0")
...
The demo project depends on common as part of its API:
dependencies {
api(project(":common")) {
isTransitive =true
}
}
When I compile both, I observe the correct dependency in common:
compileClasspath - Compile classpath for source set 'main'.
+--- org.scala-lang:scala-compiler:2.12.11
| +--- org.scala-lang:scala-library:2.12.11
| +--- org.scala-lang:scala-reflect:2.12.11
| | \--- org.scala-lang:scala-library:2.12.11
| \--- org.scala-lang.modules:scala-xml_2.12:1.0.6
+--- org.scala-lang:scala-library:2.12.11
+--- org.scala-lang:scala-reflect:2.12.11 (*)
\--- eu.timepit:singleton-ops_2.12:0.5.0
+--- org.scala-lang:scala-compiler:2.12.8 -> 2.12.11 (*)
+--- org.scala-lang:scala-library:2.12.8 -> 2.12.11
\--- com.chuusai:shapeless_2.12:2.3.3
+--- org.scala-lang:scala-library:2.12.4 -> 2.12.11
\--- org.typelevel:macro-compat_2.12:1.1.1
\--- org.scala-lang:scala-library:2.12.0 -> 2.12.11
but in demo, the transitive dependecies under common are empty!
compileClasspath - Compile classpath for source set 'main'.
+--- project :common
+--- org.scala-lang:scala-compiler:2.12.11
...
This leads to the very common classpath missing errors, like:
[Error] /xxx/DoubleVectorDemo.scala:9: Symbol 'type shapeless.ProductArgs' is missing from the classpath.
This symbol is required by 'object edu.umontreal.kotlingrad.shapesafe.tensor.DoubleVector'.
Make sure that type ProductArgs is in your classpath and check for conflicting dependencies with `-Ylog-classpath`.
A full rebuild may help if 'DoubleVector.class' was compiled against an incompatible version of shapeless.
So what's the point of dropping libraries for something that is part of your API? And how to override this behaviour in all projects?
From the gradle java-plugin doc,
The api configuration should be used to declare dependencies which are exported by the library API, whereas the implementation configuration should be used to declare dependencies which are internal to the component. Dependencies appearing in the api configurations will be transitively exposed to consumers of the library, and as such will appear on the compile classpath of consumers. Dependencies found in the implementation configuration will, on the other hand, not be exposed to consumers, and therefore not leak into the consumers' compile classpath
Let's say of you want to expose eu.timepit:singleton-ops_${vs.scalaBinaryV}:0.5.0 to all of the common library then you need to add this as api dependency in common module build.gradle.kts.
dependencies {
api("eu.timepit:singleton-ops_${vs.scalaBinaryV}:0.5.0")

How to resolve JAXB classpath issues on Java 12

Im porting application using JAXB to JDK 11/12 but am completely lost when trying to fix those JAXB classpath issues. I have googled and read basically everything related to this so Im aware of the changes made in Java11, i.e. removal of JAXB from JDK ... However in that case I would assume a trivial fix consisting of adding api and impl JARs on classpath. But this is not working and despite I have those JARs on classpath Im still getting the known exception, despite using 2.3.2 JAXB:
javax.xml.bind.JAXBException
- with linked exception:
[java.lang.ClassNotFoundException: com.sun.xml.internal.bind.v2.ContextFactory]
even if I see the class is in different package and I instruct to use correct package via system variable it does not work either:
gradle -Djavax.xml.bind.context.factory=com.sun.xml.bind.v2.ContextFactory build
javax.xml.bind.JAXBException
- with linked exception:
[java.lang.ClassNotFoundException: com.sun.xml.bind.v2.ContextFactory]
Does anyone have clue how to resolve this? I dont want to play with manifest files etc. It should be possible to just place the right JARs on classpath and that is it, or not?
Summary here but unable to get it working:
http://www.descher.at/descher-vu/2019/01/java-11-jaxb-and-osgi/
Update, dependencies used in Gradle:
- jaxb-xjc has jaxb-runtime (impl.) as transitive dependency. I see it is picked by Gradle but still the same error.
classpath "com.sun.activation:javax.activation:1.2.0"
classpath "jakarta.xml.bind:jakarta.xml.bind-api:2.3.2"
classpath "org.glassfish.jaxb:jaxb-xjc:2.3.2"
classpath"org.glassfish.jaxb:jaxb-core:2.3.0.1"
[org.gradle.internal.operations.DefaultBuildOperationExecutor] Build operation 'Resolve jaxb-runtime.jar (org.glassfish.jaxb:jaxb-runtime:2.3.2)' completed
[org.gradle.internal.component.model.ComponentAttributeMatcher] Selected match org.glassfish.jaxb:jaxb-runtime:2.3.2 configuration runtime from candidates [org.glassfish.jaxb:jaxb-runtime:2.3.2 configuration runtime] for {org.gradle.dependency.bundling=external, org.gradle.jvm.version=12, org.gradle.usage=java-runtime}
This is output of "gradle dependencies" and all the JAXB jars are there, still classpath error is being thrown. The JAR file jaxb-runtime from Glassfish for sure has this ContextFactory class.
runtimeClasspath - Runtime classpath of source set 'main'.
+--- org.springframework.boot:spring-boot-starter-log4j2 -> 2.1.0.RELEASE
| +--- org.apache.logging.log4j:log4j-slf4j-impl:2.11.1
| | +--- org.slf4j:slf4j-api:1.7.25
| | +--- org.apache.logging.log4j:log4j-api:2.11.1
| | \--- org.apache.logging.log4j:log4j-core:2.11.1
| | \--- org.apache.logging.log4j:log4j-api:2.11.1
| +--- org.apache.logging.log4j:log4j-core:2.11.1 (*)
| +--- org.apache.logging.log4j:log4j-jul:2.11.1
| | \--- org.apache.logging.log4j:log4j-api:2.11.1
| \--- org.slf4j:jul-to-slf4j:1.7.25
| \--- org.slf4j:slf4j-api:1.7.25
+--- org.projectlombok:lombok -> 1.18.2
+--- org.apache.commons:commons-lang3 -> 3.8.1
+--- org.apache.commons:commons-collections4 -> 4.4
+--- com.google.guava:guava -> 23.0
| +--- com.google.code.findbugs:jsr305:1.3.9
| +--- com.google.errorprone:error_prone_annotations:2.0.18
| +--- com.google.j2objc:j2objc-annotations:1.1
| \--- org.codehaus.mojo:animal-sniffer-annotations:1.14
+--- org.apache.ws.xmlschema:xmlschema-core -> 2.0.1
+--- org.glassfish.jaxb:jaxb-runtime:2.3.2
| +--- jakarta.xml.bind:jakarta.xml.bind-api:2.3.2
| | \--- jakarta.activation:jakarta.activation-api:1.2.1
| +--- org.glassfish.jaxb:txw2:2.3.2
| +--- com.sun.istack:istack-commons-runtime:3.0.8
| | \--- jakarta.activation:jakarta.activation-api:1.2.1
| +--- org.jvnet.staxex:stax-ex:1.8.1
| | +--- jakarta.activation:jakarta.activation-api:1.2.1
| | \--- jakarta.xml.bind:jakarta.xml.bind-api:2.3.2 (*)
| +--- com.sun.xml.fastinfoset:FastInfoset:1.2.16
| \--- jakarta.activation:jakarta.activation-api:1.2.1
\--- org.glassfish.jaxb:jaxb-core:2.3.0.1
+--- javax.xml.bind:jaxb-api:2.3.0 -> 2.3.1
| \--- javax.activation:javax.activation-api:1.2.0
+--- org.glassfish.jaxb:txw2:2.3.0.1 -> 2.3.2
\--- com.sun.istack:istack-commons-runtime:3.0.5 -> 3.0.8 (*)
From some reason I had no luck with Glassfish JARs, but those original Sun/Oracle dependencies worked.

Enforce the highest version from among several conflicting transitive dependencies in gradle

I work on a large project with multiple services and libraries, mostly in grails, with gradle builder. I'm trying to update a library (say logback) for security reasons.
I already updated it in one of our libraries (say our-logger), like so:
#our-logger/build.gradle
...
dependencies {
...
compile 'ch.qos.logback:logback-classic:1.2.3'
...
}
when I update a service (say our-service) to use the new version of our-logger i get logback included from other libraries, and gradle chooses the lower version coming through cobertura and some other dependencies, instead of the higher version coming through our-logger.
#our-service/build.gradle
...
apply plugin: 'cobertura'
...
dependencies {
...
compile 'our-logger:9.99' # safe now with logback-1.2.3
...
}
~/our-service $ ./gradlew dependencies
...
cobertura
\--- net.sourceforge.cobertura:cobertura:2.1.1
+--- ch.qos.logback:logback-classic:1.0.13 -> 1.1.11
| \--- ch.qos.logback:logback-core:1.1.11
...
compile - Dependencies for source set 'main' (deprecated, use 'implementation ' instead).
+--- org.grails:grails-dependencies:3.3.8
| +--- org.springframework.boot:spring-boot-starter-logging:1.4.2.RELEASE -> 1.5.15.RELEASE
| | +--- ch.qos.logback:logback-classic:1.1.11
| | | +--- ch.qos.logback:logback-core:1.1.11
...
+--- our-logger:9.99
| +--- ch.qos.logback:logback-classic:1.2.3 -> 1.1.11 (*)
How do I enforce logback-1.2.3 without explicitly declaring it in all services?
The gradle docs file this under Advanced Dependency Management. You should be able to satisfy your goal using excludes. There are other ways too Gradle Docs
compile(“some:other:dependency”) {
exclude group: 'ch.qos.logback', module: 'logback-classic'
}

Codenarc strange dependencies

We are using codenarc plugin and gradle, and i see the strange things in dependencies:
codenarc - The CodeNarc libraries to be used for this project.
\--- org.codenarc:CodeNarc:0.25.2
+--- junit:junit:4.8.1 -> 4.12
| \--- org.hamcrest:hamcrest-core:1.3
+--- org.codehaus.groovy:groovy-xml:2.1.8 -> 2.6.0-alpha-1
| \--- org.codehaus.groovy:groovy:2.6.0-alpha-1
+--- org.codehaus.groovy:groovy:2.1.8 -> 2.6.0-alpha-1
+--- org.codehaus.groovy:groovy-ant:2.1.8 -> 2.6.0-alpha-1
| +--- org.codehaus.groovy:groovy:2.6.0-alpha-1
| +--- org.codehaus.groovy:groovy-groovydoc:2.6.0-alpha-1 -> 2.4.9
| | +--- org.codehaus.groovy:groovy-templates:2.4.9
| | | +--- org.codehaus.groovy:groovy:2.4.9 -> 2.6.0-alpha-1
| | | \--- org.codehaus.groovy:groovy-xml:2.4.9 -> 2.6.0-alpha-1 (*)
| | \--- org.codehaus.groovy:groovy:2.4.9 -> 2.6.0-alpha-1
| +--- org.apache.ant:ant-junit:1.9.9
| \--- org.apache.ant:ant-antlr:1.9.9
\--- org.gmetrics:GMetrics:0.7
+--- org.codehaus.groovy:groovy:[2.1.0,) -> 2.6.0-alpha-1
+--- org.codehaus.groovy:groovy-xml:[2.1.0,) -> 2.6.0-alpha-1 (*)
\--- org.codehaus.groovy:groovy-ant:[2.1.0,) -> 2.6.0-alpha-1 (*)
Version of codenark is 0.25.2 and in pom it depends on groovy 2.1.8, but wtf - why it links to 2.6.0-alpha-1? How i can tell for codenark to use version of Groovy 2.1.8?
Thanks for help.
As you can see in your output the culprit is GMetrics.
CodeNarc 0.25.2 depends on GMetrics 0.7 which in turn depends on Groovy 2.1.0 or newer which resolves to the newest available version 2.6.0-alpha-1.
Default version conflict resolution strategy is to use the newest version on conflict, which then is the 2.6.0-alpha-1.
It is an error (in my opinion) for a lib to publish with a dynamic range.
GMetrics obviously also have seen this as error and fixed this dependency in 1.0 where they depend on a specific Groovy version instead.
CodeNarc 1.0 in turn depends on GMetrics 1.0.
So the easiest you could do if feasible, is to depend on CodeNarc 1.0 and your problem will be gone.
Alternatively you can also declare the Groovy version to be used in your own dependencies with force true which will force the version you define.
Alternatively you can configure the dependency resolution to influence the version selected.

Gradle dependency - com.google.auto:auto-common:1.0-SNAPSHOT

How do I get com.google.auto:auto-common:1.0-SNAPSHOT (transitive dependency) to resolve, in my gradle build?
build.gradle:
apply plugin: 'java'
repositories {
maven {
mavenLocal()
mavenCentral()
url "http://snapshots.maven.codehaus.org/maven2"
url "http://oss.sonatype.org/content/groups/public"
url "http://nativelibs4java.sourceforge.net/maven"
url "http://repository.jboss.org/"
}
}
dependencies {
compile 'com.google.dagger:dagger:2.0-SNAPSHOT'
compile 'com.google.dagger:dagger-compiler:2.0-SNAPSHOT'
compile 'com.google.guava:guava:18.0'
compile 'com.google.protobuf:protobuf-java:2.6.1'
compile 'com.nativelibs4java:javacl:1.0-SNAPSHOT'
compile 'org.jogamp.gluegen:gluegen-rt-main:2.0.2'
compile 'org.jogamp.jogl:jogl-all-main:2.0.2'
testCompile 'junit:junit:4.12'
testCompile 'org.mockito:mockito-core:1.9.5'
testCompile 'com.google.truth:truth:0.25'
}
Results:
$ gradle build
:compileJava
FAILURE: Build failed with an exception.
* What went wrong:
Could not resolve all dependencies for configuration ':compile'.
> Artifact 'com.google.auto:auto-common:1.0-SNAPSHOT#jar' not found.
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
BUILD FAILED
Dependency Tree: (truncated)
$ gradle dependencies
compile - Classpath for compiling the main sources.
+--- com.google.dagger:dagger:2.0-SNAPSHOT
| \--- javax.inject:javax.inject:1
+--- com.google.dagger:dagger-compiler:2.0-SNAPSHOT
| +--- com.google.dagger:dagger:2.0-SNAPSHOT (*)
| +--- com.google.dagger:dagger-producers:2.0-SNAPSHOT
| | +--- com.google.dagger:dagger:2.0-SNAPSHOT (*)
| | \--- com.google.guava:guava:18.0
| +--- com.google.auto:auto-common:1.0-SNAPSHOT <-------auto-common--------
| | \--- com.google.guava:guava:18.0
| \--- com.google.guava:guava:18.0
+--- com.google.guava:guava:18.0
+--- com.google.protobuf:protobuf-java:2.6.1
+--- com.nativelibs4java:javacl:1.0-SNAPSHOT
| \--- com.nativelibs4java:javacl-core:1.0-SNAPSHOT
| +--- com.nativelibs4java:opencl4java:1.0-SNAPSHOT
| | \--- com.nativelibs4java:bridj:0.7-SNAPSHOT
| | \--- com.google.android.tools:dx:1.7
| \--- com.nativelibs4java:nativelibs4java-utils:1.6-SNAPSHOT
+--- org.jogamp.gluegen:gluegen-rt-main:2.0.2
| \--- org.jogamp.gluegen:gluegen-rt:2.0.2
\--- org.jogamp.jogl:jogl-all-main:2.0.2
\--- org.jogamp.jogl:jogl-all:2.0.2
I have tried adding an explicit dependency for auto-common, with no luck.
To my surprise, searching things like "com.google.auto:auto-common:1.0-SNAPSHOT repository" turns up very little. It looks like the 1.0-SNAPSHOT simply isn't in Maven Central. Interestingly enough, it looks like the 1.0-SNAPSHOT is in jboss's repository, but my gradle build doesn't seem to find it.
Anyone seen something like this before? Help?
It will work in the following way - every maven url should be specified in a separate maven{} block - run copyToLibs task to verify:
apply plugin: 'java'
repositories {
mavenLocal()
mavenCentral()
[
"http://snapshots.maven.codehaus.org/maven2",
"http://oss.sonatype.org/content/groups/public",
"http://nativelibs4java.sourceforge.net/maven",
"http://repository.jboss.org/"
].each { address ->
maven {
url address
}
}
}
dependencies {
compile 'com.google.dagger:dagger:2.0-SNAPSHOT'
compile 'com.google.dagger:dagger-compiler:2.0-SNAPSHOT'
compile 'com.google.guava:guava:18.0'
compile 'com.google.protobuf:protobuf-java:2.6.1'
compile 'com.nativelibs4java:javacl:1.0-SNAPSHOT'
compile 'org.jogamp.gluegen:gluegen-rt-main:2.0.2'
compile 'org.jogamp.jogl:jogl-all-main:2.0.2'
testCompile 'junit:junit:4.12'
testCompile 'org.mockito:mockito-core:1.9.5'
testCompile 'com.google.truth:truth:0.25'
}
task copyToLib(type: Copy) {
from configurations.runtime
into 'libs'
}
In the way You specified the urls the last one was winning (covering all previously defined).

Resources