My Journey with Camunda — Part 4— External Service Task With Golang
This is multipart series where I wrote my journey using Camunda from a non-java developer perspective.
We have deployed our BPMN to Camunda engine. Before we create Golang external service task, let’s see if we can create instance with it.
Something is wrong here. I have deployment, but no definition.
I checked Camunda logs, and I found following line
05-May-2019 13:32:50.616 INFO [http-nio-8080-exec-10] org.camunda.commons.logging.BaseLogger.logInfo ENGINE-01002 Ignoring non-executable process with id 'Process_1bvk6g2'. Set the attribute isExecutable="true" to deploy this process.
Turns out that we not set executable property of the BPMN. Let’s go to Modeler and fix this. I think default should be Executable, right?
After we deploy and refresh Camunda Cockpit, we can see now there is definition deployed.
To create an instance, we can use start process instance API.
curl -X POST \
http://localhost:8080/engine-rest/process-definition/key/Process_1bvk6g2/start \
-H 'Content-Type: application/json' \
-d '{
"variables": {
"id" : {
"value" : "sampurple",
"type": "String"
},
"name" : {
"value" : "Sam Purple",
"type": "String"
},
"email" : {
"value" : "sam.purple@journey.com",
"type": "String"
},
"level" : {
"value" : "junior",
"type": "String"
},
"days" : {
"value" : 10,
"type": "Integer"
}
},
"businessKey" : "Leave-123"
}'
And we have our instances
If you notice, our instances is waiting at Validate available days
service task. It waits until some external service task process then completed the task. Check service task with fetchAndLock API
curl -X POST \
http://localhost:8080/engine-rest/external-task/fetchAndLock \
-H 'Content-Type: application/json' \
-d '{
"workerId":"worker1",
"maxTasks":2,
"usePriority":true,
"topics": [
{
"topicName": "available-leave-days",
"lockDuration": 30000
}
]
}'
After we get tasks for particular topic, we process it and then complete the task.
curl -X POST \
http://localhost:8080/engine-rest/external-task/{{TASK_ID}}/complete \
-H 'Content-Type: application/json' \
-d '{
"workerId": "worker1",
"variables":{
"daysAvailable": {"value": true}
}
}'
After service task is completed, execution will continue to next activity which is Business Rules Task, where it will select assignee. After that, we go to User Task
External Service Task With Golang
Now we know that External service task implementation must implement 2 APIs: fetchAndLock and complete. There are more but for now we only use these APIs. I have created simple Golang application to handle Camunda External Task. You can check following repo in Github
It has two main parts:
Periodically fetch tasks with specific topic
c := cron.New()
availableLeaveDays := &camunda.FetchAndLock{
WorkerID: "worker1",
MaxTasks: 1,
Topics: []camunda.Topic{
camunda.Topic{
Name: "available-leave-days",
LockDuration: 10000,
},
},
}
c.AddFunc("@every 5s", call(client, availableLeaveDays, handlers.AvailableLeaveDaysHandler))
c.Start()
Handler to handle specific topic and complete the task
func AvailableLeaveDaysHandler(client *camunda.Client, tasks []camunda.Task) error {
for _, task := range tasks {
// pretend to do something
time.Sleep(2 * time.Second)
// complete
err := client.Complete(task.ID, &camunda.Complete{
WorkerID: "worker1",
Variables: map[string]camunda.Variable{
"daysAvailable": camunda.Variable{
Value: true,
},
},
})
if err != nil {
return err
}
}
return nil
}
Handlers will be implementation specific and for now we just use sleep function.
We are done here. Next, we will see how we can improve Tasklist experience with form fields.