jackson-module-scala icon indicating copy to clipboard operation
jackson-module-scala copied to clipboard

[2.11.4.1] Fix compatibility with jackson 2.9.x

Open eugeniyk opened this issue 4 years ago • 5 comments

Fixes #451 for the cases when you have mix of old clients with 2.9.x and want to onboard gradually to 2.11.x

Root causes

  1. Missing $init$ in deprecated interfaces

decompiled java for 2.9.10 ScalaObjectMapper.$init$ - under com.fasterxml.jackson.module.scala.experimental package:

   static void $init$(final ScalaObjectMapper $this) {
      $this.com$fasterxml$jackson$module$scala$experimental$ScalaObjectMapper$_setter_$com$fasterxml$jackson$module$scala$experimental$ScalaObjectMapper$$MAP_$eq(Map.class);
      $this.com$fasterxml$jackson$module$scala$experimental$ScalaObjectMapper$_setter_$com$fasterxml$jackson$module$scala$experimental$ScalaObjectMapper$$OPTION_$eq(Option.class);
      $this.com$fasterxml$jackson$module$scala$experimental$ScalaObjectMapper$_setter_$com$fasterxml$jackson$module$scala$experimental$ScalaObjectMapper$$ITERABLE_$eq(Iterable.class);
   }

decompiled java for 2.11.4 ScalaObjectMapper.$init$ - same code but under com.fasterxml.jackson.module.scala package.

same situation with RequiredPropertiesSchemaModule

  1. Missing default interface methods in deprecated interfaces. Scala encoding in 2.12 uses default methods for trait methods

before:

public interface ScalaObjectMapper extends com.fasterxml.jackson.module.scala.ScalaObjectMapper

after:

public interface ScalaObjectMapper extends com.fasterxml.jackson.module.scala.ScalaObjectMapper {
   ...
      // $FF: synthetic method
   Object com$fasterxml$jackson$module$scala$experimental$ScalaObjectMapper$$super$readValue(final String content, final Manifest evidence$13);
   
   // $FF: synthetic method
   static Object readValue$(final ScalaObjectMapper $this, final String content, final Manifest evidence$8) {
      return $this.readValue(content, evidence$8);
   }

   default Object readValue(final String content, final Manifest evidence$8) {
      return this.com$fasterxml$jackson$module$scala$experimental$ScalaObjectMapper$$super$readValue(content, evidence$8);
   }
  ...
}

Solution

  1. Trick compiler to create $init$ method by inserting custom code inside trait to emulate constructor behavior (be aware it shouldn't have any members, otherwise you'll have AbstractMember error).
  2. override current members from stable interface inside deprecated one

Next time we can introduce MIMA to spot binary-compat issues

eugeniyk avatar Jan 13 '21 04:01 eugeniyk

2.11 is no longer supported. I see no need to merge this.

We make zero claims about binary compatibilty. We could add MIMA checks but that would be going forward.

This commit would break binary compatibility for users coming from Jackson 2.10. There is no pretty solution to this problem this late in the day. If we had fixed the binary compatibility shortly after it was introduced then it would have been ok but at this late stage it is too late.

There is a workaround. Users can recompile there code with the new jackson jars.

pjfanning avatar Jan 13 '21 09:01 pjfanning

2.11 is no longer supported. I see no need to merge this.

https://github.com/FasterXML/jackson#active-developed-jackson-2x-branches - 2.11 is still supported for patch releases, I wouldn't close branch for changes

@pjfanning the value I see is to provide safe ground between 2.9.x (which is 2017-2019 Sep, I believe still in use in many projects for these 3 years) and 2.11.x;

I see many libraries has jackson as compile/runtime dependencies - which is fine, 2.9 vs 2.11/12 are binary compatible in java world as it should - semantic versioning is obeyed and you can easily substitute 1 version with another

Situation is different with scala module component and frankly it's sad situation for projects with 10+ dependencies all stuck on 2.9.x. It is a workaround for such cases, and as you says if 2.11.x is not maintained anymore - let it be as the bridge to 2.12.x world for such projects.

This commit would break binary compatibility for users coming from Jackson 2.10. There is no pretty solution to this problem this late in the day. If we had fixed the binary compatibility shortly after it was introduced then it would have been ok but at this late stage it is too late.

How this will break compat for users coming from Jackson 2.10.x? experimental package was originated in 2.9.x and existed till 2.11.x, were there any interface removed in 2.11?

eugeniyk avatar Jan 14 '21 14:01 eugeniyk

Check maven usages of jackson module scala: https://mvnrepository.com/artifact/com.fasterxml.jackson.module/jackson-module-scala

2.9.x has top place by amount of users - this can let big projects evolve to 2.11.x without worrying about other stale components

Anyway, it will be maintainers' decision to let this change to be merged, at the end 1.5 year old library in an enterprise is literally up-to-date =)

eugeniyk avatar Jan 14 '21 14:01 eugeniyk

I am not inclined to merge this. It is too late to backtrack. Feel free to fork the solution and to publish your own jar with this change. ScalaObjectMapper has already been deprecated as of 2.12.1 and is due to be removed because the solution won't work with Scala 3.

pjfanning avatar Jan 14 '21 15:01 pjfanning

I'll let @pjfanning make ultimate decision here, and will only say that further full patch releases of 2.10 are less likely than 2.11 (although not ruled out, unlike with 2.9). Likelihood of full 2.11 release depends on whether there are critical fixes for it -- I am guessing there's 50/50 chance for just one more patch release.

cowtowncoder avatar Jan 14 '21 20:01 cowtowncoder