I have a User Task and I assign it to a user. In the runtime, after the assignment, the task is in waiting state until it’s completed, right?
I don’t want the user to complete the task by clicking “Complete” in the Tasklist application but I want to complete it with a REST call when I receive an external trigger.
Can anyone point me a very simple example to call some code to complete a User Task with REST API?
Thanks @Niall, I’ve seen that documentation but I’m looking for a github example what to write in my code, how to trigger the POST method from an Execution/Task Listener, etc.
Whatever your code (in which language do you work ?), you have to send a post request to your rest API.
for me (4gl), it’s look like that :
LET taskId = arg_val(1);
LET url = "http://localhost:8080/camunda/api/engine/engine/default/task/", taskId, "/submit-form";
LET req = com.HttpRequest.Create(URL);
CALL req.setMethod("POST");
CALL req.setHeader("Content-Type", "application/json")
CALL req.setHeader("Accept", "application/json")
CALL req.doTextRequest(data); #send the request to submit the task
TRY
LET res = req.getResponse()
IF res.getStatusCode() != 200 or res.getStatusCode() != 204 THEN #StatusCode have to be 204
DISPLAY "HTTP Error ("||res.getStatusCode()||") ",res.getStatusDescription()
RETURN "error"
END IF
CATCH
DISPLAY "request don't work"
END TRY
my variable “data” is a JSON like explain in the docs.
but I’m not very familiar with.
What are the configurations I need in order to make such code work?
So, I’m looking for a simple example with a Java code to make the POST call that is described in the documentation.
as you mentioned before you are in a Task/Execution Listener?
So, why do you want to you use the REST API to complete the Task?
You could easily use the taskService.
If this is not the case, here an example to call the post request from JAVA. But don’t forget, you have to know the task id.
String url = "http://localhost:8080/engine-rest/task/c44b7c61-5026-11e7-9d74-064bed1e2b33/complete";
URL obj = new URL(url);
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
// Setting basic post request
con.setRequestMethod("POST");
con.setRequestProperty("Content-Type","application/json");
//if you want to add some variables
String postJsonData = "{\"variables\":\r\n {\"aVariable\": {\"value\": \"aStringValue\"},\r\n \"anotherVariable\": {\"value\": 42},\r\n \"aThirdVariable\": {\"value\": true}}\r\n}";
// Send post request
con.setDoOutput(true);
DataOutputStream wr = new DataOutputStream(con.getOutputStream());
wr.writeBytes(postJsonData);
wr.flush();
wr.close();
int responseCode = con.getResponseCode();
System.out.println("nSending 'POST' request to URL : " + url);
System.out.println("Post Data : " + postJsonData);
System.out.println("Response Code : " + responseCode);
No I’m not in an Execution/Task Listener.
Actully, what I want to achieve is while the User Task is in waiting state (meaning it’s being worked on), I get an external trigger and I want with the REST call to complete the task.
If you don’t want to pass any variables you can set postJsonData to an empty String.
Is this the normal behavior of your Process? Or is the external trigger some kind of special case?
There’s a chance that some variables need to be passed for the rest of the control flow, but in most cases it’s just the action of completion of the task (I can handle the variables from the external trigger somehow).
The process model is not that complex, at least the main idea.
There’s a task to be executed by an external system. When the external system completes the task, it sends a message to my application and the flow can move on.
Initially, I thought something like the following:
Then I thought the idea of using a User Task, which is in a waiting state and when I receive the message from the external system, I want to complete the Task with the API.
The point is that what if the task is not completed? What if it needs to be re-assigned to another user?
Then in the catching message I should check many options.
So I started to think of a solution with the User Task where the task is still in waiting state and I can keep receiving many messages.
Still, not sure which one is better solution for me at the moment but since I achieved the first one with the Service Task - Message correlation, I want now to try the User Task - REST API completion.
I also considered the External Task pattern but I don’t want the external users to be responsible and go fetch the tasks themselves. I want my application to have control and assign the tasks immediately.
Let’s go some steps back.
Is your external System some kind of Tasklist?
If this is the case you could just create a UserTask and add an TaskListener. With this Listener you can inform the external system when the task is created.
To complete the Task you can call the post request I mentioned before.
With external system, I mean an external application that will further do some actions. From Camunda, I want actually to trigger the movement of a robot. When the movement is complete, the robot will inform me back with a message that the task is complete.
Your idea is what I’m trying to achieve at the moment. With a Task Listener (or maybe Execution Listener??) I will send information to the robot to perform a movement. The User Task will be in waiting state until the robot informs me back and at that point I will call the Complete method of the API to move on.
given your description, I would model this as a service task followed by a receive task, something like;
Initiate Movement -> Receive Movement Complete
Hence the Initiate movement service task generates some sort of signal, message or API call to instruct the machine to move. The process then transitions to a wait sate on the receive task. When the movement is complete, the Robot initiates a message back to the engine indicating the movement is complete.
Thanks @Webcyberrob,
So you are in favor of the first approach I explained above (with the bpmn example I gave).
Can you argue about such a design choice?
This what I’m currently struggling to decide on.
Rationale for this design over a user task;
I tend to reserve user tasks for a human interaction. In particular, the human is often a knowledge worker and thus the ‘wait state’ associated with the user task is often the ‘think time’. In addition, a user task often has a user interface associated with it.
In your case, the process is orchestrating an asynchronous remote procedure call to initiate an activity in an external system and wait for a signal indicating the activity is complete. You could model this as a single service task and use the asynchronous Camunda service task, however this is advanced Camunda usage and I would only recommend it use for advanced Camunda users. A simpler approach with the same behaviour is a service task to initiate and a receive task to wait for the response. Note I am advocating using a receive task rather than a receive message event as per your model. Rationale for this choice is you can add interrupting boundary events on the receive task. It can be done with a receive message event, but then you get into an event driven gate…
On the other hand, if you had many robots and each robot just grabbed the next ‘task’ to do, then an external service task may be even more approriate…
I see your points and I fully agree!
I was thinking though that the User tasks can help me in the cases where the robot task is paused, or needs to be re-assigned to another user. With the Service-Receive Task, once you send the task, then your process sits on the waiting state while the actual work being done is before that state. Think of the cockpit, where the token will be in the Receive Task and not in the Service Task.
In any case, many things to argue and thanks for the discussions!