TSK-1938: Add RequestChangesProvider
This commit is contained in:
parent
1f9d20f76f
commit
340236c4a2
|
|
@ -0,0 +1,271 @@
|
||||||
|
package acceptance.task.requestchanges;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
|
||||||
|
import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy;
|
||||||
|
import static pro.taskana.common.internal.util.CheckedSupplier.wrap;
|
||||||
|
import static pro.taskana.testapi.DefaultTestEntities.defaultTestClassification;
|
||||||
|
import static pro.taskana.testapi.DefaultTestEntities.defaultTestWorkbasket;
|
||||||
|
|
||||||
|
import org.assertj.core.api.ThrowableAssert.ThrowingCallable;
|
||||||
|
import org.junit.jupiter.api.BeforeAll;
|
||||||
|
import org.junit.jupiter.api.Nested;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.TestInstance;
|
||||||
|
import org.junit.jupiter.api.TestInstance.Lifecycle;
|
||||||
|
|
||||||
|
import pro.taskana.TaskanaEngineConfiguration;
|
||||||
|
import pro.taskana.classification.api.ClassificationService;
|
||||||
|
import pro.taskana.classification.api.models.Classification;
|
||||||
|
import pro.taskana.classification.api.models.ClassificationSummary;
|
||||||
|
import pro.taskana.common.api.TaskanaEngine;
|
||||||
|
import pro.taskana.common.api.exceptions.SystemException;
|
||||||
|
import pro.taskana.common.internal.jobs.PlainJavaTransactionProvider;
|
||||||
|
import pro.taskana.spi.task.api.AfterRequestChangesProvider;
|
||||||
|
import pro.taskana.task.api.TaskCustomField;
|
||||||
|
import pro.taskana.task.api.TaskService;
|
||||||
|
import pro.taskana.task.api.TaskState;
|
||||||
|
import pro.taskana.task.api.models.ObjectReference;
|
||||||
|
import pro.taskana.task.api.models.Task;
|
||||||
|
import pro.taskana.testapi.DefaultTestEntities;
|
||||||
|
import pro.taskana.testapi.TaskanaInject;
|
||||||
|
import pro.taskana.testapi.TaskanaIntegrationTest;
|
||||||
|
import pro.taskana.testapi.WithServiceProvider;
|
||||||
|
import pro.taskana.testapi.builder.TaskBuilder;
|
||||||
|
import pro.taskana.testapi.builder.WorkbasketAccessItemBuilder;
|
||||||
|
import pro.taskana.testapi.security.WithAccessId;
|
||||||
|
import pro.taskana.workbasket.api.WorkbasketPermission;
|
||||||
|
import pro.taskana.workbasket.api.WorkbasketService;
|
||||||
|
import pro.taskana.workbasket.api.models.WorkbasketSummary;
|
||||||
|
|
||||||
|
@TaskanaIntegrationTest
|
||||||
|
public class RequestChangesWithSpiAccTest {
|
||||||
|
|
||||||
|
private static final String NEW_WORKBASKET_KEY = "W1000";
|
||||||
|
ClassificationSummary defaultClassificationSummary;
|
||||||
|
WorkbasketSummary defaultWorkbasketSummary;
|
||||||
|
ObjectReference defaultObjectReference;
|
||||||
|
|
||||||
|
WorkbasketSummary newWorkbasket;
|
||||||
|
|
||||||
|
@WithAccessId(user = "businessadmin")
|
||||||
|
@BeforeAll
|
||||||
|
void setup(ClassificationService classificationService, WorkbasketService workbasketService)
|
||||||
|
throws Exception {
|
||||||
|
defaultClassificationSummary =
|
||||||
|
defaultTestClassification().buildAndStoreAsSummary(classificationService);
|
||||||
|
defaultWorkbasketSummary = defaultTestWorkbasket().buildAndStoreAsSummary(workbasketService);
|
||||||
|
newWorkbasket =
|
||||||
|
defaultTestWorkbasket().key(NEW_WORKBASKET_KEY).buildAndStoreAsSummary(workbasketService);
|
||||||
|
|
||||||
|
WorkbasketAccessItemBuilder.newWorkbasketAccessItem()
|
||||||
|
.workbasketId(defaultWorkbasketSummary.getId())
|
||||||
|
.accessId("user-1-1")
|
||||||
|
.permission(WorkbasketPermission.READ)
|
||||||
|
.permission(WorkbasketPermission.APPEND)
|
||||||
|
.permission(WorkbasketPermission.TRANSFER)
|
||||||
|
.buildAndStore(workbasketService);
|
||||||
|
|
||||||
|
WorkbasketAccessItemBuilder.newWorkbasketAccessItem()
|
||||||
|
.workbasketId(newWorkbasket.getId())
|
||||||
|
.accessId("user-1-1")
|
||||||
|
.permission(WorkbasketPermission.READ)
|
||||||
|
.permission(WorkbasketPermission.APPEND)
|
||||||
|
.buildAndStore(workbasketService);
|
||||||
|
|
||||||
|
defaultObjectReference = DefaultTestEntities.defaultTestObjectReference().build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private TaskBuilder createTaskInReviewByUser(String owner) {
|
||||||
|
return createDefaultTask().owner(owner).state(TaskState.IN_REVIEW);
|
||||||
|
}
|
||||||
|
|
||||||
|
private TaskBuilder createDefaultTask() {
|
||||||
|
return TaskBuilder.newTask()
|
||||||
|
.classificationSummary(defaultClassificationSummary)
|
||||||
|
.workbasketSummary(defaultWorkbasketSummary)
|
||||||
|
.primaryObjRef(defaultObjectReference);
|
||||||
|
}
|
||||||
|
|
||||||
|
static class ExceptionThrower implements AfterRequestChangesProvider {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize(TaskanaEngine taskanaEngine) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Task afterRequestChanges(Task task) {
|
||||||
|
throw new SystemException("I AM THE EXCEPTION THROWER (*_*)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class TaskModifierAndTransferrer implements AfterRequestChangesProvider {
|
||||||
|
private static final String NEW_CUSTOM_3_VALUE = "bla";
|
||||||
|
|
||||||
|
private TaskanaEngine taskanaEngine;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize(TaskanaEngine taskanaEngine) {
|
||||||
|
this.taskanaEngine = taskanaEngine;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Task afterRequestChanges(Task task) throws Exception {
|
||||||
|
task.setCustomField(TaskCustomField.CUSTOM_3, NEW_CUSTOM_3_VALUE);
|
||||||
|
task = taskanaEngine.getTaskService().updateTask(task);
|
||||||
|
task = taskanaEngine.getTaskService().transfer(task.getId(), NEW_WORKBASKET_KEY, "DOMAIN_A");
|
||||||
|
return task;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class ClassificationUpdater implements AfterRequestChangesProvider {
|
||||||
|
|
||||||
|
public static final String SPI_CLASSIFICATION_NAME = "Neuer Classification Name";
|
||||||
|
|
||||||
|
private TaskanaEngine taskanaEngine;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize(TaskanaEngine taskanaEngine) {
|
||||||
|
this.taskanaEngine = taskanaEngine;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Task afterRequestChanges(Task task) throws Exception {
|
||||||
|
Classification newClassification =
|
||||||
|
defaultTestClassification().buildAndStore(taskanaEngine.getClassificationService());
|
||||||
|
|
||||||
|
task.setClassificationKey(newClassification.getKey());
|
||||||
|
task = taskanaEngine.getTaskService().updateTask(task);
|
||||||
|
|
||||||
|
newClassification.setName(SPI_CLASSIFICATION_NAME);
|
||||||
|
taskanaEngine.getClassificationService().updateClassification(newClassification);
|
||||||
|
|
||||||
|
return task;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@TestInstance(Lifecycle.PER_CLASS)
|
||||||
|
@WithServiceProvider(
|
||||||
|
serviceProviderInterface = AfterRequestChangesProvider.class,
|
||||||
|
serviceProviders = TaskModifierAndTransferrer.class)
|
||||||
|
class SpiModifiesTask {
|
||||||
|
|
||||||
|
@TaskanaInject TaskService taskService;
|
||||||
|
|
||||||
|
@WithAccessId(user = "user-1-1")
|
||||||
|
@Test
|
||||||
|
void should_ReturnModifiedTask_When_SpiModifiesAndTransfersTask() throws Exception {
|
||||||
|
Task task = createTaskInReviewByUser("user-1-1").buildAndStore(taskService);
|
||||||
|
|
||||||
|
Task result = taskService.requestChanges(task.getId());
|
||||||
|
|
||||||
|
assertThat(result.getCustomField(TaskCustomField.CUSTOM_3))
|
||||||
|
.isEqualTo(TaskModifierAndTransferrer.NEW_CUSTOM_3_VALUE);
|
||||||
|
assertThat(result.getWorkbasketSummary()).isEqualTo(newWorkbasket);
|
||||||
|
}
|
||||||
|
|
||||||
|
@WithAccessId(user = "user-1-1")
|
||||||
|
@Test
|
||||||
|
void should_ReturnPersistentModifiedTask_When_SpiModifiesAndTransfersTask() throws Exception {
|
||||||
|
Task task = createTaskInReviewByUser("user-1-1").buildAndStore(taskService);
|
||||||
|
|
||||||
|
taskService.requestChanges(task.getId());
|
||||||
|
Task result = taskService.getTask(task.getId());
|
||||||
|
|
||||||
|
assertThat(result.getCustomField(TaskCustomField.CUSTOM_3))
|
||||||
|
.isEqualTo(TaskModifierAndTransferrer.NEW_CUSTOM_3_VALUE);
|
||||||
|
assertThat(result.getWorkbasketSummary()).isEqualTo(newWorkbasket);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@TestInstance(Lifecycle.PER_CLASS)
|
||||||
|
@WithServiceProvider(
|
||||||
|
serviceProviderInterface = AfterRequestChangesProvider.class,
|
||||||
|
serviceProviders = ClassificationUpdater.class)
|
||||||
|
class SpiModifiesTaskAndClassification {
|
||||||
|
|
||||||
|
@TaskanaInject TaskService taskService;
|
||||||
|
|
||||||
|
@WithAccessId(user = "user-1-1", groups = "businessadmin")
|
||||||
|
@Test
|
||||||
|
void should_ChangeMultipleEntities_When_SpiModifiesMoreThanTheTask() throws Exception {
|
||||||
|
Task task = createTaskInReviewByUser("user-1-1").buildAndStore(taskService);
|
||||||
|
|
||||||
|
taskService.requestChanges(task.getId());
|
||||||
|
Task result = taskService.getTask(task.getId());
|
||||||
|
|
||||||
|
assertThat(result.getClassificationSummary().getId())
|
||||||
|
.isNotEqualTo(task.getClassificationSummary().getId());
|
||||||
|
assertThat(result.getClassificationSummary().getName())
|
||||||
|
.isEqualTo(ClassificationUpdater.SPI_CLASSIFICATION_NAME);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@TestInstance(Lifecycle.PER_CLASS)
|
||||||
|
@WithServiceProvider(
|
||||||
|
serviceProviderInterface = AfterRequestChangesProvider.class,
|
||||||
|
serviceProviders = {TaskModifierAndTransferrer.class, ClassificationUpdater.class})
|
||||||
|
class MultipleSpisAreDefined {
|
||||||
|
|
||||||
|
@TaskanaInject TaskService taskService;
|
||||||
|
|
||||||
|
@WithAccessId(user = "user-1-1", groups = "businessadmin")
|
||||||
|
@Test
|
||||||
|
void should_ApplyMultipleChanges_When_MultipleSpisAreChained() throws Exception {
|
||||||
|
Task task = createTaskInReviewByUser("user-1-1").buildAndStore(taskService);
|
||||||
|
|
||||||
|
taskService.requestChanges(task.getId());
|
||||||
|
Task result = taskService.getTask(task.getId());
|
||||||
|
|
||||||
|
// changes from TaskModifierAndTransferrer
|
||||||
|
assertThat(result.getCustomField(TaskCustomField.CUSTOM_3))
|
||||||
|
.isEqualTo(TaskModifierAndTransferrer.NEW_CUSTOM_3_VALUE);
|
||||||
|
assertThat(result.getWorkbasketSummary()).isEqualTo(newWorkbasket);
|
||||||
|
// changes from ClassificationUpdater
|
||||||
|
assertThat(result.getClassificationSummary().getId())
|
||||||
|
.isNotEqualTo(task.getClassificationSummary().getId());
|
||||||
|
assertThat(result.getClassificationSummary().getName())
|
||||||
|
.isEqualTo(ClassificationUpdater.SPI_CLASSIFICATION_NAME);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@TestInstance(Lifecycle.PER_CLASS)
|
||||||
|
@WithServiceProvider(
|
||||||
|
serviceProviderInterface = AfterRequestChangesProvider.class,
|
||||||
|
serviceProviders = ExceptionThrower.class)
|
||||||
|
class SpiThrowsException {
|
||||||
|
@TaskanaInject TaskService taskService;
|
||||||
|
@TaskanaInject TaskanaEngine taskanaEngine;
|
||||||
|
PlainJavaTransactionProvider transactionProvider;
|
||||||
|
|
||||||
|
@BeforeAll
|
||||||
|
void setup(TaskanaEngineConfiguration taskanaEngineConfiguration) {
|
||||||
|
transactionProvider =
|
||||||
|
new PlainJavaTransactionProvider(
|
||||||
|
taskanaEngine, taskanaEngineConfiguration.getDatasource());
|
||||||
|
}
|
||||||
|
|
||||||
|
@WithAccessId(user = "user-1-1")
|
||||||
|
@Test
|
||||||
|
void should_RollbackTransaction_When_SpiThrowsAnException() throws Exception {
|
||||||
|
Task task = createTaskInReviewByUser("user-1-1").buildAndStore(taskService);
|
||||||
|
|
||||||
|
ThrowingCallable call =
|
||||||
|
() ->
|
||||||
|
transactionProvider.executeInTransaction(
|
||||||
|
wrap(() -> taskService.requestChanges(task.getId())));
|
||||||
|
|
||||||
|
assertThatThrownBy(call)
|
||||||
|
.isInstanceOf(SystemException.class)
|
||||||
|
.getCause() // unwrap the "wrap" within "call"
|
||||||
|
.hasMessage("service provider '%s' threw an exception", ExceptionThrower.class.getName())
|
||||||
|
.getCause() // unwrap the "wrap" from the service provider manager
|
||||||
|
.hasMessage("I AM THE EXCEPTION THROWER (*_*)");
|
||||||
|
|
||||||
|
Task persistentTask = taskService.getTask(task.getId());
|
||||||
|
assertThat(persistentTask).isEqualTo(task);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -98,6 +98,7 @@ public class RequestReviewWithSpiAccTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
static class TaskModifierAndTransferrer implements AfterRequestReviewProvider {
|
static class TaskModifierAndTransferrer implements AfterRequestReviewProvider {
|
||||||
|
private static final String NEW_CUSTOM_3_VALUE = "bla";
|
||||||
|
|
||||||
private TaskanaEngine taskanaEngine;
|
private TaskanaEngine taskanaEngine;
|
||||||
|
|
||||||
|
|
@ -108,7 +109,7 @@ public class RequestReviewWithSpiAccTest {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Task afterRequestReview(Task task) throws Exception {
|
public Task afterRequestReview(Task task) throws Exception {
|
||||||
task.setCustomField(TaskCustomField.CUSTOM_3, "bla");
|
task.setCustomField(TaskCustomField.CUSTOM_3, NEW_CUSTOM_3_VALUE);
|
||||||
task = taskanaEngine.getTaskService().updateTask(task);
|
task = taskanaEngine.getTaskService().updateTask(task);
|
||||||
task = taskanaEngine.getTaskService().transfer(task.getId(), NEW_WORKBASKET_KEY, "DOMAIN_A");
|
task = taskanaEngine.getTaskService().transfer(task.getId(), NEW_WORKBASKET_KEY, "DOMAIN_A");
|
||||||
return task;
|
return task;
|
||||||
|
|
@ -157,7 +158,8 @@ public class RequestReviewWithSpiAccTest {
|
||||||
|
|
||||||
Task result = taskService.requestReview(task.getId());
|
Task result = taskService.requestReview(task.getId());
|
||||||
|
|
||||||
assertThat(result.getCustomField(TaskCustomField.CUSTOM_3)).isEqualTo("bla");
|
assertThat(result.getCustomField(TaskCustomField.CUSTOM_3))
|
||||||
|
.isEqualTo(TaskModifierAndTransferrer.NEW_CUSTOM_3_VALUE);
|
||||||
assertThat(result.getWorkbasketSummary()).isEqualTo(newWorkbasket);
|
assertThat(result.getWorkbasketSummary()).isEqualTo(newWorkbasket);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -169,7 +171,8 @@ public class RequestReviewWithSpiAccTest {
|
||||||
taskService.requestReview(task.getId());
|
taskService.requestReview(task.getId());
|
||||||
Task result = taskService.getTask(task.getId());
|
Task result = taskService.getTask(task.getId());
|
||||||
|
|
||||||
assertThat(result.getCustomField(TaskCustomField.CUSTOM_3)).isEqualTo("bla");
|
assertThat(result.getCustomField(TaskCustomField.CUSTOM_3))
|
||||||
|
.isEqualTo(TaskModifierAndTransferrer.NEW_CUSTOM_3_VALUE);
|
||||||
assertThat(result.getWorkbasketSummary()).isEqualTo(newWorkbasket);
|
assertThat(result.getWorkbasketSummary()).isEqualTo(newWorkbasket);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -185,7 +188,7 @@ public class RequestReviewWithSpiAccTest {
|
||||||
|
|
||||||
@WithAccessId(user = "user-1-1", groups = "businessadmin")
|
@WithAccessId(user = "user-1-1", groups = "businessadmin")
|
||||||
@Test
|
@Test
|
||||||
void should_ReturnUpdateMultipleEntities_When_SpiModifiesTask() throws Exception {
|
void should_ChangeMultipleEntities_When_SpiModifiesMoreThanTheTask() throws Exception {
|
||||||
Task task = createTaskClaimedByUser("user-1-1").buildAndStore(taskService);
|
Task task = createTaskClaimedByUser("user-1-1").buildAndStore(taskService);
|
||||||
|
|
||||||
taskService.requestReview(task.getId());
|
taskService.requestReview(task.getId());
|
||||||
|
|
@ -216,7 +219,8 @@ public class RequestReviewWithSpiAccTest {
|
||||||
Task result = taskService.getTask(task.getId());
|
Task result = taskService.getTask(task.getId());
|
||||||
|
|
||||||
// changes from TaskModifierAndTransferrer
|
// changes from TaskModifierAndTransferrer
|
||||||
assertThat(result.getCustomField(TaskCustomField.CUSTOM_3)).isEqualTo("bla");
|
assertThat(result.getCustomField(TaskCustomField.CUSTOM_3))
|
||||||
|
.isEqualTo(TaskModifierAndTransferrer.NEW_CUSTOM_3_VALUE);
|
||||||
assertThat(result.getWorkbasketSummary()).isEqualTo(newWorkbasket);
|
assertThat(result.getWorkbasketSummary()).isEqualTo(newWorkbasket);
|
||||||
// changes from ClassificationUpdater
|
// changes from ClassificationUpdater
|
||||||
assertThat(result.getClassificationSummary().getId())
|
assertThat(result.getClassificationSummary().getId())
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import pro.taskana.common.api.TaskanaEngine;
|
||||||
import pro.taskana.spi.history.internal.HistoryEventManager;
|
import pro.taskana.spi.history.internal.HistoryEventManager;
|
||||||
import pro.taskana.spi.priority.internal.PriorityServiceManager;
|
import pro.taskana.spi.priority.internal.PriorityServiceManager;
|
||||||
import pro.taskana.spi.routing.internal.TaskRoutingManager;
|
import pro.taskana.spi.routing.internal.TaskRoutingManager;
|
||||||
|
import pro.taskana.spi.task.internal.AfterRequestChangesManager;
|
||||||
import pro.taskana.spi.task.internal.AfterRequestReviewManager;
|
import pro.taskana.spi.task.internal.AfterRequestReviewManager;
|
||||||
import pro.taskana.spi.task.internal.CreateTaskPreprocessorManager;
|
import pro.taskana.spi.task.internal.CreateTaskPreprocessorManager;
|
||||||
|
|
||||||
|
|
@ -113,4 +114,11 @@ public interface InternalTaskanaEngine {
|
||||||
* @return the {@linkplain AfterRequestReviewManager} instance
|
* @return the {@linkplain AfterRequestReviewManager} instance
|
||||||
*/
|
*/
|
||||||
AfterRequestReviewManager getAfterRequestReviewManager();
|
AfterRequestReviewManager getAfterRequestReviewManager();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the {@linkplain AfterRequestChangesManager}.
|
||||||
|
*
|
||||||
|
* @return the {@linkplain AfterRequestChangesManager} instance
|
||||||
|
*/
|
||||||
|
AfterRequestChangesManager getAfterRequestChangesManager();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,7 @@ import pro.taskana.monitor.internal.MonitorServiceImpl;
|
||||||
import pro.taskana.spi.history.internal.HistoryEventManager;
|
import pro.taskana.spi.history.internal.HistoryEventManager;
|
||||||
import pro.taskana.spi.priority.internal.PriorityServiceManager;
|
import pro.taskana.spi.priority.internal.PriorityServiceManager;
|
||||||
import pro.taskana.spi.routing.internal.TaskRoutingManager;
|
import pro.taskana.spi.routing.internal.TaskRoutingManager;
|
||||||
|
import pro.taskana.spi.task.internal.AfterRequestChangesManager;
|
||||||
import pro.taskana.spi.task.internal.AfterRequestReviewManager;
|
import pro.taskana.spi.task.internal.AfterRequestReviewManager;
|
||||||
import pro.taskana.spi.task.internal.CreateTaskPreprocessorManager;
|
import pro.taskana.spi.task.internal.CreateTaskPreprocessorManager;
|
||||||
import pro.taskana.task.api.TaskService;
|
import pro.taskana.task.api.TaskService;
|
||||||
|
|
@ -84,6 +85,8 @@ public class TaskanaEngineImpl implements TaskanaEngine {
|
||||||
private final CreateTaskPreprocessorManager createTaskPreprocessorManager;
|
private final CreateTaskPreprocessorManager createTaskPreprocessorManager;
|
||||||
private final PriorityServiceManager priorityServiceManager;
|
private final PriorityServiceManager priorityServiceManager;
|
||||||
private final AfterRequestReviewManager afterRequestReviewManager;
|
private final AfterRequestReviewManager afterRequestReviewManager;
|
||||||
|
private final AfterRequestChangesManager afterRequestChangesManager;
|
||||||
|
|
||||||
private final InternalTaskanaEngineImpl internalTaskanaEngineImpl;
|
private final InternalTaskanaEngineImpl internalTaskanaEngineImpl;
|
||||||
private final WorkingDaysToDaysConverter workingDaysToDaysConverter;
|
private final WorkingDaysToDaysConverter workingDaysToDaysConverter;
|
||||||
private final HistoryEventManager historyEventManager;
|
private final HistoryEventManager historyEventManager;
|
||||||
|
|
@ -120,6 +123,7 @@ public class TaskanaEngineImpl implements TaskanaEngine {
|
||||||
historyEventManager = new HistoryEventManager(this);
|
historyEventManager = new HistoryEventManager(this);
|
||||||
taskRoutingManager = new TaskRoutingManager(this);
|
taskRoutingManager = new TaskRoutingManager(this);
|
||||||
afterRequestReviewManager = new AfterRequestReviewManager(this);
|
afterRequestReviewManager = new AfterRequestReviewManager(this);
|
||||||
|
afterRequestChangesManager = new AfterRequestChangesManager(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TaskanaEngine createTaskanaEngine(
|
public static TaskanaEngine createTaskanaEngine(
|
||||||
|
|
@ -529,5 +533,10 @@ public class TaskanaEngineImpl implements TaskanaEngine {
|
||||||
public AfterRequestReviewManager getAfterRequestReviewManager() {
|
public AfterRequestReviewManager getAfterRequestReviewManager() {
|
||||||
return afterRequestReviewManager;
|
return afterRequestReviewManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AfterRequestChangesManager getAfterRequestChangesManager() {
|
||||||
|
return afterRequestChangesManager;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
package pro.taskana.spi.task.api;
|
||||||
|
|
||||||
|
import pro.taskana.common.api.TaskanaEngine;
|
||||||
|
import pro.taskana.task.api.models.Task;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The AfterRequestChangesProvider allows to implement customized behaviour after changes have been
|
||||||
|
* requested on a given {@linkplain Task}.
|
||||||
|
*/
|
||||||
|
public interface AfterRequestChangesProvider {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provide the active {@linkplain TaskanaEngine} which is initialized for this TASKANA
|
||||||
|
* installation.
|
||||||
|
*
|
||||||
|
* <p>This method is called during TASKANA startup and allows the service provider to store the
|
||||||
|
* active {@linkplain TaskanaEngine} for later usage.
|
||||||
|
*
|
||||||
|
* @param taskanaEngine the active {@linkplain TaskanaEngine} which is initialized for this
|
||||||
|
* installation
|
||||||
|
*/
|
||||||
|
void initialize(TaskanaEngine taskanaEngine);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform any action after changes have been requested on a {@linkplain Task} through {@linkplain
|
||||||
|
* pro.taskana.task.api.TaskService#requestChanges(String)}.
|
||||||
|
*
|
||||||
|
* <p>This SPI is executed within the same transaction staple as {@linkplain
|
||||||
|
* pro.taskana.task.api.TaskService#requestChanges(String)}.
|
||||||
|
*
|
||||||
|
* <p>This SPI is executed with the same {@linkplain
|
||||||
|
* pro.taskana.common.api.security.UserPrincipal} and {@linkplain
|
||||||
|
* pro.taskana.common.api.security.GroupPrincipal} as in {@linkplain
|
||||||
|
* pro.taskana.task.api.TaskService#requestChanges(String)}.
|
||||||
|
*
|
||||||
|
* @param task the {@linkplain Task} after {@linkplain
|
||||||
|
* pro.taskana.task.api.TaskService#requestChanges(String)} has completed
|
||||||
|
* @return the modified {@linkplain Task}. <b>IMPORTANT:</b> persistent changes to the {@linkplain
|
||||||
|
* Task} have to be managed by the service provider.
|
||||||
|
* @throws Exception if the service provider throws any exception.
|
||||||
|
*/
|
||||||
|
Task afterRequestChanges(Task task) throws Exception;
|
||||||
|
}
|
||||||
|
|
@ -17,7 +17,7 @@ public interface AfterRequestReviewProvider {
|
||||||
* active {@linkplain TaskanaEngine} for later usage.
|
* active {@linkplain TaskanaEngine} for later usage.
|
||||||
*
|
*
|
||||||
* @param taskanaEngine the active {@linkplain TaskanaEngine} which is initialized for this
|
* @param taskanaEngine the active {@linkplain TaskanaEngine} which is initialized for this
|
||||||
* installation.
|
* installation
|
||||||
*/
|
*/
|
||||||
void initialize(TaskanaEngine taskanaEngine);
|
void initialize(TaskanaEngine taskanaEngine);
|
||||||
|
|
||||||
|
|
@ -36,8 +36,8 @@ public interface AfterRequestReviewProvider {
|
||||||
* @param task the {@linkplain Task} after {@linkplain
|
* @param task the {@linkplain Task} after {@linkplain
|
||||||
* pro.taskana.task.api.TaskService#requestReview(String)} has completed
|
* pro.taskana.task.api.TaskService#requestReview(String)} has completed
|
||||||
* @return the modified {@linkplain Task}. <b>IMPORTANT:</b> persistent changes to the {@linkplain
|
* @return the modified {@linkplain Task}. <b>IMPORTANT:</b> persistent changes to the {@linkplain
|
||||||
* Task} have to be managed by the service provider.
|
* Task} have to be managed by the service provider
|
||||||
* @throws Exception if the service provider throws any exception.
|
* @throws Exception if the service provider throws any exception
|
||||||
*/
|
*/
|
||||||
Task afterRequestReview(Task task) throws Exception;
|
Task afterRequestReview(Task task) throws Exception;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
package pro.taskana.spi.task.internal;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import pro.taskana.common.api.TaskanaEngine;
|
||||||
|
import pro.taskana.common.api.exceptions.SystemException;
|
||||||
|
import pro.taskana.common.internal.util.SpiLoader;
|
||||||
|
import pro.taskana.spi.task.api.AfterRequestChangesProvider;
|
||||||
|
import pro.taskana.task.api.models.Task;
|
||||||
|
|
||||||
|
public class AfterRequestChangesManager {
|
||||||
|
|
||||||
|
private static final Logger LOGGER = LoggerFactory.getLogger(AfterRequestChangesManager.class);
|
||||||
|
|
||||||
|
private final List<AfterRequestChangesProvider> afterRequestChangesProviders;
|
||||||
|
|
||||||
|
public AfterRequestChangesManager(TaskanaEngine taskanaEngine) {
|
||||||
|
afterRequestChangesProviders = SpiLoader.load(AfterRequestChangesProvider.class);
|
||||||
|
for (AfterRequestChangesProvider serviceProvider : afterRequestChangesProviders) {
|
||||||
|
serviceProvider.initialize(taskanaEngine);
|
||||||
|
LOGGER.info(
|
||||||
|
"Registered AfterRequestChanges service provider: {}",
|
||||||
|
serviceProvider.getClass().getName());
|
||||||
|
}
|
||||||
|
if (afterRequestChangesProviders.isEmpty()) {
|
||||||
|
LOGGER.info(
|
||||||
|
"No AfterRequestChangesProvider service provider found. "
|
||||||
|
+ "Running without any AfterRequestChangesProvider implementation.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task afterRequestChanges(Task task) {
|
||||||
|
if (LOGGER.isDebugEnabled()) {
|
||||||
|
LOGGER.debug("Sending Task to AfterRequestChanges service providers: {}", task);
|
||||||
|
}
|
||||||
|
for (AfterRequestChangesProvider serviceProvider : afterRequestChangesProviders) {
|
||||||
|
try {
|
||||||
|
task = serviceProvider.afterRequestChanges(task);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new SystemException(
|
||||||
|
String.format(
|
||||||
|
"service provider '%s' threw an exception", serviceProvider.getClass().getName()),
|
||||||
|
e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return task;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -53,6 +53,7 @@ import pro.taskana.spi.history.api.events.task.TaskTerminatedEvent;
|
||||||
import pro.taskana.spi.history.api.events.task.TaskUpdatedEvent;
|
import pro.taskana.spi.history.api.events.task.TaskUpdatedEvent;
|
||||||
import pro.taskana.spi.history.internal.HistoryEventManager;
|
import pro.taskana.spi.history.internal.HistoryEventManager;
|
||||||
import pro.taskana.spi.priority.internal.PriorityServiceManager;
|
import pro.taskana.spi.priority.internal.PriorityServiceManager;
|
||||||
|
import pro.taskana.spi.task.internal.AfterRequestChangesManager;
|
||||||
import pro.taskana.spi.task.internal.AfterRequestReviewManager;
|
import pro.taskana.spi.task.internal.AfterRequestReviewManager;
|
||||||
import pro.taskana.spi.task.internal.CreateTaskPreprocessorManager;
|
import pro.taskana.spi.task.internal.CreateTaskPreprocessorManager;
|
||||||
import pro.taskana.task.api.CallbackState;
|
import pro.taskana.task.api.CallbackState;
|
||||||
|
|
@ -116,6 +117,7 @@ public class TaskServiceImpl implements TaskService {
|
||||||
private final CreateTaskPreprocessorManager createTaskPreprocessorManager;
|
private final CreateTaskPreprocessorManager createTaskPreprocessorManager;
|
||||||
private final PriorityServiceManager priorityServiceManager;
|
private final PriorityServiceManager priorityServiceManager;
|
||||||
private final AfterRequestReviewManager afterRequestReviewManager;
|
private final AfterRequestReviewManager afterRequestReviewManager;
|
||||||
|
private final AfterRequestChangesManager afterRequestChangesManager;
|
||||||
|
|
||||||
public TaskServiceImpl(
|
public TaskServiceImpl(
|
||||||
InternalTaskanaEngine taskanaEngine,
|
InternalTaskanaEngine taskanaEngine,
|
||||||
|
|
@ -135,6 +137,7 @@ public class TaskServiceImpl implements TaskService {
|
||||||
this.createTaskPreprocessorManager = taskanaEngine.getCreateTaskPreprocessorManager();
|
this.createTaskPreprocessorManager = taskanaEngine.getCreateTaskPreprocessorManager();
|
||||||
this.priorityServiceManager = taskanaEngine.getPriorityServiceManager();
|
this.priorityServiceManager = taskanaEngine.getPriorityServiceManager();
|
||||||
this.afterRequestReviewManager = taskanaEngine.getAfterRequestReviewManager();
|
this.afterRequestReviewManager = taskanaEngine.getAfterRequestReviewManager();
|
||||||
|
this.afterRequestChangesManager = taskanaEngine.getAfterRequestChangesManager();
|
||||||
this.taskTransferrer = new TaskTransferrer(taskanaEngine, taskMapper, this);
|
this.taskTransferrer = new TaskTransferrer(taskanaEngine, taskMapper, this);
|
||||||
this.taskCommentService =
|
this.taskCommentService =
|
||||||
new TaskCommentServiceImpl(taskanaEngine, taskCommentMapper, userMapper, this);
|
new TaskCommentServiceImpl(taskanaEngine, taskCommentMapper, userMapper, this);
|
||||||
|
|
@ -1312,6 +1315,7 @@ public class TaskServiceImpl implements TaskService {
|
||||||
taskanaEngine.getEngine().getCurrentUserContext().getUserid(),
|
taskanaEngine.getEngine().getCurrentUserContext().getUserid(),
|
||||||
changeDetails));
|
changeDetails));
|
||||||
}
|
}
|
||||||
|
task = (TaskImpl) afterRequestChangesManager.afterRequestChanges(task);
|
||||||
} finally {
|
} finally {
|
||||||
taskanaEngine.returnConnection();
|
taskanaEngine.returnConnection();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ import org.junit.platform.commons.JUnitException;
|
||||||
import pro.taskana.spi.history.api.TaskanaHistory;
|
import pro.taskana.spi.history.api.TaskanaHistory;
|
||||||
import pro.taskana.spi.priority.api.PriorityServiceProvider;
|
import pro.taskana.spi.priority.api.PriorityServiceProvider;
|
||||||
import pro.taskana.spi.routing.api.TaskRoutingProvider;
|
import pro.taskana.spi.routing.api.TaskRoutingProvider;
|
||||||
|
import pro.taskana.spi.task.api.AfterRequestChangesProvider;
|
||||||
import pro.taskana.spi.task.api.AfterRequestReviewProvider;
|
import pro.taskana.spi.task.api.AfterRequestReviewProvider;
|
||||||
import pro.taskana.spi.task.api.CreateTaskPreprocessor;
|
import pro.taskana.spi.task.api.CreateTaskPreprocessor;
|
||||||
import pro.taskana.testapi.WithServiceProvider;
|
import pro.taskana.testapi.WithServiceProvider;
|
||||||
|
|
@ -28,7 +29,8 @@ public class ServiceProviderExtractor {
|
||||||
PriorityServiceProvider.class,
|
PriorityServiceProvider.class,
|
||||||
TaskRoutingProvider.class,
|
TaskRoutingProvider.class,
|
||||||
CreateTaskPreprocessor.class,
|
CreateTaskPreprocessor.class,
|
||||||
AfterRequestReviewProvider.class);
|
AfterRequestReviewProvider.class,
|
||||||
|
AfterRequestChangesProvider.class);
|
||||||
|
|
||||||
private ServiceProviderExtractor() {
|
private ServiceProviderExtractor() {
|
||||||
throw new IllegalStateException("utility class");
|
throw new IllegalStateException("utility class");
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue