TSK-722: added HistoryEventProducer to completeTask

This commit is contained in:
Holger Hagen 2018-09-26 12:57:46 +02:00
parent e3b472ed84
commit d6a38d7f29
7 changed files with 332 additions and 9 deletions

View File

@ -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);
});
}
}

View File

@ -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();
}
}

View File

@ -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;
}
}

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -44,6 +44,8 @@ import pro.taskana.exceptions.TaskAlreadyExistException;
import pro.taskana.exceptions.TaskNotFoundException;
import pro.taskana.exceptions.TaskanaException;
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.util.IdGenerator;
import pro.taskana.impl.util.LoggerUtils;
@ -69,6 +71,7 @@ public class TaskServiceImpl implements TaskService {
private ClassificationServiceImpl classificationService;
private TaskMapper taskMapper;
private AttachmentMapper attachmentMapper;
private HistoryEventProducer historyEventProducer;
TaskServiceImpl(TaskanaEngine taskanaEngine, TaskMapper taskMapper,
AttachmentMapper attachmentMapper) {
@ -84,6 +87,7 @@ public class TaskServiceImpl implements TaskService {
this.workbasketService = taskanaEngine.getWorkbasketService();
this.attachmentMapper = attachmentMapper;
this.classificationService = (ClassificationServiceImpl) taskanaEngine.getClassificationService();
this.historyEventProducer = ((TaskanaEngineImpl) taskanaEngine).getHistoryEventProducer();
}
@Override
@ -219,6 +223,12 @@ public class TaskServiceImpl implements TaskService {
task.setOwner(userId);
taskMapper.update(task);
LOGGER.debug("Task '{}' completed by user '{}'.", taskId, userId);
if (HistoryEventProducer.isHistoryEnabled()) {
TaskCompletionEvent event = new TaskCompletionEvent(task);
historyEventProducer.createEvent(event);
}
} finally {
taskanaEngine.returnConnection();
LOGGER.debug("exit from completeTask()");
@ -618,8 +628,10 @@ public class TaskServiceImpl implements TaskService {
}
// filter taskSummaries and update values
taskSummaries = taskSummaries.stream().filter(ts -> taskIds.contains(ts.getTaskId())).collect(
Collectors.toList());
taskSummaries = taskSummaries.stream()
.filter(ts -> taskIds.contains(ts.getTaskId()))
.collect(
Collectors.toList());
if (!taskSummaries.isEmpty()) {
Instant now = Instant.now();
TaskSummaryImpl updateObject = new TaskSummaryImpl();
@ -803,8 +815,10 @@ public class TaskServiceImpl implements TaskService {
return new ArrayList<>();
}
Set<String> classificationIdSet = taskSummaries.stream().map(t -> t.getClassificationSummary().getId()).collect(
Collectors.toSet());
Set<String> classificationIdSet = taskSummaries.stream()
.map(t -> t.getClassificationSummary().getId())
.collect(
Collectors.toSet());
if (attachmentSummaries != null && !attachmentSummaries.isEmpty()) {
for (AttachmentSummaryImpl att : attachmentSummaries) {
@ -845,8 +859,10 @@ public class TaskServiceImpl implements TaskService {
return;
}
// calculate parameters for workbasket query: workbasket keys
Set<String> workbasketIdSet = taskSummaries.stream().map(t -> t.getWorkbasketSummary().getId()).collect(
Collectors.toSet());
Set<String> workbasketIdSet = taskSummaries.stream()
.map(t -> t.getWorkbasketSummary().getId())
.collect(
Collectors.toSet());
String[] workbasketIdArray = workbasketIdSet.toArray(new String[0]);
// perform workbasket query
LOGGER.debug("addWorkbasketSummariesToTaskSummaries() about to query workbaskets");
@ -1500,8 +1516,10 @@ public class TaskServiceImpl implements TaskService {
if (attachmentImpls == null || attachmentImpls.isEmpty()) {
return result;
}
Set<String> classificationIds = attachmentImpls.stream().map(t -> t.getClassificationSummary().getId()).collect(
Collectors.toSet());
Set<String> classificationIds = attachmentImpls.stream()
.map(t -> t.getClassificationSummary().getId())
.collect(
Collectors.toSet());
List<ClassificationSummary> classifications = classificationService.createClassificationQuery()
.idIn(classificationIds.toArray(new String[0]))
.list();

View File

@ -34,6 +34,7 @@ import pro.taskana.exceptions.ConnectionNotSetException;
import pro.taskana.exceptions.NotAuthorizedException;
import pro.taskana.exceptions.SystemException;
import pro.taskana.exceptions.UnsupportedDatabaseException;
import pro.taskana.history.HistoryEventProducer;
import pro.taskana.impl.persistence.MapTypeHandler;
import pro.taskana.impl.util.LoggerUtils;
import pro.taskana.mappings.AttachmentMapper;
@ -61,11 +62,13 @@ public class TaskanaEngineImpl implements TaskanaEngine {
protected SqlSessionManager sessionManager;
protected ConnectionManagementMode mode = ConnectionManagementMode.PARTICIPATE;
protected java.sql.Connection connection = null;
protected HistoryEventProducer historyEventProducer;
protected TaskanaEngineImpl(TaskanaEngineConfiguration taskanaEngineConfiguration) {
this.taskanaEngineConfiguration = taskanaEngineConfiguration;
createTransactionFactory(taskanaEngineConfiguration.getUseManagedTransactions());
this.sessionManager = createSqlSessionManager();
this.historyEventProducer = HistoryEventProducer.getInstance();
}
public static TaskanaEngine createTaskanaEngine(TaskanaEngineConfiguration taskanaEngineConfiguration) {
@ -165,6 +168,10 @@ public class TaskanaEngineImpl implements TaskanaEngine {
return this.taskanaEngineConfiguration;
}
public HistoryEventProducer getHistoryEventProducer() {
return this.historyEventProducer;
}
/**
* 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
*
*/
void openConnection() {
initSqlSession();