Skip to content

Commit

Permalink
feat(engine): handle escalation for user tasks
Browse files Browse the repository at this point in the history
* escalation event can be attached to an user task
* adjust exsisting tests accordingly
* Java API
* Rest API

Related to CAM-10397
  • Loading branch information
yanavasileva authored and tmetzke committed Sep 11, 2019
1 parent e57e488 commit 445f723
Show file tree
Hide file tree
Showing 19 changed files with 976 additions and 112 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH
* under one or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information regarding copyright
* ownership. Camunda licenses this file to you under the Apache License,
* Version 2.0; you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.camunda.bpm.engine.rest.dto.task;

import java.util.Map;

import org.camunda.bpm.engine.rest.dto.VariableValueDto;

public class TaskEscalationDto {

protected String escalationCode;
protected Map<String, VariableValueDto> variables;


public String getEscalationCode() {
return escalationCode;
}

public void setEscalationCode(String escalationCode) {
this.escalationCode = escalationCode;
}

public Map<String, VariableValueDto> getVariables() {
return variables;
}

public void setVariables(Map<String, VariableValueDto> variables) {
this.variables = variables;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import org.camunda.bpm.engine.rest.dto.task.FormDto;
import org.camunda.bpm.engine.rest.dto.task.IdentityLinkDto;
import org.camunda.bpm.engine.rest.dto.task.TaskBpmnErrorDto;
import org.camunda.bpm.engine.rest.dto.task.TaskEscalationDto;
import org.camunda.bpm.engine.rest.dto.task.TaskDto;
import org.camunda.bpm.engine.rest.dto.task.UserIdDto;
import org.camunda.bpm.engine.rest.hal.Hal;
Expand Down Expand Up @@ -144,4 +145,9 @@ Map<String, VariableValueDto> getFormVariables(@QueryParam("variableNames") Stri
@Path("/bpmnError")
@Consumes(MediaType.APPLICATION_JSON)
void handleBpmnError(TaskBpmnErrorDto dto);

@POST
@Path("/bpmnEscalation")
@Consumes(MediaType.APPLICATION_JSON)
void handleEscalation(TaskEscalationDto dto);
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
import org.camunda.bpm.engine.rest.dto.task.IdentityLinkDto;
import org.camunda.bpm.engine.rest.dto.task.TaskBpmnErrorDto;
import org.camunda.bpm.engine.rest.dto.task.TaskDto;
import org.camunda.bpm.engine.rest.dto.task.TaskEscalationDto;
import org.camunda.bpm.engine.rest.dto.task.UserIdDto;
import org.camunda.bpm.engine.rest.exception.InvalidRequestException;
import org.camunda.bpm.engine.rest.exception.RestException;
Expand Down Expand Up @@ -426,4 +427,18 @@ public void handleBpmnError(TaskBpmnErrorDto dto) {
throw new RestException(Status.BAD_REQUEST, e, e.getMessage());
}
}

@Override
public void handleEscalation(TaskEscalationDto dto) {
TaskService taskService = engine.getTaskService();

try {
taskService.handleEscalation(taskId, dto.getEscalationCode(), VariableValueDto.toMap(dto.getVariables(), engine, objectMapper));
} catch (NullValueException e) {
throw new RestException(Status.NOT_FOUND, e, "Task with id " + taskId + " does not exist");
} catch (BadUserRequestException e) {
throw new RestException(Status.BAD_REQUEST, e, e.getMessage());
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ public class TaskRestServiceInteractionTest extends
protected static final String TASK_CREATE_URL = TASK_SERVICE_URL + "/create";

protected static final String HANDLE_BPMN_ERROR_URL = SINGLE_TASK_URL + "/bpmnError";
protected static final String HANDLE_BPMN_ESCALATION_URL = SINGLE_TASK_URL + "/bpmnEscalation";

private Task mockTask;
private TaskService taskServiceMock;
Expand Down Expand Up @@ -3412,7 +3413,7 @@ public void testHandleBpmnErrorThrowsBadUserRequestException() {
given()
.contentType(POST_JSON_CONTENT_TYPE)
.body(parameters)
.pathParam("id", "anExternalTaskId")
.pathParam("id", "aTaskId")
.then()
.expect()
.statusCode(Status.BAD_REQUEST.getStatusCode())
Expand All @@ -3422,6 +3423,128 @@ public void testHandleBpmnErrorThrowsBadUserRequestException() {
.post(HANDLE_BPMN_ERROR_URL);
}


@Test
public void testHandleBpmnEscalation() {
Map<String, Object> parameters = new HashMap<String, Object>();
parameters.put("escalationCode", "anEscalationCode");

given()
.contentType(POST_JSON_CONTENT_TYPE)
.body(parameters)
.pathParam("id", "aTaskId")
.then()
.expect()
.statusCode(Status.NO_CONTENT.getStatusCode())
.when()
.post(HANDLE_BPMN_ESCALATION_URL);

verify(taskServiceMock).handleEscalation("aTaskId", "anEscalationCode", null);
verifyNoMoreInteractions(taskServiceMock);
}

@Test
public void testHandleBpmnEscalationWithVariables() {
Map<String, Object> parameters = new HashMap<String, Object>();
parameters.put("escalationCode", "anEscalationCode");
Map<String, Object> variables = VariablesBuilder
.create()
.variable("var1", "val1")
.variable("var2", "val2", "String")
.variable("var3", ValueType.OBJECT.getName(), "val3", "aFormat", "aRootType")
.getVariables();
parameters.put("variables", variables);

given()
.contentType(POST_JSON_CONTENT_TYPE)
.body(parameters)
.pathParam("id", "aTaskId")
.then()
.expect()
.statusCode(Status.NO_CONTENT.getStatusCode())
.when()
.post(HANDLE_BPMN_ESCALATION_URL);

verify(taskServiceMock).handleEscalation(
eq("aTaskId"),
eq("anEscalationCode"),
argThat(EqualsVariableMap.matches()
.matcher("var1", EqualsUntypedValue.matcher().value("val1"))
.matcher("var2", EqualsPrimitiveValue.stringValue("val2"))
.matcher("var3",
EqualsObjectValue.objectValueMatcher()
.type(ValueType.OBJECT)
.serializedValue("val3")
.serializationFormat("aFormat")
.objectTypeName("aRootType"))));
verifyNoMoreInteractions(taskServiceMock);
}

@Test
public void testHandleBpmnEscalationNonExistingTask() {
doThrow(new NullValueException())
.when(taskServiceMock)
.handleEscalation(anyString(), anyString(), anyMapOf(String.class, Object.class));

Map<String, Object> parameters = new HashMap<String, Object>();
parameters.put("escalationCode", "anEscalationCode");
given()
.contentType(POST_JSON_CONTENT_TYPE)
.body(parameters)
.pathParam("id", "aTaskId")
.then()
.expect()
.statusCode(Status.NOT_FOUND.getStatusCode())
.body("type", equalTo(RestException.class.getSimpleName()))
.body("message", equalTo("Task with id aTaskId does not exist"))
.when()
.post(HANDLE_BPMN_ESCALATION_URL);
}

@Test
public void testHandleBpmnEscalationThrowsAuthorizationException() {
doThrow(new AuthorizationException("aMessage"))
.when(taskServiceMock)
.handleEscalation(any(String.class), any(String.class),anyMapOf(String.class, Object.class));

Map<String, Object> parameters = new HashMap<String, Object>();
parameters.put("escalationCode", "escalationCode");

given()
.contentType(POST_JSON_CONTENT_TYPE)
.body(parameters)
.pathParam("id", "aTaskId")
.then()
.expect()
.statusCode(Status.FORBIDDEN.getStatusCode())
.body("type", equalTo(AuthorizationException.class.getSimpleName()))
.body("message", equalTo("aMessage"))
.when()
.post(HANDLE_BPMN_ESCALATION_URL);
}

@Test
public void testHandleBpmnEscalationThrowsBadUserRequestException() {
doThrow(new BadUserRequestException("aMessage"))
.when(taskServiceMock)
.handleEscalation(any(String.class), any(String.class), anyMapOf(String.class, Object.class));

Map<String, Object> parameters = new HashMap<String, Object>();
parameters.put("escalationCode", "escalationCode");

given()
.contentType(POST_JSON_CONTENT_TYPE)
.body(parameters)
.pathParam("id", "aTaskId")
.then()
.expect()
.statusCode(Status.BAD_REQUEST.getStatusCode())
.body("type", equalTo(RestException.class.getSimpleName()))
.body("message", equalTo("aMessage"))
.when()
.post(HANDLE_BPMN_ESCALATION_URL);
}

@SuppressWarnings({ "rawtypes", "unchecked" })
private void verifyTaskComments(List<Comment> mockTaskComments, Response response) {
List list = response.as(List.class);
Expand Down
36 changes: 35 additions & 1 deletion engine/src/main/java/org/camunda/bpm/engine/TaskService.java
Original file line number Diff line number Diff line change
Expand Up @@ -1152,7 +1152,7 @@ public interface TaskService {
TaskReport createTaskReport();

/**
* Signals that an business error appears, which should be handled by the process engine.
* Signals that a business error appears, which should be handled by the process engine.
*
* @param taskId the id of an existing active task
* @param errorCode the error code of the corresponding bmpn error
Expand Down Expand Up @@ -1185,4 +1185,38 @@ public interface TaskService {
* @param variables the variables to pass to the execution
*/
void handleBpmnError(String taskId, String errorCode, String errorMessage, Map<String, Object> variables);

/**
* Signals that an escalation appears, which should be handled by the process engine.
*
* @param taskId the id of an existing active task
* @param escalationCode the escalation code of the corresponding escalation
* @param variables the variables to pass to the execution
*
* @throws NullValueException if no task with the given id exists
* @throws SuspendedEntityInteractionException if the task is suspended
* @throws AuthorizationException if the user has none of the following permissions:
* <li>{@link Permissions#TASK_WORK} permission on {@link Resources#TASK} or
* {@link Resources#PROCESS_DEFINITION} resource</li>
* <li>{@link Permissions#UPDATE} permission on {@link Resources#TASK} resource</li>
* <li>{@link Permissions#UPDATE_TASK} permission on {@link Resources#PROCESS_DEFINITION} resource</li>
*/
void handleEscalation(String taskId, String escalationCode);

/**
* Signals that an escalation appears, which should be handled by the process engine.
*
* @param taskId the id of an existing active task
* @param escalationCode the escalation code of the corresponding escalation
* @param variables the variables to pass to the execution
*
* @throws NullValueException if no task with the given id exists
* @throws SuspendedEntityInteractionException if the task is suspended
* @throws AuthorizationException if the user has none of the following permissions:
* <li>{@link Permissions#TASK_WORK} permission on {@link Resources#TASK} or
* {@link Resources#PROCESS_DEFINITION} resource</li>
* <li>{@link Permissions#UPDATE} permission on {@link Resources#TASK} resource</li>
* <li>{@link Permissions#UPDATE_TASK} permission on {@link Resources#PROCESS_DEFINITION} resource</li>
*/
void handleEscalation(String taskId, String escalationCode, Map<String, Object> variables);
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
import org.camunda.bpm.engine.impl.cmd.GetTaskVariableCmdTyped;
import org.camunda.bpm.engine.impl.cmd.GetTaskVariablesCmd;
import org.camunda.bpm.engine.impl.cmd.HandleTaskBpmnErrorCmd;
import org.camunda.bpm.engine.impl.cmd.HandleTaskEscalationCmd;
import org.camunda.bpm.engine.impl.cmd.PatchTaskVariablesCmd;
import org.camunda.bpm.engine.impl.cmd.RemoveTaskVariablesCmd;
import org.camunda.bpm.engine.impl.cmd.ResolveTaskCmd;
Expand Down Expand Up @@ -437,4 +438,14 @@ public void handleBpmnError(String taskId, String errorCode, String errorMessage
public void handleBpmnError(String taskId, String errorCode, String errorMessage, Map<String, Object> variables) {
commandExecutor.execute(new HandleTaskBpmnErrorCmd(taskId, errorCode, errorMessage, variables));
}

@Override
public void handleEscalation(String taskId, String escalationCode) {
commandExecutor.execute(new HandleTaskEscalationCmd(taskId, escalationCode));
}

@Override
public void handleEscalation(String taskId, String escalationCode, Map<String, Object> variables) {
commandExecutor.execute(new HandleTaskEscalationCmd(taskId, escalationCode, variables));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -271,4 +271,14 @@ public ProcessEngineException missingBoundaryCatchEventError(String executionId,
errorCode));
}


public ProcessEngineException missingBoundaryCatchEventEscalation(String executionId, String escalationCode) {
return new ProcessEngineException(
exceptionMessage(
"043",
"Execution with id '{}' throws an escalation event with escalationCode '{}', but no escalation handler was defined. ",
executionId,
escalationCode));
}

}
Loading

0 comments on commit 445f723

Please sign in to comment.