We have a java backend and a Go backend. How can I start a workflow written in Java that is registered with the java worker from Go?
I also want to do the reverse.
I saw in the docs that we import a workflow in a worker and register the workflow and activities. So I can’t figure out how in Go I can get the java code and register in the worker.
Also, does a worker only listen for one task queue name? and any workflow that is started with a task queue name either in Go or java is executed by a worker that listens for that task queue name? Is my understanding correct?
I’m a frontend developer who just started learning Go and all this is a bit overwhelming. So please help me out… if possible with an example.
I saw in the docs that we import a workflow in a worker and register the workflow and activities. So I can’t figure out how in Go I can get the java code and register in the worker.
Only activities and workflows that a given worker implements have to be registered. So if a workflow starts activities that its worker doesn’t implement they don’t need to be registered.
Also, does a worker only listen for one task queue name? and any workflow that is started with a task queue name either in Go or java is executed by a worker that listens for that task queue name? Is my understanding correct?
Yes, this is correct. One important implication is that workers that implement different sets of workflows and activities must listen to different task queues. It also implies that when calling workflows and activities a correct task queue must be always specified.
I’m a frontend developer who just started learning Go and all this is a bit overwhelming. So please help me out… if possible with an example.
Welcome to Temporal, feel free to ask more questions when in doubt. We do plan to add the cross-language example.
FWIW this is how I’m starting workflows from a Kotlin Ktor server using the Temporal java-sdk. The workflows are all hosted by workers running on separate services in our cloud, and are currently written in Go.
So to call one of the golang Workflows (from the Temporal samples) with a function definition:
// Set up the connection to the temporal server
val hostPort = "my-temporal-service-frontend.default.svc.cluster.local:7233"
val workflowServiceStubsOptions = WorkflowServiceStubsOptions
.newBuilder()
.setTarget(hostPort)
.build()
val serviceStubs = WorkflowServiceStubs.newInstance(workflowServiceStubsOptions)
// Get a client instance (one per Temporal namespace)
val namespace = "examples"
val workflowClient = WorkflowClient.newInstance(
serviceStubs,
WorkflowClientOptions
.newBuilder()
.setNamespace(namespace)
.build()
)
// Create a stub we'll use to start the workflow
val workflowType = "TransferMoney"
val taskQueue = "TRANSFER_MONEY_TASK_QUEUE"
val workflowOptions = WorkflowOptions
.newBuilder()
.setTaskQueue(taskQueue)
.build()
val workflowStub = workflowClient.newUntypedWorkflowStub(workflowType, workflowOptions)
// Temporal expects the workflow params in a specific format, the SDK will use a JSON encoder
// to serialize the args to that format. Since you're kicking off a workflow that was written in Go
// you likely don't have access to the `TransferDetails` struct within your code, so you have to either
// model up a POJO or data class, or mock up a string template like the 'jsonString' above. It's far
// easier IMO to give the _start()_ method something the JSON parser can encode than trying to send
// it a String - unless the workflow param is an actual golang `string`.
val jsonString = "{\n" +
" \"Amount\":22.19, \n" +
" \"FromAccount\":\"acct1\",\n" +
" \"ToAccount\":\"acct2\",\n" +
" \"ReferenceID\":\"my-test-3\"\n" +
"}"
val workflowArgs: JsonNode = jacksonObjectMapper().readTree(jsonString)
val execution = workflowStub.start(workflowArgs)
I did have a few issues passing workflow arguments which is why I wanted to post this. There isn’t a lot in the documentation about how to send an argument payload that the Temporal service will understand, so maybe this will save someone a lot of trial and error.
To start a workflow running in another application in your cloud you need to know:
The namespace in which the Workflow belongs
The taskQueue to which the Workflow implementation has subscribed
The workflowType which is generally the class name
Thank you, @Fredric_Doddridge for the code sample. I personally think that passing raw JSON is not a ideal in this case. I think having POJO that matches the Go structure is a much cleaner way to pass arguments across languages. Another option is to use Protobufs which have code generation to these languages.
Yeah I agree, using raw JSON is messy. For example only
For most of our apps we use a schema repository so we can use strongly typed structures. I’d like to make more use of protobufs. The code above is from a service we expose to a third-party that sends us a JSON payload to start one of an approved list of workflows in our system, based on auth:
data class StartWorkflowRequest(val namespace: String = "default", val workflowType: String, val taskQueue: String, val workflowArgs: Iterable<JsonNode>?)
I made it generic to have a single endpoint, but that also means I don’t know the parameter types ahead of time. The client sends a payload that looks like this: