How do I override the DataConverter for ChildWorkflow executions

I followed this sample here to be able to use some encryption for some sensitive data (like customer phone number and address)

It works great for my Main workflow execution (after lowering the iteration count in jackson-json-crypto because it was causing delays that temporal was very upset with.

My issue now is, I’m trying to start a ChildWorkflow with the phone number that is encrypted. This led to temporal throwing some DataConverterException

"cause": {
        "message": "Cannot construct instance of `com.yodawy.narodoosync.models.sms.SMSRequest` (no Creators, like default constructor, exist): cannot deserialize from Object value (no delegate- or property-based Creator)\n at [Source: (byte[])\"{\"phoneNumber\":{\"salt\":\"+EtiAaItatjS0sq4fWT0v3WyBmQ=\",\"iv\":\"9VbouSI6Npf9wKtbwV05gQ==\",\"value\":\"0FtSkrjX0EK3xTD9d6vHlg==\"},\"content\":\"content",\"delayInMilliseconds\":276684}\"; line: 1, column: 2]",
        "source": "JavaSDK",
        "stackTrace": "com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:67)\ncom.fasterxml.jackson.databind.DeserializationContext.reportBadDefinition(DeserializationContext.java:1764)\ncom.fasterxml.jackson.databind.DatabindContext.reportBadDefinition(DatabindContext.java:400)\ncom.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1209)\ncom.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1415)\ncom.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:362)\ncom.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:195)\ncom.fasterxml.jackson.databind.deser.DefaultDeserializationContext.readRootValue(DefaultDeserializationContext.java:322)\ncom.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4593)\ncom.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3643)\nio.temporal.common.converter.JacksonJsonPayloadConverter.fromData(JacksonJsonPayloadConverter.java:80)\nio.temporal.common.converter.DefaultDataConverter.fromPayload(DefaultDataConverter.java:132)\nio.temporal.common.converter.DataConverter.arrayFromPayloads(DataConverter.java:104)\nio.temporal.internal.sync.POJOWorkflowImplementationFactory$POJOWorkflowImplementation.execute(POJOWorkflowImplementationFactory.java:288)\nio.temporal.internal.sync.WorkflowExecuteRunnable.run(WorkflowExecuteRunnable.java:53)\nio.temporal.internal.sync.SyncWorkflow.lambda$start$0(SyncWorkflow.java:131)\nio.temporal.internal.sync.CancellationScopeImpl.run(CancellationScopeImpl.java:101)\nio.temporal.internal.sync.WorkflowThreadImpl$RunnableWrapper.run(WorkflowThreadImpl.java:110)\njava.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)\njava.util.concurrent.FutureTask.run(FutureTask.java:266)\njava.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)\njava.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)\njava.lang.Thread.run(Thread.java:748)\n",
        "encodedAttributes": null,
        "cause": null,
        "applicationFailureInfo": {
          "type": "com.fasterxml.jackson.databind.exc.InvalidDefinitionException",
          "nonRetryable": false,
          "details": null
        }
      },

This leads me to believe that the child workflow did not inherit the data converter override I used for the main workflow:

JacksonJsonPayloadConverter dataConverter = JacksonEncryptedDataConverter.getCryptoJacksonJsonPayloadConverter();
            WorkflowServiceStubsOptions workflowServiceStubsOptions =
                    WorkflowServiceStubsOptions.newBuilder()
                            .setTarget(currentConfig.getString("temporal.url"))
                            .build();

            WorkflowServiceStubs service = WorkflowServiceStubs.newInstance(workflowServiceStubsOptions);
            WorkflowClientOptions clientOptions =
                    WorkflowClientOptions
                            .newBuilder()
                            .setDataConverter(
                                    DefaultDataConverter.newDefaultInstance()
                                            .withPayloadConverterOverrides(dataConverter))
                            .setNamespace(currentConfig.getString("temporal.namespace"))
                            .build();

            client = WorkflowClient.newInstance(service, clientOptions);
            options = WorkflowOptions.newBuilder()
                    .setTaskQueue(currentConfig.getString("temporal.queue"))
                    .build();

When I went to try and do the same overrides for the ChildWorkflowOptions, I realized that that option does not exist for the ChildWorkflowOptions class.

How can I fix this?

I have the same issue with Typescript. I’m using an EJSON converter from samples-typescript/ejson at main · temporalio/samples-typescript · GitHub. Dates are successfully converted for parent workflows, but child workflows get strings, and fail.

My solution is to trigger the workflow from an activity, instead of using startChild.