diff --git a/lib/taskana-core/src/main/java/pro/taskana/TaskService.java b/lib/taskana-core/src/main/java/pro/taskana/TaskService.java index 944c091d8..b68979ef0 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/TaskService.java +++ b/lib/taskana-core/src/main/java/pro/taskana/TaskService.java @@ -289,4 +289,39 @@ public interface TaskService { */ BulkOperationResults transferBulk(String destinationWorkbasketKey, List taskIds) throws NotAuthorizedException, InvalidArgumentException, WorkbasketNotFoundException; + + /** + * Deletes the task with the given Id. + * + * @param taskId + * The Id of the task to delete. + * @throws TaskNotFoundException + * If the given Id does not refer to an existing task. + * @throws InvalidStateException + * If the state of the referenced task is not Completed. + */ + void deleteTask(String taskId) throws TaskNotFoundException, InvalidStateException; + + /** + * Deletes the task with the given Id. + * + * @param taskId + * The Id of the task to delete. + * @param forceDelete + * force the deletion. If true, a task is deleted even if it is not in state completed. + * @throws TaskNotFoundException + * If the given Id does not refer to an existing task. + * @throws InvalidStateException + * If the state of the referenced task is not Completed and forceDelet is false. + */ + void deleteTask(String taskId, boolean forceDelete) throws TaskNotFoundException, InvalidStateException; + + /** + * Deletes a list of tasks. + * + * @param tasks + * the ids of the tasks to delete. + * @return the result of the operations with Id and Exception for each failed task deletion. + */ + BulkOperationResults deleteTasks(List tasks); } diff --git a/lib/taskana-core/src/main/java/pro/taskana/impl/BulkOperationResults.java b/lib/taskana-core/src/main/java/pro/taskana/impl/BulkOperationResults.java index f84349c6e..47d8143d8 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/impl/BulkOperationResults.java +++ b/lib/taskana-core/src/main/java/pro/taskana/impl/BulkOperationResults.java @@ -1,8 +1,9 @@ package pro.taskana.impl; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; -import java.util.Optional; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -17,7 +18,7 @@ import org.slf4j.LoggerFactory; */ public class BulkOperationResults { - private Optional> errorMap = Optional.of(new HashMap()); + private Map errorMap = new HashMap(); private static final Logger LOGGER = LoggerFactory.getLogger(BulkOperationResults.class); /** @@ -26,7 +27,7 @@ public class BulkOperationResults { * @return map of errors which can“t be null. */ public Map getErrorMap() { - return this.errorMap.get(); + return this.errorMap; } /** @@ -42,7 +43,7 @@ public class BulkOperationResults { boolean status = false; try { if (objectId != null) { - this.errorMap.get().put(objectId, error); + this.errorMap.put(objectId, error); status = true; } } catch (Exception e) { @@ -58,9 +59,9 @@ public class BulkOperationResults { * * @return true if there are logged errors. */ - public boolean containErrors() { + public boolean containsErrors() { boolean isContainingErrors = false; - if (!this.errorMap.get().isEmpty()) { + if (!this.errorMap.isEmpty()) { isContainingErrors = true; } return isContainingErrors; @@ -76,15 +77,24 @@ public class BulkOperationResults { public V getErrorForId(K idKey) { V result = null; if (idKey != null) { - result = this.errorMap.get().get(idKey); + result = this.errorMap.get(idKey); } return result; } + /** + * Returns the IDs of the Object with failed requests. + * + * @return a List of IDs that could not be processed successfully. + */ + public List getFailedIds() { + return new ArrayList<>(this.errorMap.keySet()); + } + /** * Clearing the map - all entries will be removed. */ public void clearErrors() { - this.errorMap.get().clear(); + this.errorMap.clear(); } } diff --git a/lib/taskana-core/src/main/java/pro/taskana/impl/MinimalTaskSummary.java b/lib/taskana-core/src/main/java/pro/taskana/impl/MinimalTaskSummary.java new file mode 100644 index 000000000..857ee06a1 --- /dev/null +++ b/lib/taskana-core/src/main/java/pro/taskana/impl/MinimalTaskSummary.java @@ -0,0 +1,38 @@ +package pro.taskana.impl; + +import pro.taskana.model.TaskState; + +/** + * A convenience class to represent pairs of task id and task state. + */ +public class MinimalTaskSummary { + + private String taskId; + private String workbasketKey; + private TaskState taskState; + + public String getTaskId() { + return taskId; + } + + public void setTaskId(String taskId) { + this.taskId = taskId; + } + + public String getWorkbasketKey() { + return workbasketKey; + } + + public void setWorkbasketKey(String workbasketKey) { + this.workbasketKey = workbasketKey; + } + + public TaskState getTaskState() { + return taskState; + } + + public void setTaskState(TaskState taskState) { + this.taskState = taskState; + } + +} diff --git a/lib/taskana-core/src/main/java/pro/taskana/impl/TaskServiceImpl.java b/lib/taskana-core/src/main/java/pro/taskana/impl/TaskServiceImpl.java index 276162745..c1fcdab56 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/impl/TaskServiceImpl.java +++ b/lib/taskana-core/src/main/java/pro/taskana/impl/TaskServiceImpl.java @@ -338,8 +338,8 @@ public class TaskServiceImpl implements TaskService { Workbasket destinationWorkbasket = workbasketService.getWorkbasketByKey(destinationWorkbasketKey); BulkOperationResults bulkLog = new BulkOperationResults<>(); - // check tasks exist and Ids valid - log and remove - List taskSummaries = this.createTaskQuery().idIn(taskIds.toArray(new String[0])).list(); + + // check tasks Ids exist and not empty - log and remove Iterator taskIdIterator = taskIds.iterator(); while (taskIdIterator.hasNext()) { String currentTaskId = taskIdIterator.next(); @@ -347,18 +347,16 @@ public class TaskServiceImpl implements TaskService { bulkLog.addError("", new InvalidArgumentException("IDs with EMPTY or NULL value are not allowed.")); taskIdIterator.remove(); - } else if (!taskSummaries.stream() - .filter(taskSummary -> currentTaskId.equals(taskSummary.getTaskId())) - .findFirst() - .isPresent()) { - bulkLog.addError(currentTaskId, new TaskNotFoundException(currentTaskId)); - taskIdIterator.remove(); } } + // query for existing tasks. use taskMapper.findExistingTasks because this method + // returns only the required information. + List taskSummaries = taskMapper.findExistingTasks(taskIds); + // check source WB (read)+transfer Set workbasketKeys = new HashSet<>(); - taskSummaries.stream().forEach(t -> workbasketKeys.add(t.getWorkbasketSummary().getKey())); + taskSummaries.stream().forEach(t -> workbasketKeys.add(t.getWorkbasketKey())); List sourceWorkbaskets = workbasketService.createWorkbasketQuery() .callerHasPermission(WorkbasketAuthorization.TRANSFER) .keyIn(workbasketKeys.toArray(new String[0])) @@ -366,20 +364,19 @@ public class TaskServiceImpl implements TaskService { taskIdIterator = taskIds.iterator(); while (taskIdIterator.hasNext()) { String currentTaskId = taskIdIterator.next(); - TaskSummary taskSummary = taskSummaries.stream() + MinimalTaskSummary taskSummary = taskSummaries.stream() .filter(t -> currentTaskId.equals(t.getTaskId())) .findFirst() .orElse(null); - if (taskSummaries != null) { - if (!sourceWorkbaskets.stream() - .filter(wb -> taskSummary.getWorkbasketSummary().getKey().equals(wb.getKey())) - .findFirst() - .isPresent()) { - bulkLog.addError(currentTaskId, - new NotAuthorizedException( - "The workbasket of this task got not TRANSFER permissions. TaskId=" + currentTaskId)); - taskIdIterator.remove(); - } + if (taskSummary == null) { + bulkLog.addError(currentTaskId, new TaskNotFoundException(currentTaskId)); + taskIdIterator.remove(); + } else if (!sourceWorkbaskets.stream() + .anyMatch(wb -> taskSummary.getWorkbasketKey().equals(wb.getKey()))) { + bulkLog.addError(currentTaskId, + new NotAuthorizedException( + "The workbasket of this task got not TRANSFER permissions. TaskId=" + currentTaskId)); + taskIdIterator.remove(); } } @@ -388,19 +385,15 @@ public class TaskServiceImpl implements TaskService { Collectors.toList()); if (!taskSummaries.isEmpty()) { Instant now = Instant.now(); - List updateObjects = new ArrayList<>(); - for (TaskSummary ts : taskSummaries) { - TaskSummaryImpl taskSummary = (TaskSummaryImpl) ts; - taskSummary.setRead(false); - taskSummary.setTransferred(true); - taskSummary.setWorkbasketSummary(destinationWorkbasket.asSummary()); - taskSummary.setDomain(destinationWorkbasket.getDomain()); - taskSummary.setModified(now); - taskSummary.setState(TaskState.READY); - taskSummary.setOwner(null); - updateObjects.add(taskSummary); - } - taskMapper.updateTransfered(taskIds, updateObjects.get(0)); + TaskSummaryImpl updateObject = new TaskSummaryImpl(); + updateObject.setRead(false); + updateObject.setTransferred(true); + updateObject.setWorkbasketSummary(destinationWorkbasket.asSummary()); + updateObject.setDomain(destinationWorkbasket.getDomain()); + updateObject.setModified(now); + updateObject.setState(TaskState.READY); + updateObject.setOwner(null); + taskMapper.updateTransfered(taskIds, updateObject); } return bulkLog; } finally { @@ -815,6 +808,76 @@ public class TaskServiceImpl implements TaskService { return new AttachmentImpl(); } + @Override + public void deleteTask(String taskId) throws TaskNotFoundException, InvalidStateException { + deleteTask(taskId, false); + } + + @Override + public void deleteTask(String taskId, boolean forceDelete) throws TaskNotFoundException, InvalidStateException { + LOGGER.debug("entry to deleteTask(taskId = {} , forceDelete = {} )", taskId, forceDelete); + TaskImpl task = null; + try { + taskanaEngineImpl.openConnection(); + task = (TaskImpl) getTask(taskId); + + // reset read flag and set transferred flag + if (!TaskState.COMPLETED.equals(task.getState()) && !forceDelete) { + LOGGER.warn( + "Method deleteTask() found that task {} is not completed and forceDelete is false. Throwing InvalidStateException", + task); + throw new InvalidStateException("Cannot delete Task " + taskId + " because it is not completed"); + } + taskMapper.delete(taskId); + LOGGER.debug("Method deleteTask() deleted Task {}", taskId); + } finally { + taskanaEngineImpl.returnConnection(); + LOGGER.debug("exit from deleteTask(). "); + } + } + + @Override + public BulkOperationResults deleteTasks(List taskIds) { + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("entry to deleteTasks(tasks = {})", LoggerUtils.listToString(taskIds)); + } + try { + taskanaEngineImpl.openConnection(); + BulkOperationResults bulkLog = new BulkOperationResults<>(); + + List taskSummaries = taskMapper.findExistingTasks(taskIds); + + Iterator taskIdIterator = taskIds.iterator(); + while (taskIdIterator.hasNext()) { + String currentTaskId = taskIdIterator.next(); + if (currentTaskId == null || currentTaskId.equals("")) { + bulkLog.addError("", + new InvalidArgumentException("IDs with EMPTY or NULL value are not allowed.")); + taskIdIterator.remove(); + } else { + MinimalTaskSummary foundSummary = taskSummaries.stream() + .filter(taskState -> currentTaskId.equals(taskState.getTaskId())) + .findFirst() + .orElse(null); + if (foundSummary == null) { + bulkLog.addError(currentTaskId, new TaskNotFoundException(currentTaskId)); + taskIdIterator.remove(); + } else { + if (!TaskState.COMPLETED.equals(foundSummary.getTaskState())) { + bulkLog.addError(currentTaskId, new InvalidStateException(currentTaskId)); + taskIdIterator.remove(); + } + } + } + } + taskMapper.deleteMultiple(taskIds); + return bulkLog; + } finally { + LOGGER.debug("exit from deleteTasks()"); + taskanaEngineImpl.returnConnection(); + } + } + private void validateObjectReference(ObjectReference objRef, String objRefType, String objName) throws InvalidArgumentException { // check that all values in the ObjectReference are set correctly @@ -1007,4 +1070,5 @@ public class TaskServiceImpl implements TaskService { attachment.setTaskId(newTask.getId()); } } + } diff --git a/lib/taskana-core/src/main/java/pro/taskana/model/mappings/TaskMapper.java b/lib/taskana-core/src/main/java/pro/taskana/model/mappings/TaskMapper.java index 2cd6d7351..6928ca3a1 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/model/mappings/TaskMapper.java +++ b/lib/taskana-core/src/main/java/pro/taskana/model/mappings/TaskMapper.java @@ -14,6 +14,7 @@ import org.apache.ibatis.annotations.Select; import org.apache.ibatis.annotations.Update; import org.apache.ibatis.type.JdbcType; +import pro.taskana.impl.MinimalTaskSummary; import pro.taskana.impl.TaskImpl; import pro.taskana.impl.TaskSummaryImpl; import pro.taskana.impl.WorkbasketSummaryImpl; @@ -89,6 +90,9 @@ public interface TaskMapper { @Delete("DELETE FROM TASK WHERE ID = #{id}") void delete(String id); + @Delete("") + void deleteMultiple(@Param("ids") List ids); + @Select("SELECT ID, CREATED, CLAIMED, COMPLETED, MODIFIED, PLANNED, DUE, NAME, DESCRIPTION, PRIORITY, STATE, CLASSIFICATION_KEY, WORKBASKET_KEY, DOMAIN, BUSINESS_PROCESS_ID, PARENT_BUSINESS_PROCESS_ID, OWNER, POR_COMPANY, POR_SYSTEM, POR_INSTANCE, POR_TYPE, POR_VALUE, IS_READ, IS_TRANSFERRED, CUSTOM_ATTRIBUTES, CUSTOM_1, CUSTOM_2, CUSTOM_3, CUSTOM_4, CUSTOM_5, CUSTOM_6, CUSTOM_7, CUSTOM_8, CUSTOM_9, CUSTOM_10 " + "FROM TASK " + "WHERE WORKBASKET_KEY = #{workbasketKey} " @@ -178,4 +182,14 @@ public interface TaskMapper { + "") void updateTransfered(@Param("taskIds") List taskIds, @Param("referencetask") TaskSummaryImpl referencetask); + + @Select("") + @Results(value = { + @Result(property = "taskId", column = "ID"), + @Result(property = "workbasketKey", column = "WORKBASKET_KEY"), + @Result(property = "taskState", column = "STATE")}) + List findExistingTasks(@Param("taskIds") List taskIds); + } diff --git a/lib/taskana-core/src/test/java/acceptance/task/DeleteTaskAccTest.java b/lib/taskana-core/src/test/java/acceptance/task/DeleteTaskAccTest.java index 9aa05c8bc..28e61c73d 100644 --- a/lib/taskana-core/src/test/java/acceptance/task/DeleteTaskAccTest.java +++ b/lib/taskana-core/src/test/java/acceptance/task/DeleteTaskAccTest.java @@ -1,27 +1,25 @@ package acceptance.task; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + import java.sql.SQLException; import java.util.ArrayList; +import java.util.List; import org.h2.store.fs.FileUtils; import org.junit.AfterClass; -import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import acceptance.AbstractAccTest; import pro.taskana.Task; import pro.taskana.TaskService; -import pro.taskana.exceptions.AttachmentPersistenceException; -import pro.taskana.exceptions.ClassificationNotFoundException; -import pro.taskana.exceptions.ConcurrencyException; -import pro.taskana.exceptions.InvalidArgumentException; import pro.taskana.exceptions.InvalidStateException; -import pro.taskana.exceptions.InvalidWorkbasketException; -import pro.taskana.exceptions.NotAuthorizedException; -import pro.taskana.exceptions.TaskAlreadyExistException; import pro.taskana.exceptions.TaskNotFoundException; -import pro.taskana.exceptions.WorkbasketNotFoundException; +import pro.taskana.exceptions.TaskanaException; +import pro.taskana.impl.BulkOperationResults; import pro.taskana.security.JAASRunner; import pro.taskana.security.WithAccessId; @@ -35,88 +33,71 @@ public class DeleteTaskAccTest extends AbstractAccTest { super(); } - @Ignore @WithAccessId( userName = "user_1_2", groupNames = {"group_1"}) @Test(expected = TaskNotFoundException.class) - public void testDeleteSingleTask() - throws SQLException, NotAuthorizedException, InvalidArgumentException, ClassificationNotFoundException, - WorkbasketNotFoundException, TaskAlreadyExistException, InvalidWorkbasketException, TaskNotFoundException, - ConcurrencyException, AttachmentPersistenceException { + public void testDeleteSingleTask() throws TaskNotFoundException, InvalidStateException { TaskService taskService = taskanaEngine.getTaskService(); Task task = taskService.getTask("TKI:000000000000000000000000000000000036"); - // taskService.deleteTask(task.getId()); + taskService.deleteTask(task.getId()); - Task deletedTask = taskService.getTask("TKI:000000000000000000000000000000000036"); + taskService.getTask("TKI:000000000000000000000000000000000036"); } - @Ignore @WithAccessId( userName = "user_1_2", groupNames = {"group_1"}) @Test(expected = InvalidStateException.class) public void testThrowsExceptionIfTaskIsNotCompleted() - throws SQLException, NotAuthorizedException, InvalidArgumentException, ClassificationNotFoundException, - WorkbasketNotFoundException, TaskAlreadyExistException, InvalidWorkbasketException, TaskNotFoundException, - ConcurrencyException, AttachmentPersistenceException { - + throws TaskNotFoundException, InvalidStateException, SQLException { TaskService taskService = taskanaEngine.getTaskService(); - Task task = taskService.getTask("TKI:000000000000000000000000000000000027"); + Task task = taskService.getTask("TKI:000000000000000000000000000000000029"); - // taskService.deleteTask(task.getId()); + taskService.deleteTask(task.getId()); } - @Ignore @WithAccessId( userName = "user_1_2", groupNames = {"group_1"}) @Test(expected = TaskNotFoundException.class) - public void testForceDeleteTaskIfNotCompleted() - throws SQLException, NotAuthorizedException, InvalidArgumentException, ClassificationNotFoundException, - WorkbasketNotFoundException, TaskAlreadyExistException, InvalidWorkbasketException, TaskNotFoundException, - ConcurrencyException, AttachmentPersistenceException { - + public void testForceDeleteTaskIfNotCompleted() throws SQLException, TaskNotFoundException, InvalidStateException { TaskService taskService = taskanaEngine.getTaskService(); Task task = taskService.getTask("TKI:000000000000000000000000000000000027"); + try { + taskService.deleteTask(task.getId()); + fail("Should not be possible to delete claimed task without force flag"); + } catch (InvalidStateException ex) { + taskService.deleteTask(task.getId(), true); + } - // taskService.deleteTask(task.getId(), true); - - Task deletedTask = taskService.getTask("TKI:000000000000000000000000000000000036"); + taskService.getTask("TKI:000000000000000000000000000000000027"); } - @Ignore @WithAccessId( userName = "user_1_2", groupNames = {"group_1"}) @Test(expected = TaskNotFoundException.class) - public void testBulkDeleteTask() - throws SQLException, NotAuthorizedException, InvalidArgumentException, ClassificationNotFoundException, - WorkbasketNotFoundException, TaskAlreadyExistException, InvalidWorkbasketException, TaskNotFoundException, - ConcurrencyException, AttachmentPersistenceException { + public void testBulkDeleteTask() throws TaskNotFoundException { TaskService taskService = taskanaEngine.getTaskService(); ArrayList taskIdList = new ArrayList<>(); taskIdList.add("TKI:000000000000000000000000000000000037"); taskIdList.add("TKI:000000000000000000000000000000000038"); - // BulkOperationResults results = taskService.deleteTasks(taskIdList); + BulkOperationResults results = taskService.deleteTasks(taskIdList); - // assertFalse(results.containsError()); - Task deletedTask = taskService.getTask("TKI:000000000000000000000000000000000038"); + assertFalse(results.containsErrors()); + taskService.getTask("TKI:000000000000000000000000000000000038"); } - @Ignore @WithAccessId( userName = "user_1_2", groupNames = {"group_1"}) @Test(expected = TaskNotFoundException.class) - public void testBulkDeleteTasksWithException() - throws SQLException, NotAuthorizedException, InvalidArgumentException, ClassificationNotFoundException, - WorkbasketNotFoundException, TaskAlreadyExistException, InvalidWorkbasketException, TaskNotFoundException, - ConcurrencyException, AttachmentPersistenceException { + public void testBulkDeleteTasksWithException() throws TaskNotFoundException { TaskService taskService = taskanaEngine.getTaskService(); ArrayList taskIdList = new ArrayList<>(); @@ -124,12 +105,19 @@ public class DeleteTaskAccTest extends AbstractAccTest { taskIdList.add("TKI:000000000000000000000000000000000040"); taskIdList.add("TKI:000000000000000000000000000000000028"); - // BulkOperationResults results = taskService.deleteTasks(taskIdList); + BulkOperationResults results = taskService.deleteTasks(taskIdList); + + String expectedFailedId = "TKI:000000000000000000000000000000000028"; + assertTrue(results.containsErrors()); + List failedTaskIds = results.getFailedIds(); + assertTrue(failedTaskIds.size() == 1); + assertTrue(expectedFailedId.equals(failedTaskIds.get(0))); + assertTrue(results.getErrorMap().get(expectedFailedId).getClass() == InvalidStateException.class); - // assertTrue(results.containsError()); - // more assertions ... Task notDeletedTask = taskService.getTask("TKI:000000000000000000000000000000000028"); - Task deletedTask = taskService.getTask("TKI:000000000000000000000000000000000040"); + assertTrue(notDeletedTask != null); + taskService.getTask("TKI:000000000000000000000000000000000040"); + } @AfterClass diff --git a/lib/taskana-core/src/test/java/acceptance/task/TransferTaskAccTest.java b/lib/taskana-core/src/test/java/acceptance/task/TransferTaskAccTest.java index 7fcdd842b..ccb9de12b 100644 --- a/lib/taskana-core/src/test/java/acceptance/task/TransferTaskAccTest.java +++ b/lib/taskana-core/src/test/java/acceptance/task/TransferTaskAccTest.java @@ -127,7 +127,7 @@ public class TransferTaskAccTest extends AbstractAccTest { taskIdList.add("TKI:000000000000000000000000000000000005"); BulkOperationResults results = taskService.transferBulk("USER_1_1", taskIdList); - assertFalse(results.containErrors()); + assertFalse(results.containsErrors()); Workbasket wb = taskanaEngine.getWorkbasketService().getWorkbasketByKey("USER_1_1"); Task transferredTask = taskService.getTask("TKI:000000000000000000000000000000000004"); @@ -137,7 +137,7 @@ public class TransferTaskAccTest extends AbstractAccTest { assertEquals(TaskState.READY, transferredTask.getState()); assertThat(transferredTask.getWorkbasketKey(), equalTo(wb.getKey())); assertThat(transferredTask.getDomain(), equalTo(wb.getDomain())); - assertTrue(transferredTask.getModified().isAfter(before)); + assertFalse(transferredTask.getModified().isBefore(before)); assertThat(transferredTask.getOwner(), equalTo(null)); transferredTask = taskService.getTask("TKI:000000000000000000000000000000000005"); assertNotNull(transferredTask); @@ -146,7 +146,7 @@ public class TransferTaskAccTest extends AbstractAccTest { assertEquals(TaskState.READY, transferredTask.getState()); assertThat(transferredTask.getWorkbasketKey(), equalTo(wb.getKey())); assertThat(transferredTask.getDomain(), equalTo(wb.getDomain())); - assertTrue(transferredTask.getModified().isAfter(before)); + assertFalse(transferredTask.getModified().isBefore(before)); assertThat(transferredTask.getOwner(), equalTo(null)); } @@ -167,7 +167,7 @@ public class TransferTaskAccTest extends AbstractAccTest { taskIdList.add("TKI:000000000000000000000000000000000099"); // TaskNotFound BulkOperationResults results = taskService.transferBulk("USER_1_1", taskIdList); - assertTrue(results.containErrors()); + assertTrue(results.containsErrors()); assertThat(results.getErrorMap().values().size(), equalTo(3)); // react to result for (String taskId : results.getErrorMap().keySet()) { @@ -189,7 +189,7 @@ public class TransferTaskAccTest extends AbstractAccTest { assertEquals(TaskState.READY, transferredTask.getState()); assertThat(transferredTask.getWorkbasketKey(), equalTo(wb.getKey())); assertThat(transferredTask.getDomain(), equalTo(wb.getDomain())); - assertTrue(transferredTask.getModified().isAfter(before)); + assertFalse(transferredTask.getModified().isBefore(before)); assertThat(transferredTask.getOwner(), equalTo(null)); transferredTask = taskService.getTask("TKI:000000000000000000000000000000000002");