Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

THRIFT-5548: add kotlin code gen #2556

Closed
wants to merge 1 commit into from

Conversation

Jimexist
Copy link
Member

@Jimexist Jimexist commented Apr 6, 2022

Motivation for a separate kotlin code gen:

  1. Use data class
  2. Use coroutine interface (and jdk8 adapter)
  3. Use idiomatic kotlin syntax
  4. Leverage existing java libthrift (it does not have a new runtime, instead the generated code will be relying on the libthrift runtime code)
  • Did you create an Apache Jira ticket? (not required for trivial changes)
  • If a ticket exists: Does your pull request title follow the pattern "THRIFT-NNNN: describe my issue"?
  • Did you squash your changes to a single commit? (not required, but preferred)
  • Did you do your best to avoid breaking changes? If one was needed, did you label the Jira ticket with "Breaking-Change"?
  • If your change does not involve any code, include [skip ci] anywhere in the commit message to free up build resources.

@Jimexist Jimexist changed the title THRIFT-5548: add kotlin code gen THRIFT-5548: (work in progress) add kotlin code gen Apr 6, 2022
@Jimexist Jimexist force-pushed the add-kotlin-code-gen branch 6 times, most recently from 7ab4b6f to c9453ee Compare April 11, 2022 10:27
@Jimexist Jimexist changed the title THRIFT-5548: (work in progress) add kotlin code gen THRIFT-5548: add kotlin code gen Apr 11, 2022
@Jimexist Jimexist marked this pull request as ready for review April 11, 2022 10:28
@Jimexist Jimexist force-pushed the add-kotlin-code-gen branch 2 times, most recently from f56d858 to 5f5b0d7 Compare April 11, 2022 10:43
@Jimexist
Copy link
Member Author

cc @benjamin-bader the author of https://github.com/microsoft/thrifty in case you might be interested

@Jimexist
Copy link
Member Author

Example generated struct:

StructA.kt
/**
 * Autogenerated by Thrift Compiler (0.17.0)
 *
 * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
 *  @generated
 */
@file:Suppress("ClassName", "PropertyName", "RedundantUnitReturnType", "NestedLambdaShadowedImplicitParameter", "RemoveRedundantQualifierName")
package thrift.test

@javax.annotation.Generated
data class StructA(
  private var _s: kotlin.String? = null
) : org.apache.thrift.TBase<StructA, StructA._Fields> {
  val s: kotlin.String get() = _s!!
  enum class _Fields(private val thriftFieldId: kotlin.Short, private val fieldName: kotlin.String) : org.apache.thrift.TFieldIdEnum {
    S(1, "s");

    override fun getThriftFieldId() = thriftFieldId

    override fun getFieldName() = fieldName

    companion object {
      @kotlin.jvm.JvmStatic
      fun findByValue(value: kotlin.Int): _Fields? {
        return when (value) {
          1 -> S
          else -> null
        }
      }

      @kotlin.jvm.JvmStatic
      fun findByName(name: kotlin.String): _Fields? {
        return when (name) {
          "s" -> S
          else -> null
        }
      }
    }
  }

  companion object {
    private val STRUCT_DESC: org.apache.thrift.protocol.TStruct = org.apache.thrift.protocol.TStruct("StructA")
    private val S_FIELD_DESC: org.apache.thrift.protocol.TField = org.apache.thrift.protocol.TField("s", org.apache.thrift.protocol.TType.STRING, 1)
  }

  private object StructAStandardScheme : org.apache.thrift.scheme.StandardScheme<StructA>() {
    override fun read(iproto: org.apache.thrift.protocol.TProtocol, struct: StructA) {
      iproto.apply {
        readStruct {
          var stopped = false
          while (!stopped) {
            stopped = readField {
              val skipNext = { org.apache.thrift.protocol.TProtocolUtil.skip(iproto, type) }
              when (id.toInt()) {
                1 -> {
                  if (type == org.apache.thrift.protocol.TType.STRING) {
                    struct._s = readString()
                  } else {
                    skipNext()
                  }
                }
                else -> skipNext()
              }
            }
          }
          struct.validate()
        }
      }
    }

    override fun write(oproto: org.apache.thrift.protocol.TProtocol, struct: StructA) {
      struct.validate()
      oproto.apply {
        writeStruct(STRUCT_DESC) {
          struct.s.let {
            writeField(S_FIELD_DESC) {
              writeString(it)
            }
          }
          writeFieldStop()
        }
      }
    }

  }

  override fun compareTo(other: StructA?): kotlin.Int {
    val comparator = compareBy<StructA> { it::class.java.name }
      .thenBy { it.s } 
    return nullsFirst(comparator).compare(this, other)
  }

  override fun fieldForId(fieldId: kotlin.Int): _Fields {
    return _Fields.findByValue(fieldId) ?: throw kotlin.IllegalArgumentException("invalid fieldId $fieldId")
  }

  override fun getFieldValue(field: _Fields): kotlin.Any? {
    return when (field) {
      _Fields.S -> this.s
    }
  }

  @Suppress("UNCHECKED_CAST")
  override fun setFieldValue(field: _Fields, value: kotlin.Any?): kotlin.Unit {
    when (field) {
      _Fields.S -> this._s = value as kotlin.String?
    }
  }

  override fun isSet(field: _Fields): kotlin.Boolean {
    return when (field) {
      _Fields.S -> this._s != null
    }
  }

  override fun deepCopy(): StructA {
    return StructA (
      s,
    )
  }

  override fun clear(): kotlin.Unit {
    _s = null
  }

  @kotlin.jvm.Throws(org.apache.thrift.TException::class)
  fun validate(): kotlin.Unit {
    if (_s == null) {
      throw org.apache.thrift.TException("Required field `s' is null, struct is: $this")
    }
  }

  override fun read(iproto: org.apache.thrift.protocol.TProtocol): kotlin.Unit {
    require(org.apache.thrift.scheme.StandardScheme::class == iproto.scheme) { "only standard scheme is supported for now" }
    StructAStandardScheme.read(iproto, this)
  }

  override fun write(oproto: org.apache.thrift.protocol.TProtocol): kotlin.Unit {
    require(org.apache.thrift.scheme.StandardScheme::class == oproto.scheme) { "only standard scheme is supported for now" }
    StructAStandardScheme.write(oproto, this)
  }

}
ThriftTest.kt
/**
 * Autogenerated by Thrift Compiler (0.17.0)
 *
 * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
 *  @generated
 */
package thrift.test

interface ThriftTest {
  /**
   * Prints "testVoid()" and returns nothing.
   */
  suspend fun testVoid(): kotlin.Unit
  /**
   * Prints 'testString("%s")' with thing as '%s'
   * @param string thing - the string to print
   * @return string - returns the string 'thing'
   */
  suspend fun testString(thing: kotlin.String): kotlin.String
  /**
   * Prints 'testBool("%s")' where '%s' with thing as 'true' or 'false'
   * @param bool  thing - the bool data to print
   * @return bool  - returns the bool 'thing'
   */
  suspend fun testBool(thing: kotlin.Boolean): kotlin.Boolean
  /**
   * Prints 'testByte("%d")' with thing as '%d'
   * The types i8 and byte are synonyms, use of i8 is encouraged, byte still exists for the sake of compatibility.
   * @param byte thing - the i8/byte to print
   * @return i8 - returns the i8/byte 'thing'
   */
  suspend fun testByte(thing: kotlin.Byte): kotlin.Byte
  /**
   * Prints 'testI32("%d")' with thing as '%d'
   * @param i32 thing - the i32 to print
   * @return i32 - returns the i32 'thing'
   */
  suspend fun testI32(thing: kotlin.Int): kotlin.Int
  /**
   * Prints 'testI64("%d")' with thing as '%d'
   * @param i64 thing - the i64 to print
   * @return i64 - returns the i64 'thing'
   */
  suspend fun testI64(thing: kotlin.Long): kotlin.Long
  /**
   * Prints 'testDouble("%f")' with thing as '%f'
   * @param double thing - the double to print
   * @return double - returns the double 'thing'
   */
  suspend fun testDouble(thing: kotlin.Double): kotlin.Double
  /**
   * Prints 'testBinary("%s")' where '%s' is a hex-formatted string of thing's data
   * @param binary  thing - the binary data to print
   * @return binary  - returns the binary 'thing'
   */
  suspend fun testBinary(thing: kotlin.ByteArray): kotlin.ByteArray
  /**
   * Prints 'testStruct("{%s}")' where thing has been formatted into a string of comma separated values
   * @param Xtruct thing - the Xtruct to print
   * @return Xtruct - returns the Xtruct 'thing'
   */
  suspend fun testStruct(thing: Xtruct): Xtruct
  /**
   * Prints 'testNest("{%s}")' where thing has been formatted into a string of the nested struct
   * @param Xtruct2 thing - the Xtruct2 to print
   * @return Xtruct2 - returns the Xtruct2 'thing'
   */
  suspend fun testNest(thing: Xtruct2): Xtruct2
  /**
   * Prints 'testMap("{%s")' where thing has been formatted into a string of 'key => value' pairs
   *  separated by commas and new lines
   * @param map<i32,i32> thing - the map<i32,i32> to print
   * @return map<i32,i32> - returns the map<i32,i32> 'thing'
   */
  suspend fun testMap(thing: kotlin.collections.Map<kotlin.Int, kotlin.Int>): kotlin.collections.Map<kotlin.Int, kotlin.Int>
  /**
   * Prints 'testStringMap("{%s}")' where thing has been formatted into a string of 'key => value' pairs
   *  separated by commas and new lines
   * @param map<string,string> thing - the map<string,string> to print
   * @return map<string,string> - returns the map<string,string> 'thing'
   */
  suspend fun testStringMap(thing: kotlin.collections.Map<kotlin.String, kotlin.String>): kotlin.collections.Map<kotlin.String, kotlin.String>
  /**
   * Prints 'testSet("{%s}")' where thing has been formatted into a string of values
   *  separated by commas and new lines
   * @param set<i32> thing - the set<i32> to print
   * @return set<i32> - returns the set<i32> 'thing'
   */
  suspend fun testSet(thing: kotlin.collections.Set<kotlin.Int>): kotlin.collections.Set<kotlin.Int>
  /**
   * Prints 'testList("{%s}")' where thing has been formatted into a string of values
   *  separated by commas and new lines
   * @param list<i32> thing - the list<i32> to print
   * @return list<i32> - returns the list<i32> 'thing'
   */
  suspend fun testList(thing: kotlin.collections.List<kotlin.Int>): kotlin.collections.List<kotlin.Int>
  /**
   * Prints 'testEnum("%d")' where thing has been formatted into its numeric value
   * @param Numberz thing - the Numberz to print
   * @return Numberz - returns the Numberz 'thing'
   */
  suspend fun testEnum(thing: Numberz): Numberz
  /**
   * Prints 'testTypedef("%d")' with thing as '%d'
   * @param UserId thing - the UserId to print
   * @return UserId - returns the UserId 'thing'
   */
  suspend fun testTypedef(thing: kotlin.Long): kotlin.Long
  /**
   * Prints 'testMapMap("%d")' with hello as '%d'
   * @param i32 hello - the i32 to print
   * @return map<i32,map<i32,i32>> - returns a dictionary with these values:
   *   {-4 => {-4 => -4, -3 => -3, -2 => -2, -1 => -1, }, 4 => {1 => 1, 2 => 2, 3 => 3, 4 => 4, }, }
   */
  suspend fun testMapMap(hello: kotlin.Int): kotlin.collections.Map<kotlin.Int, kotlin.collections.Map<kotlin.Int, kotlin.Int>>
  /**
   * So you think you've got this all worked out, eh?
   * 
   * Creates a map with these values and prints it out:
   *   { 1 => { 2 => argument,
   *            3 => argument,
   *          },
   *     2 => { 6 => <empty Insanity struct>, },
   *   }
   * @return map<UserId, map<Numberz,Insanity>> - a map with the above values
   */
  suspend fun testInsanity(argument: Insanity): kotlin.collections.Map<kotlin.Long, kotlin.collections.Map<Numberz, Insanity>>
  /**
   * Prints 'testMulti()'
   * @param i8 arg0 -
   * @param i32 arg1 -
   * @param i64 arg2 -
   * @param map<i16, string> arg3 -
   * @param Numberz arg4 -
   * @param UserId arg5 -
   * @return Xtruct - returns an Xtruct with string_thing = "Hello2, byte_thing = arg0, i32_thing = arg1
   *    and i64_thing = arg2
   */
  suspend fun testMulti(arg0: kotlin.Byte, arg1: kotlin.Int, arg2: kotlin.Long, arg3: kotlin.collections.Map<kotlin.Short, kotlin.String>, arg4: Numberz, arg5: kotlin.Long): Xtruct
  /**
   * Print 'testException(%s)' with arg as '%s'
   * @param string arg - a string indication what type of exception to throw
   * if arg == "Xception" throw Xception with errorCode = 1001 and message = arg
   * else if arg == "TException" throw TException
   * else do not throw anything
   */
  suspend fun testException(arg: kotlin.String): kotlin.Unit
  /**
   * Print 'testMultiException(%s, %s)' with arg0 as '%s' and arg1 as '%s'
   * @param string arg - a string indicating what type of exception to throw
   * if arg0 == "Xception" throw Xception with errorCode = 1001 and message = "This is an Xception"
   * else if arg0 == "Xception2" throw Xception2 with errorCode = 2002 and struct_thing.string_thing = "This is an Xception2"
   * else do not throw anything
   * @return Xtruct - an Xtruct with string_thing = arg1
   */
  suspend fun testMultiException(arg0: kotlin.String, arg1: kotlin.String): Xtruct
  /**
   * Print 'testOneway(%d): Sleeping...' with secondsToSleep as '%d'
   * sleep 'secondsToSleep'
   * Print 'testOneway(%d): done sleeping!' with secondsToSleep as '%d'
   * @param i32 secondsToSleep - the number of seconds to sleep
   */
  suspend fun testOneway(secondsToSleep: kotlin.Int): kotlin.Unit
}
ThriftTestProcessor.kt
/**
 * Autogenerated by Thrift Compiler (0.17.0)
 *
 * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
 *  @generated
 */
@file:Suppress("ClassName", "PropertyName", "RedundantUnitReturnType", "NestedLambdaShadowedImplicitParameter", "RemoveRedundantQualifierName")
package thrift.test

import kotlinx.coroutines.future.future

/**
 * server implementation for [ThriftTest]
 */
@javax.annotation.Generated
class ThriftTestProcessor(
  handler: ThriftTest,
  private val scope: kotlinx.coroutines.CoroutineScope,
  private val processMap: kotlin.collections.Map<kotlin.String, org.apache.thrift.AsyncProcessFunction<ThriftTest, out org.apache.thrift.TBase<*, *>, out kotlin.Any>> = mapOf(
    "testVoid" to ProcessFunction.testVoid(scope),
    "testString" to ProcessFunction.testString(scope),
    "testBool" to ProcessFunction.testBool(scope),
    "testByte" to ProcessFunction.testByte(scope),
    "testI32" to ProcessFunction.testI32(scope),
    "testI64" to ProcessFunction.testI64(scope),
    "testDouble" to ProcessFunction.testDouble(scope),
    "testBinary" to ProcessFunction.testBinary(scope),
    "testStruct" to ProcessFunction.testStruct(scope),
    "testNest" to ProcessFunction.testNest(scope),
    "testMap" to ProcessFunction.testMap(scope),
    "testStringMap" to ProcessFunction.testStringMap(scope),
    "testSet" to ProcessFunction.testSet(scope),
    "testList" to ProcessFunction.testList(scope),
    "testEnum" to ProcessFunction.testEnum(scope),
    "testTypedef" to ProcessFunction.testTypedef(scope),
    "testMapMap" to ProcessFunction.testMapMap(scope),
    "testInsanity" to ProcessFunction.testInsanity(scope),
    "testMulti" to ProcessFunction.testMulti(scope),
    "testException" to ProcessFunction.testException(scope),
    "testMultiException" to ProcessFunction.testMultiException(scope),
    "testOneway" to ProcessFunction.testOneway(scope),
  )
): org.apache.thrift.TBaseAsyncProcessor<ThriftTest>(handler, processMap) {
  companion object {
    internal val logger: org.slf4j.Logger = org.slf4j.LoggerFactory.getLogger(ThriftTestProcessor::class.java)
  }
  sealed interface ProcessFunction {
    @javax.annotation.Generated
    class testVoid<I : ThriftTest>(private val scope: kotlinx.coroutines.CoroutineScope) : org.apache.thrift.AsyncProcessFunction<I, ThriftTestFunctionArgs.testVoid_args, kotlin.Unit>("testVoid"), ProcessFunction {
      override fun isOneway() = false
      override fun getEmptyArgsInstance() = ThriftTestFunctionArgs.testVoid_args()
      override fun start(iface: I, args: ThriftTestFunctionArgs.testVoid_args, resultHandler: org.apache.thrift.async.AsyncMethodCallback<kotlin.Unit>) {
        scope.future {
          iface.testVoid()
        }.whenComplete { r, t ->
          if (t != null) {
            resultHandler.onError(t as java.lang.Exception)
          } else {
            resultHandler.onComplete(r)
          }
        }
      }
      override fun getResultHandler(fb: org.apache.thrift.server.AbstractNonblockingServer.AsyncFrameBuffer, seqid: Int) =
        object : org.apache.thrift.async.AsyncMethodCallback<kotlin.Unit>{
          override fun onComplete(response: kotlin.Unit) {
            val result = ThriftTestFunctionResult.testVoid_result()
            try {
              sendResponse(fb, result, org.apache.thrift.protocol.TMessageType.REPLY, seqid)
            } catch (e: org.apache.thrift.transport.TTransportException) {
              logger.error("TTransportException writing to internal frame buffer", e)
              fb.close()
            } catch (e: Exception) {
              logger.error("Exception writing to internal frame buffer", e)
              onError(e)
            }
          }
          override fun onError(exception: kotlin.Exception) {
            val (msgType, msg) = when (exception) {
              is org.apache.thrift.transport.TTransportException -> {
                logger.error("TTransportException inside handler", exception)
                fb.close()
                return
              }
              is org.apache.thrift.TApplicationException -> {
                logger.error("TApplicationException inside handler", exception)
                org.apache.thrift.protocol.TMessageType.EXCEPTION to exception
              }
              else -> {
                logger.error("Exception inside handler", exception)
                org.apache.thrift.protocol.TMessageType.EXCEPTION to org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, exception.message)
              }
            }
            try {
              sendResponse(fb, msg, msgType, seqid)
            } catch (ex: java.lang.Exception) {
              logger.error("Exception writing to internal frame buffer", ex)
              fb.close()
            }
          }
        }
    }
    @javax.annotation.Generated
    class testString<I : ThriftTest>(private val scope: kotlinx.coroutines.CoroutineScope) : org.apache.thrift.AsyncProcessFunction<I, ThriftTestFunctionArgs.testString_args, kotlin.String>("testString"), ProcessFunction {
      override fun isOneway() = false
      override fun getEmptyArgsInstance() = ThriftTestFunctionArgs.testString_args()
      override fun start(iface: I, args: ThriftTestFunctionArgs.testString_args, resultHandler: org.apache.thrift.async.AsyncMethodCallback<kotlin.String>) {
        scope.future {
          iface.testString(args.thing!!)
        }.whenComplete { r, t ->
          if (t != null) {
            resultHandler.onError(t as java.lang.Exception)
          } else {
            resultHandler.onComplete(r)
          }
        }
      }
      override fun getResultHandler(fb: org.apache.thrift.server.AbstractNonblockingServer.AsyncFrameBuffer, seqid: Int) =
        object : org.apache.thrift.async.AsyncMethodCallback<kotlin.String>{
          override fun onComplete(response: kotlin.String) {
            val result = ThriftTestFunctionResult.testString_result()
            result.success = response
            try {
              sendResponse(fb, result, org.apache.thrift.protocol.TMessageType.REPLY, seqid)
            } catch (e: org.apache.thrift.transport.TTransportException) {
              logger.error("TTransportException writing to internal frame buffer", e)
              fb.close()
            } catch (e: Exception) {
              logger.error("Exception writing to internal frame buffer", e)
              onError(e)
            }
          }
          override fun onError(exception: kotlin.Exception) {
            val (msgType, msg) = when (exception) {
              is org.apache.thrift.transport.TTransportException -> {
                logger.error("TTransportException inside handler", exception)
                fb.close()
                return
              }
              is org.apache.thrift.TApplicationException -> {
                logger.error("TApplicationException inside handler", exception)
                org.apache.thrift.protocol.TMessageType.EXCEPTION to exception
              }
              else -> {
                logger.error("Exception inside handler", exception)
                org.apache.thrift.protocol.TMessageType.EXCEPTION to org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, exception.message)
              }
            }
            try {
              sendResponse(fb, msg, msgType, seqid)
            } catch (ex: java.lang.Exception) {
              logger.error("Exception writing to internal frame buffer", ex)
              fb.close()
            }
          }
        }
    }
    @javax.annotation.Generated
    class testBool<I : ThriftTest>(private val scope: kotlinx.coroutines.CoroutineScope) : org.apache.thrift.AsyncProcessFunction<I, ThriftTestFunctionArgs.testBool_args, kotlin.Boolean>("testBool"), ProcessFunction {
      override fun isOneway() = false
      override fun getEmptyArgsInstance() = ThriftTestFunctionArgs.testBool_args()
      override fun start(iface: I, args: ThriftTestFunctionArgs.testBool_args, resultHandler: org.apache.thrift.async.AsyncMethodCallback<kotlin.Boolean>) {
        scope.future {
          iface.testBool(args.thing!!)
        }.whenComplete { r, t ->
          if (t != null) {
            resultHandler.onError(t as java.lang.Exception)
          } else {
            resultHandler.onComplete(r)
          }
        }
      }
      override fun getResultHandler(fb: org.apache.thrift.server.AbstractNonblockingServer.AsyncFrameBuffer, seqid: Int) =
        object : org.apache.thrift.async.AsyncMethodCallback<kotlin.Boolean>{
          override fun onComplete(response: kotlin.Boolean) {
            val result = ThriftTestFunctionResult.testBool_result()
            result.success = response
            try {
              sendResponse(fb, result, org.apache.thrift.protocol.TMessageType.REPLY, seqid)
            } catch (e: org.apache.thrift.transport.TTransportException) {
              logger.error("TTransportException writing to internal frame buffer", e)
              fb.close()
            } catch (e: Exception) {
              logger.error("Exception writing to internal frame buffer", e)
              onError(e)
            }
          }
          override fun onError(exception: kotlin.Exception) {
            val (msgType, msg) = when (exception) {
              is org.apache.thrift.transport.TTransportException -> {
                logger.error("TTransportException inside handler", exception)
                fb.close()
                return
              }
              is org.apache.thrift.TApplicationException -> {
                logger.error("TApplicationException inside handler", exception)
                org.apache.thrift.protocol.TMessageType.EXCEPTION to exception
              }
              else -> {
                logger.error("Exception inside handler", exception)
                org.apache.thrift.protocol.TMessageType.EXCEPTION to org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, exception.message)
              }
            }
            try {
              sendResponse(fb, msg, msgType, seqid)
            } catch (ex: java.lang.Exception) {
              logger.error("Exception writing to internal frame buffer", ex)
              fb.close()
            }
          }
        }
    }
    @javax.annotation.Generated
    class testByte<I : ThriftTest>(private val scope: kotlinx.coroutines.CoroutineScope) : org.apache.thrift.AsyncProcessFunction<I, ThriftTestFunctionArgs.testByte_args, kotlin.Byte>("testByte"), ProcessFunction {
      override fun isOneway() = false
      override fun getEmptyArgsInstance() = ThriftTestFunctionArgs.testByte_args()
      override fun start(iface: I, args: ThriftTestFunctionArgs.testByte_args, resultHandler: org.apache.thrift.async.AsyncMethodCallback<kotlin.Byte>) {
        scope.future {
          iface.testByte(args.thing!!)
        }.whenComplete { r, t ->
          if (t != null) {
            resultHandler.onError(t as java.lang.Exception)
          } else {
            resultHandler.onComplete(r)
          }
        }
      }
      override fun getResultHandler(fb: org.apache.thrift.server.AbstractNonblockingServer.AsyncFrameBuffer, seqid: Int) =
        object : org.apache.thrift.async.AsyncMethodCallback<kotlin.Byte>{
          override fun onComplete(response: kotlin.Byte) {
            val result = ThriftTestFunctionResult.testByte_result()
            result.success = response
            try {
              sendResponse(fb, result, org.apache.thrift.protocol.TMessageType.REPLY, seqid)
            } catch (e: org.apache.thrift.transport.TTransportException) {
              logger.error("TTransportException writing to internal frame buffer", e)
              fb.close()
            } catch (e: Exception) {
              logger.error("Exception writing to internal frame buffer", e)
              onError(e)
            }
          }
          override fun onError(exception: kotlin.Exception) {
            val (msgType, msg) = when (exception) {
              is org.apache.thrift.transport.TTransportException -> {
                logger.error("TTransportException inside handler", exception)
                fb.close()
                return
              }
              is org.apache.thrift.TApplicationException -> {
                logger.error("TApplicationException inside handler", exception)
                org.apache.thrift.protocol.TMessageType.EXCEPTION to exception
              }
              else -> {
                logger.error("Exception inside handler", exception)
                org.apache.thrift.protocol.TMessageType.EXCEPTION to org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, exception.message)
              }
            }
            try {
              sendResponse(fb, msg, msgType, seqid)
            } catch (ex: java.lang.Exception) {
              logger.error("Exception writing to internal frame buffer", ex)
              fb.close()
            }
          }
        }
    }
    @javax.annotation.Generated
    class testI32<I : ThriftTest>(private val scope: kotlinx.coroutines.CoroutineScope) : org.apache.thrift.AsyncProcessFunction<I, ThriftTestFunctionArgs.testI32_args, kotlin.Int>("testI32"), ProcessFunction {
      override fun isOneway() = false
      override fun getEmptyArgsInstance() = ThriftTestFunctionArgs.testI32_args()
      override fun start(iface: I, args: ThriftTestFunctionArgs.testI32_args, resultHandler: org.apache.thrift.async.AsyncMethodCallback<kotlin.Int>) {
        scope.future {
          iface.testI32(args.thing!!)
        }.whenComplete { r, t ->
          if (t != null) {
            resultHandler.onError(t as java.lang.Exception)
          } else {
            resultHandler.onComplete(r)
          }
        }
      }
      override fun getResultHandler(fb: org.apache.thrift.server.AbstractNonblockingServer.AsyncFrameBuffer, seqid: Int) =
        object : org.apache.thrift.async.AsyncMethodCallback<kotlin.Int>{
          override fun onComplete(response: kotlin.Int) {
            val result = ThriftTestFunctionResult.testI32_result()
            result.success = response
            try {
              sendResponse(fb, result, org.apache.thrift.protocol.TMessageType.REPLY, seqid)
            } catch (e: org.apache.thrift.transport.TTransportException) {
              logger.error("TTransportException writing to internal frame buffer", e)
              fb.close()
            } catch (e: Exception) {
              logger.error("Exception writing to internal frame buffer", e)
              onError(e)
            }
          }
          override fun onError(exception: kotlin.Exception) {
            val (msgType, msg) = when (exception) {
              is org.apache.thrift.transport.TTransportException -> {
                logger.error("TTransportException inside handler", exception)
                fb.close()
                return
              }
              is org.apache.thrift.TApplicationException -> {
                logger.error("TApplicationException inside handler", exception)
                org.apache.thrift.protocol.TMessageType.EXCEPTION to exception
              }
              else -> {
                logger.error("Exception inside handler", exception)
                org.apache.thrift.protocol.TMessageType.EXCEPTION to org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, exception.message)
              }
            }
            try {
              sendResponse(fb, msg, msgType, seqid)
            } catch (ex: java.lang.Exception) {
              logger.error("Exception writing to internal frame buffer", ex)
              fb.close()
            }
          }
        }
    }
    @javax.annotation.Generated
    class testI64<I : ThriftTest>(private val scope: kotlinx.coroutines.CoroutineScope) : org.apache.thrift.AsyncProcessFunction<I, ThriftTestFunctionArgs.testI64_args, kotlin.Long>("testI64"), ProcessFunction {
      override fun isOneway() = false
      override fun getEmptyArgsInstance() = ThriftTestFunctionArgs.testI64_args()
      override fun start(iface: I, args: ThriftTestFunctionArgs.testI64_args, resultHandler: org.apache.thrift.async.AsyncMethodCallback<kotlin.Long>) {
        scope.future {
          iface.testI64(args.thing!!)
        }.whenComplete { r, t ->
          if (t != null) {
            resultHandler.onError(t as java.lang.Exception)
          } else {
            resultHandler.onComplete(r)
          }
        }
      }
      override fun getResultHandler(fb: org.apache.thrift.server.AbstractNonblockingServer.AsyncFrameBuffer, seqid: Int) =
        object : org.apache.thrift.async.AsyncMethodCallback<kotlin.Long>{
          override fun onComplete(response: kotlin.Long) {
            val result = ThriftTestFunctionResult.testI64_result()
            result.success = response
            try {
              sendResponse(fb, result, org.apache.thrift.protocol.TMessageType.REPLY, seqid)
            } catch (e: org.apache.thrift.transport.TTransportException) {
              logger.error("TTransportException writing to internal frame buffer", e)
              fb.close()
            } catch (e: Exception) {
              logger.error("Exception writing to internal frame buffer", e)
              onError(e)
            }
          }
          override fun onError(exception: kotlin.Exception) {
            val (msgType, msg) = when (exception) {
              is org.apache.thrift.transport.TTransportException -> {
                logger.error("TTransportException inside handler", exception)
                fb.close()
                return
              }
              is org.apache.thrift.TApplicationException -> {
                logger.error("TApplicationException inside handler", exception)
                org.apache.thrift.protocol.TMessageType.EXCEPTION to exception
              }
              else -> {
                logger.error("Exception inside handler", exception)
                org.apache.thrift.protocol.TMessageType.EXCEPTION to org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, exception.message)
              }
            }
            try {
              sendResponse(fb, msg, msgType, seqid)
            } catch (ex: java.lang.Exception) {
              logger.error("Exception writing to internal frame buffer", ex)
              fb.close()
            }
          }
        }
    }
    @javax.annotation.Generated
    class testDouble<I : ThriftTest>(private val scope: kotlinx.coroutines.CoroutineScope) : org.apache.thrift.AsyncProcessFunction<I, ThriftTestFunctionArgs.testDouble_args, kotlin.Double>("testDouble"), ProcessFunction {
      override fun isOneway() = false
      override fun getEmptyArgsInstance() = ThriftTestFunctionArgs.testDouble_args()
      override fun start(iface: I, args: ThriftTestFunctionArgs.testDouble_args, resultHandler: org.apache.thrift.async.AsyncMethodCallback<kotlin.Double>) {
        scope.future {
          iface.testDouble(args.thing!!)
        }.whenComplete { r, t ->
          if (t != null) {
            resultHandler.onError(t as java.lang.Exception)
          } else {
            resultHandler.onComplete(r)
          }
        }
      }
      override fun getResultHandler(fb: org.apache.thrift.server.AbstractNonblockingServer.AsyncFrameBuffer, seqid: Int) =
        object : org.apache.thrift.async.AsyncMethodCallback<kotlin.Double>{
          override fun onComplete(response: kotlin.Double) {
            val result = ThriftTestFunctionResult.testDouble_result()
            result.success = response
            try {
              sendResponse(fb, result, org.apache.thrift.protocol.TMessageType.REPLY, seqid)
            } catch (e: org.apache.thrift.transport.TTransportException) {
              logger.error("TTransportException writing to internal frame buffer", e)
              fb.close()
            } catch (e: Exception) {
              logger.error("Exception writing to internal frame buffer", e)
              onError(e)
            }
          }
          override fun onError(exception: kotlin.Exception) {
            val (msgType, msg) = when (exception) {
              is org.apache.thrift.transport.TTransportException -> {
                logger.error("TTransportException inside handler", exception)
                fb.close()
                return
              }
              is org.apache.thrift.TApplicationException -> {
                logger.error("TApplicationException inside handler", exception)
                org.apache.thrift.protocol.TMessageType.EXCEPTION to exception
              }
              else -> {
                logger.error("Exception inside handler", exception)
                org.apache.thrift.protocol.TMessageType.EXCEPTION to org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, exception.message)
              }
            }
            try {
              sendResponse(fb, msg, msgType, seqid)
            } catch (ex: java.lang.Exception) {
              logger.error("Exception writing to internal frame buffer", ex)
              fb.close()
            }
          }
        }
    }
    @javax.annotation.Generated
    class testBinary<I : ThriftTest>(private val scope: kotlinx.coroutines.CoroutineScope) : org.apache.thrift.AsyncProcessFunction<I, ThriftTestFunctionArgs.testBinary_args, kotlin.ByteArray>("testBinary"), ProcessFunction {
      override fun isOneway() = false
      override fun getEmptyArgsInstance() = ThriftTestFunctionArgs.testBinary_args()
      override fun start(iface: I, args: ThriftTestFunctionArgs.testBinary_args, resultHandler: org.apache.thrift.async.AsyncMethodCallback<kotlin.ByteArray>) {
        scope.future {
          iface.testBinary(args.thing!!)
        }.whenComplete { r, t ->
          if (t != null) {
            resultHandler.onError(t as java.lang.Exception)
          } else {
            resultHandler.onComplete(r)
          }
        }
      }
      override fun getResultHandler(fb: org.apache.thrift.server.AbstractNonblockingServer.AsyncFrameBuffer, seqid: Int) =
        object : org.apache.thrift.async.AsyncMethodCallback<kotlin.ByteArray>{
          override fun onComplete(response: kotlin.ByteArray) {
            val result = ThriftTestFunctionResult.testBinary_result()
            result.success = response
            try {
              sendResponse(fb, result, org.apache.thrift.protocol.TMessageType.REPLY, seqid)
            } catch (e: org.apache.thrift.transport.TTransportException) {
              logger.error("TTransportException writing to internal frame buffer", e)
              fb.close()
            } catch (e: Exception) {
              logger.error("Exception writing to internal frame buffer", e)
              onError(e)
            }
          }
          override fun onError(exception: kotlin.Exception) {
            val (msgType, msg) = when (exception) {
              is org.apache.thrift.transport.TTransportException -> {
                logger.error("TTransportException inside handler", exception)
                fb.close()
                return
              }
              is org.apache.thrift.TApplicationException -> {
                logger.error("TApplicationException inside handler", exception)
                org.apache.thrift.protocol.TMessageType.EXCEPTION to exception
              }
              else -> {
                logger.error("Exception inside handler", exception)
                org.apache.thrift.protocol.TMessageType.EXCEPTION to org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, exception.message)
              }
            }
            try {
              sendResponse(fb, msg, msgType, seqid)
            } catch (ex: java.lang.Exception) {
              logger.error("Exception writing to internal frame buffer", ex)
              fb.close()
            }
          }
        }
    }
    @javax.annotation.Generated
    class testStruct<I : ThriftTest>(private val scope: kotlinx.coroutines.CoroutineScope) : org.apache.thrift.AsyncProcessFunction<I, ThriftTestFunctionArgs.testStruct_args, Xtruct>("testStruct"), ProcessFunction {
      override fun isOneway() = false
      override fun getEmptyArgsInstance() = ThriftTestFunctionArgs.testStruct_args()
      override fun start(iface: I, args: ThriftTestFunctionArgs.testStruct_args, resultHandler: org.apache.thrift.async.AsyncMethodCallback<Xtruct>) {
        scope.future {
          iface.testStruct(args.thing!!)
        }.whenComplete { r, t ->
          if (t != null) {
            resultHandler.onError(t as java.lang.Exception)
          } else {
            resultHandler.onComplete(r)
          }
        }
      }
      override fun getResultHandler(fb: org.apache.thrift.server.AbstractNonblockingServer.AsyncFrameBuffer, seqid: Int) =
        object : org.apache.thrift.async.AsyncMethodCallback<Xtruct>{
          override fun onComplete(response: Xtruct) {
            val result = ThriftTestFunctionResult.testStruct_result()
            result.success = response
            try {
              sendResponse(fb, result, org.apache.thrift.protocol.TMessageType.REPLY, seqid)
            } catch (e: org.apache.thrift.transport.TTransportException) {
              logger.error("TTransportException writing to internal frame buffer", e)
              fb.close()
            } catch (e: Exception) {
              logger.error("Exception writing to internal frame buffer", e)
              onError(e)
            }
          }
          override fun onError(exception: kotlin.Exception) {
            val (msgType, msg) = when (exception) {
              is org.apache.thrift.transport.TTransportException -> {
                logger.error("TTransportException inside handler", exception)
                fb.close()
                return
              }
              is org.apache.thrift.TApplicationException -> {
                logger.error("TApplicationException inside handler", exception)
                org.apache.thrift.protocol.TMessageType.EXCEPTION to exception
              }
              else -> {
                logger.error("Exception inside handler", exception)
                org.apache.thrift.protocol.TMessageType.EXCEPTION to org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, exception.message)
              }
            }
            try {
              sendResponse(fb, msg, msgType, seqid)
            } catch (ex: java.lang.Exception) {
              logger.error("Exception writing to internal frame buffer", ex)
              fb.close()
            }
          }
        }
    }
    @javax.annotation.Generated
    class testNest<I : ThriftTest>(private val scope: kotlinx.coroutines.CoroutineScope) : org.apache.thrift.AsyncProcessFunction<I, ThriftTestFunctionArgs.testNest_args, Xtruct2>("testNest"), ProcessFunction {
      override fun isOneway() = false
      override fun getEmptyArgsInstance() = ThriftTestFunctionArgs.testNest_args()
      override fun start(iface: I, args: ThriftTestFunctionArgs.testNest_args, resultHandler: org.apache.thrift.async.AsyncMethodCallback<Xtruct2>) {
        scope.future {
          iface.testNest(args.thing!!)
        }.whenComplete { r, t ->
          if (t != null) {
            resultHandler.onError(t as java.lang.Exception)
          } else {
            resultHandler.onComplete(r)
          }
        }
      }
      override fun getResultHandler(fb: org.apache.thrift.server.AbstractNonblockingServer.AsyncFrameBuffer, seqid: Int) =
        object : org.apache.thrift.async.AsyncMethodCallback<Xtruct2>{
          override fun onComplete(response: Xtruct2) {
            val result = ThriftTestFunctionResult.testNest_result()
            result.success = response
            try {
              sendResponse(fb, result, org.apache.thrift.protocol.TMessageType.REPLY, seqid)
            } catch (e: org.apache.thrift.transport.TTransportException) {
              logger.error("TTransportException writing to internal frame buffer", e)
              fb.close()
            } catch (e: Exception) {
              logger.error("Exception writing to internal frame buffer", e)
              onError(e)
            }
          }
          override fun onError(exception: kotlin.Exception) {
            val (msgType, msg) = when (exception) {
              is org.apache.thrift.transport.TTransportException -> {
                logger.error("TTransportException inside handler", exception)
                fb.close()
                return
              }
              is org.apache.thrift.TApplicationException -> {
                logger.error("TApplicationException inside handler", exception)
                org.apache.thrift.protocol.TMessageType.EXCEPTION to exception
              }
              else -> {
                logger.error("Exception inside handler", exception)
                org.apache.thrift.protocol.TMessageType.EXCEPTION to org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, exception.message)
              }
            }
            try {
              sendResponse(fb, msg, msgType, seqid)
            } catch (ex: java.lang.Exception) {
              logger.error("Exception writing to internal frame buffer", ex)
              fb.close()
            }
          }
        }
    }
    @javax.annotation.Generated
    class testMap<I : ThriftTest>(private val scope: kotlinx.coroutines.CoroutineScope) : org.apache.thrift.AsyncProcessFunction<I, ThriftTestFunctionArgs.testMap_args, kotlin.collections.Map<kotlin.Int, kotlin.Int>>("testMap"), ProcessFunction {
      override fun isOneway() = false
      override fun getEmptyArgsInstance() = ThriftTestFunctionArgs.testMap_args()
      override fun start(iface: I, args: ThriftTestFunctionArgs.testMap_args, resultHandler: org.apache.thrift.async.AsyncMethodCallback<kotlin.collections.Map<kotlin.Int, kotlin.Int>>) {
        scope.future {
          iface.testMap(args.thing!!)
        }.whenComplete { r, t ->
          if (t != null) {
            resultHandler.onError(t as java.lang.Exception)
          } else {
            resultHandler.onComplete(r)
          }
        }
      }
      override fun getResultHandler(fb: org.apache.thrift.server.AbstractNonblockingServer.AsyncFrameBuffer, seqid: Int) =
        object : org.apache.thrift.async.AsyncMethodCallback<kotlin.collections.Map<kotlin.Int, kotlin.Int>>{
          override fun onComplete(response: kotlin.collections.Map<kotlin.Int, kotlin.Int>) {
            val result = ThriftTestFunctionResult.testMap_result()
            result.success = response
            try {
              sendResponse(fb, result, org.apache.thrift.protocol.TMessageType.REPLY, seqid)
            } catch (e: org.apache.thrift.transport.TTransportException) {
              logger.error("TTransportException writing to internal frame buffer", e)
              fb.close()
            } catch (e: Exception) {
              logger.error("Exception writing to internal frame buffer", e)
              onError(e)
            }
          }
          override fun onError(exception: kotlin.Exception) {
            val (msgType, msg) = when (exception) {
              is org.apache.thrift.transport.TTransportException -> {
                logger.error("TTransportException inside handler", exception)
                fb.close()
                return
              }
              is org.apache.thrift.TApplicationException -> {
                logger.error("TApplicationException inside handler", exception)
                org.apache.thrift.protocol.TMessageType.EXCEPTION to exception
              }
              else -> {
                logger.error("Exception inside handler", exception)
                org.apache.thrift.protocol.TMessageType.EXCEPTION to org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, exception.message)
              }
            }
            try {
              sendResponse(fb, msg, msgType, seqid)
            } catch (ex: java.lang.Exception) {
              logger.error("Exception writing to internal frame buffer", ex)
              fb.close()
            }
          }
        }
    }
    @javax.annotation.Generated
    class testStringMap<I : ThriftTest>(private val scope: kotlinx.coroutines.CoroutineScope) : org.apache.thrift.AsyncProcessFunction<I, ThriftTestFunctionArgs.testStringMap_args, kotlin.collections.Map<kotlin.String, kotlin.String>>("testStringMap"), ProcessFunction {
      override fun isOneway() = false
      override fun getEmptyArgsInstance() = ThriftTestFunctionArgs.testStringMap_args()
      override fun start(iface: I, args: ThriftTestFunctionArgs.testStringMap_args, resultHandler: org.apache.thrift.async.AsyncMethodCallback<kotlin.collections.Map<kotlin.String, kotlin.String>>) {
        scope.future {
          iface.testStringMap(args.thing!!)
        }.whenComplete { r, t ->
          if (t != null) {
            resultHandler.onError(t as java.lang.Exception)
          } else {
            resultHandler.onComplete(r)
          }
        }
      }
      override fun getResultHandler(fb: org.apache.thrift.server.AbstractNonblockingServer.AsyncFrameBuffer, seqid: Int) =
        object : org.apache.thrift.async.AsyncMethodCallback<kotlin.collections.Map<kotlin.String, kotlin.String>>{
          override fun onComplete(response: kotlin.collections.Map<kotlin.String, kotlin.String>) {
            val result = ThriftTestFunctionResult.testStringMap_result()
            result.success = response
            try {
              sendResponse(fb, result, org.apache.thrift.protocol.TMessageType.REPLY, seqid)
            } catch (e: org.apache.thrift.transport.TTransportException) {
              logger.error("TTransportException writing to internal frame buffer", e)
              fb.close()
            } catch (e: Exception) {
              logger.error("Exception writing to internal frame buffer", e)
              onError(e)
            }
          }
          override fun onError(exception: kotlin.Exception) {
            val (msgType, msg) = when (exception) {
              is org.apache.thrift.transport.TTransportException -> {
                logger.error("TTransportException inside handler", exception)
                fb.close()
                return
              }
              is org.apache.thrift.TApplicationException -> {
                logger.error("TApplicationException inside handler", exception)
                org.apache.thrift.protocol.TMessageType.EXCEPTION to exception
              }
              else -> {
                logger.error("Exception inside handler", exception)
                org.apache.thrift.protocol.TMessageType.EXCEPTION to org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, exception.message)
              }
            }
            try {
              sendResponse(fb, msg, msgType, seqid)
            } catch (ex: java.lang.Exception) {
              logger.error("Exception writing to internal frame buffer", ex)
              fb.close()
            }
          }
        }
    }
    @javax.annotation.Generated
    class testSet<I : ThriftTest>(private val scope: kotlinx.coroutines.CoroutineScope) : org.apache.thrift.AsyncProcessFunction<I, ThriftTestFunctionArgs.testSet_args, kotlin.collections.Set<kotlin.Int>>("testSet"), ProcessFunction {
      override fun isOneway() = false
      override fun getEmptyArgsInstance() = ThriftTestFunctionArgs.testSet_args()
      override fun start(iface: I, args: ThriftTestFunctionArgs.testSet_args, resultHandler: org.apache.thrift.async.AsyncMethodCallback<kotlin.collections.Set<kotlin.Int>>) {
        scope.future {
          iface.testSet(args.thing!!)
        }.whenComplete { r, t ->
          if (t != null) {
            resultHandler.onError(t as java.lang.Exception)
          } else {
            resultHandler.onComplete(r)
          }
        }
      }
      override fun getResultHandler(fb: org.apache.thrift.server.AbstractNonblockingServer.AsyncFrameBuffer, seqid: Int) =
        object : org.apache.thrift.async.AsyncMethodCallback<kotlin.collections.Set<kotlin.Int>>{
          override fun onComplete(response: kotlin.collections.Set<kotlin.Int>) {
            val result = ThriftTestFunctionResult.testSet_result()
            result.success = response
            try {
              sendResponse(fb, result, org.apache.thrift.protocol.TMessageType.REPLY, seqid)
            } catch (e: org.apache.thrift.transport.TTransportException) {
              logger.error("TTransportException writing to internal frame buffer", e)
              fb.close()
            } catch (e: Exception) {
              logger.error("Exception writing to internal frame buffer", e)
              onError(e)
            }
          }
          override fun onError(exception: kotlin.Exception) {
            val (msgType, msg) = when (exception) {
              is org.apache.thrift.transport.TTransportException -> {
                logger.error("TTransportException inside handler", exception)
                fb.close()
                return
              }
              is org.apache.thrift.TApplicationException -> {
                logger.error("TApplicationException inside handler", exception)
                org.apache.thrift.protocol.TMessageType.EXCEPTION to exception
              }
              else -> {
                logger.error("Exception inside handler", exception)
                org.apache.thrift.protocol.TMessageType.EXCEPTION to org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, exception.message)
              }
            }
            try {
              sendResponse(fb, msg, msgType, seqid)
            } catch (ex: java.lang.Exception) {
              logger.error("Exception writing to internal frame buffer", ex)
              fb.close()
            }
          }
        }
    }
    @javax.annotation.Generated
    class testList<I : ThriftTest>(private val scope: kotlinx.coroutines.CoroutineScope) : org.apache.thrift.AsyncProcessFunction<I, ThriftTestFunctionArgs.testList_args, kotlin.collections.List<kotlin.Int>>("testList"), ProcessFunction {
      override fun isOneway() = false
      override fun getEmptyArgsInstance() = ThriftTestFunctionArgs.testList_args()
      override fun start(iface: I, args: ThriftTestFunctionArgs.testList_args, resultHandler: org.apache.thrift.async.AsyncMethodCallback<kotlin.collections.List<kotlin.Int>>) {
        scope.future {
          iface.testList(args.thing!!)
        }.whenComplete { r, t ->
          if (t != null) {
            resultHandler.onError(t as java.lang.Exception)
          } else {
            resultHandler.onComplete(r)
          }
        }
      }
      override fun getResultHandler(fb: org.apache.thrift.server.AbstractNonblockingServer.AsyncFrameBuffer, seqid: Int) =
        object : org.apache.thrift.async.AsyncMethodCallback<kotlin.collections.List<kotlin.Int>>{
          override fun onComplete(response: kotlin.collections.List<kotlin.Int>) {
            val result = ThriftTestFunctionResult.testList_result()
            result.success = response
            try {
              sendResponse(fb, result, org.apache.thrift.protocol.TMessageType.REPLY, seqid)
            } catch (e: org.apache.thrift.transport.TTransportException) {
              logger.error("TTransportException writing to internal frame buffer", e)
              fb.close()
            } catch (e: Exception) {
              logger.error("Exception writing to internal frame buffer", e)
              onError(e)
            }
          }
          override fun onError(exception: kotlin.Exception) {
            val (msgType, msg) = when (exception) {
              is org.apache.thrift.transport.TTransportException -> {
                logger.error("TTransportException inside handler", exception)
                fb.close()
                return
              }
              is org.apache.thrift.TApplicationException -> {
                logger.error("TApplicationException inside handler", exception)
                org.apache.thrift.protocol.TMessageType.EXCEPTION to exception
              }
              else -> {
                logger.error("Exception inside handler", exception)
                org.apache.thrift.protocol.TMessageType.EXCEPTION to org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, exception.message)
              }
            }
            try {
              sendResponse(fb, msg, msgType, seqid)
            } catch (ex: java.lang.Exception) {
              logger.error("Exception writing to internal frame buffer", ex)
              fb.close()
            }
          }
        }
    }
    @javax.annotation.Generated
    class testEnum<I : ThriftTest>(private val scope: kotlinx.coroutines.CoroutineScope) : org.apache.thrift.AsyncProcessFunction<I, ThriftTestFunctionArgs.testEnum_args, Numberz>("testEnum"), ProcessFunction {
      override fun isOneway() = false
      override fun getEmptyArgsInstance() = ThriftTestFunctionArgs.testEnum_args()
      override fun start(iface: I, args: ThriftTestFunctionArgs.testEnum_args, resultHandler: org.apache.thrift.async.AsyncMethodCallback<Numberz>) {
        scope.future {
          iface.testEnum(args.thing!!)
        }.whenComplete { r, t ->
          if (t != null) {
            resultHandler.onError(t as java.lang.Exception)
          } else {
            resultHandler.onComplete(r)
          }
        }
      }
      override fun getResultHandler(fb: org.apache.thrift.server.AbstractNonblockingServer.AsyncFrameBuffer, seqid: Int) =
        object : org.apache.thrift.async.AsyncMethodCallback<Numberz>{
          override fun onComplete(response: Numberz) {
            val result = ThriftTestFunctionResult.testEnum_result()
            result.success = response
            try {
              sendResponse(fb, result, org.apache.thrift.protocol.TMessageType.REPLY, seqid)
            } catch (e: org.apache.thrift.transport.TTransportException) {
              logger.error("TTransportException writing to internal frame buffer", e)
              fb.close()
            } catch (e: Exception) {
              logger.error("Exception writing to internal frame buffer", e)
              onError(e)
            }
          }
          override fun onError(exception: kotlin.Exception) {
            val (msgType, msg) = when (exception) {
              is org.apache.thrift.transport.TTransportException -> {
                logger.error("TTransportException inside handler", exception)
                fb.close()
                return
              }
              is org.apache.thrift.TApplicationException -> {
                logger.error("TApplicationException inside handler", exception)
                org.apache.thrift.protocol.TMessageType.EXCEPTION to exception
              }
              else -> {
                logger.error("Exception inside handler", exception)
                org.apache.thrift.protocol.TMessageType.EXCEPTION to org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, exception.message)
              }
            }
            try {
              sendResponse(fb, msg, msgType, seqid)
            } catch (ex: java.lang.Exception) {
              logger.error("Exception writing to internal frame buffer", ex)
              fb.close()
            }
          }
        }
    }
    @javax.annotation.Generated
    class testTypedef<I : ThriftTest>(private val scope: kotlinx.coroutines.CoroutineScope) : org.apache.thrift.AsyncProcessFunction<I, ThriftTestFunctionArgs.testTypedef_args, kotlin.Long>("testTypedef"), ProcessFunction {
      override fun isOneway() = false
      override fun getEmptyArgsInstance() = ThriftTestFunctionArgs.testTypedef_args()
      override fun start(iface: I, args: ThriftTestFunctionArgs.testTypedef_args, resultHandler: org.apache.thrift.async.AsyncMethodCallback<kotlin.Long>) {
        scope.future {
          iface.testTypedef(args.thing!!)
        }.whenComplete { r, t ->
          if (t != null) {
            resultHandler.onError(t as java.lang.Exception)
          } else {
            resultHandler.onComplete(r)
          }
        }
      }
      override fun getResultHandler(fb: org.apache.thrift.server.AbstractNonblockingServer.AsyncFrameBuffer, seqid: Int) =
        object : org.apache.thrift.async.AsyncMethodCallback<kotlin.Long>{
          override fun onComplete(response: kotlin.Long) {
            val result = ThriftTestFunctionResult.testTypedef_result()
            result.success = response
            try {
              sendResponse(fb, result, org.apache.thrift.protocol.TMessageType.REPLY, seqid)
            } catch (e: org.apache.thrift.transport.TTransportException) {
              logger.error("TTransportException writing to internal frame buffer", e)
              fb.close()
            } catch (e: Exception) {
              logger.error("Exception writing to internal frame buffer", e)
              onError(e)
            }
          }
          override fun onError(exception: kotlin.Exception) {
            val (msgType, msg) = when (exception) {
              is org.apache.thrift.transport.TTransportException -> {
                logger.error("TTransportException inside handler", exception)
                fb.close()
                return
              }
              is org.apache.thrift.TApplicationException -> {
                logger.error("TApplicationException inside handler", exception)
                org.apache.thrift.protocol.TMessageType.EXCEPTION to exception
              }
              else -> {
                logger.error("Exception inside handler", exception)
                org.apache.thrift.protocol.TMessageType.EXCEPTION to org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, exception.message)
              }
            }
            try {
              sendResponse(fb, msg, msgType, seqid)
            } catch (ex: java.lang.Exception) {
              logger.error("Exception writing to internal frame buffer", ex)
              fb.close()
            }
          }
        }
    }
    @javax.annotation.Generated
    class testMapMap<I : ThriftTest>(private val scope: kotlinx.coroutines.CoroutineScope) : org.apache.thrift.AsyncProcessFunction<I, ThriftTestFunctionArgs.testMapMap_args, kotlin.collections.Map<kotlin.Int, kotlin.collections.Map<kotlin.Int, kotlin.Int>>>("testMapMap"), ProcessFunction {
      override fun isOneway() = false
      override fun getEmptyArgsInstance() = ThriftTestFunctionArgs.testMapMap_args()
      override fun start(iface: I, args: ThriftTestFunctionArgs.testMapMap_args, resultHandler: org.apache.thrift.async.AsyncMethodCallback<kotlin.collections.Map<kotlin.Int, kotlin.collections.Map<kotlin.Int, kotlin.Int>>>) {
        scope.future {
          iface.testMapMap(args.hello!!)
        }.whenComplete { r, t ->
          if (t != null) {
            resultHandler.onError(t as java.lang.Exception)
          } else {
            resultHandler.onComplete(r)
          }
        }
      }
      override fun getResultHandler(fb: org.apache.thrift.server.AbstractNonblockingServer.AsyncFrameBuffer, seqid: Int) =
        object : org.apache.thrift.async.AsyncMethodCallback<kotlin.collections.Map<kotlin.Int, kotlin.collections.Map<kotlin.Int, kotlin.Int>>>{
          override fun onComplete(response: kotlin.collections.Map<kotlin.Int, kotlin.collections.Map<kotlin.Int, kotlin.Int>>) {
            val result = ThriftTestFunctionResult.testMapMap_result()
            result.success = response
            try {
              sendResponse(fb, result, org.apache.thrift.protocol.TMessageType.REPLY, seqid)
            } catch (e: org.apache.thrift.transport.TTransportException) {
              logger.error("TTransportException writing to internal frame buffer", e)
              fb.close()
            } catch (e: Exception) {
              logger.error("Exception writing to internal frame buffer", e)
              onError(e)
            }
          }
          override fun onError(exception: kotlin.Exception) {
            val (msgType, msg) = when (exception) {
              is org.apache.thrift.transport.TTransportException -> {
                logger.error("TTransportException inside handler", exception)
                fb.close()
                return
              }
              is org.apache.thrift.TApplicationException -> {
                logger.error("TApplicationException inside handler", exception)
                org.apache.thrift.protocol.TMessageType.EXCEPTION to exception
              }
              else -> {
                logger.error("Exception inside handler", exception)
                org.apache.thrift.protocol.TMessageType.EXCEPTION to org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, exception.message)
              }
            }
            try {
              sendResponse(fb, msg, msgType, seqid)
            } catch (ex: java.lang.Exception) {
              logger.error("Exception writing to internal frame buffer", ex)
              fb.close()
            }
          }
        }
    }
    @javax.annotation.Generated
    class testInsanity<I : ThriftTest>(private val scope: kotlinx.coroutines.CoroutineScope) : org.apache.thrift.AsyncProcessFunction<I, ThriftTestFunctionArgs.testInsanity_args, kotlin.collections.Map<kotlin.Long, kotlin.collections.Map<Numberz, Insanity>>>("testInsanity"), ProcessFunction {
      override fun isOneway() = false
      override fun getEmptyArgsInstance() = ThriftTestFunctionArgs.testInsanity_args()
      override fun start(iface: I, args: ThriftTestFunctionArgs.testInsanity_args, resultHandler: org.apache.thrift.async.AsyncMethodCallback<kotlin.collections.Map<kotlin.Long, kotlin.collections.Map<Numberz, Insanity>>>) {
        scope.future {
          iface.testInsanity(args.argument!!)
        }.whenComplete { r, t ->
          if (t != null) {
            resultHandler.onError(t as java.lang.Exception)
          } else {
            resultHandler.onComplete(r)
          }
        }
      }
      override fun getResultHandler(fb: org.apache.thrift.server.AbstractNonblockingServer.AsyncFrameBuffer, seqid: Int) =
        object : org.apache.thrift.async.AsyncMethodCallback<kotlin.collections.Map<kotlin.Long, kotlin.collections.Map<Numberz, Insanity>>>{
          override fun onComplete(response: kotlin.collections.Map<kotlin.Long, kotlin.collections.Map<Numberz, Insanity>>) {
            val result = ThriftTestFunctionResult.testInsanity_result()
            result.success = response
            try {
              sendResponse(fb, result, org.apache.thrift.protocol.TMessageType.REPLY, seqid)
            } catch (e: org.apache.thrift.transport.TTransportException) {
              logger.error("TTransportException writing to internal frame buffer", e)
              fb.close()
            } catch (e: Exception) {
              logger.error("Exception writing to internal frame buffer", e)
              onError(e)
            }
          }
          override fun onError(exception: kotlin.Exception) {
            val (msgType, msg) = when (exception) {
              is org.apache.thrift.transport.TTransportException -> {
                logger.error("TTransportException inside handler", exception)
                fb.close()
                return
              }
              is org.apache.thrift.TApplicationException -> {
                logger.error("TApplicationException inside handler", exception)
                org.apache.thrift.protocol.TMessageType.EXCEPTION to exception
              }
              else -> {
                logger.error("Exception inside handler", exception)
                org.apache.thrift.protocol.TMessageType.EXCEPTION to org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, exception.message)
              }
            }
            try {
              sendResponse(fb, msg, msgType, seqid)
            } catch (ex: java.lang.Exception) {
              logger.error("Exception writing to internal frame buffer", ex)
              fb.close()
            }
          }
        }
    }
    @javax.annotation.Generated
    class testMulti<I : ThriftTest>(private val scope: kotlinx.coroutines.CoroutineScope) : org.apache.thrift.AsyncProcessFunction<I, ThriftTestFunctionArgs.testMulti_args, Xtruct>("testMulti"), ProcessFunction {
      override fun isOneway() = false
      override fun getEmptyArgsInstance() = ThriftTestFunctionArgs.testMulti_args()
      override fun start(iface: I, args: ThriftTestFunctionArgs.testMulti_args, resultHandler: org.apache.thrift.async.AsyncMethodCallback<Xtruct>) {
        scope.future {
          iface.testMulti(args.arg0!!, args.arg1!!, args.arg2!!, args.arg3!!, args.arg4!!, args.arg5!!)
        }.whenComplete { r, t ->
          if (t != null) {
            resultHandler.onError(t as java.lang.Exception)
          } else {
            resultHandler.onComplete(r)
          }
        }
      }
      override fun getResultHandler(fb: org.apache.thrift.server.AbstractNonblockingServer.AsyncFrameBuffer, seqid: Int) =
        object : org.apache.thrift.async.AsyncMethodCallback<Xtruct>{
          override fun onComplete(response: Xtruct) {
            val result = ThriftTestFunctionResult.testMulti_result()
            result.success = response
            try {
              sendResponse(fb, result, org.apache.thrift.protocol.TMessageType.REPLY, seqid)
            } catch (e: org.apache.thrift.transport.TTransportException) {
              logger.error("TTransportException writing to internal frame buffer", e)
              fb.close()
            } catch (e: Exception) {
              logger.error("Exception writing to internal frame buffer", e)
              onError(e)
            }
          }
          override fun onError(exception: kotlin.Exception) {
            val (msgType, msg) = when (exception) {
              is org.apache.thrift.transport.TTransportException -> {
                logger.error("TTransportException inside handler", exception)
                fb.close()
                return
              }
              is org.apache.thrift.TApplicationException -> {
                logger.error("TApplicationException inside handler", exception)
                org.apache.thrift.protocol.TMessageType.EXCEPTION to exception
              }
              else -> {
                logger.error("Exception inside handler", exception)
                org.apache.thrift.protocol.TMessageType.EXCEPTION to org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, exception.message)
              }
            }
            try {
              sendResponse(fb, msg, msgType, seqid)
            } catch (ex: java.lang.Exception) {
              logger.error("Exception writing to internal frame buffer", ex)
              fb.close()
            }
          }
        }
    }
    @javax.annotation.Generated
    class testException<I : ThriftTest>(private val scope: kotlinx.coroutines.CoroutineScope) : org.apache.thrift.AsyncProcessFunction<I, ThriftTestFunctionArgs.testException_args, kotlin.Unit>("testException"), ProcessFunction {
      override fun isOneway() = false
      override fun getEmptyArgsInstance() = ThriftTestFunctionArgs.testException_args()
      override fun start(iface: I, args: ThriftTestFunctionArgs.testException_args, resultHandler: org.apache.thrift.async.AsyncMethodCallback<kotlin.Unit>) {
        scope.future {
          iface.testException(args.arg!!)
        }.whenComplete { r, t ->
          if (t != null) {
            resultHandler.onError(t as java.lang.Exception)
          } else {
            resultHandler.onComplete(r)
          }
        }
      }
      override fun getResultHandler(fb: org.apache.thrift.server.AbstractNonblockingServer.AsyncFrameBuffer, seqid: Int) =
        object : org.apache.thrift.async.AsyncMethodCallback<kotlin.Unit>{
          override fun onComplete(response: kotlin.Unit) {
            val result = ThriftTestFunctionResult.testException_result()
            try {
              sendResponse(fb, result, org.apache.thrift.protocol.TMessageType.REPLY, seqid)
            } catch (e: org.apache.thrift.transport.TTransportException) {
              logger.error("TTransportException writing to internal frame buffer", e)
              fb.close()
            } catch (e: Exception) {
              logger.error("Exception writing to internal frame buffer", e)
              onError(e)
            }
          }
          override fun onError(exception: kotlin.Exception) {
            val (msgType, msg) = when (exception) {
              is Xception -> {
                val result = ThriftTestFunctionResult.testException_result()
                result.err1 = exception
                org.apache.thrift.protocol.TMessageType.REPLY to result
              }
              is org.apache.thrift.transport.TTransportException -> {
                logger.error("TTransportException inside handler", exception)
                fb.close()
                return
              }
              is org.apache.thrift.TApplicationException -> {
                logger.error("TApplicationException inside handler", exception)
                org.apache.thrift.protocol.TMessageType.EXCEPTION to exception
              }
              else -> {
                logger.error("Exception inside handler", exception)
                org.apache.thrift.protocol.TMessageType.EXCEPTION to org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, exception.message)
              }
            }
            try {
              sendResponse(fb, msg, msgType, seqid)
            } catch (ex: java.lang.Exception) {
              logger.error("Exception writing to internal frame buffer", ex)
              fb.close()
            }
          }
        }
    }
    @javax.annotation.Generated
    class testMultiException<I : ThriftTest>(private val scope: kotlinx.coroutines.CoroutineScope) : org.apache.thrift.AsyncProcessFunction<I, ThriftTestFunctionArgs.testMultiException_args, Xtruct>("testMultiException"), ProcessFunction {
      override fun isOneway() = false
      override fun getEmptyArgsInstance() = ThriftTestFunctionArgs.testMultiException_args()
      override fun start(iface: I, args: ThriftTestFunctionArgs.testMultiException_args, resultHandler: org.apache.thrift.async.AsyncMethodCallback<Xtruct>) {
        scope.future {
          iface.testMultiException(args.arg0!!, args.arg1!!)
        }.whenComplete { r, t ->
          if (t != null) {
            resultHandler.onError(t as java.lang.Exception)
          } else {
            resultHandler.onComplete(r)
          }
        }
      }
      override fun getResultHandler(fb: org.apache.thrift.server.AbstractNonblockingServer.AsyncFrameBuffer, seqid: Int) =
        object : org.apache.thrift.async.AsyncMethodCallback<Xtruct>{
          override fun onComplete(response: Xtruct) {
            val result = ThriftTestFunctionResult.testMultiException_result()
            result.success = response
            try {
              sendResponse(fb, result, org.apache.thrift.protocol.TMessageType.REPLY, seqid)
            } catch (e: org.apache.thrift.transport.TTransportException) {
              logger.error("TTransportException writing to internal frame buffer", e)
              fb.close()
            } catch (e: Exception) {
              logger.error("Exception writing to internal frame buffer", e)
              onError(e)
            }
          }
          override fun onError(exception: kotlin.Exception) {
            val (msgType, msg) = when (exception) {
              is Xception -> {
                val result = ThriftTestFunctionResult.testMultiException_result()
                result.err1 = exception
                org.apache.thrift.protocol.TMessageType.REPLY to result
              }
              is Xception2 -> {
                val result = ThriftTestFunctionResult.testMultiException_result()
                result.err2 = exception
                org.apache.thrift.protocol.TMessageType.REPLY to result
              }
              is org.apache.thrift.transport.TTransportException -> {
                logger.error("TTransportException inside handler", exception)
                fb.close()
                return
              }
              is org.apache.thrift.TApplicationException -> {
                logger.error("TApplicationException inside handler", exception)
                org.apache.thrift.protocol.TMessageType.EXCEPTION to exception
              }
              else -> {
                logger.error("Exception inside handler", exception)
                org.apache.thrift.protocol.TMessageType.EXCEPTION to org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, exception.message)
              }
            }
            try {
              sendResponse(fb, msg, msgType, seqid)
            } catch (ex: java.lang.Exception) {
              logger.error("Exception writing to internal frame buffer", ex)
              fb.close()
            }
          }
        }
    }
    @javax.annotation.Generated
    class testOneway<I : ThriftTest>(private val scope: kotlinx.coroutines.CoroutineScope) : org.apache.thrift.AsyncProcessFunction<I, ThriftTestFunctionArgs.testOneway_args, kotlin.Unit>("testOneway"), ProcessFunction {
      override fun isOneway() = true
      override fun getEmptyArgsInstance() = ThriftTestFunctionArgs.testOneway_args()
      override fun start(iface: I, args: ThriftTestFunctionArgs.testOneway_args, resultHandler: org.apache.thrift.async.AsyncMethodCallback<kotlin.Unit>) {
        scope.future {
          iface.testOneway(args.secondsToSleep!!)
        }.whenComplete { r, t ->
          if (t != null) {
            resultHandler.onError(t as java.lang.Exception)
          } else {
            resultHandler.onComplete(r)
          }
        }
      }
      override fun getResultHandler(fb: org.apache.thrift.server.AbstractNonblockingServer.AsyncFrameBuffer, seqid: Int) =
        object : org.apache.thrift.async.AsyncMethodCallback<kotlin.Unit>{
          override fun onComplete(response: kotlin.Unit) {
            // one way function, no result handling
          }
          override fun onError(exception: kotlin.Exception) {
            if (exception is org.apache.thrift.transport.TTransportException) {
              logger.error("TTransportException inside handler", exception)
              fb.close()
            } else {
              logger.error("Exception inside oneway handler", exception)
            }
          }
        }
    }
  }
}

