3

I have a gradle project P which has module A and B. Module A has this jackson dependencies:

...
dependencies {
    ...
    compile 'com.fasterxml.jackson.core:jackson-core:2.12.0-rc1'
    compile 'com.fasterxml.jackson.core:jackson-annotations:2.12.0-rc1'
    compile 'com.fasterxml.jackson.core:jackson-databind:2.12.0-rc1'
    compile 'com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.12.0-rc1'
    ...
}
...

and module B uses module A, and has no need for including this dependencies because jackson usage is encapsulated in module A. But when code executed from module B reaches a statement that invokes code from Module A using it, I get exception:

java.lang.NoClassDefFoundError: com/fasterxml/jackson/dataformat/xml/XmlMapper

If I add the same dependencies to Module's B gradle.build file, the code works. The question is, why would I include them if Module A does not use the library? Shouldn't dependencies in Module A be compiled, packaged, so that when Module A is used elsewhere, its code works (using its included dependencies such as jackson library as in this example)

zaerymoghaddam
  • 3,037
  • 1
  • 27
  • 33
transgressoft
  • 155
  • 2
  • 13
  • Is you application packaged as war/ear artifacts and gets deployed on a container or it's just a plain java jar with main? – zaerymoghaddam Nov 03 '20 at 21:02
  • It's just plain java with no main class. Let's say Module A is api code from project P and module B is core which has it as dependency. No plan to deliver Module A outside the entire project P. Project P is bundled as java (javafx in fact, using spring boot) application packaged as jar. – transgressoft Nov 03 '20 at 21:20
  • 1
    you mean you execute some code from `module B`? If moduleB has a dedicated `build.gradle` then of course those dependencies are not going to be there. you could create a common `build.gradle` for both modules and include all the needed dependencies via `subprojects`... – Eugene Nov 20 '20 at 19:49

1 Answers1

2

Disclaimer: I don't know Gradle, but this sounds like a problem common to Maven and Gradle.

The fact that you can build the module, but not run the module, means that somewhere you are not bringing the transitive dependencies into the Spring Boot fat jar. Jackson doesn't do anything weird with metadata files, classloaders, etc. It plays well with others in a fat jar.

Given that you haven't shared much of your build files, the easiest way to figure out if something has excluded the Jackson XML module is to just run jar -xvf target/app.jar and inspect the output to see if it's in there.

If it's not, look for a Gradle equivalent of the Maven dependency plugin's dependency-tree target that will show you the whole transitive dependency tree. If it's being excluded you'll definitely see it missing from a dependency dump.

Mike Thomsen
  • 36,828
  • 10
  • 60
  • 83
  • 1
    The created jar for the module that contains the jackson dependencies only contain my production code, nothing else, no classes from the dependencies. This highlights that probably I need to build a `fatJar` somehow, I think. – transgressoft Nov 23 '20 at 19:14