wanglingsong / JsonSurfer

A streaming JsonPath processor in Java
MIT License
294 stars 55 forks source link

Problems using JsonSurfer in projects using a different version of ANTLR #82

Closed jetztgradnet closed 1 year ago

jetztgradnet commented 1 year ago

Hi! I'm using JsonSurfer as a transitive dependency of CARML within an AWS Lambda application based on the Quarkus framework. Unfortunately, Quarkus uses a different, higher version of ANTLR (4.10.1), which leads to this error when running the app:

Exception in thread "Lambda Thread (DEVELOPMENT)" java.lang.ExceptionInInitializerError
    at org.jsfr.json.compiler.JsonPathCompiler.compile(JsonPathCompiler.java:279)
    at org.jsfr.json.SurfingConfiguration$Builder.bind(SurfingConfiguration.java:201)
    at io.carml.logicalsourceresolver.JsonPathResolver.lambda$bridgeAndListen$6(JsonPathResolver.java:138)
    at java.base/java.lang.Iterable.forEach(Iterable.java:75)
    at io.carml.logicalsourceresolver.JsonPathResolver.bridgeAndListen(JsonPathResolver.java:136)
    at io.carml.logicalsourceresolver.JsonPathResolver.lambda$getObjectFlux$3(JsonPathResolver.java:120)
    at reactor.core.publisher.FluxCreate.subscribe(FluxCreate.java:95)
[snip]
    at io.carml.engine.rdf.RdfRmlMapper.toModel(RdfRmlMapper.java:368)
    at io.carml.engine.rdf.RdfRmlMapper.mapToModel(RdfRmlMapper.java:343)
[snip]
Caused by: java.lang.UnsupportedOperationException: java.io.InvalidClassException: org.antlr.v4.runtime.atn.ATN; Could not deserialize ATN with version 3 (expected 4).
    at org.antlr.v4.runtime.atn.ATNDeserializer.deserialize(ATNDeserializer.java:56)
    at org.antlr.v4.runtime.atn.ATNDeserializer.deserialize(ATNDeserializer.java:48)
    at org.jsfr.json.compiler.JsonPathLexer.<clinit>(JsonPathLexer.java:204)
    ... 31 more
Caused by: java.io.InvalidClassException: org.antlr.v4.runtime.atn.ATN; Could not deserialize ATN with version 3 (expected 4).
    ... 34 more

Fixing the version of antlr to 4.7.2 as used by JsonSurfer does not work for Quarkus.

Would it be possible to either update antlr (which would possibly lead to problems by other users of this library) or provide jsonsurfer-core with antlr shaded into the jar? The latter would provide maximum compatibility to everybody while getting rid of this (external) dependency. This could possibly also be done as a variant with a -shaded classifier?

jetztgradnet commented 1 year ago

I found a local solution: creating a jar based on jsonsurfer with antlr shaded in a different package and using this instead of the original one.

  1. I created a new Gradle project jsonsurfer-shaded within my project with the following build.gradle file:
plugins {
  id 'java'
  id 'com.github.johnrengelman.shadow' version '7.1.2'
}

repositories {
    mavenCentral()
    mavenLocal()
}

dependencies {
  implementation group: 'com.github.jsurfer', name: 'jsurfer-all', version: '1.6.4'
  implementation group: 'com.github.jsurfer', name: 'jsurfer-core', version: '1.6.4'
}

shadowJar {
   relocate 'org.antlr.v4', 'com.github.jsurfer.shaded.org.antlr.v4'
}
  1. in my project's main build.gradle file I am referencing this shaded project instead of the original one:
    
    // ...

dependencies { // ... other dependencies

// shaded version of jsonsurfer implementation project(path: ':jsonsurfer-shaded', configuration: 'shadow') }

//...



A similar approach should be possible for Maven projects as well.

Updating `antlr` might still make sense for other users, though.