@Jimexist Jimexist force-pushed the add-kotlin-code-gen branch 3 times, most recently from f5c79e3 to 32a0036 Compare April 12, 2022 01:47

static const string endl = "\n"; // avoid ostream << std::endl flushes

static const string java_generated_annotation = "@javax.annotation.Generated";

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Herein lies danger - JDK9 and above have "repackaged" this annotation. Prior to 9, everyone used javax.annotation.Generated. After, the annotation is javax.annotation.processing.Generated. If you hardcode one or the other, the generated code will be uncompilable by a large portion of Java toolchains.

In Thrifty we went through a bunch of contortions before dropping support for generated annotations entirely - Kotlin MPP doesn't support them. I don't think MPP-compatibility is a goal here, but you definitely should reconsider whether and how to use this annotation.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for the valuable lessons. in this case let me remove this altogether.


This directory (`/lib/kotlin`) contains test only library code for Kotlin code gen. Because Kotlin code gen produces code that works on top of libthrift (i.e. Java library), the purpose of this library is to encode the cross test server and client to make sure it conforms to the thrift specifications.

The output artifact in this library is *not* published to Maven central.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

however, we might reserve the possibility of publishing a helper library in future e.g. containing extension functions

@Jimexist
Copy link
Member Author

cc @ctubbsii if case you are interested - i think we can use more 👀 s on Java changes

