cancel
Showing results for 
Search instead for 
Did you mean: 

Cannot complete a task using REST API (Activiti 5.14)

obdurate
Champ in-the-making
Champ in-the-making
I have created a process definition in Activiti (5.14) which is made up of a mixture of user and service tasks.  I have created two versions, in one version the user tasks have forms so they can be run in Activiti Explorer.  In the second version the user tasks do not have forms so everything needs to be done programmatically.

I am able to unit test both process definitions using Eclipse with no problems.  I can start the process instance, set process variables, get tasks, complete tasks, etc.  All of this is done using Java calls, none of it uses REST. I can also start a process instance (with forms) and run through it using Activiti Explorer.

Using REST I am able to start a process instance and get tasks; however, I cannot complete the tasks. I have tried to complete tasks with and without forms and I keep running into the same issue.  I am making REST calls using the Advanced REST client app in Chrome.  All calls have the Content-Type set to application/json in the header. Below are my calls and responses the the process-instance without forms in the user task.

Post to http://localhost:8080/activiti-rest/service/runtime/process-instances
Payload:
{
    "processDefinitionKey":"AddSquaresRestPOC",
     "variables": [
        {
        "name": "numbertosquare",
        "value": "4"
        }
    ]
}

Response:
{
id: "508"
url: "http://localhost:8080/activiti-rest/service/runtime/process-instances/508"
businessKey: null
suspended: false
processDefinitionId: "AddSquaresRestPOC:1:604"
processDefinitionUrl: "http://localhost:8080/activiti-rest/service/repository/process-definitions/AddSquaresRestPOC%3A1%3A6..."
activityId: "usertask1"
variables: [0]
}

Post to http://localhost:8080/activiti-rest/service/query/tasks
Payload:
{
    "executionId":"508"
}
Response:
{
data: [1]
0:  {
id: "520"
url: "http://localhost:8080/activiti-rest/service/runtime/tasks/520"
owner: null
assignee: "turner"
delegationState: null
name: "Enter First Number"
description: null
createTime: "2014-02-26T20:49:39.132+0000"
dueDate: null
priority: 50
suspended: false
taskDefinitionKey: "usertask1"
parentTaskId: null
parentTaskUrl: null
executionId: "508"
executionUrl: "http://localhost:8080/activiti-rest/service/runtime/executions/508"
processInstanceId: "508"
processInstanceUrl: "http://localhost:8080/activiti-rest/service/runtime/process-instances/508"
processDefinitionId: "AddSquaresRestPOC:1:604"
processDefinitionUrl: "http://localhost:8080/activiti-rest/service/repository/process-definitions/AddSquaresRestPOC%3A1%3A6..."
variables: [0]
}
total: 1
start: 0
sort: "id"
order: "asc"
size: 1
}

Get to http://localhost:8080/activiti-rest/service/task/520
Response:
{
assignee: "turner"
createTime: "2014-02-26T15:49:39EST"
delegationState: null
description: null
dueDate: null
executionId: "508"
id: "520"
name: "Enter First Number"
owner: null
parentTaskId: null
priority: 50
processDefinitionId: "AddSquaresRestPOC:1:604"
processInstanceId: "508"
taskDefinitionKey: "usertask1"
formResourceKey: null
subTaskList: [0]
identityLinkList: [1]
0:  {
type: "assignee"
userId: "turner"
groupId: null
}
attachmentList: [0]
}

Put to http://localhost:8080/activiti-rest/service/task/520/complete
Response:
{
errorMessage: "Not Found"
statusCode: 404
}

Post to http://localhost:8080/activiti-rest/service/runtime/tasks/520
Payload:
{
    "action":"complete"
}
Response:
{
errorMessage: "Not Found"
statusCode: 404
}

I have attached catalina.out to this message as catalina.txt.  Any help would be appreciated.
11 REPLIES 11

tstephen
Champ on-the-rise
Champ on-the-rise
I don't recognise the REST URL you are using to complete a task. The user guide describes a POST to the task with a payload containing the action here: http://activiti.org/userguide/index.html#N1444D. Furthermore the PUT semantic is supposed to create / change a resource so it would be a bit unusual to use that to take away (complete) a task IMHO.

obdurate
Champ in-the-making
Champ in-the-making
Thanks for the response.  I found the put example here: http://forums.activiti.org/content/rest-api-complete-task-variable.  I suspect it was part of the old REST api but I could be wrong.  I also tried to submit the call per the current documentation.  Here is another example (using variables this time):

Request:
Post to: http://kermit:kermit@localhost:8080/activiti-rest/service/runtime/tasks/1183

Payload:
{
    "action":"complete",
    "variables": [
        {
            "name":"numbertosquare",
            "value":"4"
        }
    ]
}

Response:
{
errorMessage: "Not Found"
statusCode: 404
}

If I change the variable name to something else (say the form field name) it gives me a 500 error so I know something is happening with the correct variable specified.

I know the task is there because a get call to http://kermit:kermit@localhost:8080/activiti-rest/service/runtime/tasks/1183 returns data:
{
id: "1183"
url: "http://localhost:8080/activiti-rest/service/runtime/tasks/1183"
owner: null
assignee: "kermit"
delegationState: null
name: "Enter First Number"
description: null

}

