You need to customize the DataConverter.
DataConvert is for converting between your argument(Class) and byte array so that your client can send the argument to Cadence server, and then server send it to workflow worker.
For example, you can do something like below.
NOTE that this is just an example for you to implement DataConverter. To encode/decode ZonedDataTime you need to find out a way to do it correctly. You may need to refer to Spring Data JPA - ZonedDateTime format for json serialization
data class WorkflowArgs(
val currentTime: ZonedDateTime
)
fun main1() { // this doesn't work
val dataConverter = JsonDataConverter.getInstance()
val args = WorkflowArgs( ZonedDateTime.now())
println(args.currentTime.zone)
val encoded = dataConverter.toData(args)
val decoded: WorkflowArgs = dataConverter.fromData(encoded, args.javaClass, args.javaClass)
println(decoded.currentTime.zone)
/**
* Results:
America/Los_Angeles
Exception in thread "main" com.uber.cadence.converter.DataConverterException: when parsing:"{"currentTime":{"dateTime":{"date":{"year":2021,"month":9,"day":13},"time":{"hour":9,"minute":14,"second":46,"nano":517000000}},"offset":{"totalSeconds":-25200},"zone":{"id":"America/Los_Angeles"}}}" into following types: [class com.uber.cadence.converter.WorkflowArgs]
at com.uber.cadence.converter.JsonDataConverter.fromData(JsonDataConverter.java:111)
at com.uber.cadence.converter.TestZonedDatatimeKt.main(TestZonedDatatime.kt:14)
at com.uber.cadence.converter.TestZonedDatatimeKt.main(TestZonedDatatime.kt)
Caused by: java.lang.RuntimeException: Failed to invoke java.time.ZoneId() with no args
at com.google.gson.internal.ConstructorConstructor$3.construct(ConstructorConstructor.java:113)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:212)
...
at com.uber.cadence.converter.JsonDataConverter.fromData(JsonDataConverter.java:109)
... 2 more
*/
}
fun main() { // you need to implement another DataConverter like this
val dataConverter = MyDataConvert()
val args = WorkflowArgs( ZonedDateTime.now())
println(args.currentTime.zone)
val encoded = dataConverter.toData(args)
val decoded: WorkflowArgs = dataConverter.fromData(encoded, args.javaClass, args.javaClass)
println(decoded.currentTime.zone)
/**
Resutls:
America/Los_Angeles
America/Los_Angeles
**/
}
class MyDataConvert:DataConverter{
val originalDataConverter = JsonDataConverter.getInstance()
override fun toData(vararg value: Any?): ByteArray {
if( (value.size == 1) && (value[0] is WorkflowArgs)){
val v = value[0] as WorkflowArgs
val zoneId = v.currentTime.zone.id
val br = zoneId.toByteArray()
return br
}else{
return originalDataConverter.toData(value)
}
}
override fun <T : Any?> fromData(content: ByteArray?, valueClass: Class<T>?, valueType: Type?): T {
if(valueClass!!.canonicalName.contains("WorkflowArgs") ){
val zi = String(content!!)
val zoneId: ZoneId = ZoneId.of(zi)
val dt = ZonedDateTime.now(zoneId)
return WorkflowArgs(dt) as T
}else{
return originalDataConverter.fromData(content, valueClass, valueType)
}
}
override fun fromDataArray(content: ByteArray?, vararg valueType: Type?): Array<Any> {
if( (valueType.size == 1) && (valueType[0]!!.typeName.contains("WorkflowArgs"))){
val zi = String(content!!)
val zoneId: ZoneId = ZoneId.of(zi)
val dt = ZonedDateTime.now(zoneId)
val arr = arrayOf(WorkflowArgs(dt))
return arr as Array<Any>
}
return originalDataConverter.fromDataArray(content, *valueType)
}
}
This is another example of implmenting DataConverter: https://github.com/uber/cadence-java-samples/pull/37