@ctubbsii
Copy link
Member

cc @ctubbsii if case you are interested - i think we can use more eyes s on Java changes

Thanks for the ping. I've tried to watch the Java changes a bit when I have time. But, for this... I really don't know Kotlin stuff at all.

@Jimexist Jimexist force-pushed the add-kotlin-code-gen branch 2 times, most recently from 5180530 to 429c52f Compare April 16, 2022 00:27
@Jens-G
Copy link
Member

Jens-G commented Apr 16, 2022

There are still a few files lacking a proper ASF license header

@Jens-G
Copy link
Member

Jens-G commented Apr 16, 2022

Also, I'm, not sure about that JAR file being added to the source tree.

@Jimexist
Copy link
Member Author

Jimexist commented Apr 16, 2022

Also, I'm, not sure about that JAR file being added to the source tree.

Did you mean the gradle wrapper jar? It is expected to be checked in in order to have consistent build, per gradle doc: https://docs.gradle.org/current/userguide/gradle_wrapper.html

To make the Wrapper files available to other developers and execution environments you’ll need to check them into version control. All Wrapper files including the JAR file are very small in size. Adding the JAR file to version control is expected.

Also I think it is the same situation for lib/java

@Jimexist
Copy link
Member Author

I think I've added the missing license headers

@ctubbsii
Copy link
Member

Also, I'm, not sure about that JAR file being added to the source tree.

Did you mean the gradle wrapper jar? It is expected to be checked in in order to have consistent build, per gradle doc: https://docs.gradle.org/current/userguide/gradle_wrapper.html

To make the Wrapper files available to other developers and execution environments you’ll need to check them into version control. All Wrapper files including the JAR file are very small in size. Adding the JAR file to version control is expected.

Also I think it is the same situation for lib/java

This has been discussed at length in other forums. I understand why people like using the gradle wrapper... but the jar shouldn't be in the source tree. If that means no gradle wrapper, then so be it. I understand people feel strongly about this, and want to argue in favor of it, but it can't be there. The one in lib/java should be removed.

@Jimexist
Copy link
Member Author

Also, I'm, not sure about that JAR file being added to the source tree.

Did you mean the gradle wrapper jar? It is expected to be checked in in order to have consistent build, per gradle doc: https://docs.gradle.org/current/userguide/gradle_wrapper.html

To make the Wrapper files available to other developers and execution environments you’ll need to check them into version control. All Wrapper files including the JAR file are very small in size. Adding the JAR file to version control is expected.

Also I think it is the same situation for lib/java

This has been discussed at length in other forums. I understand why people like using the gradle wrapper... but the jar shouldn't be in the source tree. If that means no gradle wrapper, then so be it. I understand people feel strongly about this, and want to argue in favor of it, but it can't be there. The one in lib/java should be removed.

ok in that case i'll just symbolically link to the java one so they are identical.

there's a way to verify the wrapper jar using sha256sum, i can maybe modify FindGradlew.cmake in another pull request to make it more secure.

@Jimexist
Copy link
Member Author

The one in lib/java should be removed.

@ctubbsii removing that requires significant rework on the build script, i'll probably find another time to do it?

@Jimexist Jimexist force-pushed the add-kotlin-code-gen branch 2 times, most recently from 57ec4a8 to 9d0cacb Compare April 17, 2022 07:51
@ctubbsii
Copy link
Member

The one in lib/java should be removed.

@ctubbsii removing that requires significant rework on the build script, i'll probably find another time to do it?

It's probably okay as long as the source tarball that is voted on and released doesn't include it. To remove it from git, the easiest thing to do is probably to just have the bootstrap.sh script download it. But, most of the places can probably just call gradle directly and leave it to the user to get the specified version.

In any case, it doesn't need to be done as part of this PR, but it probably should be done before the next release. I'm not a PMC member, and releases are ultimately a PMC responsibility. I'd help but I don't really know Gradle very well, as I mostly use Maven.

@Jens-G
Copy link
Member

Jens-G commented Apr 17, 2022

@Jimexist
I agree to what stubbsii wrote. Extra ticket and PR is fine. Next release is around summer (unless someone wants to do it earlier himself ... unlikely) so we have enough time. Long story short: May I ask you to take care of that issue?

@Jimexist
Copy link
Member Author

@Jimexist I agree to what stubbsii wrote. Extra ticket and PR is fine. Next release is around summer (unless someone wants to do it earlier himself ... unlikely) so we have enough time. Long story short: May I ask you to take care of that issue?

yes let me track it in https://issues.apache.org/jira/browse/THRIFT-5562

@Jimexist
Copy link
Member Author

Next release is around summer (unless someone wants to do it earlier himself ... unlikely)

I may be able to help do a release sometime in May if that's desired, after my recent changes are merged. My current dogfooding is done at master branch but for some of the changes it requires Java lib release and it's a bit hard to keep the process compared to a proper release. Given my best effort to do non-breaking changes I guess a new release before summer can be a patch release instead of a minor one.

I also don't know the effort involved, which I assume is non-trivial, since there are > 10 languages involved, but I'm willing to try (I personally had experience with publishing to maven central (java), crate (rust), npm (js), pypi (python), etc.). Also I'm not yet a committer (I'm only a committer at another project (Apache Arrow)) and not sure if it's possible.

@Jimexist Jimexist force-pushed the add-kotlin-code-gen branch 2 times, most recently from 8b17a30 to 9067bdf Compare April 19, 2022 03:08
@Jimexist
Copy link
Member Author

the latest cross tests failed because they are flaky: most of the kotlin-* and *-kotlin tests passed except for netstd because of a netstd side failure - not sure how it happened

# for bash scripts, 128+N is the exit code for signal N, since we are sending
# DEFAULT_SIGNAL=1, 128+1 is the expected err code
# http://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
allowed_return_code = set([-1, 0, 128+1])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure why its says "./test/crossrunner/run.py:249:58: E226 missing whitespace around arithmetic operator" but it does

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed, adding _ around +

@Jens-G
Copy link
Member

Jens-G commented Apr 20, 2022

One final remark. The primary idea of the /test folder is to house the cross test suite. Over time there have been placed also some other *.thrift files that are of common interest across languages, which I think is ok. All else should be placed under /lib/lang. Long story short, the cross-test client and server fit better under /test. It's not a blocker though.

@Jens-G
Copy link
Member

Jens-G commented Apr 20, 2022

PS: Congrats for getting this done!

@Jimexist Jimexist deleted the add-kotlin-code-gen branch April 21, 2022 00:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
4 participants