Closes #2374: Deadlock when creating HistoryEvents from many connections simultaneously
-Write operations are now performed with the regular TaskanEngine and its' SqlSession and TransactionFactory which provides the needed transactionality and doesn't open multiple connections
This commit is contained in:
parent
31100a54dd
commit
34c060e1a6
|
@ -1,31 +0,0 @@
|
||||||
package pro.taskana.simplehistory;
|
|
||||||
|
|
||||||
import pro.taskana.common.api.TaskanaRole;
|
|
||||||
import pro.taskana.common.api.exceptions.NotAuthorizedException;
|
|
||||||
import pro.taskana.spi.history.api.TaskanaHistory;
|
|
||||||
|
|
||||||
/** The TaskanaHistoryEngine represents an overall set of all needed services. */
|
|
||||||
public interface TaskanaHistoryEngine {
|
|
||||||
/**
|
|
||||||
* The TaskanaHistory can be used for operations on all history events.
|
|
||||||
*
|
|
||||||
* @return the HistoryService
|
|
||||||
*/
|
|
||||||
TaskanaHistory getTaskanaHistoryService();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* check whether the current user is member of one of the roles specified.
|
|
||||||
*
|
|
||||||
* @param roles The roles that are checked for membership of the current user
|
|
||||||
* @return true if the current user is a member of at least one of the specified groups
|
|
||||||
*/
|
|
||||||
boolean isUserInRole(TaskanaRole... roles);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks whether current user is member of any of the specified roles.
|
|
||||||
*
|
|
||||||
* @param roles The roles that are checked for membership of the current user
|
|
||||||
* @throws NotAuthorizedException If the current user is not member of any specified role
|
|
||||||
*/
|
|
||||||
void checkRoleMembership(TaskanaRole... roles) throws NotAuthorizedException;
|
|
||||||
}
|
|
|
@ -2,7 +2,6 @@ package pro.taskana.simplehistory.impl;
|
||||||
|
|
||||||
import static pro.taskana.common.api.BaseQuery.toLowerCopy;
|
import static pro.taskana.common.api.BaseQuery.toLowerCopy;
|
||||||
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import org.apache.ibatis.session.RowBounds;
|
import org.apache.ibatis.session.RowBounds;
|
||||||
|
@ -12,6 +11,7 @@ import pro.taskana.classification.api.ClassificationCustomField;
|
||||||
import pro.taskana.common.api.TimeInterval;
|
import pro.taskana.common.api.TimeInterval;
|
||||||
import pro.taskana.common.api.exceptions.InvalidArgumentException;
|
import pro.taskana.common.api.exceptions.InvalidArgumentException;
|
||||||
import pro.taskana.common.api.exceptions.SystemException;
|
import pro.taskana.common.api.exceptions.SystemException;
|
||||||
|
import pro.taskana.common.internal.InternalTaskanaEngine;
|
||||||
import pro.taskana.simplehistory.impl.classification.ClassificationHistoryQuery;
|
import pro.taskana.simplehistory.impl.classification.ClassificationHistoryQuery;
|
||||||
import pro.taskana.simplehistory.impl.classification.ClassificationHistoryQueryColumnName;
|
import pro.taskana.simplehistory.impl.classification.ClassificationHistoryQueryColumnName;
|
||||||
import pro.taskana.spi.history.api.events.classification.ClassificationHistoryEvent;
|
import pro.taskana.spi.history.api.events.classification.ClassificationHistoryEvent;
|
||||||
|
@ -33,7 +33,7 @@ public class ClassificationHistoryQueryImpl implements ClassificationHistoryQuer
|
||||||
private static final String SQL_EXCEPTION_MESSAGE =
|
private static final String SQL_EXCEPTION_MESSAGE =
|
||||||
"Method openConnection() could not open a connection to the database.";
|
"Method openConnection() could not open a connection to the database.";
|
||||||
|
|
||||||
private final TaskanaHistoryEngineImpl taskanaHistoryEngine;
|
private final InternalTaskanaEngine internalTaskanaEngine;
|
||||||
|
|
||||||
private final List<String> orderBy = new ArrayList<>();
|
private final List<String> orderBy = new ArrayList<>();
|
||||||
private final List<String> orderColumns = new ArrayList<>();
|
private final List<String> orderColumns = new ArrayList<>();
|
||||||
|
@ -82,8 +82,8 @@ public class ClassificationHistoryQueryImpl implements ClassificationHistoryQuer
|
||||||
private String[] custom7Like;
|
private String[] custom7Like;
|
||||||
private String[] custom8Like;
|
private String[] custom8Like;
|
||||||
|
|
||||||
public ClassificationHistoryQueryImpl(TaskanaHistoryEngineImpl internalTaskanaHistoryEngine) {
|
public ClassificationHistoryQueryImpl(InternalTaskanaEngine internalTaskanaEngine) {
|
||||||
this.taskanaHistoryEngine = internalTaskanaHistoryEngine;
|
this.internalTaskanaEngine = internalTaskanaEngine;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -415,16 +415,13 @@ public class ClassificationHistoryQueryImpl implements ClassificationHistoryQuer
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ClassificationHistoryEvent> list() {
|
public List<ClassificationHistoryEvent> list() {
|
||||||
List<ClassificationHistoryEvent> result = new ArrayList<>();
|
List<ClassificationHistoryEvent> result;
|
||||||
try {
|
try {
|
||||||
taskanaHistoryEngine.openConnection();
|
internalTaskanaEngine.openConnection();
|
||||||
result = taskanaHistoryEngine.getSqlSession().selectList(LINK_TO_MAPPER, this);
|
result = internalTaskanaEngine.getSqlSession().selectList(LINK_TO_MAPPER, this);
|
||||||
return result;
|
|
||||||
} catch (SQLException e) {
|
|
||||||
LOGGER.error(SQL_EXCEPTION_MESSAGE, e.getCause());
|
|
||||||
return result;
|
return result;
|
||||||
} finally {
|
} finally {
|
||||||
taskanaHistoryEngine.returnConnection();
|
internalTaskanaEngine.returnConnection();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -432,15 +429,12 @@ public class ClassificationHistoryQueryImpl implements ClassificationHistoryQuer
|
||||||
public List<ClassificationHistoryEvent> list(int offset, int limit) {
|
public List<ClassificationHistoryEvent> list(int offset, int limit) {
|
||||||
List<ClassificationHistoryEvent> result = new ArrayList<>();
|
List<ClassificationHistoryEvent> result = new ArrayList<>();
|
||||||
try {
|
try {
|
||||||
taskanaHistoryEngine.openConnection();
|
internalTaskanaEngine.openConnection();
|
||||||
RowBounds rowBounds = new RowBounds(offset, limit);
|
RowBounds rowBounds = new RowBounds(offset, limit);
|
||||||
result = taskanaHistoryEngine.getSqlSession().selectList(LINK_TO_MAPPER, this, rowBounds);
|
result = internalTaskanaEngine.getSqlSession().selectList(LINK_TO_MAPPER, this, rowBounds);
|
||||||
return result;
|
|
||||||
} catch (SQLException e) {
|
|
||||||
LOGGER.error(SQL_EXCEPTION_MESSAGE, e.getCause());
|
|
||||||
return result;
|
return result;
|
||||||
} finally {
|
} finally {
|
||||||
taskanaHistoryEngine.returnConnection();
|
internalTaskanaEngine.returnConnection();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -454,17 +448,14 @@ public class ClassificationHistoryQueryImpl implements ClassificationHistoryQuer
|
||||||
this.addOrderCriteria(columnName.toString(), sortDirection);
|
this.addOrderCriteria(columnName.toString(), sortDirection);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
taskanaHistoryEngine.openConnection();
|
internalTaskanaEngine.openConnection();
|
||||||
result = taskanaHistoryEngine.getSqlSession().selectList(LINK_TO_VALUE_MAPPER, this);
|
result = internalTaskanaEngine.getSqlSession().selectList(LINK_TO_VALUE_MAPPER, this);
|
||||||
return result;
|
|
||||||
} catch (SQLException e) {
|
|
||||||
LOGGER.error(SQL_EXCEPTION_MESSAGE, e.getCause());
|
|
||||||
return result;
|
return result;
|
||||||
} finally {
|
} finally {
|
||||||
this.orderBy.addAll(cacheOrderBy);
|
this.orderBy.addAll(cacheOrderBy);
|
||||||
this.columnName = null;
|
this.columnName = null;
|
||||||
this.orderColumns.remove(orderColumns.size() - 1);
|
this.orderColumns.remove(orderColumns.size() - 1);
|
||||||
taskanaHistoryEngine.returnConnection();
|
internalTaskanaEngine.returnConnection();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -473,15 +464,12 @@ public class ClassificationHistoryQueryImpl implements ClassificationHistoryQuer
|
||||||
ClassificationHistoryEvent result = null;
|
ClassificationHistoryEvent result = null;
|
||||||
try {
|
try {
|
||||||
|
|
||||||
taskanaHistoryEngine.openConnection();
|
internalTaskanaEngine.openConnection();
|
||||||
result = taskanaHistoryEngine.getSqlSession().selectOne(LINK_TO_MAPPER, this);
|
result = internalTaskanaEngine.getSqlSession().selectOne(LINK_TO_MAPPER, this);
|
||||||
|
|
||||||
return result;
|
|
||||||
} catch (SQLException e) {
|
|
||||||
LOGGER.error(SQL_EXCEPTION_MESSAGE, e.getCause());
|
|
||||||
return result;
|
return result;
|
||||||
} finally {
|
} finally {
|
||||||
taskanaHistoryEngine.returnConnection();
|
internalTaskanaEngine.returnConnection();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -489,14 +477,11 @@ public class ClassificationHistoryQueryImpl implements ClassificationHistoryQuer
|
||||||
public long count() {
|
public long count() {
|
||||||
Long rowCount = null;
|
Long rowCount = null;
|
||||||
try {
|
try {
|
||||||
taskanaHistoryEngine.openConnection();
|
internalTaskanaEngine.openConnection();
|
||||||
rowCount = taskanaHistoryEngine.getSqlSession().selectOne(LINK_TO_COUNTER, this);
|
rowCount = internalTaskanaEngine.getSqlSession().selectOne(LINK_TO_COUNTER, this);
|
||||||
return (rowCount == null) ? 0L : rowCount;
|
return (rowCount == null) ? 0L : rowCount;
|
||||||
} catch (SQLException e) {
|
|
||||||
LOGGER.error(SQL_EXCEPTION_MESSAGE, e.getCause());
|
|
||||||
return -1;
|
|
||||||
} finally {
|
} finally {
|
||||||
taskanaHistoryEngine.returnConnection();
|
internalTaskanaEngine.returnConnection();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,20 +1,27 @@
|
||||||
package pro.taskana.simplehistory.impl;
|
package pro.taskana.simplehistory.impl;
|
||||||
|
|
||||||
import java.sql.SQLException;
|
import java.lang.reflect.Field;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import org.apache.ibatis.session.SqlSession;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import pro.taskana.common.api.TaskanaEngine;
|
import pro.taskana.common.api.TaskanaEngine;
|
||||||
import pro.taskana.common.api.TaskanaRole;
|
import pro.taskana.common.api.TaskanaRole;
|
||||||
import pro.taskana.common.api.exceptions.InvalidArgumentException;
|
import pro.taskana.common.api.exceptions.InvalidArgumentException;
|
||||||
import pro.taskana.common.api.exceptions.NotAuthorizedException;
|
import pro.taskana.common.api.exceptions.NotAuthorizedException;
|
||||||
|
import pro.taskana.common.api.exceptions.SystemException;
|
||||||
|
import pro.taskana.common.internal.InternalTaskanaEngine;
|
||||||
|
import pro.taskana.common.internal.TaskanaEngineImpl;
|
||||||
import pro.taskana.simplehistory.impl.classification.ClassificationHistoryEventMapper;
|
import pro.taskana.simplehistory.impl.classification.ClassificationHistoryEventMapper;
|
||||||
import pro.taskana.simplehistory.impl.classification.ClassificationHistoryQuery;
|
import pro.taskana.simplehistory.impl.classification.ClassificationHistoryQuery;
|
||||||
|
import pro.taskana.simplehistory.impl.classification.ClassificationHistoryQueryMapper;
|
||||||
import pro.taskana.simplehistory.impl.task.TaskHistoryEventMapper;
|
import pro.taskana.simplehistory.impl.task.TaskHistoryEventMapper;
|
||||||
import pro.taskana.simplehistory.impl.task.TaskHistoryQuery;
|
import pro.taskana.simplehistory.impl.task.TaskHistoryQuery;
|
||||||
|
import pro.taskana.simplehistory.impl.task.TaskHistoryQueryMapper;
|
||||||
import pro.taskana.simplehistory.impl.workbasket.WorkbasketHistoryEventMapper;
|
import pro.taskana.simplehistory.impl.workbasket.WorkbasketHistoryEventMapper;
|
||||||
import pro.taskana.simplehistory.impl.workbasket.WorkbasketHistoryQuery;
|
import pro.taskana.simplehistory.impl.workbasket.WorkbasketHistoryQuery;
|
||||||
|
import pro.taskana.simplehistory.impl.workbasket.WorkbasketHistoryQueryMapper;
|
||||||
import pro.taskana.spi.history.api.TaskanaHistory;
|
import pro.taskana.spi.history.api.TaskanaHistory;
|
||||||
import pro.taskana.spi.history.api.events.classification.ClassificationHistoryEvent;
|
import pro.taskana.spi.history.api.events.classification.ClassificationHistoryEvent;
|
||||||
import pro.taskana.spi.history.api.events.task.TaskHistoryEvent;
|
import pro.taskana.spi.history.api.events.task.TaskHistoryEvent;
|
||||||
|
@ -27,110 +34,149 @@ import pro.taskana.user.internal.UserMapper;
|
||||||
public class SimpleHistoryServiceImpl implements TaskanaHistory {
|
public class SimpleHistoryServiceImpl implements TaskanaHistory {
|
||||||
|
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(SimpleHistoryServiceImpl.class);
|
private static final Logger LOGGER = LoggerFactory.getLogger(SimpleHistoryServiceImpl.class);
|
||||||
private TaskanaHistoryEngineImpl taskanaHistoryEngine;
|
|
||||||
private TaskHistoryEventMapper taskHistoryEventMapper;
|
private TaskHistoryEventMapper taskHistoryEventMapper;
|
||||||
private WorkbasketHistoryEventMapper workbasketHistoryEventMapper;
|
private WorkbasketHistoryEventMapper workbasketHistoryEventMapper;
|
||||||
private ClassificationHistoryEventMapper classificationHistoryEventMapper;
|
private ClassificationHistoryEventMapper classificationHistoryEventMapper;
|
||||||
private UserMapper userMapper;
|
private UserMapper userMapper;
|
||||||
|
|
||||||
|
private InternalTaskanaEngine internalTaskanaEngine;
|
||||||
|
|
||||||
public void initialize(TaskanaEngine taskanaEngine) {
|
public void initialize(TaskanaEngine taskanaEngine) {
|
||||||
|
|
||||||
this.taskanaHistoryEngine = getTaskanaEngine(taskanaEngine);
|
LOGGER.info(
|
||||||
|
|
||||||
if (LOGGER.isDebugEnabled()) {
|
|
||||||
LOGGER.debug(
|
|
||||||
"Simple history service implementation initialized with schemaName: {} ",
|
"Simple history service implementation initialized with schemaName: {} ",
|
||||||
taskanaEngine.getConfiguration().getSchemaName());
|
taskanaEngine.getConfiguration().getSchemaName());
|
||||||
|
|
||||||
|
Field sessionManager = null;
|
||||||
|
try {
|
||||||
|
Field internalTaskanaEngineImpl =
|
||||||
|
TaskanaEngineImpl.class.getDeclaredField("internalTaskanaEngineImpl");
|
||||||
|
internalTaskanaEngineImpl.setAccessible(true);
|
||||||
|
this.internalTaskanaEngine =
|
||||||
|
(InternalTaskanaEngine) internalTaskanaEngineImpl.get(taskanaEngine);
|
||||||
|
sessionManager = TaskanaEngineImpl.class.getDeclaredField("sessionManager");
|
||||||
|
sessionManager.setAccessible(true);
|
||||||
|
} catch (NoSuchFieldException e) {
|
||||||
|
throw new SystemException("SQL Session could not be retrieved. Aborting Startup");
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
throw new SystemException(e.getMessage());
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
SqlSession sqlSession = (SqlSession) sessionManager.get(taskanaEngine);
|
||||||
|
if (!sqlSession
|
||||||
|
.getConfiguration()
|
||||||
|
.getMapperRegistry()
|
||||||
|
.hasMapper(TaskHistoryEventMapper.class)) {
|
||||||
|
sqlSession.getConfiguration().addMapper(TaskHistoryEventMapper.class);
|
||||||
|
}
|
||||||
|
if (!sqlSession
|
||||||
|
.getConfiguration()
|
||||||
|
.getMapperRegistry()
|
||||||
|
.hasMapper(WorkbasketHistoryEventMapper.class)) {
|
||||||
|
|
||||||
|
sqlSession.getConfiguration().addMapper(WorkbasketHistoryEventMapper.class);
|
||||||
|
}
|
||||||
|
if (!sqlSession
|
||||||
|
.getConfiguration()
|
||||||
|
.getMapperRegistry()
|
||||||
|
.hasMapper(ClassificationHistoryEventMapper.class)) {
|
||||||
|
|
||||||
|
sqlSession.getConfiguration().addMapper(ClassificationHistoryEventMapper.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.taskHistoryEventMapper =
|
if (!sqlSession
|
||||||
this.taskanaHistoryEngine.getSqlSession().getMapper(TaskHistoryEventMapper.class);
|
.getConfiguration()
|
||||||
this.workbasketHistoryEventMapper =
|
.getMapperRegistry()
|
||||||
this.taskanaHistoryEngine.getSqlSession().getMapper(WorkbasketHistoryEventMapper.class);
|
.hasMapper(ClassificationHistoryQueryMapper.class)) {
|
||||||
|
|
||||||
|
sqlSession.getConfiguration().addMapper(ClassificationHistoryQueryMapper.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sqlSession
|
||||||
|
.getConfiguration()
|
||||||
|
.getMapperRegistry()
|
||||||
|
.hasMapper(TaskHistoryQueryMapper.class)) {
|
||||||
|
|
||||||
|
sqlSession.getConfiguration().addMapper(TaskHistoryQueryMapper.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sqlSession
|
||||||
|
.getConfiguration()
|
||||||
|
.getMapperRegistry()
|
||||||
|
.hasMapper(WorkbasketHistoryQueryMapper.class)) {
|
||||||
|
|
||||||
|
sqlSession.getConfiguration().addMapper(WorkbasketHistoryQueryMapper.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.taskHistoryEventMapper = sqlSession.getMapper(TaskHistoryEventMapper.class);
|
||||||
|
this.workbasketHistoryEventMapper = sqlSession.getMapper(WorkbasketHistoryEventMapper.class);
|
||||||
this.classificationHistoryEventMapper =
|
this.classificationHistoryEventMapper =
|
||||||
this.taskanaHistoryEngine.getSqlSession().getMapper(ClassificationHistoryEventMapper.class);
|
sqlSession.getMapper(ClassificationHistoryEventMapper.class);
|
||||||
this.userMapper = taskanaHistoryEngine.getSqlSession().getMapper(UserMapper.class);
|
this.userMapper = sqlSession.getMapper(UserMapper.class);
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
throw new SystemException(
|
||||||
|
"TASKANA engine of Session Manager could not be retrieved. Aborting Startup");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void create(TaskHistoryEvent event) {
|
public void create(TaskHistoryEvent event) {
|
||||||
try {
|
|
||||||
taskanaHistoryEngine.openConnection();
|
|
||||||
if (event.getCreated() == null) {
|
if (event.getCreated() == null) {
|
||||||
Instant now = Instant.now();
|
Instant now = Instant.now();
|
||||||
event.setCreated(now);
|
event.setCreated(now);
|
||||||
}
|
}
|
||||||
taskHistoryEventMapper.insert(event);
|
taskHistoryEventMapper.insert(event);
|
||||||
} catch (SQLException e) {
|
|
||||||
LOGGER.error("Error while inserting task history event into database", e);
|
|
||||||
} finally {
|
|
||||||
taskanaHistoryEngine.returnConnection();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void create(WorkbasketHistoryEvent event) {
|
public void create(WorkbasketHistoryEvent event) {
|
||||||
try {
|
|
||||||
taskanaHistoryEngine.openConnection();
|
|
||||||
if (event.getCreated() == null) {
|
if (event.getCreated() == null) {
|
||||||
Instant now = Instant.now();
|
Instant now = Instant.now();
|
||||||
event.setCreated(now);
|
event.setCreated(now);
|
||||||
}
|
}
|
||||||
workbasketHistoryEventMapper.insert(event);
|
workbasketHistoryEventMapper.insert(event);
|
||||||
} catch (SQLException e) {
|
|
||||||
LOGGER.error("Error while inserting workbasket history event into database", e);
|
|
||||||
} finally {
|
|
||||||
taskanaHistoryEngine.returnConnection();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void create(ClassificationHistoryEvent event) {
|
public void create(ClassificationHistoryEvent event) {
|
||||||
try {
|
|
||||||
taskanaHistoryEngine.openConnection();
|
|
||||||
if (event.getCreated() == null) {
|
if (event.getCreated() == null) {
|
||||||
Instant now = Instant.now();
|
Instant now = Instant.now();
|
||||||
event.setCreated(now);
|
event.setCreated(now);
|
||||||
}
|
}
|
||||||
classificationHistoryEventMapper.insert(event);
|
classificationHistoryEventMapper.insert(event);
|
||||||
} catch (SQLException e) {
|
|
||||||
LOGGER.error("Error while inserting classification history event into database", e);
|
|
||||||
} finally {
|
|
||||||
taskanaHistoryEngine.returnConnection();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void deleteHistoryEventsByTaskIds(List<String> taskIds)
|
public void deleteHistoryEventsByTaskIds(List<String> taskIds)
|
||||||
throws InvalidArgumentException, NotAuthorizedException {
|
throws InvalidArgumentException, NotAuthorizedException {
|
||||||
taskanaHistoryEngine.checkRoleMembership(TaskanaRole.ADMIN);
|
|
||||||
|
internalTaskanaEngine.openConnection();
|
||||||
|
internalTaskanaEngine.getEngine().checkRoleMembership(TaskanaRole.ADMIN);
|
||||||
|
|
||||||
if (taskIds == null) {
|
if (taskIds == null) {
|
||||||
throw new InvalidArgumentException("List of taskIds must not be null.");
|
throw new InvalidArgumentException("List of taskIds must not be null.");
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
|
||||||
taskanaHistoryEngine.openConnection();
|
|
||||||
taskHistoryEventMapper.deleteMultipleByTaskIds(taskIds);
|
taskHistoryEventMapper.deleteMultipleByTaskIds(taskIds);
|
||||||
} catch (SQLException e) {
|
|
||||||
LOGGER.error("Caught exception while trying to delete history events", e);
|
internalTaskanaEngine.returnConnection();
|
||||||
} finally {
|
|
||||||
taskanaHistoryEngine.returnConnection();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public TaskHistoryEvent getTaskHistoryEvent(String historyEventId)
|
public TaskHistoryEvent getTaskHistoryEvent(String historyEventId)
|
||||||
throws TaskanaHistoryEventNotFoundException {
|
throws TaskanaHistoryEventNotFoundException {
|
||||||
TaskHistoryEvent resultEvent = null;
|
TaskHistoryEvent resultEvent = null;
|
||||||
try {
|
try {
|
||||||
taskanaHistoryEngine.openConnection();
|
internalTaskanaEngine.openConnection();
|
||||||
resultEvent = taskHistoryEventMapper.findById(historyEventId);
|
resultEvent = taskHistoryEventMapper.findById(historyEventId);
|
||||||
|
|
||||||
if (resultEvent == null) {
|
if (resultEvent == null) {
|
||||||
throw new TaskanaHistoryEventNotFoundException(historyEventId);
|
throw new TaskanaHistoryEventNotFoundException(historyEventId);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (taskanaHistoryEngine.getConfiguration().isAddAdditionalUserInfo()) {
|
if (internalTaskanaEngine.getEngine().getConfiguration().isAddAdditionalUserInfo()) {
|
||||||
User user = userMapper.findById(resultEvent.getUserId());
|
User user = userMapper.findById(resultEvent.getUserId());
|
||||||
if (user != null) {
|
if (user != null) {
|
||||||
resultEvent.setUserLongName(user.getLongName());
|
resultEvent.setUserLongName(user.getLongName());
|
||||||
|
@ -138,30 +184,20 @@ public class SimpleHistoryServiceImpl implements TaskanaHistory {
|
||||||
}
|
}
|
||||||
return resultEvent;
|
return resultEvent;
|
||||||
|
|
||||||
} catch (SQLException e) {
|
|
||||||
LOGGER.error("Caught exception while trying to retrieve a history event", e);
|
|
||||||
return resultEvent;
|
|
||||||
} finally {
|
} finally {
|
||||||
taskanaHistoryEngine.returnConnection();
|
internalTaskanaEngine.returnConnection();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public TaskHistoryQuery createTaskHistoryQuery() {
|
public TaskHistoryQuery createTaskHistoryQuery() {
|
||||||
return new TaskHistoryQueryImpl(taskanaHistoryEngine);
|
return new TaskHistoryQueryImpl(internalTaskanaEngine);
|
||||||
}
|
}
|
||||||
|
|
||||||
public WorkbasketHistoryQuery createWorkbasketHistoryQuery() {
|
public WorkbasketHistoryQuery createWorkbasketHistoryQuery() {
|
||||||
return new WorkbasketHistoryQueryImpl(taskanaHistoryEngine);
|
return new WorkbasketHistoryQueryImpl(internalTaskanaEngine);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ClassificationHistoryQuery createClassificationHistoryQuery() {
|
public ClassificationHistoryQuery createClassificationHistoryQuery() {
|
||||||
return new ClassificationHistoryQueryImpl(taskanaHistoryEngine);
|
return new ClassificationHistoryQueryImpl(internalTaskanaEngine);
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* ATTENTION: This method exists for testing purposes.
|
|
||||||
*/
|
|
||||||
TaskanaHistoryEngineImpl getTaskanaEngine(TaskanaEngine taskanaEngine) {
|
|
||||||
return TaskanaHistoryEngineImpl.createTaskanaEngine(taskanaEngine);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,6 @@ package pro.taskana.simplehistory.impl;
|
||||||
|
|
||||||
import static pro.taskana.common.api.BaseQuery.toLowerCopy;
|
import static pro.taskana.common.api.BaseQuery.toLowerCopy;
|
||||||
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import org.apache.ibatis.session.RowBounds;
|
import org.apache.ibatis.session.RowBounds;
|
||||||
|
@ -10,6 +9,7 @@ import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import pro.taskana.common.api.TimeInterval;
|
import pro.taskana.common.api.TimeInterval;
|
||||||
import pro.taskana.common.api.exceptions.SystemException;
|
import pro.taskana.common.api.exceptions.SystemException;
|
||||||
|
import pro.taskana.common.internal.InternalTaskanaEngine;
|
||||||
import pro.taskana.simplehistory.impl.task.TaskHistoryQuery;
|
import pro.taskana.simplehistory.impl.task.TaskHistoryQuery;
|
||||||
import pro.taskana.simplehistory.impl.task.TaskHistoryQueryColumnName;
|
import pro.taskana.simplehistory.impl.task.TaskHistoryQueryColumnName;
|
||||||
import pro.taskana.spi.history.api.events.task.TaskHistoryCustomField;
|
import pro.taskana.spi.history.api.events.task.TaskHistoryCustomField;
|
||||||
|
@ -30,7 +30,7 @@ public class TaskHistoryQueryImpl implements TaskHistoryQuery {
|
||||||
private static final String SQL_EXCEPTION_MESSAGE =
|
private static final String SQL_EXCEPTION_MESSAGE =
|
||||||
"Method openConnection() could not open a connection to the database.";
|
"Method openConnection() could not open a connection to the database.";
|
||||||
|
|
||||||
private final TaskanaHistoryEngineImpl taskanaHistoryEngine;
|
private final InternalTaskanaEngine internalTaskanaEngine;
|
||||||
private final List<String> orderBy;
|
private final List<String> orderBy;
|
||||||
private final List<String> orderColumns;
|
private final List<String> orderColumns;
|
||||||
private boolean joinWithUserInfo;
|
private boolean joinWithUserInfo;
|
||||||
|
@ -83,11 +83,12 @@ public class TaskHistoryQueryImpl implements TaskHistoryQuery {
|
||||||
private String[] custom3Like;
|
private String[] custom3Like;
|
||||||
private String[] custom4Like;
|
private String[] custom4Like;
|
||||||
|
|
||||||
public TaskHistoryQueryImpl(TaskanaHistoryEngineImpl taskanaHistoryEngine) {
|
public TaskHistoryQueryImpl(InternalTaskanaEngine internalTaskanaEngine) {
|
||||||
this.taskanaHistoryEngine = taskanaHistoryEngine;
|
this.internalTaskanaEngine = internalTaskanaEngine;
|
||||||
this.orderBy = new ArrayList<>();
|
this.orderBy = new ArrayList<>();
|
||||||
this.orderColumns = new ArrayList<>();
|
this.orderColumns = new ArrayList<>();
|
||||||
this.joinWithUserInfo = taskanaHistoryEngine.getConfiguration().isAddAdditionalUserInfo();
|
this.joinWithUserInfo =
|
||||||
|
internalTaskanaEngine.getEngine().getConfiguration().isAddAdditionalUserInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String[] getIdIn() {
|
public String[] getIdIn() {
|
||||||
|
@ -631,14 +632,11 @@ public class TaskHistoryQueryImpl implements TaskHistoryQuery {
|
||||||
public List<TaskHistoryEvent> list() {
|
public List<TaskHistoryEvent> list() {
|
||||||
List<TaskHistoryEvent> result = new ArrayList<>();
|
List<TaskHistoryEvent> result = new ArrayList<>();
|
||||||
try {
|
try {
|
||||||
taskanaHistoryEngine.openConnection();
|
internalTaskanaEngine.openConnection();
|
||||||
result = taskanaHistoryEngine.getSqlSession().selectList(LINK_TO_MAPPER, this);
|
result = internalTaskanaEngine.getSqlSession().selectList(LINK_TO_MAPPER, this);
|
||||||
return result;
|
|
||||||
} catch (SQLException e) {
|
|
||||||
LOGGER.error(SQL_EXCEPTION_MESSAGE, e.getCause());
|
|
||||||
return result;
|
return result;
|
||||||
} finally {
|
} finally {
|
||||||
taskanaHistoryEngine.returnConnection();
|
internalTaskanaEngine.returnConnection();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -646,15 +644,12 @@ public class TaskHistoryQueryImpl implements TaskHistoryQuery {
|
||||||
public List<TaskHistoryEvent> list(int offset, int limit) {
|
public List<TaskHistoryEvent> list(int offset, int limit) {
|
||||||
List<TaskHistoryEvent> result = new ArrayList<>();
|
List<TaskHistoryEvent> result = new ArrayList<>();
|
||||||
try {
|
try {
|
||||||
taskanaHistoryEngine.openConnection();
|
internalTaskanaEngine.openConnection();
|
||||||
RowBounds rowBounds = new RowBounds(offset, limit);
|
RowBounds rowBounds = new RowBounds(offset, limit);
|
||||||
result = taskanaHistoryEngine.getSqlSession().selectList(LINK_TO_MAPPER, this, rowBounds);
|
result = internalTaskanaEngine.getSqlSession().selectList(LINK_TO_MAPPER, this, rowBounds);
|
||||||
return result;
|
|
||||||
} catch (SQLException e) {
|
|
||||||
LOGGER.error(SQL_EXCEPTION_MESSAGE, e.getCause());
|
|
||||||
return result;
|
return result;
|
||||||
} finally {
|
} finally {
|
||||||
taskanaHistoryEngine.returnConnection();
|
internalTaskanaEngine.returnConnection();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -672,15 +667,12 @@ public class TaskHistoryQueryImpl implements TaskHistoryQuery {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
taskanaHistoryEngine.openConnection();
|
internalTaskanaEngine.openConnection();
|
||||||
result = taskanaHistoryEngine.getSqlSession().selectList(LINK_TO_VALUE_MAPPER, this);
|
result = internalTaskanaEngine.getSqlSession().selectList(LINK_TO_VALUE_MAPPER, this);
|
||||||
return result;
|
|
||||||
} catch (SQLException e) {
|
|
||||||
LOGGER.error(SQL_EXCEPTION_MESSAGE, e.getCause());
|
|
||||||
return result;
|
return result;
|
||||||
} finally {
|
} finally {
|
||||||
this.orderColumns.remove(orderColumns.size() - 1);
|
this.orderColumns.remove(orderColumns.size() - 1);
|
||||||
taskanaHistoryEngine.returnConnection();
|
internalTaskanaEngine.returnConnection();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -688,16 +680,13 @@ public class TaskHistoryQueryImpl implements TaskHistoryQuery {
|
||||||
public TaskHistoryEvent single() {
|
public TaskHistoryEvent single() {
|
||||||
TaskHistoryEvent result = null;
|
TaskHistoryEvent result = null;
|
||||||
try {
|
try {
|
||||||
taskanaHistoryEngine.openConnection();
|
internalTaskanaEngine.openConnection();
|
||||||
result = taskanaHistoryEngine.getSqlSession().selectOne(LINK_TO_MAPPER, this);
|
result = internalTaskanaEngine.getSqlSession().selectOne(LINK_TO_MAPPER, this);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
} catch (SQLException e) {
|
|
||||||
LOGGER.error(SQL_EXCEPTION_MESSAGE, e.getCause());
|
|
||||||
return result;
|
|
||||||
} finally {
|
} finally {
|
||||||
taskanaHistoryEngine.returnConnection();
|
internalTaskanaEngine.returnConnection();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -705,14 +694,11 @@ public class TaskHistoryQueryImpl implements TaskHistoryQuery {
|
||||||
public long count() {
|
public long count() {
|
||||||
Long rowCount;
|
Long rowCount;
|
||||||
try {
|
try {
|
||||||
taskanaHistoryEngine.openConnection();
|
internalTaskanaEngine.openConnection();
|
||||||
rowCount = taskanaHistoryEngine.getSqlSession().selectOne(LINK_TO_COUNTER, this);
|
rowCount = internalTaskanaEngine.getSqlSession().selectOne(LINK_TO_COUNTER, this);
|
||||||
return (rowCount == null) ? 0L : rowCount;
|
return (rowCount == null) ? 0L : rowCount;
|
||||||
} catch (SQLException e) {
|
|
||||||
LOGGER.error(SQL_EXCEPTION_MESSAGE, e.getCause());
|
|
||||||
return -1;
|
|
||||||
} finally {
|
} finally {
|
||||||
taskanaHistoryEngine.returnConnection();
|
internalTaskanaEngine.returnConnection();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,255 +0,0 @@
|
||||||
package pro.taskana.simplehistory.impl;
|
|
||||||
|
|
||||||
import java.sql.Connection;
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.time.Instant;
|
|
||||||
import java.util.ArrayDeque;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Deque;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
import org.apache.ibatis.mapping.Environment;
|
|
||||||
import org.apache.ibatis.session.Configuration;
|
|
||||||
import org.apache.ibatis.session.SqlSession;
|
|
||||||
import org.apache.ibatis.session.SqlSessionFactory;
|
|
||||||
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
|
|
||||||
import org.apache.ibatis.session.SqlSessionManager;
|
|
||||||
import org.apache.ibatis.transaction.TransactionFactory;
|
|
||||||
import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;
|
|
||||||
import org.apache.ibatis.transaction.managed.ManagedTransactionFactory;
|
|
||||||
import org.apache.ibatis.type.JdbcType;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import pro.taskana.TaskanaConfiguration;
|
|
||||||
import pro.taskana.common.api.TaskanaEngine;
|
|
||||||
import pro.taskana.common.api.TaskanaRole;
|
|
||||||
import pro.taskana.common.api.exceptions.NotAuthorizedException;
|
|
||||||
import pro.taskana.common.api.exceptions.SystemException;
|
|
||||||
import pro.taskana.common.internal.OracleSqlSessionFactory;
|
|
||||||
import pro.taskana.common.internal.configuration.DB;
|
|
||||||
import pro.taskana.common.internal.persistence.InstantTypeHandler;
|
|
||||||
import pro.taskana.common.internal.persistence.MapTypeHandler;
|
|
||||||
import pro.taskana.common.internal.persistence.StringTypeHandler;
|
|
||||||
import pro.taskana.simplehistory.TaskanaHistoryEngine;
|
|
||||||
import pro.taskana.simplehistory.impl.classification.ClassificationHistoryEventMapper;
|
|
||||||
import pro.taskana.simplehistory.impl.classification.ClassificationHistoryQueryMapper;
|
|
||||||
import pro.taskana.simplehistory.impl.task.TaskHistoryEventMapper;
|
|
||||||
import pro.taskana.simplehistory.impl.task.TaskHistoryQueryMapper;
|
|
||||||
import pro.taskana.simplehistory.impl.workbasket.WorkbasketHistoryEventMapper;
|
|
||||||
import pro.taskana.simplehistory.impl.workbasket.WorkbasketHistoryQueryMapper;
|
|
||||||
import pro.taskana.spi.history.api.TaskanaHistory;
|
|
||||||
import pro.taskana.user.internal.UserMapper;
|
|
||||||
|
|
||||||
/** This is the implementation of TaskanaHistoryEngine. */
|
|
||||||
public class TaskanaHistoryEngineImpl implements TaskanaHistoryEngine {
|
|
||||||
|
|
||||||
protected static final ThreadLocal<Deque<SqlSessionManager>> SESSION_STACK = new ThreadLocal<>();
|
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(TaskanaHistoryEngineImpl.class);
|
|
||||||
private static final String DEFAULT = "default";
|
|
||||||
private final SqlSessionManager sessionManager;
|
|
||||||
private final TaskanaConfiguration taskanaConfiguration;
|
|
||||||
private final TaskanaEngine taskanaEngine;
|
|
||||||
private TransactionFactory transactionFactory;
|
|
||||||
private TaskanaHistory taskanaHistoryService;
|
|
||||||
|
|
||||||
protected TaskanaHistoryEngineImpl(TaskanaEngine taskanaEngine) {
|
|
||||||
this.taskanaConfiguration = taskanaEngine.getConfiguration();
|
|
||||||
this.taskanaEngine = taskanaEngine;
|
|
||||||
|
|
||||||
createTransactionFactory(taskanaConfiguration.isUseManagedTransactions());
|
|
||||||
sessionManager = createSqlSessionManager();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static TaskanaHistoryEngineImpl createTaskanaEngine(TaskanaEngine taskanaEngine) {
|
|
||||||
return new TaskanaHistoryEngineImpl(taskanaEngine);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public TaskanaHistory getTaskanaHistoryService() {
|
|
||||||
if (taskanaHistoryService == null) {
|
|
||||||
SimpleHistoryServiceImpl historyService = new SimpleHistoryServiceImpl();
|
|
||||||
historyService.initialize(taskanaEngine);
|
|
||||||
taskanaHistoryService = historyService;
|
|
||||||
}
|
|
||||||
return taskanaHistoryService;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isUserInRole(TaskanaRole... roles) {
|
|
||||||
if (!getConfiguration().isSecurityEnabled()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
Set<String> rolesMembers =
|
|
||||||
Arrays.stream(roles)
|
|
||||||
.map(role -> getConfiguration().getRoleMap().get(role))
|
|
||||||
.collect(HashSet::new, Set::addAll, Set::addAll);
|
|
||||||
|
|
||||||
return taskanaEngine.getCurrentUserContext().getAccessIds().stream()
|
|
||||||
.anyMatch(rolesMembers::contains);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void checkRoleMembership(TaskanaRole... roles) throws NotAuthorizedException {
|
|
||||||
if (!isUserInRole(roles)) {
|
|
||||||
if (LOGGER.isDebugEnabled()) {
|
|
||||||
LOGGER.debug(
|
|
||||||
"Throwing NotAuthorizedException because accessIds {} are not member of roles {}",
|
|
||||||
taskanaEngine.getCurrentUserContext().getAccessIds(),
|
|
||||||
Arrays.toString(roles));
|
|
||||||
}
|
|
||||||
throw new NotAuthorizedException(taskanaEngine.getCurrentUserContext().getUserid(), roles);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public TaskanaConfiguration getConfiguration() {
|
|
||||||
return this.taskanaConfiguration;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected SqlSessionManager createSqlSessionManager() {
|
|
||||||
Environment environment =
|
|
||||||
new Environment(DEFAULT, this.transactionFactory, taskanaConfiguration.getDataSource());
|
|
||||||
Configuration configuration = new Configuration(environment);
|
|
||||||
|
|
||||||
// set databaseId
|
|
||||||
DB db;
|
|
||||||
try (Connection con = taskanaConfiguration.getDataSource().getConnection()) {
|
|
||||||
db = DB.getDB(con);
|
|
||||||
configuration.setDatabaseId(db.dbProductId);
|
|
||||||
} catch (SQLException e) {
|
|
||||||
throw new SystemException("Could not open a connection to set the databaseId", e);
|
|
||||||
}
|
|
||||||
|
|
||||||
// register type handlers
|
|
||||||
if (DB.ORACLE == db) {
|
|
||||||
// Use NULL instead of OTHER when jdbcType is not specified for null values,
|
|
||||||
// otherwise oracle driver will chunck on null values
|
|
||||||
configuration.setJdbcTypeForNull(JdbcType.NULL);
|
|
||||||
configuration.getTypeHandlerRegistry().register(String.class, new StringTypeHandler());
|
|
||||||
}
|
|
||||||
configuration.getTypeHandlerRegistry().register(new MapTypeHandler());
|
|
||||||
configuration.getTypeHandlerRegistry().register(Instant.class, new InstantTypeHandler());
|
|
||||||
configuration.getTypeHandlerRegistry().register(JdbcType.TIMESTAMP, new InstantTypeHandler());
|
|
||||||
|
|
||||||
// add mappers
|
|
||||||
configuration.addMapper(TaskHistoryEventMapper.class);
|
|
||||||
configuration.addMapper(TaskHistoryQueryMapper.class);
|
|
||||||
configuration.addMapper(WorkbasketHistoryEventMapper.class);
|
|
||||||
configuration.addMapper(WorkbasketHistoryQueryMapper.class);
|
|
||||||
configuration.addMapper(ClassificationHistoryEventMapper.class);
|
|
||||||
configuration.addMapper(ClassificationHistoryQueryMapper.class);
|
|
||||||
configuration.addMapper(UserMapper.class);
|
|
||||||
|
|
||||||
SqlSessionFactory localSessionFactory;
|
|
||||||
if (DB.ORACLE == db) {
|
|
||||||
localSessionFactory =
|
|
||||||
new SqlSessionFactoryBuilder() {
|
|
||||||
@Override
|
|
||||||
public SqlSessionFactory build(Configuration config) {
|
|
||||||
return new OracleSqlSessionFactory(config);
|
|
||||||
}
|
|
||||||
}.build(configuration);
|
|
||||||
} else {
|
|
||||||
localSessionFactory = new SqlSessionFactoryBuilder().build(configuration);
|
|
||||||
}
|
|
||||||
return SqlSessionManager.newInstance(localSessionFactory);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static void pushSessionToStack(SqlSessionManager session) {
|
|
||||||
getSessionStack().push(session);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static void popSessionFromStack() {
|
|
||||||
Deque<SqlSessionManager> stack = getSessionStack();
|
|
||||||
if (!stack.isEmpty()) {
|
|
||||||
stack.pop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* With sessionStack, we maintain a Stack of SqlSessionManager objects on a per thread basis.
|
|
||||||
* SqlSessionManager is the MyBatis object that wraps database connections. The purpose of this
|
|
||||||
* stack is to keep track of nested calls. Each external API call is wrapped into
|
|
||||||
* taskanaEngineImpl.openConnection(); ..... taskanaEngineImpl.returnConnection(); calls. In order
|
|
||||||
* to avoid duplicate opening / closing of connections, we use the sessionStack in the following
|
|
||||||
* way: Each time, an openConnection call is received, we push the current sessionManager onto the
|
|
||||||
* stack. On the first call to openConnection, we call sessionManager.startManagedSession() to
|
|
||||||
* open a database connection. On each call to returnConnection() we pop one instance of
|
|
||||||
* sessionManager from the stack. When the stack becomes empty, we close the database connection
|
|
||||||
* by calling sessionManager.close()
|
|
||||||
*
|
|
||||||
* @return Stack of SqlSessionManager
|
|
||||||
*/
|
|
||||||
protected static Deque<SqlSessionManager> getSessionStack() {
|
|
||||||
Deque<SqlSessionManager> stack = SESSION_STACK.get();
|
|
||||||
if (stack == null) {
|
|
||||||
stack = new ArrayDeque<>();
|
|
||||||
SESSION_STACK.set(stack);
|
|
||||||
}
|
|
||||||
return stack;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static SqlSessionManager getSessionFromStack() {
|
|
||||||
Deque<SqlSessionManager> stack = getSessionStack();
|
|
||||||
if (stack.isEmpty()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return stack.peek();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Open the connection to the database. to be called at the begin of each Api call that accesses
|
|
||||||
* the database
|
|
||||||
*
|
|
||||||
* @throws SQLException thrown if the connection could not be opened.
|
|
||||||
*/
|
|
||||||
void openConnection() throws SQLException {
|
|
||||||
initSqlSession();
|
|
||||||
this.sessionManager.getConnection().setSchema(taskanaConfiguration.getSchemaName());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the database connection into the pool. In the case of nested calls, simply pops the
|
|
||||||
* latest session from the session stack. Closes the connection if the session stack is empty. In
|
|
||||||
* mode AUTOCOMMIT commits before the connection is closed. To be called at the end of each Api
|
|
||||||
* call that accesses the database
|
|
||||||
*/
|
|
||||||
void returnConnection() {
|
|
||||||
popSessionFromStack();
|
|
||||||
if (getSessionStack().isEmpty()
|
|
||||||
&& this.sessionManager != null
|
|
||||||
&& this.sessionManager.isManagedSessionStarted()) {
|
|
||||||
try {
|
|
||||||
this.sessionManager.commit();
|
|
||||||
} catch (Exception e) {
|
|
||||||
// ignore
|
|
||||||
}
|
|
||||||
this.sessionManager.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Initializes the SqlSessionManager. */
|
|
||||||
void initSqlSession() {
|
|
||||||
this.sessionManager.startManagedSession();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* retrieve the SqlSession used by taskana.
|
|
||||||
*
|
|
||||||
* @return the myBatis SqlSession object used by taskana
|
|
||||||
*/
|
|
||||||
SqlSession getSqlSession() {
|
|
||||||
return this.sessionManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* creates the MyBatis transaction factory.
|
|
||||||
*
|
|
||||||
* @param useManagedTransactions true if TASKANA should use a ManagedTransactionFactory.
|
|
||||||
*/
|
|
||||||
private void createTransactionFactory(boolean useManagedTransactions) {
|
|
||||||
if (useManagedTransactions) {
|
|
||||||
this.transactionFactory = new ManagedTransactionFactory();
|
|
||||||
} else {
|
|
||||||
this.transactionFactory = new JdbcTransactionFactory();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -2,7 +2,6 @@ package pro.taskana.simplehistory.impl;
|
||||||
|
|
||||||
import static pro.taskana.common.api.BaseQuery.toLowerCopy;
|
import static pro.taskana.common.api.BaseQuery.toLowerCopy;
|
||||||
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import org.apache.ibatis.session.RowBounds;
|
import org.apache.ibatis.session.RowBounds;
|
||||||
|
@ -11,6 +10,7 @@ import org.slf4j.LoggerFactory;
|
||||||
import pro.taskana.common.api.TimeInterval;
|
import pro.taskana.common.api.TimeInterval;
|
||||||
import pro.taskana.common.api.exceptions.InvalidArgumentException;
|
import pro.taskana.common.api.exceptions.InvalidArgumentException;
|
||||||
import pro.taskana.common.api.exceptions.SystemException;
|
import pro.taskana.common.api.exceptions.SystemException;
|
||||||
|
import pro.taskana.common.internal.InternalTaskanaEngine;
|
||||||
import pro.taskana.simplehistory.impl.workbasket.WorkbasketHistoryQuery;
|
import pro.taskana.simplehistory.impl.workbasket.WorkbasketHistoryQuery;
|
||||||
import pro.taskana.simplehistory.impl.workbasket.WorkbasketHistoryQueryColumnName;
|
import pro.taskana.simplehistory.impl.workbasket.WorkbasketHistoryQueryColumnName;
|
||||||
import pro.taskana.spi.history.api.events.workbasket.WorkbasketHistoryEvent;
|
import pro.taskana.spi.history.api.events.workbasket.WorkbasketHistoryEvent;
|
||||||
|
@ -30,7 +30,7 @@ public class WorkbasketHistoryQueryImpl implements WorkbasketHistoryQuery {
|
||||||
private static final String SQL_EXCEPTION_MESSAGE =
|
private static final String SQL_EXCEPTION_MESSAGE =
|
||||||
"Method openConnection() could not open a connection to the database.";
|
"Method openConnection() could not open a connection to the database.";
|
||||||
|
|
||||||
private final TaskanaHistoryEngineImpl taskanaHistoryEngine;
|
private final InternalTaskanaEngine internalTaskanaEngine;
|
||||||
private final List<String> orderColumns;
|
private final List<String> orderColumns;
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
|
@ -71,8 +71,8 @@ public class WorkbasketHistoryQueryImpl implements WorkbasketHistoryQuery {
|
||||||
private String[] orgLevel3Like;
|
private String[] orgLevel3Like;
|
||||||
private String[] orgLevel4Like;
|
private String[] orgLevel4Like;
|
||||||
|
|
||||||
public WorkbasketHistoryQueryImpl(TaskanaHistoryEngineImpl internalTaskanaHistoryEngine) {
|
public WorkbasketHistoryQueryImpl(InternalTaskanaEngine internalTaskanaEngine) {
|
||||||
this.taskanaHistoryEngine = internalTaskanaHistoryEngine;
|
this.internalTaskanaEngine = internalTaskanaEngine;
|
||||||
this.orderBy = new ArrayList<>();
|
this.orderBy = new ArrayList<>();
|
||||||
this.orderColumns = new ArrayList<>();
|
this.orderColumns = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
@ -475,14 +475,11 @@ public class WorkbasketHistoryQueryImpl implements WorkbasketHistoryQuery {
|
||||||
public List<WorkbasketHistoryEvent> list() {
|
public List<WorkbasketHistoryEvent> list() {
|
||||||
List<WorkbasketHistoryEvent> result = new ArrayList<>();
|
List<WorkbasketHistoryEvent> result = new ArrayList<>();
|
||||||
try {
|
try {
|
||||||
taskanaHistoryEngine.openConnection();
|
internalTaskanaEngine.openConnection();
|
||||||
result = taskanaHistoryEngine.getSqlSession().selectList(LINK_TO_MAPPER, this);
|
result = internalTaskanaEngine.getSqlSession().selectList(LINK_TO_MAPPER, this);
|
||||||
return result;
|
|
||||||
} catch (SQLException e) {
|
|
||||||
LOGGER.error(SQL_EXCEPTION_MESSAGE, e.getCause());
|
|
||||||
return result;
|
return result;
|
||||||
} finally {
|
} finally {
|
||||||
taskanaHistoryEngine.returnConnection();
|
internalTaskanaEngine.returnConnection();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -490,15 +487,12 @@ public class WorkbasketHistoryQueryImpl implements WorkbasketHistoryQuery {
|
||||||
public List<WorkbasketHistoryEvent> list(int offset, int limit) {
|
public List<WorkbasketHistoryEvent> list(int offset, int limit) {
|
||||||
List<WorkbasketHistoryEvent> result = new ArrayList<>();
|
List<WorkbasketHistoryEvent> result = new ArrayList<>();
|
||||||
try {
|
try {
|
||||||
taskanaHistoryEngine.openConnection();
|
internalTaskanaEngine.openConnection();
|
||||||
RowBounds rowBounds = new RowBounds(offset, limit);
|
RowBounds rowBounds = new RowBounds(offset, limit);
|
||||||
result = taskanaHistoryEngine.getSqlSession().selectList(LINK_TO_MAPPER, this, rowBounds);
|
result = internalTaskanaEngine.getSqlSession().selectList(LINK_TO_MAPPER, this, rowBounds);
|
||||||
return result;
|
|
||||||
} catch (SQLException e) {
|
|
||||||
LOGGER.error(SQL_EXCEPTION_MESSAGE, e.getCause());
|
|
||||||
return result;
|
return result;
|
||||||
} finally {
|
} finally {
|
||||||
taskanaHistoryEngine.returnConnection();
|
internalTaskanaEngine.returnConnection();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -512,17 +506,14 @@ public class WorkbasketHistoryQueryImpl implements WorkbasketHistoryQuery {
|
||||||
this.addOrderCriteria(columnName.toString(), sortDirection);
|
this.addOrderCriteria(columnName.toString(), sortDirection);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
taskanaHistoryEngine.openConnection();
|
internalTaskanaEngine.openConnection();
|
||||||
result = taskanaHistoryEngine.getSqlSession().selectList(LINK_TO_VALUE_MAPPER, this);
|
result = internalTaskanaEngine.getSqlSession().selectList(LINK_TO_VALUE_MAPPER, this);
|
||||||
return result;
|
|
||||||
} catch (SQLException e) {
|
|
||||||
LOGGER.error(SQL_EXCEPTION_MESSAGE, e.getCause());
|
|
||||||
return result;
|
return result;
|
||||||
} finally {
|
} finally {
|
||||||
this.orderBy = cacheOrderBy;
|
this.orderBy = cacheOrderBy;
|
||||||
this.columnName = null;
|
this.columnName = null;
|
||||||
this.orderColumns.remove(orderColumns.size() - 1);
|
this.orderColumns.remove(orderColumns.size() - 1);
|
||||||
taskanaHistoryEngine.returnConnection();
|
internalTaskanaEngine.returnConnection();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -530,15 +521,12 @@ public class WorkbasketHistoryQueryImpl implements WorkbasketHistoryQuery {
|
||||||
public WorkbasketHistoryEvent single() {
|
public WorkbasketHistoryEvent single() {
|
||||||
WorkbasketHistoryEvent result = null;
|
WorkbasketHistoryEvent result = null;
|
||||||
try {
|
try {
|
||||||
taskanaHistoryEngine.openConnection();
|
internalTaskanaEngine.openConnection();
|
||||||
result = taskanaHistoryEngine.getSqlSession().selectOne(LINK_TO_MAPPER, this);
|
result = internalTaskanaEngine.getSqlSession().selectOne(LINK_TO_MAPPER, this);
|
||||||
|
|
||||||
return result;
|
|
||||||
} catch (SQLException e) {
|
|
||||||
LOGGER.error(SQL_EXCEPTION_MESSAGE, e.getCause());
|
|
||||||
return result;
|
return result;
|
||||||
} finally {
|
} finally {
|
||||||
taskanaHistoryEngine.returnConnection();
|
internalTaskanaEngine.returnConnection();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -546,14 +534,11 @@ public class WorkbasketHistoryQueryImpl implements WorkbasketHistoryQuery {
|
||||||
public long count() {
|
public long count() {
|
||||||
Long rowCount;
|
Long rowCount;
|
||||||
try {
|
try {
|
||||||
taskanaHistoryEngine.openConnection();
|
internalTaskanaEngine.openConnection();
|
||||||
rowCount = taskanaHistoryEngine.getSqlSession().selectOne(LINK_TO_COUNTER, this);
|
rowCount = internalTaskanaEngine.getSqlSession().selectOne(LINK_TO_COUNTER, this);
|
||||||
return (rowCount == null) ? 0L : rowCount;
|
return (rowCount == null) ? 0L : rowCount;
|
||||||
} catch (SQLException e) {
|
|
||||||
LOGGER.error(SQL_EXCEPTION_MESSAGE, e.getCause());
|
|
||||||
return -1;
|
|
||||||
} finally {
|
} finally {
|
||||||
taskanaHistoryEngine.returnConnection();
|
internalTaskanaEngine.returnConnection();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,32 +25,31 @@ import pro.taskana.common.internal.jobs.AbstractTaskanaJob;
|
||||||
import pro.taskana.common.internal.transaction.TaskanaTransactionProvider;
|
import pro.taskana.common.internal.transaction.TaskanaTransactionProvider;
|
||||||
import pro.taskana.common.internal.util.CollectionUtil;
|
import pro.taskana.common.internal.util.CollectionUtil;
|
||||||
import pro.taskana.simplehistory.impl.SimpleHistoryServiceImpl;
|
import pro.taskana.simplehistory.impl.SimpleHistoryServiceImpl;
|
||||||
import pro.taskana.simplehistory.impl.TaskanaHistoryEngineImpl;
|
|
||||||
import pro.taskana.spi.history.api.events.task.TaskHistoryEvent;
|
import pro.taskana.spi.history.api.events.task.TaskHistoryEvent;
|
||||||
import pro.taskana.spi.history.api.events.task.TaskHistoryEventType;
|
import pro.taskana.spi.history.api.events.task.TaskHistoryEventType;
|
||||||
|
|
||||||
public class HistoryCleanupJob extends AbstractTaskanaJob {
|
public class HistoryCleanupJob extends AbstractTaskanaJob {
|
||||||
|
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(HistoryCleanupJob.class);
|
private static final Logger LOGGER = LoggerFactory.getLogger(HistoryCleanupJob.class);
|
||||||
|
|
||||||
private final TaskanaHistoryEngineImpl taskanaHistoryEngine =
|
|
||||||
TaskanaHistoryEngineImpl.createTaskanaEngine(taskanaEngineImpl);
|
|
||||||
|
|
||||||
private final boolean allCompletedSameParentBusiness =
|
private final boolean allCompletedSameParentBusiness =
|
||||||
taskanaEngineImpl
|
taskanaEngineImpl
|
||||||
.getConfiguration()
|
.getConfiguration()
|
||||||
.isSimpleHistoryCleanupJobAllCompletedSameParentBusiness();
|
.isSimpleHistoryCleanupJobAllCompletedSameParentBusiness();
|
||||||
|
|
||||||
private final Duration minimumAge =
|
private final Duration minimumAge =
|
||||||
taskanaEngineImpl.getConfiguration().getSimpleHistoryCleanupJobMinimumAge();
|
taskanaEngineImpl.getConfiguration().getSimpleHistoryCleanupJobMinimumAge();
|
||||||
private final int batchSize =
|
private final int batchSize =
|
||||||
taskanaEngineImpl.getConfiguration().getSimpleHistoryCleanupJobBatchSize();
|
taskanaEngineImpl.getConfiguration().getSimpleHistoryCleanupJobBatchSize();
|
||||||
|
private SimpleHistoryServiceImpl simpleHistoryService = null;
|
||||||
|
|
||||||
public HistoryCleanupJob(
|
public HistoryCleanupJob(
|
||||||
TaskanaEngine taskanaEngine,
|
TaskanaEngine taskanaEngine,
|
||||||
TaskanaTransactionProvider txProvider,
|
TaskanaTransactionProvider txProvider,
|
||||||
ScheduledJob scheduledJob) {
|
ScheduledJob scheduledJob) {
|
||||||
super(taskanaEngine, txProvider, scheduledJob, true);
|
super(taskanaEngine, txProvider, scheduledJob, true);
|
||||||
|
if (simpleHistoryService == null) {
|
||||||
|
simpleHistoryService = new SimpleHistoryServiceImpl();
|
||||||
|
simpleHistoryService.initialize(taskanaEngine);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Duration getLockExpirationPeriod(TaskanaConfiguration taskanaConfiguration) {
|
public static Duration getLockExpirationPeriod(TaskanaConfiguration taskanaConfiguration) {
|
||||||
|
@ -62,9 +61,6 @@ public class HistoryCleanupJob extends AbstractTaskanaJob {
|
||||||
Instant createdBefore = Instant.now().minus(minimumAge);
|
Instant createdBefore = Instant.now().minus(minimumAge);
|
||||||
LOGGER.info("Running job to delete all history events created before ({})", createdBefore);
|
LOGGER.info("Running job to delete all history events created before ({})", createdBefore);
|
||||||
try {
|
try {
|
||||||
SimpleHistoryServiceImpl simpleHistoryService =
|
|
||||||
(SimpleHistoryServiceImpl) taskanaHistoryEngine.getTaskanaHistoryService();
|
|
||||||
|
|
||||||
List<TaskHistoryEvent> historyEventCandidatesToClean =
|
List<TaskHistoryEvent> historyEventCandidatesToClean =
|
||||||
simpleHistoryService
|
simpleHistoryService
|
||||||
.createTaskHistoryQuery()
|
.createTaskHistoryQuery()
|
||||||
|
@ -181,9 +177,6 @@ public class HistoryCleanupJob extends AbstractTaskanaJob {
|
||||||
|
|
||||||
private int deleteEvents(List<String> taskIdsToDeleteHistoryEventsFor)
|
private int deleteEvents(List<String> taskIdsToDeleteHistoryEventsFor)
|
||||||
throws InvalidArgumentException, NotAuthorizedException {
|
throws InvalidArgumentException, NotAuthorizedException {
|
||||||
SimpleHistoryServiceImpl simpleHistoryService =
|
|
||||||
(SimpleHistoryServiceImpl) taskanaHistoryEngine.getTaskanaHistoryService();
|
|
||||||
|
|
||||||
int deletedTasksCount =
|
int deletedTasksCount =
|
||||||
(int)
|
(int)
|
||||||
simpleHistoryService
|
simpleHistoryService
|
||||||
|
|
|
@ -19,7 +19,6 @@ import pro.taskana.common.internal.util.IdGenerator;
|
||||||
import pro.taskana.common.test.config.DataSourceGenerator;
|
import pro.taskana.common.test.config.DataSourceGenerator;
|
||||||
import pro.taskana.sampledata.SampleDataGenerator;
|
import pro.taskana.sampledata.SampleDataGenerator;
|
||||||
import pro.taskana.simplehistory.impl.SimpleHistoryServiceImpl;
|
import pro.taskana.simplehistory.impl.SimpleHistoryServiceImpl;
|
||||||
import pro.taskana.simplehistory.impl.TaskanaHistoryEngineImpl;
|
|
||||||
import pro.taskana.simplehistory.impl.classification.ClassificationHistoryEventMapper;
|
import pro.taskana.simplehistory.impl.classification.ClassificationHistoryEventMapper;
|
||||||
import pro.taskana.simplehistory.impl.task.TaskHistoryQueryMapper;
|
import pro.taskana.simplehistory.impl.task.TaskHistoryQueryMapper;
|
||||||
import pro.taskana.simplehistory.impl.workbasket.WorkbasketHistoryEventMapper;
|
import pro.taskana.simplehistory.impl.workbasket.WorkbasketHistoryEventMapper;
|
||||||
|
@ -33,7 +32,6 @@ import pro.taskana.task.internal.models.ObjectReferenceImpl;
|
||||||
public abstract class AbstractAccTest {
|
public abstract class AbstractAccTest {
|
||||||
|
|
||||||
protected static TaskanaConfiguration taskanaConfiguration;
|
protected static TaskanaConfiguration taskanaConfiguration;
|
||||||
protected static TaskanaHistoryEngineImpl taskanaHistoryEngine;
|
|
||||||
protected static TaskanaEngine taskanaEngine;
|
protected static TaskanaEngine taskanaEngine;
|
||||||
protected static SimpleHistoryServiceImpl historyService;
|
protected static SimpleHistoryServiceImpl historyService;
|
||||||
|
|
||||||
|
@ -116,7 +114,6 @@ public abstract class AbstractAccTest {
|
||||||
taskanaConfiguration = configuration;
|
taskanaConfiguration = configuration;
|
||||||
taskanaEngine =
|
taskanaEngine =
|
||||||
TaskanaEngine.buildTaskanaEngine(taskanaConfiguration, ConnectionManagementMode.AUTOCOMMIT);
|
TaskanaEngine.buildTaskanaEngine(taskanaConfiguration, ConnectionManagementMode.AUTOCOMMIT);
|
||||||
taskanaHistoryEngine = TaskanaHistoryEngineImpl.createTaskanaEngine(taskanaEngine);
|
|
||||||
taskService = taskanaEngine.getTaskService();
|
taskService = taskanaEngine.getTaskService();
|
||||||
historyService = new SimpleHistoryServiceImpl();
|
historyService = new SimpleHistoryServiceImpl();
|
||||||
historyService.initialize(taskanaEngine);
|
historyService.initialize(taskanaEngine);
|
||||||
|
@ -129,10 +126,10 @@ public abstract class AbstractAccTest {
|
||||||
protected TaskHistoryQueryMapper getHistoryQueryMapper()
|
protected TaskHistoryQueryMapper getHistoryQueryMapper()
|
||||||
throws NoSuchFieldException, IllegalAccessException {
|
throws NoSuchFieldException, IllegalAccessException {
|
||||||
|
|
||||||
Field sessionManagerField = TaskanaHistoryEngineImpl.class.getDeclaredField("sessionManager");
|
Field sessionManagerField = TaskanaEngineImpl.class.getDeclaredField("sessionManager");
|
||||||
sessionManagerField.setAccessible(true);
|
sessionManagerField.setAccessible(true);
|
||||||
SqlSessionManager sqlSessionManager =
|
SqlSessionManager sqlSessionManager =
|
||||||
(SqlSessionManager) sessionManagerField.get(taskanaHistoryEngine);
|
(SqlSessionManager) sessionManagerField.get(taskanaEngine);
|
||||||
|
|
||||||
return sqlSessionManager.getMapper(TaskHistoryQueryMapper.class);
|
return sqlSessionManager.getMapper(TaskHistoryQueryMapper.class);
|
||||||
}
|
}
|
||||||
|
@ -160,32 +157,32 @@ public abstract class AbstractAccTest {
|
||||||
|
|
||||||
protected static WorkbasketHistoryEventMapper getWorkbasketHistoryEventMapper() {
|
protected static WorkbasketHistoryEventMapper getWorkbasketHistoryEventMapper() {
|
||||||
try {
|
try {
|
||||||
Field sessionManager = TaskanaHistoryEngineImpl.class.getDeclaredField("sessionManager");
|
Field sessionManager = TaskanaEngineImpl.class.getDeclaredField("sessionManager");
|
||||||
sessionManager.setAccessible(true);
|
sessionManager.setAccessible(true);
|
||||||
SqlSessionManager manager = (SqlSessionManager) sessionManager.get(taskanaHistoryEngine);
|
SqlSessionManager manager = (SqlSessionManager) sessionManager.get(taskanaEngine);
|
||||||
return manager.getMapper(WorkbasketHistoryEventMapper.class);
|
return manager.getMapper(WorkbasketHistoryEventMapper.class);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new JUnitException(
|
throw new JUnitException(
|
||||||
String.format(
|
String.format(
|
||||||
"Could not extract %s from %s",
|
"Could not extract %s from %s",
|
||||||
WorkbasketHistoryEventMapper.class, TaskanaHistoryEngineImpl.class));
|
WorkbasketHistoryEventMapper.class, TaskanaEngineImpl.class));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static ClassificationHistoryEventMapper getClassificationHistoryEventMapper() {
|
protected static ClassificationHistoryEventMapper getClassificationHistoryEventMapper() {
|
||||||
try {
|
try {
|
||||||
Field sessionManager = TaskanaHistoryEngineImpl.class.getDeclaredField("sessionManager");
|
Field sessionManager = TaskanaEngineImpl.class.getDeclaredField("sessionManager");
|
||||||
|
|
||||||
sessionManager.setAccessible(true);
|
sessionManager.setAccessible(true);
|
||||||
|
|
||||||
SqlSessionManager manager = (SqlSessionManager) sessionManager.get(taskanaHistoryEngine);
|
SqlSessionManager manager = (SqlSessionManager) sessionManager.get(taskanaEngine);
|
||||||
return manager.getMapper(ClassificationHistoryEventMapper.class);
|
return manager.getMapper(ClassificationHistoryEventMapper.class);
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new JUnitException(
|
throw new JUnitException(
|
||||||
String.format(
|
String.format(
|
||||||
"Could not extract %s from %s",
|
"Could not extract %s from %s",
|
||||||
ClassificationHistoryEventMapper.class, TaskanaHistoryEngineImpl.class));
|
ClassificationHistoryEventMapper.class, TaskanaEngineImpl.class));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,9 @@ class CreateHistoryEventOnClassificationDeletionAccTest extends AbstractAccTest
|
||||||
|
|
||||||
final String classificationId = "CLI:200000000000000000000000000000000015";
|
final String classificationId = "CLI:200000000000000000000000000000000015";
|
||||||
|
|
||||||
|
taskService.createTaskQuery().list();
|
||||||
|
historyService.deleteHistoryEventsByTaskIds(List.of("test12"));
|
||||||
|
|
||||||
List<ClassificationHistoryEvent> events =
|
List<ClassificationHistoryEvent> events =
|
||||||
historyService
|
historyService
|
||||||
.createClassificationHistoryQuery()
|
.createClassificationHistoryQuery()
|
||||||
|
|
|
@ -26,10 +26,10 @@ import pro.taskana.testapi.builder.TaskBuilder;
|
||||||
import pro.taskana.workbasket.api.WorkbasketService;
|
import pro.taskana.workbasket.api.WorkbasketService;
|
||||||
import pro.taskana.workbasket.api.models.WorkbasketSummary;
|
import pro.taskana.workbasket.api.models.WorkbasketSummary;
|
||||||
|
|
||||||
|
@TaskanaIntegrationTest
|
||||||
@WithServiceProvider(
|
@WithServiceProvider(
|
||||||
serviceProviderInterface = TaskanaHistory.class,
|
serviceProviderInterface = TaskanaHistory.class,
|
||||||
serviceProviders = SimpleHistoryServiceImpl.class)
|
serviceProviders = SimpleHistoryServiceImpl.class)
|
||||||
@TaskanaIntegrationTest
|
|
||||||
@ExtendWith(JaasExtension.class)
|
@ExtendWith(JaasExtension.class)
|
||||||
class CreateHistoryEventOnTaskDeletionAccTest {
|
class CreateHistoryEventOnTaskDeletionAccTest {
|
||||||
@TaskanaInject TaskanaEngine taskanaEngine;
|
@TaskanaInject TaskanaEngine taskanaEngine;
|
||||||
|
@ -47,8 +47,6 @@ class CreateHistoryEventOnTaskDeletionAccTest {
|
||||||
@WithAccessId(user = "admin")
|
@WithAccessId(user = "admin")
|
||||||
@BeforeAll
|
@BeforeAll
|
||||||
void setUp() throws Exception {
|
void setUp() throws Exception {
|
||||||
historyService = new SimpleHistoryServiceImpl();
|
|
||||||
historyService.initialize(taskanaEngine);
|
|
||||||
|
|
||||||
defaultClassificationSummary =
|
defaultClassificationSummary =
|
||||||
DefaultTestEntities.defaultTestClassification()
|
DefaultTestEntities.defaultTestClassification()
|
||||||
|
@ -60,11 +58,15 @@ class CreateHistoryEventOnTaskDeletionAccTest {
|
||||||
task2 = createTask().state(TaskState.COMPLETED).buildAndStore(taskService);
|
task2 = createTask().state(TaskState.COMPLETED).buildAndStore(taskService);
|
||||||
task3 = createTask().state(TaskState.COMPLETED).buildAndStore(taskService);
|
task3 = createTask().state(TaskState.COMPLETED).buildAndStore(taskService);
|
||||||
task4 = createTask().state(TaskState.COMPLETED).buildAndStore(taskService);
|
task4 = createTask().state(TaskState.COMPLETED).buildAndStore(taskService);
|
||||||
|
|
||||||
|
historyService = new SimpleHistoryServiceImpl();
|
||||||
|
historyService.initialize(taskanaEngine);
|
||||||
}
|
}
|
||||||
|
|
||||||
@WithAccessId(user = "admin")
|
@WithAccessId(user = "admin")
|
||||||
@Test
|
@Test
|
||||||
void should_CreateDeleteHistoryEvent_When_TaskIsDeleted() throws Exception {
|
void should_CreateDeleteHistoryEvent_When_TaskIsDeleted() throws Exception {
|
||||||
|
|
||||||
historyService.deleteHistoryEventsByTaskIds(List.of(task4.getId()));
|
historyService.deleteHistoryEventsByTaskIds(List.of(task4.getId()));
|
||||||
|
|
||||||
taskService.deleteTask(task4.getId());
|
taskService.deleteTask(task4.getId());
|
||||||
|
|
|
@ -14,6 +14,7 @@ import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.junit.jupiter.MockitoExtension;
|
import org.mockito.junit.jupiter.MockitoExtension;
|
||||||
|
import pro.taskana.common.internal.InternalTaskanaEngine;
|
||||||
import pro.taskana.common.internal.util.IdGenerator;
|
import pro.taskana.common.internal.util.IdGenerator;
|
||||||
import pro.taskana.spi.history.api.events.classification.ClassificationHistoryEvent;
|
import pro.taskana.spi.history.api.events.classification.ClassificationHistoryEvent;
|
||||||
import pro.taskana.spi.history.api.events.classification.ClassificationHistoryEventType;
|
import pro.taskana.spi.history.api.events.classification.ClassificationHistoryEventType;
|
||||||
|
@ -24,13 +25,13 @@ class ClassificationHistoryQueryImplTest {
|
||||||
|
|
||||||
private ClassificationHistoryQueryImpl historyQueryImpl;
|
private ClassificationHistoryQueryImpl historyQueryImpl;
|
||||||
|
|
||||||
@Mock private TaskanaHistoryEngineImpl taskanaHistoryEngineMock;
|
@Mock private InternalTaskanaEngine internalTaskanaEngineMock;
|
||||||
|
|
||||||
@Mock private SqlSession sqlSessionMock;
|
@Mock private SqlSession sqlSessionMock;
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
void setup() {
|
void setup() {
|
||||||
historyQueryImpl = new ClassificationHistoryQueryImpl(taskanaHistoryEngineMock);
|
historyQueryImpl = new ClassificationHistoryQueryImpl(internalTaskanaEngineMock);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -40,9 +41,9 @@ class ClassificationHistoryQueryImplTest {
|
||||||
createHistoryEvent(
|
createHistoryEvent(
|
||||||
ClassificationHistoryEventType.CREATED.getName(), "admin", "someDetails"));
|
ClassificationHistoryEventType.CREATED.getName(), "admin", "someDetails"));
|
||||||
|
|
||||||
doNothing().when(taskanaHistoryEngineMock).openConnection();
|
doNothing().when(internalTaskanaEngineMock).openConnection();
|
||||||
doNothing().when(taskanaHistoryEngineMock).returnConnection();
|
doNothing().when(internalTaskanaEngineMock).returnConnection();
|
||||||
when(taskanaHistoryEngineMock.getSqlSession()).thenReturn(sqlSessionMock);
|
when(internalTaskanaEngineMock.getSqlSession()).thenReturn(sqlSessionMock);
|
||||||
when(sqlSessionMock.selectList(any(), any())).thenReturn(new ArrayList<>(returnList));
|
when(sqlSessionMock.selectList(any(), any())).thenReturn(new ArrayList<>(returnList));
|
||||||
|
|
||||||
List<ClassificationHistoryEvent> result =
|
List<ClassificationHistoryEvent> result =
|
||||||
|
|
|
@ -19,6 +19,7 @@ import org.mockito.Spy;
|
||||||
import org.mockito.junit.jupiter.MockitoExtension;
|
import org.mockito.junit.jupiter.MockitoExtension;
|
||||||
import pro.taskana.TaskanaConfiguration;
|
import pro.taskana.TaskanaConfiguration;
|
||||||
import pro.taskana.common.api.TaskanaEngine;
|
import pro.taskana.common.api.TaskanaEngine;
|
||||||
|
import pro.taskana.common.internal.InternalTaskanaEngine;
|
||||||
import pro.taskana.simplehistory.impl.task.TaskHistoryEventMapper;
|
import pro.taskana.simplehistory.impl.task.TaskHistoryEventMapper;
|
||||||
import pro.taskana.simplehistory.impl.task.TaskHistoryQueryMapper;
|
import pro.taskana.simplehistory.impl.task.TaskHistoryQueryMapper;
|
||||||
import pro.taskana.simplehistory.impl.workbasket.WorkbasketHistoryEventMapper;
|
import pro.taskana.simplehistory.impl.workbasket.WorkbasketHistoryEventMapper;
|
||||||
|
@ -40,13 +41,12 @@ class SimpleHistoryServiceImplTest {
|
||||||
@Mock private WorkbasketHistoryEventMapper workbasketHistoryEventMapperMock;
|
@Mock private WorkbasketHistoryEventMapper workbasketHistoryEventMapperMock;
|
||||||
|
|
||||||
@Mock private WorkbasketHistoryQueryMapper workbasketHistoryQueryMapperMock;
|
@Mock private WorkbasketHistoryQueryMapper workbasketHistoryQueryMapperMock;
|
||||||
|
|
||||||
@Mock private TaskanaHistoryEngineImpl taskanaHistoryEngineMock;
|
|
||||||
|
|
||||||
@Mock private TaskanaConfiguration taskanaConfiguration;
|
@Mock private TaskanaConfiguration taskanaConfiguration;
|
||||||
|
|
||||||
@Mock private TaskanaEngine taskanaEngine;
|
@Mock private TaskanaEngine taskanaEngine;
|
||||||
|
|
||||||
|
@Mock private InternalTaskanaEngine internalTaskanaEngine;
|
||||||
|
|
||||||
@Mock private SqlSessionManager sqlSessionManagerMock;
|
@Mock private SqlSessionManager sqlSessionManagerMock;
|
||||||
|
|
||||||
@Mock private SqlSession sqlSessionMock;
|
@Mock private SqlSession sqlSessionMock;
|
||||||
|
@ -58,9 +58,7 @@ class SimpleHistoryServiceImplTest {
|
||||||
"wbKey1", "taskId1", "type1", "wbKey2", "someUserId", "someDetails");
|
"wbKey1", "taskId1", "type1", "wbKey2", "someUserId", "someDetails");
|
||||||
|
|
||||||
cutSpy.create(expectedWb);
|
cutSpy.create(expectedWb);
|
||||||
verify(taskanaHistoryEngineMock, times(1)).openConnection();
|
|
||||||
verify(taskHistoryEventMapperMock, times(1)).insert(expectedWb);
|
verify(taskHistoryEventMapperMock, times(1)).insert(expectedWb);
|
||||||
verify(taskanaHistoryEngineMock, times(1)).returnConnection();
|
|
||||||
assertThat(expectedWb.getCreated()).isNotNull();
|
assertThat(expectedWb.getCreated()).isNotNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,9 +69,7 @@ class SimpleHistoryServiceImplTest {
|
||||||
"wbKey1", WorkbasketHistoryEventType.CREATED.getName(), "someUserId", "someDetails");
|
"wbKey1", WorkbasketHistoryEventType.CREATED.getName(), "someUserId", "someDetails");
|
||||||
|
|
||||||
cutSpy.create(expectedEvent);
|
cutSpy.create(expectedEvent);
|
||||||
verify(taskanaHistoryEngineMock, times(1)).openConnection();
|
|
||||||
verify(workbasketHistoryEventMapperMock, times(1)).insert(expectedEvent);
|
verify(workbasketHistoryEventMapperMock, times(1)).insert(expectedEvent);
|
||||||
verify(taskanaHistoryEngineMock, times(1)).returnConnection();
|
|
||||||
assertThat(expectedEvent.getCreated()).isNotNull();
|
assertThat(expectedEvent.getCreated()).isNotNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,20 +80,21 @@ class SimpleHistoryServiceImplTest {
|
||||||
AbstractAccTest.createTaskHistoryEvent(
|
AbstractAccTest.createTaskHistoryEvent(
|
||||||
"wbKey1", "taskId1", "type1", "wbKey2", "someUserId", "someDetails"));
|
"wbKey1", "taskId1", "type1", "wbKey2", "someUserId", "someDetails"));
|
||||||
|
|
||||||
when(taskanaHistoryEngineMock.getConfiguration()).thenReturn(taskanaConfiguration);
|
|
||||||
when(taskanaConfiguration.isAddAdditionalUserInfo()).thenReturn(false);
|
when(taskanaConfiguration.isAddAdditionalUserInfo()).thenReturn(false);
|
||||||
|
|
||||||
when(taskanaHistoryEngineMock.getSqlSession()).thenReturn(sqlSessionMock);
|
when(internalTaskanaEngine.getSqlSession()).thenReturn(sqlSessionMock);
|
||||||
when(sqlSessionMock.selectList(any(), any())).thenReturn(new ArrayList<>(returnList));
|
when(sqlSessionMock.selectList(any(), any())).thenReturn(new ArrayList<>(returnList));
|
||||||
|
|
||||||
|
when(internalTaskanaEngine.getEngine()).thenReturn(taskanaEngine);
|
||||||
|
when(taskanaEngine.getConfiguration()).thenReturn(taskanaConfiguration);
|
||||||
final List<TaskHistoryEvent> result =
|
final List<TaskHistoryEvent> result =
|
||||||
cutSpy.createTaskHistoryQuery().taskIdIn("taskId1").list();
|
cutSpy.createTaskHistoryQuery().taskIdIn("taskId1").list();
|
||||||
|
|
||||||
verify(taskanaHistoryEngineMock, times(1)).openConnection();
|
verify(internalTaskanaEngine, times(1)).openConnection();
|
||||||
verify(taskanaHistoryEngineMock, times(1)).getSqlSession();
|
verify(internalTaskanaEngine, times(1)).getSqlSession();
|
||||||
verify(sqlSessionMock, times(1)).selectList(any(), any());
|
verify(sqlSessionMock, times(1)).selectList(any(), any());
|
||||||
|
|
||||||
verify(taskanaHistoryEngineMock, times(1)).returnConnection();
|
verify(internalTaskanaEngine, times(1)).returnConnection();
|
||||||
assertThat(result).hasSize(returnList.size());
|
assertThat(result).hasSize(returnList.size());
|
||||||
assertThat(result.get(0).getWorkbasketKey()).isEqualTo(returnList.get(0).getWorkbasketKey());
|
assertThat(result.get(0).getWorkbasketKey()).isEqualTo(returnList.get(0).getWorkbasketKey());
|
||||||
}
|
}
|
||||||
|
@ -108,16 +105,15 @@ class SimpleHistoryServiceImplTest {
|
||||||
returnList.add(
|
returnList.add(
|
||||||
AbstractAccTest.createWorkbasketHistoryEvent(
|
AbstractAccTest.createWorkbasketHistoryEvent(
|
||||||
"wbKey1", WorkbasketHistoryEventType.CREATED.getName(), "someUserId", "someDetails"));
|
"wbKey1", WorkbasketHistoryEventType.CREATED.getName(), "someUserId", "someDetails"));
|
||||||
when(taskanaHistoryEngineMock.getSqlSession()).thenReturn(sqlSessionMock);
|
|
||||||
when(sqlSessionMock.selectList(any(), any())).thenReturn(new ArrayList<>(returnList));
|
when(sqlSessionMock.selectList(any(), any())).thenReturn(new ArrayList<>(returnList));
|
||||||
|
when(internalTaskanaEngine.getSqlSession()).thenReturn(sqlSessionMock);
|
||||||
final List<WorkbasketHistoryEvent> result =
|
final List<WorkbasketHistoryEvent> result =
|
||||||
cutSpy.createWorkbasketHistoryQuery().keyIn("wbKey1").list();
|
cutSpy.createWorkbasketHistoryQuery().keyIn("wbKey1").list();
|
||||||
|
|
||||||
verify(taskanaHistoryEngineMock, times(1)).openConnection();
|
verify(internalTaskanaEngine, times(1)).openConnection();
|
||||||
verify(taskanaHistoryEngineMock, times(1)).getSqlSession();
|
verify(internalTaskanaEngine, times(1)).getSqlSession();
|
||||||
verify(sqlSessionMock, times(1)).selectList(any(), any());
|
verify(sqlSessionMock, times(1)).selectList(any(), any());
|
||||||
verify(taskanaHistoryEngineMock, times(1)).returnConnection();
|
verify(internalTaskanaEngine, times(1)).returnConnection();
|
||||||
assertThat(result).hasSize(returnList.size());
|
assertThat(result).hasSize(returnList.size());
|
||||||
assertThat(result.get(0).getKey()).isEqualTo(returnList.get(0).getKey());
|
assertThat(result.get(0).getKey()).isEqualTo(returnList.get(0).getKey());
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@ import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.junit.jupiter.MockitoExtension;
|
import org.mockito.junit.jupiter.MockitoExtension;
|
||||||
import pro.taskana.common.api.TimeInterval;
|
import pro.taskana.common.api.TimeInterval;
|
||||||
|
import pro.taskana.common.internal.InternalTaskanaEngine;
|
||||||
import pro.taskana.common.internal.util.IdGenerator;
|
import pro.taskana.common.internal.util.IdGenerator;
|
||||||
import pro.taskana.spi.history.api.events.workbasket.WorkbasketHistoryEvent;
|
import pro.taskana.spi.history.api.events.workbasket.WorkbasketHistoryEvent;
|
||||||
import pro.taskana.spi.history.api.events.workbasket.WorkbasketHistoryEventType;
|
import pro.taskana.spi.history.api.events.workbasket.WorkbasketHistoryEventType;
|
||||||
|
@ -24,7 +25,7 @@ import pro.taskana.spi.history.api.events.workbasket.WorkbasketHistoryEventType;
|
||||||
@ExtendWith(MockitoExtension.class)
|
@ExtendWith(MockitoExtension.class)
|
||||||
class WorkbasketHistoryQueryImplTest {
|
class WorkbasketHistoryQueryImplTest {
|
||||||
|
|
||||||
@Mock private TaskanaHistoryEngineImpl taskanaHistoryEngineMock;
|
@Mock private InternalTaskanaEngine internalTaskanaEngineMock;
|
||||||
|
|
||||||
private WorkbasketHistoryQueryImpl historyQueryImpl;
|
private WorkbasketHistoryQueryImpl historyQueryImpl;
|
||||||
|
|
||||||
|
@ -32,7 +33,7 @@ class WorkbasketHistoryQueryImplTest {
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
void setup() {
|
void setup() {
|
||||||
historyQueryImpl = new WorkbasketHistoryQueryImpl(taskanaHistoryEngineMock);
|
historyQueryImpl = new WorkbasketHistoryQueryImpl(internalTaskanaEngineMock);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -47,9 +48,9 @@ class WorkbasketHistoryQueryImplTest {
|
||||||
null));
|
null));
|
||||||
TimeInterval interval = new TimeInterval(Instant.now().minusNanos(1000), Instant.now());
|
TimeInterval interval = new TimeInterval(Instant.now().minusNanos(1000), Instant.now());
|
||||||
|
|
||||||
doNothing().when(taskanaHistoryEngineMock).openConnection();
|
doNothing().when(internalTaskanaEngineMock).openConnection();
|
||||||
doNothing().when(taskanaHistoryEngineMock).returnConnection();
|
doNothing().when(internalTaskanaEngineMock).returnConnection();
|
||||||
when(taskanaHistoryEngineMock.getSqlSession()).thenReturn(sqlSessionMock);
|
when(internalTaskanaEngineMock.getSqlSession()).thenReturn(sqlSessionMock);
|
||||||
when(sqlSessionMock.selectList(any(), any())).thenReturn(new ArrayList<>(returnList));
|
when(sqlSessionMock.selectList(any(), any())).thenReturn(new ArrayList<>(returnList));
|
||||||
|
|
||||||
List<WorkbasketHistoryEvent> result =
|
List<WorkbasketHistoryEvent> result =
|
||||||
|
|
|
@ -2,7 +2,6 @@ package pro.taskana.simplehistory.rest;
|
||||||
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import java.beans.ConstructorProperties;
|
import java.beans.ConstructorProperties;
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.BiConsumer;
|
import java.util.function.BiConsumer;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
@ -14,7 +13,6 @@ import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import pro.taskana.TaskanaConfiguration;
|
|
||||||
import pro.taskana.common.api.BaseQuery.SortDirection;
|
import pro.taskana.common.api.BaseQuery.SortDirection;
|
||||||
import pro.taskana.common.api.TaskanaEngine;
|
import pro.taskana.common.api.TaskanaEngine;
|
||||||
import pro.taskana.common.api.exceptions.InvalidArgumentException;
|
import pro.taskana.common.api.exceptions.InvalidArgumentException;
|
||||||
|
@ -35,19 +33,17 @@ import pro.taskana.spi.history.api.exceptions.TaskanaHistoryEventNotFoundExcepti
|
||||||
@RestController
|
@RestController
|
||||||
@EnableHypermediaSupport(type = EnableHypermediaSupport.HypermediaType.HAL)
|
@EnableHypermediaSupport(type = EnableHypermediaSupport.HypermediaType.HAL)
|
||||||
public class TaskHistoryEventController {
|
public class TaskHistoryEventController {
|
||||||
|
|
||||||
private final SimpleHistoryServiceImpl simpleHistoryService;
|
private final SimpleHistoryServiceImpl simpleHistoryService;
|
||||||
private final TaskHistoryEventRepresentationModelAssembler assembler;
|
private final TaskHistoryEventRepresentationModelAssembler assembler;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public TaskHistoryEventController(
|
public TaskHistoryEventController(
|
||||||
TaskanaConfiguration taskanaConfiguration,
|
TaskanaEngine taskanaEngine,
|
||||||
SimpleHistoryServiceImpl simpleHistoryServiceImpl,
|
SimpleHistoryServiceImpl simpleHistoryServiceImpl,
|
||||||
TaskHistoryEventRepresentationModelAssembler assembler)
|
TaskHistoryEventRepresentationModelAssembler assembler) {
|
||||||
throws SQLException {
|
|
||||||
|
|
||||||
this.simpleHistoryService = simpleHistoryServiceImpl;
|
this.simpleHistoryService = simpleHistoryServiceImpl;
|
||||||
this.simpleHistoryService.initialize(TaskanaEngine.buildTaskanaEngine(taskanaConfiguration));
|
this.simpleHistoryService.initialize(taskanaEngine);
|
||||||
this.assembler = assembler;
|
this.assembler = assembler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ package pro.taskana.common.api;
|
||||||
|
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
import org.apache.ibatis.transaction.TransactionFactory;
|
||||||
import pro.taskana.TaskanaConfiguration;
|
import pro.taskana.TaskanaConfiguration;
|
||||||
import pro.taskana.classification.api.ClassificationService;
|
import pro.taskana.classification.api.ClassificationService;
|
||||||
import pro.taskana.common.api.exceptions.NotAuthorizedException;
|
import pro.taskana.common.api.exceptions.NotAuthorizedException;
|
||||||
|
@ -93,7 +94,7 @@ public interface TaskanaEngine {
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("checkstyle:JavadocMethod")
|
@SuppressWarnings("checkstyle:JavadocMethod")
|
||||||
static TaskanaEngine buildTaskanaEngine(TaskanaConfiguration configuration) throws SQLException {
|
static TaskanaEngine buildTaskanaEngine(TaskanaConfiguration configuration) throws SQLException {
|
||||||
return buildTaskanaEngine(configuration, ConnectionManagementMode.PARTICIPATE);
|
return buildTaskanaEngine(configuration, ConnectionManagementMode.PARTICIPATE, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -108,7 +109,26 @@ public interface TaskanaEngine {
|
||||||
static TaskanaEngine buildTaskanaEngine(
|
static TaskanaEngine buildTaskanaEngine(
|
||||||
TaskanaConfiguration configuration, ConnectionManagementMode connectionManagementMode)
|
TaskanaConfiguration configuration, ConnectionManagementMode connectionManagementMode)
|
||||||
throws SQLException {
|
throws SQLException {
|
||||||
return TaskanaEngineImpl.createTaskanaEngine(configuration, connectionManagementMode);
|
return buildTaskanaEngine(configuration, connectionManagementMode, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds an {@linkplain TaskanaEngine} based on {@linkplain TaskanaConfiguration},
|
||||||
|
* SqlConnectionMode and TransactionFactory.
|
||||||
|
*
|
||||||
|
* @param configuration complete taskanaConfig to build the engine
|
||||||
|
* @param connectionManagementMode connectionMode for the SqlSession
|
||||||
|
* @param transactionFactory the TransactionFactory
|
||||||
|
* @return a {@linkplain TaskanaEngineImpl}
|
||||||
|
* @throws SQLException when the db schema could not be initialized
|
||||||
|
*/
|
||||||
|
static TaskanaEngine buildTaskanaEngine(
|
||||||
|
TaskanaConfiguration configuration,
|
||||||
|
ConnectionManagementMode connectionManagementMode,
|
||||||
|
TransactionFactory transactionFactory)
|
||||||
|
throws SQLException {
|
||||||
|
return TaskanaEngineImpl.createTaskanaEngine(
|
||||||
|
configuration, connectionManagementMode, transactionFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -112,7 +112,9 @@ public class TaskanaEngineImpl implements TaskanaEngine {
|
||||||
protected Connection connection;
|
protected Connection connection;
|
||||||
|
|
||||||
protected TaskanaEngineImpl(
|
protected TaskanaEngineImpl(
|
||||||
TaskanaConfiguration taskanaConfiguration, ConnectionManagementMode connectionManagementMode)
|
TaskanaConfiguration taskanaConfiguration,
|
||||||
|
ConnectionManagementMode connectionManagementMode,
|
||||||
|
TransactionFactory transactionFactory)
|
||||||
throws SQLException {
|
throws SQLException {
|
||||||
LOGGER.info(
|
LOGGER.info(
|
||||||
"initializing TASKANA with this configuration: {} and this mode: {}",
|
"initializing TASKANA with this configuration: {} and this mode: {}",
|
||||||
|
@ -146,7 +148,11 @@ public class TaskanaEngineImpl implements TaskanaEngine {
|
||||||
|
|
||||||
currentUserContext =
|
currentUserContext =
|
||||||
new CurrentUserContextImpl(TaskanaConfiguration.shouldUseLowerCaseForAccessIds());
|
new CurrentUserContextImpl(TaskanaConfiguration.shouldUseLowerCaseForAccessIds());
|
||||||
|
if (transactionFactory == null) {
|
||||||
createTransactionFactory(taskanaConfiguration.isUseManagedTransactions());
|
createTransactionFactory(taskanaConfiguration.isUseManagedTransactions());
|
||||||
|
} else {
|
||||||
|
this.transactionFactory = transactionFactory;
|
||||||
|
}
|
||||||
sessionManager = createSqlSessionManager();
|
sessionManager = createSqlSessionManager();
|
||||||
|
|
||||||
initializeDbSchema(taskanaConfiguration);
|
initializeDbSchema(taskanaConfiguration);
|
||||||
|
@ -156,7 +162,8 @@ public class TaskanaEngineImpl implements TaskanaEngine {
|
||||||
new TaskanaConfiguration.Builder(this.taskanaConfiguration)
|
new TaskanaConfiguration.Builder(this.taskanaConfiguration)
|
||||||
.jobSchedulerEnabled(false)
|
.jobSchedulerEnabled(false)
|
||||||
.build();
|
.build();
|
||||||
TaskanaEngine taskanaEngine = TaskanaEngine.buildTaskanaEngine(configuration, EXPLICIT);
|
TaskanaEngine taskanaEngine =
|
||||||
|
TaskanaEngine.buildTaskanaEngine(configuration, EXPLICIT, transactionFactory);
|
||||||
RealClock clock =
|
RealClock clock =
|
||||||
new RealClock(
|
new RealClock(
|
||||||
this.taskanaConfiguration.getJobSchedulerInitialStartDelay(),
|
this.taskanaConfiguration.getJobSchedulerInitialStartDelay(),
|
||||||
|
@ -186,9 +193,12 @@ public class TaskanaEngineImpl implements TaskanaEngine {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TaskanaEngine createTaskanaEngine(
|
public static TaskanaEngine createTaskanaEngine(
|
||||||
TaskanaConfiguration taskanaConfiguration, ConnectionManagementMode connectionManagementMode)
|
TaskanaConfiguration taskanaConfiguration,
|
||||||
|
ConnectionManagementMode connectionManagementMode,
|
||||||
|
TransactionFactory transactionFactory)
|
||||||
throws SQLException {
|
throws SQLException {
|
||||||
return new TaskanaEngineImpl(taskanaConfiguration, connectionManagementMode);
|
return new TaskanaEngineImpl(
|
||||||
|
taskanaConfiguration, connectionManagementMode, transactionFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -246,7 +256,11 @@ public class TaskanaEngineImpl implements TaskanaEngine {
|
||||||
connection.setAutoCommit(false);
|
connection.setAutoCommit(false);
|
||||||
connection.setSchema(taskanaConfiguration.getSchemaName());
|
connection.setSchema(taskanaConfiguration.getSchemaName());
|
||||||
mode = EXPLICIT;
|
mode = EXPLICIT;
|
||||||
|
if (transactionFactory.getClass().getSimpleName().equals("SpringManagedTransactionFactory")) {
|
||||||
|
sessionManager.startManagedSession();
|
||||||
|
} else {
|
||||||
sessionManager.startManagedSession(connection);
|
sessionManager.startManagedSession(connection);
|
||||||
|
}
|
||||||
} else if (this.connection != null) {
|
} else if (this.connection != null) {
|
||||||
closeConnection();
|
closeConnection();
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,9 +10,7 @@ public class SpringTaskanaEngineImpl extends TaskanaEngineImpl implements Spring
|
||||||
public SpringTaskanaEngineImpl(
|
public SpringTaskanaEngineImpl(
|
||||||
TaskanaConfiguration taskanaConfiguration, ConnectionManagementMode mode)
|
TaskanaConfiguration taskanaConfiguration, ConnectionManagementMode mode)
|
||||||
throws SQLException {
|
throws SQLException {
|
||||||
super(taskanaConfiguration, mode);
|
super(taskanaConfiguration, mode, new SpringManagedTransactionFactory());
|
||||||
this.transactionFactory = new SpringManagedTransactionFactory();
|
|
||||||
this.sessionManager = createSqlSessionManager();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SpringTaskanaEngine createTaskanaEngine(
|
public static SpringTaskanaEngine createTaskanaEngine(
|
||||||
|
|
|
@ -11,6 +11,7 @@ import org.springframework.jdbc.datasource.DataSourceTransactionManager;
|
||||||
import org.springframework.transaction.PlatformTransactionManager;
|
import org.springframework.transaction.PlatformTransactionManager;
|
||||||
import pro.taskana.TaskanaConfiguration;
|
import pro.taskana.TaskanaConfiguration;
|
||||||
import pro.taskana.common.api.TaskanaEngine;
|
import pro.taskana.common.api.TaskanaEngine;
|
||||||
|
import pro.taskana.common.internal.SpringTaskanaEngine;
|
||||||
import pro.taskana.common.internal.configuration.DbSchemaCreator;
|
import pro.taskana.common.internal.configuration.DbSchemaCreator;
|
||||||
import pro.taskana.sampledata.SampleDataGenerator;
|
import pro.taskana.sampledata.SampleDataGenerator;
|
||||||
|
|
||||||
|
@ -44,7 +45,7 @@ public class ExampleRestConfiguration {
|
||||||
@DependsOn("generateSampleData")
|
@DependsOn("generateSampleData")
|
||||||
public TaskanaEngine getTaskanaEngine(TaskanaConfiguration taskanaConfiguration)
|
public TaskanaEngine getTaskanaEngine(TaskanaConfiguration taskanaConfiguration)
|
||||||
throws SQLException {
|
throws SQLException {
|
||||||
return TaskanaEngine.buildTaskanaEngine(taskanaConfiguration);
|
return SpringTaskanaEngine.buildTaskanaEngine(taskanaConfiguration);
|
||||||
}
|
}
|
||||||
|
|
||||||
// only required to let the adapter example connect to the same database
|
// only required to let the adapter example connect to the same database
|
||||||
|
|
Loading…
Reference in New Issue