Search code examples
kotlinjakarta-eejacksonresteasyjooq

Boolean fields in JOOQ classes not serialized and deserialized consistenly by Jackson/RestEasy


I have a Java EE project that uses JOOQ to auto generate records using Kotin.

One such record is:

@Suppress("UNCHECKED_CAST")
open class EmailAddressRecord() : UpdatableRecordImpl<EmailAddressRecord>(EmailAddress.EMAIL_ADDRESS),
    Record5<Int?, Int?, String?, Boolean?, Boolean?> {

//...

  var isInList: Boolean?
    set(value) = set(3, value)
    get() = get(3) as Boolean?

When sent to the client via a GET method, the record is serialized into a json like { "isInList": true } as expected.

But if I send that back to a PUT method, I get an error about isInListnot being recognized. If instead I send a json with an inList property (without the is), the record is deserialized correctly on the server side.

There are several bits involved so I'm not even sure which is causing the issue:

  • Maybe it's because of how JOOQ generates the records with a var
  • Maybe it's Wildfly / RestEasy doing some funky stuff
  • Maybe it's Jackson not deserialising the record properly (I have tried to add the jackson kotlin module but it doesn't seem to make any difference)

Any pointers would be appreciated.

Versions: jackson 2.12.2, kotlin 1.4.10, widlfly 10, jooq 3.14.10


Solution

  • This is an extension of a fix that was implemented in jOOQ 3.15.0 and 3.14.12: https://github.com/jOOQ/jOOQ/issues/11912

    The problem is that kotlin generates a setInList() setter for mutable properties named isInList, instead of setIsInList(). In the above issue, this can clash with an equally named setter for an inList property:

    class X {
      var inList: Boolean?
      var isInList: Boolean?
    }
    

    I'm not convinced this is a useful optimisation in the jOOQ case. Instead of fixing #11912 only when there is such a name clash as above, we could just always generate the @set:JvmName("...") annotation on properties for columns starting with IS_:

    class X {
      @set:JvmName("setIsInList")
      var isInList: Boolean?
    }
    

    And make this configurable, of course. These annotations can be turned of by specifying the following, starting from jOOQ 3.15.0:

    <kotlinSetterJvmNameAnnotationsOnIsPrefix>false</kotlinSetterJvmNameAnnotationsOnIsPrefix>