Hi. I'm struggling to make the dependencies for a ...
# dependency-management
a
Hi. I'm struggling to make the dependencies for a project play nice, and was wondering if anyone could point me in the right direction. Gradle version: 5.1.1, IDE: IntelliJ, Language: Java 2 dependencies. Will call them A and B. 1 transient dependency. Will call it C. A depends on C_1.0, can't use later versions. B depends on C_2.0, can't use earlier versions. Normally, it would seem like I could use exclude statements. What's causing me problems is that A is included from a local jar file. (The line in build.gradle is "compile fileTree(dir: 'lib', include: '*.jar')" 'lib' also contains C_1.0 as a jar for A to depend on. The program compiles. When I run the program, B calls C_1.0 (where I want it to call C_2.0) and throws an exception. (If I delete the C_1.0 jar file, the program calls B successfully, but then calls to A fail.) I can't delete the local jars, or edit A or B. Is there a way I can keep C_1.0 from interfering with calls to B? Any tips appreciated. I'm really stuck on this one.
c
Could consider shading one if the versions to a different package structure, allowing both to coexist
e
if you need both C_1.0 and C_2.0 but they can't coexist, you will need tricks such as shading or separate classloaders, not much way around that.
a
Thank you. Shading looks like it's going to work. I didn't realize there were plugins to automate most of it. That'll help a lot.
c
Glad to hear it. Shading is mostly straightforward - if there are service descriptor or other files in the jar that reference classnames there's a few extra steps to consider.
a
Update: I'm attempting to shade dependency B, along with its transient dependency C_2.0. I'm using the johnrengelman plugin (https://plugins.gradle.org/plugin/com.github.johnrengelman.plugin-shadow). I've created a Bshade.jar file this way and attached it to the project. It contains B in a renamed package B.shade.B. I added "B.shade." to all import statements for B in my project, and "find declaration" on those import statements goes to the decompiled .class files in the jar, so it seems to be seeing it correctly. I think B is trying to load classes through java reflection, and the shading is causing it to fail. At least, that's what I'm gathering from the errors below: "java.lang.reflect.InvocationTargetException: null java.lang.NoClassDefFoundError: B/shade/B/Class1 java.lang.ClassNotFoundException: B.shade.B.Class1" Is there a workaround for java classes loaded through reflection when shading java dependencies?
c
hmmm. that is referencing the shaded classes, which is correct (reflection issues would show the unshaded class name) - perhaps an incorrect JAR is installed at runtime (s/b the shade d JAR - if that was missing it could cause this).