A co worker has gotten this call to work with a much simpler workflow so my next step is to create a very simple workflow with one user task and try to use the REST API to complete it.  If that works I will start adding tasks back in until it breaks (or doesn't).  I will post my results.

obdurate
Champ in-the-making
Champ in-the-making
OK.  We found the issue.  Our process has a user task which calls a service task.  The user task asks for a number.  That number is then squared by the service task.

Our service task then calls a REST Service to square the number.  This all works fine in Activiti Explorer.

If we use the Activiti REST API to call our process and our process itself makes a REST call this error occurs when invoking the Activiti REST API to complete the user task than then calls the service task.  When I remove the rest call from the class that the service task calls and simply square the number using the Math library in JAVA it works fine.

This is as far as I've gotten.  I will write a proper unit test and post it to these forums at a later date to see if I can narrow down the problem further.  For now I will make a note that I am unable to use the REST API to complete a user task that calls a service task that itself makes a REST call.

If this doesn't make sense please let me know. Thanks.

trademak
Star Contributor
Star Contributor
Hi,

Be aware that the Explorer and REST applications each have their own classpath. Did you make the service task class available on the REST application classpath as well?

Best regards,

obdurate
Champ in-the-making
Champ in-the-making
Thanks for the response.  The classpath isn't the issue.  After some testing we determined that it was the rest library that the java service task was using.

So our application looks like this (simplified) User Task with From (Enter a number) - Service Task (Square the Number) - …

The service task that squares the number makes its own REST call to a page that does the work of squaring the number.

When using the org.restlet libraries in the Java Service Task we received the error detailed in my previous posts if we called the process instance using the Activiti REST APIS (via JavaScript). We did not see an issue using our unit tests in eclipse or when using Activiti Explorer.

When we switched to the org.apache.http.client libraries to make our rest call from the Java Service task it works fine whether we call the process-instance from a unit test, from Activiti explorer, or from Activiti Rest.

So it appears that if we design a java service process that uses the org.restlet libraries to make a rest call, and then call the Activiti REST API to invoke the process instance that uses the java service process we get that error.  If we use the org.apache.http.client.fluent libraries in our Java Service Task we do not have the same problem and everything works fine using Activiti Explorer, Activiti Rest via whatever (Html/Javascript in our case), Unit Tests in Eclipse, etc.

Thank you for taking the time to offer suggestions.  It is appreciated.

jbarrez
Star Contributor
Star Contributor
Thanks for posting this back, this is good information (and a bit frightening that restlet doesn't do a good job there!)

youtianhong
Champ in-the-making
Champ in-the-making
Hi jbarrez,

Is there any way to support passing nest variables in restlet client ?
I tried lots of way to test it, but no one can successful.

String fullUri = "http://localhost:8080/activitirestservice/service/runtime/tasks/2520";
//the first way
String jsonString ="{\"action\":\"complete\", \"variables\": {\"name\":\"hrPass\",\"value\": true}}";
getClientResource(fullUri).post(jsonString, MediaType.APPLICATION_JSON);
//This way will throw an exception like below:
Unprocessable Entity (422) - Unprocessable Entity



//The second way
org.codehaus.jackson.map.ObjectMapper objectMapper = new ObjectMapper();
org.codehaus.jackson.node.ObjectNode requestNode = objectMapper.createObjectNode();
requestNode.put("action", "complete");
ObjectNode node2 = objectMapper.createObjectNode();
node2.put("name", "hrPass");
node2.put("value", true);
requestNode.put("variables", node2);
//This way will throw an exception like below:
org.codehaus.jackson.JsonParseException: Unexpected end-of-String when base64 content
at [Source: N/A; line: -1, column: -1]

Can you help me and show a demo for this?




protected static ClientResource getClientResource(String uri) throws IOException{
  ClientResource clientResource = new ClientResource(uri);
  clientResource.setReference(uri);
  return clientResource;
}

vasile_dirla
Star Contributor
Star Contributor
@youtianhong ,
you need a JSON string which should be unmarshalled as an TaskActionRequest java object.
so you could use it like that:
<java>
TaskActionRequest actionRequest = new TaskActionRequest();
….
String jsonString  = objectMapper.writeValueAsString(actionRequest)
….
// post this jsonString
</java>
now compare your string with the one generated by the "writeValueAsString" method.

Thanks a lot  vasile for your response !
I did it like your mentioned, but still has a new exception threw:  ResourceException -> Unsupported Media Type (415) - Unsupported Media Type
Was there any missed for me?

<code>
TaskActionRequest actionRequest = new TaskActionRequest();
  List<RestVariable> variables = new ArrayList<RestVariable>();
  RestVariable variable = new RestVariable();
  variable.setName("hrPass");
  variable.setValue(true);
  variables.add(variable);
  actionRequest.setVariables(variables);
  actionRequest.setAction("complete");
  String jsonString = "";
  try {
   jsonString = objectMapper.writeValueAsString(actionRequest);
                        //I can see jsonString  was be generated successfully
   System.out.println("jsonString="+jsonString);
  } catch (JsonGenerationException e1) {
   e1.printStackTrace();
  } catch (JsonMappingException e1) {
   e1.printStackTrace();
  } catch (IOException e1) {
   e1.printStackTrace();
  }
 
  String fullUri = "http://localhost:8080/activitirestservice/service/runtime/tasks/2520";
  try {
   getClientResource(fullUri).post(jsonString, MediaType.APPLICATION_JSON);
   System.out.println("yes…");
  } catch (ResourceException e) {
   System.out.println(e.getMessage());
                        //here threw an exception : Unsupported Media Type (415) - Unsupported Media Type
  } catch (IOException e) {
   System.out.println(e.getMessage());
  }
</code>

The jsonString was generated successfully like below:
{"action":"complete","assignee":null,"variables":[{"name":"hrPass","type":null,"variableScope":null,"value":true,"valueUrl":null,"scope":null}]}