TSK-722: added HistoryEventProducer to completeTask
This commit is contained in:
parent
e3b472ed84
commit
d6a38d7f29
|
|
@ -0,0 +1,57 @@
|
||||||
|
package pro.taskana.history;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.ServiceLoader;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import pro.taskana.history.api.TaskanaHistory;
|
||||||
|
import pro.taskana.history.api.TaskanaHistoryEvent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates events and emits them to the registered history service providers.
|
||||||
|
*/
|
||||||
|
public final class HistoryEventProducer {
|
||||||
|
|
||||||
|
private static final Logger LOGGER = LoggerFactory.getLogger(HistoryEventProducer.class);
|
||||||
|
|
||||||
|
private static HistoryEventProducer emitterInstance;
|
||||||
|
private ServiceLoader<TaskanaHistory> serviceLoader;
|
||||||
|
private boolean enabled = false;
|
||||||
|
|
||||||
|
public static synchronized HistoryEventProducer getInstance() {
|
||||||
|
if (emitterInstance == null) {
|
||||||
|
emitterInstance = new HistoryEventProducer();
|
||||||
|
}
|
||||||
|
return emitterInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isHistoryEnabled() {
|
||||||
|
return getInstance().isEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
private HistoryEventProducer() {
|
||||||
|
serviceLoader = ServiceLoader.load(TaskanaHistory.class);
|
||||||
|
Iterator<TaskanaHistory> serviceIterator = serviceLoader.iterator();
|
||||||
|
while (serviceIterator.hasNext()) {
|
||||||
|
TaskanaHistory history = serviceIterator.next();
|
||||||
|
LOGGER.info("Registered history provider: {}", history.getClass().getName());
|
||||||
|
enabled = true;
|
||||||
|
}
|
||||||
|
if (!enabled) {
|
||||||
|
LOGGER.info("No history provider found. Running without history.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEnabled() {
|
||||||
|
return enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void createEvent(TaskanaHistoryEvent event) {
|
||||||
|
LOGGER.debug("Sending event to history service providers: {}", event);
|
||||||
|
serviceLoader.forEach(historyProvider -> {
|
||||||
|
historyProvider.create(event);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
package pro.taskana.history.api;
|
||||||
|
|
||||||
|
import pro.taskana.Task;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event fired if a task is completed.
|
||||||
|
*/
|
||||||
|
public class TaskCompletionEvent extends TaskHistoryEvent {
|
||||||
|
|
||||||
|
public TaskCompletionEvent(Task completedTask) {
|
||||||
|
super(completedTask);
|
||||||
|
type = "TASK_COMPLETED";
|
||||||
|
created = completedTask.getCompleted();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,147 @@
|
||||||
|
package pro.taskana.history.api;
|
||||||
|
|
||||||
|
import pro.taskana.Task;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Super class for all task related events.
|
||||||
|
*/
|
||||||
|
public class TaskHistoryEvent extends TaskanaHistoryEvent {
|
||||||
|
|
||||||
|
protected String taskId;
|
||||||
|
protected String businessProcessId;
|
||||||
|
protected String parentBusinessProcessId;
|
||||||
|
protected String domain;
|
||||||
|
protected String workbasketKey;
|
||||||
|
protected String taskClassificationCategory;
|
||||||
|
protected String taskClassificationKey;
|
||||||
|
protected String attachmentClassificationKey;
|
||||||
|
protected String porCompany;
|
||||||
|
protected String porSystem;
|
||||||
|
protected String porInstance;
|
||||||
|
protected String porType;
|
||||||
|
protected String porValue;
|
||||||
|
|
||||||
|
public TaskHistoryEvent(Task task) {
|
||||||
|
super();
|
||||||
|
taskId = task.getId();
|
||||||
|
businessProcessId = task.getBusinessProcessId();
|
||||||
|
parentBusinessProcessId = task.getParentBusinessProcessId();
|
||||||
|
domain = task.getDomain();
|
||||||
|
workbasketKey = task.getWorkbasketKey();
|
||||||
|
taskClassificationCategory = task.getClassificationCategory();
|
||||||
|
taskClassificationKey = task.getClassificationSummary().getKey();
|
||||||
|
if (!task.getAttachments().isEmpty()) {
|
||||||
|
attachmentClassificationKey = task.getAttachments().get(0).getClassificationSummary().getKey();
|
||||||
|
}
|
||||||
|
porCompany = task.getPrimaryObjRef().getCompany();
|
||||||
|
porSystem = task.getPrimaryObjRef().getSystem();
|
||||||
|
porInstance = task.getPrimaryObjRef().getSystemInstance();
|
||||||
|
porType = task.getPrimaryObjRef().getType();
|
||||||
|
porValue = task.getPrimaryObjRef().getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTaskId() {
|
||||||
|
return taskId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTaskId(String taskId) {
|
||||||
|
this.taskId = taskId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getBusinessProcessId() {
|
||||||
|
return businessProcessId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBusinessProcessId(String businessProcessId) {
|
||||||
|
this.businessProcessId = businessProcessId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getParentBusinessProcessId() {
|
||||||
|
return parentBusinessProcessId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setParentBusinessProcessId(String parentBusinessProcessId) {
|
||||||
|
this.parentBusinessProcessId = parentBusinessProcessId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDomain() {
|
||||||
|
return domain;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDomain(String domain) {
|
||||||
|
this.domain = domain;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getWorkbasketKey() {
|
||||||
|
return workbasketKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setWorkbasketKey(String workbasketKey) {
|
||||||
|
this.workbasketKey = workbasketKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTaskClassificationCategory() {
|
||||||
|
return taskClassificationCategory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTaskClassificationCategory(String taskClassificationCategory) {
|
||||||
|
this.taskClassificationCategory = taskClassificationCategory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTaskClassificationKey() {
|
||||||
|
return taskClassificationKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTaskClassificationKey(String taskClassificationKey) {
|
||||||
|
this.taskClassificationKey = taskClassificationKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAttachmentClassificationKey() {
|
||||||
|
return attachmentClassificationKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAttachmentClassificationKey(String attachmentClassificationKey) {
|
||||||
|
this.attachmentClassificationKey = attachmentClassificationKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPorCompany() {
|
||||||
|
return porCompany;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPorCompany(String porCompany) {
|
||||||
|
this.porCompany = porCompany;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPorSystem() {
|
||||||
|
return porSystem;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPorSystem(String porSystem) {
|
||||||
|
this.porSystem = porSystem;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPorInstance() {
|
||||||
|
return porInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPorInstance(String porInstance) {
|
||||||
|
this.porInstance = porInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPorType() {
|
||||||
|
return porType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPorType(String porType) {
|
||||||
|
this.porType = porType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPorValue() {
|
||||||
|
return porValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPorValue(String porValue) {
|
||||||
|
this.porValue = porValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
package pro.taskana.history.api;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface for TASKANA History Service Provider.
|
||||||
|
*/
|
||||||
|
public interface TaskanaHistory {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new history event.
|
||||||
|
*
|
||||||
|
* @param event
|
||||||
|
* {@link TaskanaHistoryEvent} The event to be created.
|
||||||
|
*/
|
||||||
|
void create(TaskanaHistoryEvent event);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,62 @@
|
||||||
|
package pro.taskana.history.api;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
|
||||||
|
import pro.taskana.security.CurrentUserContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Super class for all specific events from the TASKANA engine.
|
||||||
|
*/
|
||||||
|
public class TaskanaHistoryEvent {
|
||||||
|
|
||||||
|
protected long id;
|
||||||
|
protected String type;
|
||||||
|
protected String userId;
|
||||||
|
protected Instant created;
|
||||||
|
protected String comment;
|
||||||
|
|
||||||
|
public TaskanaHistoryEvent() {
|
||||||
|
userId = CurrentUserContext.getUserid();
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setType(String type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUserId() {
|
||||||
|
return userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUserId(String userId) {
|
||||||
|
this.userId = userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Instant getCreated() {
|
||||||
|
return created;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCreated(Instant created) {
|
||||||
|
this.created = created;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getComment() {
|
||||||
|
return comment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setComment(String comment) {
|
||||||
|
this.comment = comment;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -44,6 +44,8 @@ import pro.taskana.exceptions.TaskAlreadyExistException;
|
||||||
import pro.taskana.exceptions.TaskNotFoundException;
|
import pro.taskana.exceptions.TaskNotFoundException;
|
||||||
import pro.taskana.exceptions.TaskanaException;
|
import pro.taskana.exceptions.TaskanaException;
|
||||||
import pro.taskana.exceptions.WorkbasketNotFoundException;
|
import pro.taskana.exceptions.WorkbasketNotFoundException;
|
||||||
|
import pro.taskana.history.HistoryEventProducer;
|
||||||
|
import pro.taskana.history.api.TaskCompletionEvent;
|
||||||
import pro.taskana.impl.report.TimeIntervalColumnHeader;
|
import pro.taskana.impl.report.TimeIntervalColumnHeader;
|
||||||
import pro.taskana.impl.util.IdGenerator;
|
import pro.taskana.impl.util.IdGenerator;
|
||||||
import pro.taskana.impl.util.LoggerUtils;
|
import pro.taskana.impl.util.LoggerUtils;
|
||||||
|
|
@ -69,6 +71,7 @@ public class TaskServiceImpl implements TaskService {
|
||||||
private ClassificationServiceImpl classificationService;
|
private ClassificationServiceImpl classificationService;
|
||||||
private TaskMapper taskMapper;
|
private TaskMapper taskMapper;
|
||||||
private AttachmentMapper attachmentMapper;
|
private AttachmentMapper attachmentMapper;
|
||||||
|
private HistoryEventProducer historyEventProducer;
|
||||||
|
|
||||||
TaskServiceImpl(TaskanaEngine taskanaEngine, TaskMapper taskMapper,
|
TaskServiceImpl(TaskanaEngine taskanaEngine, TaskMapper taskMapper,
|
||||||
AttachmentMapper attachmentMapper) {
|
AttachmentMapper attachmentMapper) {
|
||||||
|
|
@ -84,6 +87,7 @@ public class TaskServiceImpl implements TaskService {
|
||||||
this.workbasketService = taskanaEngine.getWorkbasketService();
|
this.workbasketService = taskanaEngine.getWorkbasketService();
|
||||||
this.attachmentMapper = attachmentMapper;
|
this.attachmentMapper = attachmentMapper;
|
||||||
this.classificationService = (ClassificationServiceImpl) taskanaEngine.getClassificationService();
|
this.classificationService = (ClassificationServiceImpl) taskanaEngine.getClassificationService();
|
||||||
|
this.historyEventProducer = ((TaskanaEngineImpl) taskanaEngine).getHistoryEventProducer();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -219,6 +223,12 @@ public class TaskServiceImpl implements TaskService {
|
||||||
task.setOwner(userId);
|
task.setOwner(userId);
|
||||||
taskMapper.update(task);
|
taskMapper.update(task);
|
||||||
LOGGER.debug("Task '{}' completed by user '{}'.", taskId, userId);
|
LOGGER.debug("Task '{}' completed by user '{}'.", taskId, userId);
|
||||||
|
|
||||||
|
if (HistoryEventProducer.isHistoryEnabled()) {
|
||||||
|
TaskCompletionEvent event = new TaskCompletionEvent(task);
|
||||||
|
historyEventProducer.createEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
taskanaEngine.returnConnection();
|
taskanaEngine.returnConnection();
|
||||||
LOGGER.debug("exit from completeTask()");
|
LOGGER.debug("exit from completeTask()");
|
||||||
|
|
@ -618,8 +628,10 @@ public class TaskServiceImpl implements TaskService {
|
||||||
}
|
}
|
||||||
|
|
||||||
// filter taskSummaries and update values
|
// filter taskSummaries and update values
|
||||||
taskSummaries = taskSummaries.stream().filter(ts -> taskIds.contains(ts.getTaskId())).collect(
|
taskSummaries = taskSummaries.stream()
|
||||||
Collectors.toList());
|
.filter(ts -> taskIds.contains(ts.getTaskId()))
|
||||||
|
.collect(
|
||||||
|
Collectors.toList());
|
||||||
if (!taskSummaries.isEmpty()) {
|
if (!taskSummaries.isEmpty()) {
|
||||||
Instant now = Instant.now();
|
Instant now = Instant.now();
|
||||||
TaskSummaryImpl updateObject = new TaskSummaryImpl();
|
TaskSummaryImpl updateObject = new TaskSummaryImpl();
|
||||||
|
|
@ -803,8 +815,10 @@ public class TaskServiceImpl implements TaskService {
|
||||||
return new ArrayList<>();
|
return new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
Set<String> classificationIdSet = taskSummaries.stream().map(t -> t.getClassificationSummary().getId()).collect(
|
Set<String> classificationIdSet = taskSummaries.stream()
|
||||||
Collectors.toSet());
|
.map(t -> t.getClassificationSummary().getId())
|
||||||
|
.collect(
|
||||||
|
Collectors.toSet());
|
||||||
|
|
||||||
if (attachmentSummaries != null && !attachmentSummaries.isEmpty()) {
|
if (attachmentSummaries != null && !attachmentSummaries.isEmpty()) {
|
||||||
for (AttachmentSummaryImpl att : attachmentSummaries) {
|
for (AttachmentSummaryImpl att : attachmentSummaries) {
|
||||||
|
|
@ -845,8 +859,10 @@ public class TaskServiceImpl implements TaskService {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// calculate parameters for workbasket query: workbasket keys
|
// calculate parameters for workbasket query: workbasket keys
|
||||||
Set<String> workbasketIdSet = taskSummaries.stream().map(t -> t.getWorkbasketSummary().getId()).collect(
|
Set<String> workbasketIdSet = taskSummaries.stream()
|
||||||
Collectors.toSet());
|
.map(t -> t.getWorkbasketSummary().getId())
|
||||||
|
.collect(
|
||||||
|
Collectors.toSet());
|
||||||
String[] workbasketIdArray = workbasketIdSet.toArray(new String[0]);
|
String[] workbasketIdArray = workbasketIdSet.toArray(new String[0]);
|
||||||
// perform workbasket query
|
// perform workbasket query
|
||||||
LOGGER.debug("addWorkbasketSummariesToTaskSummaries() about to query workbaskets");
|
LOGGER.debug("addWorkbasketSummariesToTaskSummaries() about to query workbaskets");
|
||||||
|
|
@ -1500,8 +1516,10 @@ public class TaskServiceImpl implements TaskService {
|
||||||
if (attachmentImpls == null || attachmentImpls.isEmpty()) {
|
if (attachmentImpls == null || attachmentImpls.isEmpty()) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
Set<String> classificationIds = attachmentImpls.stream().map(t -> t.getClassificationSummary().getId()).collect(
|
Set<String> classificationIds = attachmentImpls.stream()
|
||||||
Collectors.toSet());
|
.map(t -> t.getClassificationSummary().getId())
|
||||||
|
.collect(
|
||||||
|
Collectors.toSet());
|
||||||
List<ClassificationSummary> classifications = classificationService.createClassificationQuery()
|
List<ClassificationSummary> classifications = classificationService.createClassificationQuery()
|
||||||
.idIn(classificationIds.toArray(new String[0]))
|
.idIn(classificationIds.toArray(new String[0]))
|
||||||
.list();
|
.list();
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@ import pro.taskana.exceptions.ConnectionNotSetException;
|
||||||
import pro.taskana.exceptions.NotAuthorizedException;
|
import pro.taskana.exceptions.NotAuthorizedException;
|
||||||
import pro.taskana.exceptions.SystemException;
|
import pro.taskana.exceptions.SystemException;
|
||||||
import pro.taskana.exceptions.UnsupportedDatabaseException;
|
import pro.taskana.exceptions.UnsupportedDatabaseException;
|
||||||
|
import pro.taskana.history.HistoryEventProducer;
|
||||||
import pro.taskana.impl.persistence.MapTypeHandler;
|
import pro.taskana.impl.persistence.MapTypeHandler;
|
||||||
import pro.taskana.impl.util.LoggerUtils;
|
import pro.taskana.impl.util.LoggerUtils;
|
||||||
import pro.taskana.mappings.AttachmentMapper;
|
import pro.taskana.mappings.AttachmentMapper;
|
||||||
|
|
@ -61,11 +62,13 @@ public class TaskanaEngineImpl implements TaskanaEngine {
|
||||||
protected SqlSessionManager sessionManager;
|
protected SqlSessionManager sessionManager;
|
||||||
protected ConnectionManagementMode mode = ConnectionManagementMode.PARTICIPATE;
|
protected ConnectionManagementMode mode = ConnectionManagementMode.PARTICIPATE;
|
||||||
protected java.sql.Connection connection = null;
|
protected java.sql.Connection connection = null;
|
||||||
|
protected HistoryEventProducer historyEventProducer;
|
||||||
|
|
||||||
protected TaskanaEngineImpl(TaskanaEngineConfiguration taskanaEngineConfiguration) {
|
protected TaskanaEngineImpl(TaskanaEngineConfiguration taskanaEngineConfiguration) {
|
||||||
this.taskanaEngineConfiguration = taskanaEngineConfiguration;
|
this.taskanaEngineConfiguration = taskanaEngineConfiguration;
|
||||||
createTransactionFactory(taskanaEngineConfiguration.getUseManagedTransactions());
|
createTransactionFactory(taskanaEngineConfiguration.getUseManagedTransactions());
|
||||||
this.sessionManager = createSqlSessionManager();
|
this.sessionManager = createSqlSessionManager();
|
||||||
|
this.historyEventProducer = HistoryEventProducer.getInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TaskanaEngine createTaskanaEngine(TaskanaEngineConfiguration taskanaEngineConfiguration) {
|
public static TaskanaEngine createTaskanaEngine(TaskanaEngineConfiguration taskanaEngineConfiguration) {
|
||||||
|
|
@ -165,6 +168,10 @@ public class TaskanaEngineImpl implements TaskanaEngine {
|
||||||
return this.taskanaEngineConfiguration;
|
return this.taskanaEngineConfiguration;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public HistoryEventProducer getHistoryEventProducer() {
|
||||||
|
return this.historyEventProducer;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* sets the connection management mode.
|
* sets the connection management mode.
|
||||||
*
|
*
|
||||||
|
|
@ -228,7 +235,6 @@ public class TaskanaEngineImpl implements TaskanaEngine {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Open the connection to the database. to be called at the begin of each Api call that accesses the database
|
* Open the connection to the database. to be called at the begin of each Api call that accesses the database
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
void openConnection() {
|
void openConnection() {
|
||||||
initSqlSession();
|
initSqlSession();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue