10

I'm parsing a XML string to convert it to a JsonNode in Scala using a XmlMapper from the Jackson library. I code on a Databricks notebook, so compilation is done on a cloud cluster. When compiling my code I got this error java.lang.NoSuchMethodError: com.fasterxml.jackson.dataformat.xml.XmlMapper.coercionConfigDefaults()Lcom/fasterxml/jackson/databind/cfg/MutableCoercionConfig; with a hundred lines of "at com.databricks. ..."

I maybe forget to import something but for me this is ok (tell me if I'm wrong) :

import ch.qos.logback.classic._
import com.typesafe.scalalogging._
import com.fasterxml.jackson._
import com.fasterxml.jackson.core._
import com.fasterxml.jackson.databind.{ObjectMapper, JsonNode}
import com.fasterxml.jackson.dataformat.xml._
import com.fasterxml.jackson.module.scala._
import com.fasterxml.jackson.module.scala.experimental.ScalaObjectMapper
import java.io._
import java.time.Instant
import java.util.concurrent.TimeUnit
import javax.xml.parsers._
import okhttp3.{Headers, OkHttpClient, Request, Response, RequestBody, FormBody}
import okhttp3.OkHttpClient.Builder._
import org.apache.spark._
import org.xml.sax._

As I'm using Databricks, there's no SBT file for dependencies. Instead I installed the libs I need directly on the cluster. Here are the ones I'm using :

com.squareup.okhttp:okhttp:2.7.5
com.squareup.okhttp3:okhttp:4.9.0
com.squareup.okhttp3:okhttp:3.14.9
org.scala-lang.modules:scala-swing_3:3.0.0
ch.qos.logback:logback-classic:1.2.6
com.typesafe:scalalogging-slf4j_2.10:1.1.0
cc.spray.json:spray-json_2.9.1:1.0.1
com.fasterxml.jackson.module:jackson-module-scala_3:2.13.0
javax.xml.parsers:jaxp-api:1.4.5
org.xml.sax:2.0.1

The code causing the error is simply (coming from here : https://www.baeldung.com/jackson-convert-xml-json Chapter 5):

val xmlMapper: XmlMapper = new XmlMapper()
val jsonNode: JsonNode = xmlMapper.readTree(responseBody.getBytes())

with responseBody being a String containing a XML document (I previously checked the integrity of the XML). When removing those two lines the code is working fine.

I've read tons of articles or forums but I can't figure out what's causing my issue. Can someone please help me ? Thanks a lot ! :)

Karzyfox
  • 319
  • 1
  • 2
  • 15

2 Answers2

10

Welcome to dependency hell and breaking changes in libraries.

This usually happens, when various lib bring in different version of same lib. In this case it is Jackson. java.lang.NoSuchMethodError: com.fasterxml.jackson.dataformat.xml.XmlMapper.coercionConfigDefaults()Lcom/fasterxml/jackson/databind/cfg/MutableCoercionConfig; means: One lib probably require Jackson version, which has this method, but on class path is version, which does not yet have this funcion or got removed bcs was deprecated or renamed.

In case like this is good to print dependency tree and check version of Jackson required in libs. And if possible use newer versions of requid libs.

Solution: use libs, which use compatible versions of Jackson lib. No other shortcut possible.

Vaclav Stengl
  • 359
  • 3
  • 8
  • Thanks for your explanation. Due to my cluster configuration (which I can not change) I'm stuck with Scala 2.12. However I don't know how I'm supposed to print the dependency tree without access to a terminal. Is there any scala command to get it ? Thanks ! : ) – Karzyfox Oct 07 '21 at 12:14
  • 1
    Multiple ways. Each jar build with maven has inside pom.xml where are listed dependencies with versions. If other packaging tool was used, then there will be similar file. Better approach would be to create project on local machine with some dependency management like gradle/maven or others and add same dependencies. Lets say you will use gradle. Gradle has task to list dependencies `gradle dependencies`. Also then you can test with some code whether your setup works - no ex is thrown during parsing. – Vaclav Stengl Oct 07 '21 at 13:52
  • @AdrienMerat this answer might be the way to the answer but it didnt help me solve - did you figure it out? – Ohad Bitton Nov 12 '21 at 18:16
  • I was only able to resolve this error by using version 2.12.5 for all jackson dependencies. Previously the project's built.sbt file was using a few jackson libs with older versions (2.10.0). – John Bonfardeci Nov 30 '21 at 00:56
  • @OhadBitton I'm working on databricks (and thus no build.sbt or pom.xml file) and fixed this error by loading jar files instead of maven dependencies. – Karzyfox Jan 06 '22 at 08:31
  • Maybe I am lost, but why is problem to use dependency management? In the end what you upload is code and dependencies as jars right? Imho should be doable to use dependency management with plugin, which allow to copy project dependencies (jar files) somewhere. From there can be uploaded to remote. For gradle this could work even tho it is fairly old thread https://discuss.gradle.org/t/how-can-i-gather-all-my-projects-dependencies-into-a-folder/7146 seems it need to register task and dependencies can be copied quite easily. – Vaclav Stengl Jan 12 '22 at 14:17
  • 1
    If printing dependency tree gives no answer, I had to debug with this solution [solution](https://stackoverflow.com/questions/17540942/how-to-get-the-path-of-running-java-program). My case was that statement: `XmlMapper.class.getSuperclass().getProtectionDomain().getCodeSource().getLocation().getPath()` returned: `/home/weblogic/wls1221/oracle_common/modules/thirdparty/jackson-databind-2.9.9.jar` this allowed me to find solution – Marek F Apr 13 '22 at 10:44
0

upgrading to 2.12.5 version fixed my issue. this issue may also appear when there are multiple versions of jackson jars in project lib directory. you should remove the older versions.