From ea988efd4628b82d2d4d385b5b1c0bc984cfe2d2 Mon Sep 17 00:00:00 2001 From: BerndBreier <33351391+BerndBreier@users.noreply.github.com> Date: Tue, 21 Nov 2017 16:18:47 +0100 Subject: [PATCH] TSK-38 Refactor session handling --- .../main/java/pro/taskana/TaskanaEngine.java | 39 +++ .../taskana/configuration/DbScriptRunner.java | 6 +- .../TaskanaEngineConfiguration.java | 4 +- .../exceptions/ConnectionNotSetException.java | 14 + .../impl/ClassificationServiceImpl.java | 108 ++++-- .../pro/taskana/impl/TaskServiceImpl.java | 212 +++++++----- .../pro/taskana/impl/TaskanaEngineImpl.java | 223 ++++++++++--- .../taskana/impl/WorkbasketServiceImpl.java | 194 +++++++---- .../persistence/ClassificationQueryImpl.java | 27 +- .../persistence/ObjectReferenceQueryImpl.java | 27 +- .../impl/persistence/TaskQueryImpl.java | 41 ++- .../impl/ClassificationServiceImplTest.java | 10 +- .../pro/taskana/impl/TaskServiceImplTest.java | 59 ++-- .../impl/WorkbasketServiceImplTest.java | 13 +- .../taskana/impl/configuration/DBCleaner.java | 6 +- .../TaskanaEngineConfigurationTest.java | 26 +- ...ficationServiceImplIntAutoCommitTest.java} | 15 +- ...ssificationServiceImplIntExplicitTest.java | 311 ++++++++++++++++++ ... => TaskServiceImplIntAutocommitTest.java} | 35 +- .../TaskServiceImplIntExplicitTest.java | 158 +++++++++ ...rkbasketServiceImplIntAutocommitTest.java} | 9 +- .../WorkbasketServiceImplIntExplicitTest.java | 262 +++++++++++++++ .../ClassificationQueryImplTest.java | 6 +- .../ObjectReferenceQueryImplTest.java | 6 +- .../impl/persistence/TaskQueryImplTest.java | 6 +- 25 files changed, 1488 insertions(+), 329 deletions(-) create mode 100644 lib/taskana-core/src/main/java/pro/taskana/exceptions/ConnectionNotSetException.java rename lib/taskana-core/src/test/java/pro/taskana/impl/integration/{ClassificationServiceImplIntTest.java => ClassificationServiceImplIntAutoCommitTest.java} (97%) create mode 100644 lib/taskana-core/src/test/java/pro/taskana/impl/integration/ClassificationServiceImplIntExplicitTest.java rename lib/taskana-core/src/test/java/pro/taskana/impl/integration/{TaskServiceImplTransactionTest.java => TaskServiceImplIntAutocommitTest.java} (91%) create mode 100644 lib/taskana-core/src/test/java/pro/taskana/impl/integration/TaskServiceImplIntExplicitTest.java rename lib/taskana-core/src/test/java/pro/taskana/impl/integration/{WorkbasketServiceImplIntTest.java => WorkbasketServiceImplIntAutocommitTest.java} (96%) create mode 100644 lib/taskana-core/src/test/java/pro/taskana/impl/integration/WorkbasketServiceImplIntExplicitTest.java diff --git a/lib/taskana-core/src/main/java/pro/taskana/TaskanaEngine.java b/lib/taskana-core/src/main/java/pro/taskana/TaskanaEngine.java index c2fabae30..f01b31a9f 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/TaskanaEngine.java +++ b/lib/taskana-core/src/main/java/pro/taskana/TaskanaEngine.java @@ -1,5 +1,6 @@ package pro.taskana; +import pro.taskana.TaskanaEngine.ConnectionManagementMode; import pro.taskana.configuration.TaskanaEngineConfiguration; /** @@ -30,4 +31,42 @@ public interface TaskanaEngine { * @return the TaskanaConfiguration */ TaskanaEngineConfiguration getConfiguration(); + + /** + * sets the connection management mode for taskana. + * + * @param mode. See ConnectionManagementMode + */ + void setConnectionManagementMode(ConnectionManagementMode mode); + + /** + * Set the connection to be used by taskana in mode CONNECTION_MANAGED_EXTERNALLY. + * If this Api is called, taskana uses the connection passed by the client for all subsequent API calls + * until the client resets this connection. + * Control over commit and rollback of the connection is the responsibility of the client. + * In order to close the connection, closeConnection() or setConnection(null) has to be called. + * + * @param connection - The java.sql.Connection that is controlled by the client + */ + void setConnection(java.sql.Connection connection); + + /** + * Closes the client's connection, sets it to null and switches to mode PARTICIPATE. + * Only applicable in mode EXPLICIT. Has the same effect as setConnection(null). + */ + void closeConnection(); + + /** + * Connection management mode. + * Controls the connection handling of taskana + * PARTICIPATE - taskana participates in global transaction. This is the default mode + * AUTOCOMMIT - taskana commits each API call separately + * EXPLICIT - commit processing is managed explicitly by the client + */ + enum ConnectionManagementMode { + PARTICIPATE, + AUTOCOMMIT, + EXPLICIT + } + } diff --git a/lib/taskana-core/src/main/java/pro/taskana/configuration/DbScriptRunner.java b/lib/taskana-core/src/main/java/pro/taskana/configuration/DbScriptRunner.java index 8820e6e02..c55b7ffb6 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/configuration/DbScriptRunner.java +++ b/lib/taskana-core/src/main/java/pro/taskana/configuration/DbScriptRunner.java @@ -3,6 +3,7 @@ package pro.taskana.configuration; import java.io.InputStreamReader; import java.io.PrintWriter; import java.io.StringWriter; +import java.sql.Connection; import java.sql.SQLException; import javax.sql.DataSource; @@ -39,8 +40,9 @@ public class DbScriptRunner { * @throws SQLException */ public void run() throws SQLException { - ScriptRunner runner = new ScriptRunner(dataSource.getConnection()); - LOGGER.debug(dataSource.getConnection().getMetaData().toString()); + Connection connection = dataSource.getConnection(); + ScriptRunner runner = new ScriptRunner(connection); + LOGGER.debug(connection.getMetaData().toString()); runner.setStopOnError(true); runner.setLogWriter(logWriter); diff --git a/lib/taskana-core/src/main/java/pro/taskana/configuration/TaskanaEngineConfiguration.java b/lib/taskana-core/src/main/java/pro/taskana/configuration/TaskanaEngineConfiguration.java index d9fb30821..381fafdd5 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/configuration/TaskanaEngineConfiguration.java +++ b/lib/taskana-core/src/main/java/pro/taskana/configuration/TaskanaEngineConfiguration.java @@ -55,7 +55,7 @@ public class TaskanaEngineConfiguration { this.securityEnabled = securityEnabled; } - public DataSource createDefaultDataSource() { + public static DataSource createDefaultDataSource() { LOGGER.warn("No datasource is provided. A inmemory db is used: " + "'org.h2.Driver', 'jdbc:h2:mem:taskana', 'sa', 'sa'"); return createDatasource(H2_DRIVER, JDBC_H2_MEM_TASKANA, USER_NAME, USER_PASSWORD); @@ -75,7 +75,7 @@ public class TaskanaEngineConfiguration { * @param dbConfiguration * @return DataSource */ - public DataSource createDatasource(String driver, String jdbcUrl, String username, String password) { + public static DataSource createDatasource(String driver, String jdbcUrl, String username, String password) { return new PooledDataSource(driver, jdbcUrl, username, password); } diff --git a/lib/taskana-core/src/main/java/pro/taskana/exceptions/ConnectionNotSetException.java b/lib/taskana-core/src/main/java/pro/taskana/exceptions/ConnectionNotSetException.java new file mode 100644 index 000000000..ae2e0713e --- /dev/null +++ b/lib/taskana-core/src/main/java/pro/taskana/exceptions/ConnectionNotSetException.java @@ -0,0 +1,14 @@ +package pro.taskana.exceptions; + +/** + * Thrown if ConnectionManagementMode is CONNECTION_MANAGED_EXTERNALLY and an attempt is made to call an API method before the setConnection() method has been called. + * + */ +@SuppressWarnings("serial") +public class ConnectionNotSetException extends RuntimeException { + + public ConnectionNotSetException() { + super("Connection not set"); + } + +} diff --git a/lib/taskana-core/src/main/java/pro/taskana/impl/ClassificationServiceImpl.java b/lib/taskana-core/src/main/java/pro/taskana/impl/ClassificationServiceImpl.java index ef1d55a1c..08f08ef34 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/impl/ClassificationServiceImpl.java +++ b/lib/taskana-core/src/main/java/pro/taskana/impl/ClassificationServiceImpl.java @@ -26,64 +26,87 @@ public class ClassificationServiceImpl implements ClassificationService { private ClassificationMapper classificationMapper; private TaskanaEngine taskanaEngine; + private TaskanaEngineImpl taskanaEngineImpl; public ClassificationServiceImpl(TaskanaEngine taskanaEngine, ClassificationMapper classificationMapper) { super(); this.taskanaEngine = taskanaEngine; + this.taskanaEngineImpl = (TaskanaEngineImpl) taskanaEngine; this.classificationMapper = classificationMapper; } @Override public List getClassificationTree() throws NotAuthorizedException { - List rootClassifications; - rootClassifications = this.createClassificationQuery().parentClassification("").validUntil(CURRENT_CLASSIFICATIONS_VALID_UNTIL).list(); - return this.populateChildClassifications(rootClassifications); + try { + taskanaEngineImpl.openConnection(); + List rootClassifications; + rootClassifications = this.createClassificationQuery().parentClassification("").validUntil(CURRENT_CLASSIFICATIONS_VALID_UNTIL).list(); + return this.populateChildClassifications(rootClassifications); + } finally { + taskanaEngineImpl.returnConnection(); + } } private List populateChildClassifications(List classifications) throws NotAuthorizedException { - List children = new ArrayList<>(); - for (Classification classification : classifications) { - List childClassifications = this.createClassificationQuery().parentClassification(classification.getId()).validUntil(CURRENT_CLASSIFICATIONS_VALID_UNTIL).list(); - children.addAll(populateChildClassifications(childClassifications)); + try { + taskanaEngineImpl.openConnection(); + List children = new ArrayList<>(); + for (Classification classification : classifications) { + List childClassifications = this.createClassificationQuery().parentClassification(classification.getId()).validUntil(CURRENT_CLASSIFICATIONS_VALID_UNTIL).list(); + children.addAll(populateChildClassifications(childClassifications)); + } + classifications.addAll(children); + return classifications; + } finally { + taskanaEngineImpl.returnConnection(); } - classifications.addAll(children); - return classifications; } @Override public void addClassification(Classification classification) { - classification.setId(IdGenerator.generateWithPrefix(ID_PREFIX_CLASSIFICATION)); - classification.setCreated(Date.valueOf(LocalDate.now())); + try { + taskanaEngineImpl.openConnection(); + classification.setId(IdGenerator.generateWithPrefix(ID_PREFIX_CLASSIFICATION)); + classification.setCreated(Date.valueOf(LocalDate.now())); - this.setDefaultValues(classification); + this.setDefaultValues(classification); - classificationMapper.insert(classification); + classificationMapper.insert(classification); + } finally { + taskanaEngineImpl.returnConnection(); + } } @Override public void updateClassification(Classification classification) { - this.setDefaultValues(classification); + try { + taskanaEngineImpl.openConnection(); + this.setDefaultValues(classification); - Classification oldClassification = this.getClassification(classification.getId(), classification.getDomain()); + Classification oldClassification = this.getClassification(classification.getId(), classification.getDomain()); - if (oldClassification == null) { - classification.setId(IdGenerator.generateWithPrefix(ID_PREFIX_CLASSIFICATION)); - classification.setCreated(Date.valueOf(LocalDate.now())); - classificationMapper.insert(classification); + if (oldClassification == null) { + classification.setId(IdGenerator.generateWithPrefix(ID_PREFIX_CLASSIFICATION)); + classification.setCreated(Date.valueOf(LocalDate.now())); + classificationMapper.insert(classification); + } else { + + // ! If you update an classification twice the same day, + // the older version is valid from today until yesterday. + if (!oldClassification.getDomain().equals(classification.getDomain())) { + classification.setCreated(Date.valueOf(LocalDate.now())); + classificationMapper.insert(classification); + } else { + oldClassification.setValidUntil(Date.valueOf(LocalDate.now().minusDays(1))); + classificationMapper.update(oldClassification); + classificationMapper.insert(classification); + } + } return; - } - - // ! If you update an classification twice the same day, - // the older version is valid from today until yesterday. - if (!oldClassification.getDomain().equals(classification.getDomain())) { - classification.setCreated(Date.valueOf(LocalDate.now())); - classificationMapper.insert(classification); - } else { - oldClassification.setValidUntil(Date.valueOf(LocalDate.now().minusDays(1))); - classificationMapper.update(oldClassification); - classificationMapper.insert(classification); + } finally { + taskanaEngineImpl.returnConnection(); } } @@ -109,22 +132,35 @@ public class ClassificationServiceImpl implements ClassificationService { if (classification.getDomain() == null) { classification.setDomain(""); } + } @Override public List getAllClassificationsWithId(String id, String domain) { - return classificationMapper.getAllClassificationsWithId(id, domain); + try { + taskanaEngineImpl.openConnection(); + return classificationMapper.getAllClassificationsWithId(id, domain); + } finally { + taskanaEngineImpl.returnConnection(); + } + } @Override public Classification getClassification(String id, String domain) { - Classification classification = classificationMapper.findByIdAndDomain(id, domain, CURRENT_CLASSIFICATIONS_VALID_UNTIL); + try { + taskanaEngineImpl.openConnection(); + Classification result = null; + Classification classification = classificationMapper.findByIdAndDomain(id, domain, CURRENT_CLASSIFICATIONS_VALID_UNTIL); - if (classification == null) { - return classificationMapper.findByIdAndDomain(id, "", CURRENT_CLASSIFICATIONS_VALID_UNTIL); - } else { - return classification; + if (classification == null) { + return classificationMapper.findByIdAndDomain(id, "", CURRENT_CLASSIFICATIONS_VALID_UNTIL); + } else { + return classification; + } + } finally { + taskanaEngineImpl.returnConnection(); } } diff --git a/lib/taskana-core/src/main/java/pro/taskana/impl/TaskServiceImpl.java b/lib/taskana-core/src/main/java/pro/taskana/impl/TaskServiceImpl.java index 874ed85bb..8b887fd4b 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/impl/TaskServiceImpl.java +++ b/lib/taskana-core/src/main/java/pro/taskana/impl/TaskServiceImpl.java @@ -8,6 +8,7 @@ import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; + import pro.taskana.TaskService; import pro.taskana.TaskanaEngine; import pro.taskana.exceptions.NotAuthorizedException; @@ -36,6 +37,7 @@ public class TaskServiceImpl implements TaskService { private static final String ID_PREFIX_TASK = "TKI"; private TaskanaEngine taskanaEngine; + private TaskanaEngineImpl taskanaEngineImpl; private TaskMapper taskMapper; private ObjectReferenceMapper objectReferenceMapper; @@ -43,139 +45,181 @@ public class TaskServiceImpl implements TaskService { ObjectReferenceMapper objectReferenceMapper) { super(); this.taskanaEngine = taskanaEngine; + this.taskanaEngineImpl = (TaskanaEngineImpl) taskanaEngine; this.taskMapper = taskMapper; this.objectReferenceMapper = objectReferenceMapper; } @Override public void claim(String id, String userName) throws TaskNotFoundException { - Task task = taskMapper.findById(id); - if (task != null) { - Timestamp now = new Timestamp(System.currentTimeMillis()); - task.setOwner(userName); - task.setModified(now); - task.setClaimed(now); - task.setState(TaskState.CLAIMED); - taskMapper.update(task); - LOGGER.debug("User '{}' claimed task '{}'.", userName, id); - } else { - throw new TaskNotFoundException(id); + try { + taskanaEngineImpl.openConnection(); + Task task = taskMapper.findById(id); + if (task != null) { + Timestamp now = new Timestamp(System.currentTimeMillis()); + task.setOwner(userName); + task.setModified(now); + task.setClaimed(now); + task.setState(TaskState.CLAIMED); + taskMapper.update(task); + LOGGER.debug("User '{}' claimed task '{}'.", userName, id); + } else { + throw new TaskNotFoundException(id); + } + } finally { + taskanaEngineImpl.returnConnection(); } } @Override public void complete(String id) throws TaskNotFoundException { - Task task = taskMapper.findById(id); - if (task != null) { - Timestamp now = new Timestamp(System.currentTimeMillis()); - task.setCompleted(now); - task.setModified(now); - task.setState(TaskState.COMPLETED); - taskMapper.update(task); - LOGGER.debug("Task '{}' completed.", id); - } else { - throw new TaskNotFoundException(id); + try { + taskanaEngineImpl.openConnection(); + Task task = taskMapper.findById(id); + if (task != null) { + Timestamp now = new Timestamp(System.currentTimeMillis()); + task.setCompleted(now); + task.setModified(now); + task.setState(TaskState.COMPLETED); + taskMapper.update(task); + LOGGER.debug("Task '{}' completed.", id); + } else { + throw new TaskNotFoundException(id); + } + } finally { + taskanaEngineImpl.returnConnection(); } } @Override public Task create(Task task) throws NotAuthorizedException { - taskanaEngine.getWorkbasketService().checkAuthorization(task.getWorkbasketId(), WorkbasketAuthorization.APPEND); + try { + taskanaEngineImpl.openConnection(); + taskanaEngine.getWorkbasketService().checkAuthorization(task.getWorkbasketId(), WorkbasketAuthorization.APPEND); - Timestamp now = new Timestamp(System.currentTimeMillis()); - task.setId(IdGenerator.generateWithPrefix(ID_PREFIX_TASK)); - task.setState(TaskState.READY); - task.setCreated(now); - task.setModified(now); - task.setRead(false); - task.setTransferred(false); + Timestamp now = new Timestamp(System.currentTimeMillis()); + task.setId(IdGenerator.generateWithPrefix(ID_PREFIX_TASK)); + task.setState(TaskState.READY); + task.setCreated(now); + task.setModified(now); + task.setRead(false); + task.setTransferred(false); - // insert ObjectReference if needed. - if (task.getPrimaryObjRef() != null) { - ObjectReference objectReference = this.objectReferenceMapper.findByObjectReference(task.getPrimaryObjRef()); - if (objectReference == null) { - objectReference = task.getPrimaryObjRef(); - objectReference.setId(IdGenerator.generateWithPrefix(ID_PREFIX_OBJECTR_EFERENCE)); - this.objectReferenceMapper.insert(objectReference); + // insert ObjectReference if needed. + if (task.getPrimaryObjRef() != null) { + ObjectReference objectReference = this.objectReferenceMapper.findByObjectReference(task.getPrimaryObjRef()); + if (objectReference == null) { + objectReference = task.getPrimaryObjRef(); + objectReference.setId(IdGenerator.generateWithPrefix(ID_PREFIX_OBJECTR_EFERENCE)); + this.objectReferenceMapper.insert(objectReference); + } + task.setPrimaryObjRef(objectReference); } - task.setPrimaryObjRef(objectReference); - } - this.taskMapper.insert(task); + this.taskMapper.insert(task); - LOGGER.debug("Task '{}' created.", task.getId()); - return task; + LOGGER.debug("Task '{}' created.", task.getId()); + return task; + } finally { + taskanaEngineImpl.returnConnection(); + } } @Override public Task getTaskById(String id) throws TaskNotFoundException { - Task task = taskMapper.findById(id); - if (task != null) { - return task; - } else { - throw new TaskNotFoundException(id); + try { + taskanaEngineImpl.openConnection(); + Task task = taskMapper.findById(id); + if (task != null) { + return task; + } else { + throw new TaskNotFoundException(id); + } + } finally { + taskanaEngineImpl.returnConnection(); } } @Override public List getTaskCountForState(List states) { - return taskMapper.getTaskCountForState(states); + try { + taskanaEngineImpl.openConnection(); + return taskMapper.getTaskCountForState(states); + } finally { + taskanaEngineImpl.returnConnection(); + } } @Override - public long getTaskCountForWorkbasketByDaysInPastAndState(String workbasketId, long daysInPast, - List states) { - LocalDate time = LocalDate.now(); - time = time.minusDays(daysInPast); - Date fromDate = Date.valueOf(time); - return taskMapper.getTaskCountForWorkbasketByDaysInPastAndState(workbasketId, fromDate, states); + public long getTaskCountForWorkbasketByDaysInPastAndState(String workbasketId, long daysInPast, List states) { + try { + taskanaEngineImpl.openConnection(); + LocalDate time = LocalDate.now(); + time = time.minusDays(daysInPast); + Date fromDate = Date.valueOf(time); + return taskMapper.getTaskCountForWorkbasketByDaysInPastAndState(workbasketId, fromDate, states); + } finally { + taskanaEngineImpl.returnConnection(); + } } @Override public Task transfer(String taskId, String destinationWorkbasketId) throws TaskNotFoundException, WorkbasketNotFoundException, NotAuthorizedException { - Task task = getTaskById(taskId); + try { + taskanaEngineImpl.openConnection(); + Task task = getTaskById(taskId); - // transfer requires TRANSFER in source and APPEND on destination - // workbasket - taskanaEngine.getWorkbasketService().checkAuthorization(destinationWorkbasketId, - WorkbasketAuthorization.APPEND); - taskanaEngine.getWorkbasketService().checkAuthorization(task.getWorkbasketId(), - WorkbasketAuthorization.TRANSFER); + // transfer requires TRANSFER in source and APPEND on destination workbasket + taskanaEngine.getWorkbasketService().checkAuthorization(destinationWorkbasketId, WorkbasketAuthorization.APPEND); + taskanaEngine.getWorkbasketService().checkAuthorization(task.getWorkbasketId(), WorkbasketAuthorization.TRANSFER); - // if security is disabled, the implicit existance check on the - // destination workbasket has been skipped and needs to be performed - if (!taskanaEngine.getConfiguration().isSecurityEnabled()) { - taskanaEngine.getWorkbasketService().getWorkbasket(destinationWorkbasketId); + // if security is disabled, the implicit existance check on the + // destination workbasket has been skipped and needs to be performed + if (!taskanaEngine.getConfiguration().isSecurityEnabled()) { + taskanaEngine.getWorkbasketService().getWorkbasket(destinationWorkbasketId); + } + + // reset read flag and set transferred flag + task.setRead(false); + task.setTransferred(true); + + // transfer task from source to destination workbasket + task.setWorkbasketId(destinationWorkbasketId); + task.setModified(Timestamp.valueOf(LocalDateTime.now())); + taskMapper.update(task); + + return getTaskById(taskId); + } finally { + taskanaEngineImpl.returnConnection(); } - - // reset read flag and set transferred flag - task.setRead(false); - task.setTransferred(true); - - // transfer task from source to destination workbasket - task.setWorkbasketId(destinationWorkbasketId); - task.setModified(Timestamp.valueOf(LocalDateTime.now())); - taskMapper.update(task); - - return getTaskById(taskId); } @Override public List getTaskCountByWorkbasketAndDaysInPastAndState(long daysInPast, List states) { - LocalDate time = LocalDate.now(); - time = time.minusDays(daysInPast); - Date fromDate = Date.valueOf(time); - return taskMapper.getTaskCountByWorkbasketIdAndDaysInPastAndState(fromDate, states); + try { + taskanaEngineImpl.openConnection(); + LocalDate time = LocalDate.now(); + time = time.minusDays(daysInPast); + Date fromDate = Date.valueOf(time); + return taskMapper.getTaskCountByWorkbasketIdAndDaysInPastAndState(fromDate, states); + } finally { + taskanaEngineImpl.returnConnection(); + } } @Override public Task setTaskRead(String taskId, boolean isRead) throws TaskNotFoundException { - Task task = getTaskById(taskId); - task.setRead(true); - task.setModified(Timestamp.valueOf(LocalDateTime.now())); - taskMapper.update(task); - return getTaskById(taskId); + try { + taskanaEngineImpl.openConnection(); + Task task = getTaskById(taskId); + task.setRead(true); + task.setModified(Timestamp.valueOf(LocalDateTime.now())); + taskMapper.update(task); + return getTaskById(taskId); + } finally { + taskanaEngineImpl.returnConnection(); + } } @Override diff --git a/lib/taskana-core/src/main/java/pro/taskana/impl/TaskanaEngineImpl.java b/lib/taskana-core/src/main/java/pro/taskana/impl/TaskanaEngineImpl.java index 55e8368fe..488c5dbf0 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/impl/TaskanaEngineImpl.java +++ b/lib/taskana-core/src/main/java/pro/taskana/impl/TaskanaEngineImpl.java @@ -1,18 +1,26 @@ package pro.taskana.impl; +import java.sql.SQLException; +import java.util.Stack; + 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.slf4j.Logger; +import org.slf4j.LoggerFactory; + import pro.taskana.ClassificationService; import pro.taskana.TaskService; import pro.taskana.TaskanaEngine; import pro.taskana.WorkbasketService; import pro.taskana.configuration.TaskanaEngineConfiguration; +import pro.taskana.exceptions.ConnectionNotSetException; import pro.taskana.impl.persistence.MapTypeHandler; import pro.taskana.model.mappings.ClassificationMapper; import pro.taskana.model.mappings.DistributionTargetMapper; @@ -28,52 +36,42 @@ import pro.taskana.model.mappings.WorkbasketMapper; public class TaskanaEngineImpl implements TaskanaEngine { private static final String DEFAULT = "default"; + private static final Logger LOGGER = LoggerFactory.getLogger(TaskanaEngineImpl.class); + protected static ThreadLocal> sessionStack = new ThreadLocal>(); protected TaskanaEngineConfiguration taskanaEngineConfiguration; - protected SqlSession session; protected TransactionFactory transactionFactory; + protected SqlSessionManager sessionManager; protected SqlSessionFactory sessionFactory; - - private TaskMapper taskMapper; - private WorkbasketMapper workbasketMapper; - private DistributionTargetMapper distributionTargetMapper; - private ClassificationMapper classificationMapper; - private WorkbasketAccessMapper workbasketAccessMapper; - private ObjectReferenceMapper objectReferenceMapper; - - private TaskServiceImpl taskServiceImpl; - private WorkbasketServiceImpl workbasketServiceImpl; + protected ConnectionManagementMode mode = ConnectionManagementMode.PARTICIPATE; + protected java.sql.Connection connection = null; public TaskanaEngineImpl(TaskanaEngineConfiguration taskanaEngineConfiguration) { this.taskanaEngineConfiguration = taskanaEngineConfiguration; - createTransactionFactory(taskanaEngineConfiguration.getUseContainerManagedTransactions()); - - this.session = createSqlSessionFactory().openSession(); - this.taskMapper = session.getMapper(TaskMapper.class); - this.workbasketMapper = session.getMapper(WorkbasketMapper.class); - this.distributionTargetMapper = session.getMapper(DistributionTargetMapper.class); - this.classificationMapper = session.getMapper(ClassificationMapper.class); - this.workbasketAccessMapper = session.getMapper(WorkbasketAccessMapper.class); - this.objectReferenceMapper = session.getMapper(ObjectReferenceMapper.class); + this.sessionManager = createSqlSessionManager(); } @Override public TaskService getTaskService() { - this.taskServiceImpl = new TaskServiceImpl(this, this.taskMapper, this.objectReferenceMapper); + SqlSession session = this.sessionManager; + TaskServiceImpl taskServiceImpl = new TaskServiceImpl(this, session.getMapper(TaskMapper.class), session.getMapper(ObjectReferenceMapper.class)); return taskServiceImpl; } @Override public WorkbasketService getWorkbasketService() { - this.workbasketServiceImpl = new WorkbasketServiceImpl(this, this.workbasketMapper, - this.distributionTargetMapper, this.workbasketAccessMapper); + SqlSession session = this.sessionManager; + WorkbasketServiceImpl workbasketServiceImpl = new WorkbasketServiceImpl(this, session.getMapper(WorkbasketMapper.class), + session.getMapper(DistributionTargetMapper.class), + session.getMapper(WorkbasketAccessMapper.class)); return workbasketServiceImpl; } @Override public ClassificationService getClassificationService() { - return new ClassificationServiceImpl(this, this.classificationMapper); + SqlSession session = this.sessionManager; + return new ClassificationServiceImpl(this, session.getMapper(ClassificationMapper.class)); } @Override @@ -82,20 +80,134 @@ public class TaskanaEngineImpl implements TaskanaEngine { } /** - * Close session manually, to be done, if a JdbcTransactionFactory is used. - * Perhaps it is better to separate the commit and the closing mechanism ... + * Open the connection to the database. + * to be called at the begin of each Api call that accesses the database + * */ - public void closeSession() { - this.session.commit(); - this.session.close(); + public void openConnection() { + initSqlSession(); + if (mode != ConnectionManagementMode.EXPLICIT) { + pushSessionToStack(this.sessionManager); + } } /** - * This method creates the sqlSessionFactory of myBatis. It integrates all the + * Initializes the SqlSessionManager. + * + */ + void initSqlSession() { + if (mode == ConnectionManagementMode.EXPLICIT && this.connection == null) { + throw new ConnectionNotSetException(); + } else if (mode != ConnectionManagementMode.EXPLICIT) { + if (!this.sessionManager.isManagedSessionStarted()) { + this.sessionManager.startManagedSession(); + } + } + } + + /** + * closes the connection to the database in mode EXPLICIT. + * In mode EXPLICIT, closes the client's connection, sets it to null and switches to mode PARTICIPATE + * Has the same effect as setConnection(null) + */ + @Override + public void closeConnection() { + if (this.mode == ConnectionManagementMode.EXPLICIT) { + this.connection = null; + if (sessionManager.isManagedSessionStarted()) { + sessionManager.close(); + } + mode = ConnectionManagementMode.PARTICIPATE; + } + } + + /** + * 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 + */ + public void returnConnection() { + if (this.mode != ConnectionManagementMode.EXPLICIT) { + popSessionFromStack(); + if (getSessionStack().isEmpty() + && this.sessionManager != null && this.sessionManager.isManagedSessionStarted()) { + if (this.mode == ConnectionManagementMode.AUTOCOMMIT) { + try { + this.sessionManager.commit(); + } catch (Exception e) { + LOGGER.debug("closeSession(): Tried to Autocommit and caught exception" + e); + } + } + this.sessionManager.close(); + } + } + } + + /** + * sets the connection management mode. + * + * @param mode - the connection management mode + * Valid values are + * PARTICIPATE - to be used in managed environments where taskana participates in surrounding transactions + * AUTOCOMMIT - to be used in non-managed environments. Taskana commits each single API call explicitly + * EXPLICIT - to be used in non-managed environments. Gives commit control to the client. + */ + @Override + public void setConnectionManagementMode(ConnectionManagementMode mode) { + if (this.mode == ConnectionManagementMode.EXPLICIT && connection != null + && mode != ConnectionManagementMode.EXPLICIT) { + try { + connection.close(); + } catch (SQLException e) { + LOGGER.debug("setConnectionManagementMode(" + mode + ") tried to close connection and caught " + e); + } + connection = null; + this.mode = mode; + } else { + this.mode = mode; + } + } + + /** + * retrieve the SqlSession used by taskana. + * @return the myBatis SqlSession object used by taskana + */ + public SqlSession getSqlSession() { + return this.sessionManager; + } + + /** + * Set the database connection to be used by taskana. + * If this Api is called, taskana uses the connection passed by the client for database + * access in all subsequent API calls until the client resets this connection. + * Control over commit and rollback is the responsibility of the client. + * In order to close the connection, the client can call TaskanaEngine.closeConnection() or + * TaskanaEngine.setConnection(null). Both calls have the same effect. + * @param connection + */ + @Override + public void setConnection(java.sql.Connection connection) { + if (connection != null) { + this.connection = connection; + mode = ConnectionManagementMode.EXPLICIT; + sessionManager.startManagedSession(connection); + } else { + this.connection = null; + if (sessionManager.isManagedSessionStarted()) { + sessionManager.close(); + } + mode = ConnectionManagementMode.PARTICIPATE; + } + } + + /** + * This method creates the sqlSessionManager of myBatis. It integrates all the * SQL mappers * @return a {@link SqlSessionFactory} */ - private SqlSessionFactory createSqlSessionFactory() { + private SqlSessionManager createSqlSessionManager() { Environment environment = new Environment(DEFAULT, this.transactionFactory, taskanaEngineConfiguration.getDatasource()); Configuration configuration = new Configuration(environment); @@ -108,10 +220,15 @@ public class TaskanaEngineImpl implements TaskanaEngine { configuration.addMapper(ObjectReferenceMapper.class); configuration.addMapper(QueryMapper.class); configuration.getTypeHandlerRegistry().register(MapTypeHandler.class); - sessionFactory = new SqlSessionFactoryBuilder().build(configuration); - return sessionFactory; + SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(configuration); + SqlSessionManager sessionManager = SqlSessionManager.newInstance(sessionFactory); + return sessionManager; } + /** + * creates the MyBatis transaction factory. + * @param useContainerManagedTransactions + */ private void createTransactionFactory(boolean useContainerManagedTransactions) { if (useContainerManagedTransactions) { this.transactionFactory = new ManagedTransactionFactory(); @@ -120,12 +237,44 @@ public class TaskanaEngineImpl implements TaskanaEngine { } } - public SqlSession getSession() { - return session; + /** + * 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() + * @param + * @return Stack of SqlSessionManager + */ + protected static Stack getSessionStack() { + Stack stack = sessionStack.get(); + if (stack == null) { + stack = new Stack(); + sessionStack.set(stack); + } + return stack; } - public void setSession(SqlSession session) { - this.session = session; + protected static SqlSessionManager getSessionFromStack() { + Stack stack = getSessionStack(); + if (stack.isEmpty()) { + return null; + } + return stack.peek(); } + protected static void pushSessionToStack(SqlSessionManager session) { + getSessionStack().push(session); + } + + protected static void popSessionFromStack() { + Stack stack = getSessionStack(); + if (!stack.isEmpty()) { + stack.pop(); + } + } } diff --git a/lib/taskana-core/src/main/java/pro/taskana/impl/WorkbasketServiceImpl.java b/lib/taskana-core/src/main/java/pro/taskana/impl/WorkbasketServiceImpl.java index 841c29a6b..d617780cb 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/impl/WorkbasketServiceImpl.java +++ b/lib/taskana-core/src/main/java/pro/taskana/impl/WorkbasketServiceImpl.java @@ -32,6 +32,7 @@ public class WorkbasketServiceImpl implements WorkbasketService { private static final String ID_PREFIX_WORKBASKET_AUTHORIZATION = "WAI"; private TaskanaEngine taskanaEngine; + private TaskanaEngineImpl taskanaEngineImpl; private WorkbasketMapper workbasketMapper; private DistributionTargetMapper distributionTargetMapper; @@ -43,6 +44,7 @@ public class WorkbasketServiceImpl implements WorkbasketService { public WorkbasketServiceImpl(TaskanaEngine taskanaEngine, WorkbasketMapper workbasketMapper, DistributionTargetMapper distributionTargetMapper, WorkbasketAccessMapper workbasketAccessMapper) { this.taskanaEngine = taskanaEngine; + this.taskanaEngineImpl = (TaskanaEngineImpl) taskanaEngine; this.workbasketMapper = workbasketMapper; this.distributionTargetMapper = distributionTargetMapper; this.workbasketAccessMapper = workbasketAccessMapper; @@ -50,130 +52,190 @@ public class WorkbasketServiceImpl implements WorkbasketService { @Override public Workbasket getWorkbasket(String workbasketId) throws WorkbasketNotFoundException { - Workbasket workbasket = workbasketMapper.findById(workbasketId); - if (workbasket == null) { - throw new WorkbasketNotFoundException(workbasketId); + try { + taskanaEngineImpl.openConnection(); + Workbasket workbasket = workbasketMapper.findById(workbasketId); + if (workbasket == null) { + throw new WorkbasketNotFoundException(workbasketId); + } + + return workbasket; + } finally { + taskanaEngineImpl.returnConnection(); } - return workbasket; } @Override public List getWorkbaskets(List permissions) { - //use a set to avoid duplicates - Set workbaskets = new HashSet<>(); - for (String accessId : CurrentUserContext.getAccessIds()) { - workbaskets.addAll(workbasketMapper.findByPermission(permissions, accessId)); + try { + taskanaEngineImpl.openConnection(); + //use a set to avoid duplicates + Set workbaskets = new HashSet<>(); + for (String accessId : CurrentUserContext.getAccessIds()) { + workbaskets.addAll(workbasketMapper.findByPermission(permissions, accessId)); + } + List workbasketList = new ArrayList(); + workbasketList.addAll(workbaskets); + return workbasketList; + } finally { + taskanaEngineImpl.returnConnection(); } - List workbasketList = new ArrayList(); - workbasketList.addAll(workbaskets); - return workbasketList; } @Override public List getWorkbaskets() { - return workbasketMapper.findAll(); + try { + taskanaEngineImpl.openConnection(); + return workbasketMapper.findAll(); + } finally { + taskanaEngineImpl.returnConnection(); + } } @Override public Workbasket createWorkbasket(Workbasket workbasket) { - Timestamp now = new Timestamp(System.currentTimeMillis()); - workbasket.setCreated(now); - workbasket.setModified(now); - if (workbasket.getId() == null || workbasket.getId().isEmpty()) { - workbasket.setId(IdGenerator.generateWithPrefix(ID_PREFIX_WORKBASKET)); - } - workbasketMapper.insert(workbasket); - LOGGER.debug("Workbasket '{}' created", workbasket.getId()); - if (workbasket.getDistributionTargets() != null) { - for (Workbasket distributionTarget : workbasket.getDistributionTargets()) { - if (workbasketMapper.findById(distributionTarget.getId()) == null) { - distributionTarget.setCreated(now); - distributionTarget.setModified(now); - workbasketMapper.insert(distributionTarget); - LOGGER.debug("Workbasket '{}' created", distributionTarget.getId()); - } - distributionTargetMapper.insert(workbasket.getId(), distributionTarget.getId()); + try { + taskanaEngineImpl.openConnection(); + Timestamp now = new Timestamp(System.currentTimeMillis()); + workbasket.setCreated(now); + workbasket.setModified(now); + if (workbasket.getId() == null || workbasket.getId().isEmpty()) { + workbasket.setId(IdGenerator.generateWithPrefix(ID_PREFIX_WORKBASKET)); } + workbasketMapper.insert(workbasket); + LOGGER.debug("Workbasket '{}' created", workbasket.getId()); + if (workbasket.getDistributionTargets() != null) { + for (Workbasket distributionTarget : workbasket.getDistributionTargets()) { + if (workbasketMapper.findById(distributionTarget.getId()) == null) { + distributionTarget.setCreated(now); + distributionTarget.setModified(now); + workbasketMapper.insert(distributionTarget); + LOGGER.debug("Workbasket '{}' created", distributionTarget.getId()); + } + distributionTargetMapper.insert(workbasket.getId(), distributionTarget.getId()); + } + } + return workbasketMapper.findById(workbasket.getId()); + } finally { + taskanaEngineImpl.returnConnection(); } - return workbasketMapper.findById(workbasket.getId()); } @Override public Workbasket updateWorkbasket(Workbasket workbasket) throws NotAuthorizedException { - workbasket.setModified(new Timestamp(System.currentTimeMillis())); - workbasketMapper.update(workbasket); - List oldDistributionTargets = distributionTargetMapper.findBySourceId(workbasket.getId()); - List distributionTargets = workbasket.getDistributionTargets(); - for (Workbasket distributionTarget : distributionTargets) { - if (!oldDistributionTargets.contains(distributionTarget.getId())) { - if (workbasketMapper.findById(distributionTarget.getId()) == null) { - workbasketMapper.insert(distributionTarget); - LOGGER.debug("Workbasket '{}' created", distributionTarget.getId()); + try { + taskanaEngineImpl.openConnection(); + workbasket.setModified(new Timestamp(System.currentTimeMillis())); + workbasketMapper.update(workbasket); + List oldDistributionTargets = distributionTargetMapper.findBySourceId(workbasket.getId()); + List distributionTargets = workbasket.getDistributionTargets(); + for (Workbasket distributionTarget : distributionTargets) { + if (!oldDistributionTargets.contains(distributionTarget.getId())) { + if (workbasketMapper.findById(distributionTarget.getId()) == null) { + workbasketMapper.insert(distributionTarget); + LOGGER.debug("Workbasket '{}' created", distributionTarget.getId()); + } + distributionTargetMapper.insert(workbasket.getId(), distributionTarget.getId()); + } else { + oldDistributionTargets.remove(distributionTarget.getId()); } - distributionTargetMapper.insert(workbasket.getId(), distributionTarget.getId()); - } else { - oldDistributionTargets.remove(distributionTarget.getId()); } + distributionTargetMapper.deleteMultiple(workbasket.getId(), oldDistributionTargets); + LOGGER.debug("Workbasket '{}' updated", workbasket.getId()); + return workbasketMapper.findById(workbasket.getId()); + } finally { + taskanaEngineImpl.returnConnection(); } - distributionTargetMapper.deleteMultiple(workbasket.getId(), oldDistributionTargets); - LOGGER.debug("Workbasket '{}' updated", workbasket.getId()); - return workbasketMapper.findById(workbasket.getId()); } @Override public WorkbasketAccessItem createWorkbasketAuthorization(WorkbasketAccessItem workbasketAccessItem) { - workbasketAccessItem.setId(IdGenerator.generateWithPrefix(ID_PREFIX_WORKBASKET_AUTHORIZATION)); - workbasketAccessMapper.insert(workbasketAccessItem); - return workbasketAccessItem; + try { + taskanaEngineImpl.openConnection(); + workbasketAccessItem.setId(IdGenerator.generateWithPrefix(ID_PREFIX_WORKBASKET_AUTHORIZATION)); + workbasketAccessMapper.insert(workbasketAccessItem); + return workbasketAccessItem; + } finally { + taskanaEngineImpl.returnConnection(); + } } @Override public WorkbasketAccessItem getWorkbasketAuthorization(String id) { - return workbasketAccessMapper.findById(id); + try { + taskanaEngineImpl.openConnection(); + return workbasketAccessMapper.findById(id); + } finally { + taskanaEngineImpl.returnConnection(); + } } @Override public void deleteWorkbasketAuthorization(String id) { - workbasketAccessMapper.delete(id); + try { + taskanaEngineImpl.openConnection(); + workbasketAccessMapper.delete(id); + } finally { + taskanaEngineImpl.returnConnection(); + } } @Override public List getAllAuthorizations() { - return workbasketAccessMapper.findAll(); + try { + taskanaEngineImpl.openConnection(); + return workbasketAccessMapper.findAll(); + } finally { + taskanaEngineImpl.returnConnection(); + } } @Override public void checkAuthorization(String workbasketId, WorkbasketAuthorization workbasketAuthorization) throws NotAuthorizedException { + try { + taskanaEngineImpl.openConnection(); + // Skip permission check is security is not enabled + if (!taskanaEngine.getConfiguration().isSecurityEnabled()) { + LOGGER.debug("Skipping permissions check since security is disabled."); + return; + } - // Skip permission check if security is not enabled - if (!taskanaEngine.getConfiguration().isSecurityEnabled()) { - LOGGER.debug("Skipping permissions check since security is disabled."); - return; - } - - List accessIds = CurrentUserContext.getAccessIds(); - LOGGER.debug("Verifying that {} has the permission {} on workbasket {}", + List accessIds = CurrentUserContext.getAccessIds(); + LOGGER.debug("Verifying that {} has the permission {} on workbasket {}", CurrentUserContext.getUserid(), workbasketAuthorization.name(), workbasketId); - List accessItems = workbasketAccessMapper + List accessItems = workbasketAccessMapper .findByWorkbasketAndAccessIdAndAuthorizations(workbasketId, accessIds, workbasketAuthorization.name()); - if (accessItems.size() <= 0) { - throw new NotAuthorizedException("Not authorized. Authorization '" + workbasketAuthorization.name() - + "' on workbasket '" + workbasketId + "' is needed."); + if (accessItems.size() <= 0) { + throw new NotAuthorizedException("Not authorized. Authorization '" + workbasketAuthorization.name() + + "' on workbasket '" + workbasketId + "' is needed."); + } + } finally { + taskanaEngineImpl.returnConnection(); } } @Override public WorkbasketAccessItem updateWorkbasketAuthorization(WorkbasketAccessItem workbasketAccessItem) { - workbasketAccessMapper.update(workbasketAccessItem); - return workbasketAccessItem; + try { + taskanaEngineImpl.openConnection(); + workbasketAccessMapper.update(workbasketAccessItem); + return workbasketAccessItem; + } finally { + taskanaEngineImpl.returnConnection(); + } } @Override public List getWorkbasketAuthorizations(String workbasketId) { - return workbasketAccessMapper.findByWorkbasketId(workbasketId); + try { + taskanaEngineImpl.openConnection(); + return workbasketAccessMapper.findByWorkbasketId(workbasketId); + } finally { + taskanaEngineImpl.returnConnection(); + } } } diff --git a/lib/taskana-core/src/main/java/pro/taskana/impl/persistence/ClassificationQueryImpl.java b/lib/taskana-core/src/main/java/pro/taskana/impl/persistence/ClassificationQueryImpl.java index 9c9247d81..ce9b6d272 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/impl/persistence/ClassificationQueryImpl.java +++ b/lib/taskana-core/src/main/java/pro/taskana/impl/persistence/ClassificationQueryImpl.java @@ -16,7 +16,7 @@ import java.util.List; public class ClassificationQueryImpl implements ClassificationQuery { private static final String LINK_TO_MAPPER = "pro.taskana.model.mappings.QueryMapper.queryClassification"; - private TaskanaEngineImpl taskanaEngine; + private TaskanaEngineImpl taskanaEngineImpl; private String[] parentClassificationId; private String[] category; private String[] type; @@ -32,7 +32,7 @@ public class ClassificationQueryImpl implements ClassificationQuery { private Date[] validUntil; public ClassificationQueryImpl(TaskanaEngine taskanaEngine) { - this.taskanaEngine = (TaskanaEngineImpl) taskanaEngine; + this.taskanaEngineImpl = (TaskanaEngineImpl) taskanaEngine; } @Override @@ -115,18 +115,33 @@ public class ClassificationQueryImpl implements ClassificationQuery { @Override public List list() { - return taskanaEngine.getSession().selectList(LINK_TO_MAPPER, this); + try { + taskanaEngineImpl.openConnection(); + return taskanaEngineImpl.getSqlSession().selectList(LINK_TO_MAPPER, this); + } finally { + taskanaEngineImpl.returnConnection(); + } } @Override public List list(int offset, int limit) { - RowBounds rowBounds = new RowBounds(offset, limit); - return taskanaEngine.getSession().selectList(LINK_TO_MAPPER, this, rowBounds); + try { + taskanaEngineImpl.openConnection(); + RowBounds rowBounds = new RowBounds(offset, limit); + return taskanaEngineImpl.getSqlSession().selectList(LINK_TO_MAPPER, this, rowBounds); + } finally { + taskanaEngineImpl.returnConnection(); + } } @Override public Classification single() { - return taskanaEngine.getSession().selectOne(LINK_TO_MAPPER, this); + try { + taskanaEngineImpl.openConnection(); + return taskanaEngineImpl.getSqlSession().selectOne(LINK_TO_MAPPER, this); + } finally { + taskanaEngineImpl.returnConnection(); + } } public String[] getParentClassificationId() { diff --git a/lib/taskana-core/src/main/java/pro/taskana/impl/persistence/ObjectReferenceQueryImpl.java b/lib/taskana-core/src/main/java/pro/taskana/impl/persistence/ObjectReferenceQueryImpl.java index c40360434..40f81d382 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/impl/persistence/ObjectReferenceQueryImpl.java +++ b/lib/taskana-core/src/main/java/pro/taskana/impl/persistence/ObjectReferenceQueryImpl.java @@ -16,7 +16,7 @@ public class ObjectReferenceQueryImpl implements ObjectReferenceQuery { private static final String LINK_TO_MAPPER = "pro.taskana.model.mappings.QueryMapper.queryObjectReference"; - private TaskanaEngineImpl taskanaEngine; + private TaskanaEngineImpl taskanaEngineImpl; private String[] company; private String[] system; private String[] systemInstance; @@ -24,7 +24,7 @@ public class ObjectReferenceQueryImpl implements ObjectReferenceQuery { private String[] value; public ObjectReferenceQueryImpl(TaskanaEngine taskanaEngine) { - this.taskanaEngine = (TaskanaEngineImpl) taskanaEngine; + this.taskanaEngineImpl = (TaskanaEngineImpl) taskanaEngine; } @Override @@ -59,18 +59,33 @@ public class ObjectReferenceQueryImpl implements ObjectReferenceQuery { @Override public List list() { - return taskanaEngine.getSession().selectList(LINK_TO_MAPPER, this); + try { + taskanaEngineImpl.openConnection(); + return taskanaEngineImpl.getSqlSession().selectList(LINK_TO_MAPPER, this); + } finally { + taskanaEngineImpl.returnConnection(); + } } @Override public List list(int offset, int limit) { - RowBounds rowBounds = new RowBounds(offset, limit); - return taskanaEngine.getSession().selectList(LINK_TO_MAPPER, this, rowBounds); + try { + taskanaEngineImpl.openConnection(); + RowBounds rowBounds = new RowBounds(offset, limit); + return taskanaEngineImpl.getSqlSession().selectList(LINK_TO_MAPPER, this, rowBounds); + } finally { + taskanaEngineImpl.returnConnection(); + } } @Override public ObjectReference single() { - return taskanaEngine.getSession().selectOne(LINK_TO_MAPPER, this); + try { + taskanaEngineImpl.openConnection(); + return taskanaEngineImpl.getSqlSession().selectOne(LINK_TO_MAPPER, this); + } finally { + taskanaEngineImpl.returnConnection(); + } } public String[] getCompany() { diff --git a/lib/taskana-core/src/main/java/pro/taskana/impl/persistence/TaskQueryImpl.java b/lib/taskana-core/src/main/java/pro/taskana/impl/persistence/TaskQueryImpl.java index 2e9257a72..3a97609dc 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/impl/persistence/TaskQueryImpl.java +++ b/lib/taskana-core/src/main/java/pro/taskana/impl/persistence/TaskQueryImpl.java @@ -20,7 +20,7 @@ public class TaskQueryImpl implements TaskQuery { private static final String LINK_TO_MAPPER = "pro.taskana.model.mappings.QueryMapper.queryTasks"; - private TaskanaEngineImpl taskanaEngine; + private TaskanaEngineImpl taskanaEngineImpl; private String[] name; private String description; @@ -35,7 +35,7 @@ public class TaskQueryImpl implements TaskQuery { private String[] customFields; public TaskQueryImpl(TaskanaEngine taskanaEngine) { - this.taskanaEngine = (TaskanaEngineImpl) taskanaEngine; + this.taskanaEngineImpl = (TaskanaEngineImpl) taskanaEngine; } @Override @@ -106,42 +106,57 @@ public class TaskQueryImpl implements TaskQuery { @Override public ObjectReferenceQuery createObjectReferenceQuery() { - return new ObjectReferenceQueryImpl(taskanaEngine); + return new ObjectReferenceQueryImpl(taskanaEngineImpl); } @Override public List list() throws NotAuthorizedException { - checkAuthorization(); - return taskanaEngine.getSession().selectList(LINK_TO_MAPPER, this); + try { + taskanaEngineImpl.openConnection(); + checkAuthorization(); + return taskanaEngineImpl.getSqlSession().selectList(LINK_TO_MAPPER, this); + } finally { + taskanaEngineImpl.returnConnection(); + } } @Override public List list(int offset, int limit) throws NotAuthorizedException { - checkAuthorization(); - RowBounds rowBounds = new RowBounds(offset, limit); - return taskanaEngine.getSession().selectList(LINK_TO_MAPPER, this, rowBounds); + try { + taskanaEngineImpl.openConnection(); + checkAuthorization(); + RowBounds rowBounds = new RowBounds(offset, limit); + return taskanaEngineImpl.getSqlSession().selectList(LINK_TO_MAPPER, this, rowBounds); + } finally { + taskanaEngineImpl.returnConnection(); + } } @Override public Task single() throws NotAuthorizedException { - checkAuthorization(); - return taskanaEngine.getSession().selectOne(LINK_TO_MAPPER, this); + try { + taskanaEngineImpl.openConnection(); + checkAuthorization(); + return taskanaEngineImpl.getSqlSession().selectOne(LINK_TO_MAPPER, this); + } finally { + taskanaEngineImpl.returnConnection(); + } } private void checkAuthorization() throws NotAuthorizedException { if (this.workbasketId != null && this.workbasketId.length > 0) { for (String workbasket : this.workbasketId) { - taskanaEngine.getWorkbasketService().checkAuthorization(workbasket, WorkbasketAuthorization.OPEN); + taskanaEngineImpl.getWorkbasketService().checkAuthorization(workbasket, WorkbasketAuthorization.OPEN); } } } public TaskanaEngineImpl getTaskanaEngine() { - return taskanaEngine; + return taskanaEngineImpl; } public void setTaskanaEngine(TaskanaEngineImpl taskanaEngine) { - this.taskanaEngine = taskanaEngine; + this.taskanaEngineImpl = taskanaEngine; } public String[] getName() { diff --git a/lib/taskana-core/src/test/java/pro/taskana/impl/ClassificationServiceImplTest.java b/lib/taskana-core/src/test/java/pro/taskana/impl/ClassificationServiceImplTest.java index c025994e7..b2942c497 100644 --- a/lib/taskana-core/src/test/java/pro/taskana/impl/ClassificationServiceImplTest.java +++ b/lib/taskana-core/src/test/java/pro/taskana/impl/ClassificationServiceImplTest.java @@ -34,6 +34,9 @@ public class ClassificationServiceImplTest { @Mock ClassificationMapper classificationMapper; + @Mock + TaskanaEngineImpl taskanaEngineImpl; + @Test public void testAddClassification() { @@ -52,6 +55,8 @@ public class ClassificationServiceImplTest { public void testModifiedClassification() { doNothing().when(classificationMapper).insert(any()); doNothing().when(classificationMapper).update(any()); + doNothing().when(taskanaEngineImpl).openConnection(); + doNothing().when(taskanaEngineImpl).returnConnection(); int insert = 0; @@ -86,6 +91,8 @@ public class ClassificationServiceImplTest { @Test public void testFindAllClassifications() throws NotAuthorizedException { doNothing().when(classificationMapper).insert(any()); + doNothing().when(taskanaEngineImpl).openConnection(); + doNothing().when(taskanaEngineImpl).returnConnection(); // insert Classifications Classification classification0 = new Classification(); @@ -118,7 +125,8 @@ public class ClassificationServiceImplTest { @Test public void testClassificationQuery() throws NotAuthorizedException { doNothing().when(classificationMapper).insert(any()); - + doNothing().when(taskanaEngineImpl).openConnection(); + doNothing().when(taskanaEngineImpl).returnConnection(); Classification classification = new Classification(); classification.setDescription("DESC"); classificationService.addClassification(classification); diff --git a/lib/taskana-core/src/test/java/pro/taskana/impl/TaskServiceImplTest.java b/lib/taskana-core/src/test/java/pro/taskana/impl/TaskServiceImplTest.java index d341a6cbd..80072dabe 100644 --- a/lib/taskana-core/src/test/java/pro/taskana/impl/TaskServiceImplTest.java +++ b/lib/taskana-core/src/test/java/pro/taskana/impl/TaskServiceImplTest.java @@ -6,13 +6,16 @@ import static org.mockito.ArgumentMatchers.eq; import java.sql.Timestamp; import org.junit.Assert; +import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; import org.mockito.junit.MockitoJUnitRunner; -import pro.taskana.TaskanaEngine; + +import pro.taskana.WorkbasketService; import pro.taskana.configuration.TaskanaEngineConfiguration; import pro.taskana.exceptions.NotAuthorizedException; import pro.taskana.exceptions.TaskNotFoundException; @@ -32,25 +35,39 @@ import pro.taskana.model.mappings.TaskMapper; public class TaskServiceImplTest { private static final int SLEEP_TIME = 100; + @Mock + TaskanaEngineConfiguration taskanaEngineConfiguration; + @InjectMocks TaskServiceImpl taskServiceImpl; @Mock - TaskanaEngine taskanaEngine; + TaskanaEngineImpl taskanaEngine; @Mock - TaskanaEngineConfiguration taskanaEngineConfiguration; - @Mock - WorkbasketServiceImpl workbasketServiceImpl; + TaskanaEngineImpl taskanaEngineImpl; @Mock TaskMapper taskMapper; @Mock ObjectReferenceMapper objectReferenceMapper; + @Mock + WorkbasketService workbasketService; + + + @Before + public void setup() { + MockitoAnnotations.initMocks(this); + Mockito.when(taskanaEngine.getWorkbasketService()).thenReturn(workbasketService); + try { + Mockito.doNothing().when(workbasketService).checkAuthorization(any(), any()); + } catch (NotAuthorizedException e) { + e.printStackTrace(); + } + Mockito.doNothing().when(taskanaEngineImpl).openConnection(); + Mockito.doNothing().when(taskanaEngineImpl).returnConnection(); + } @Test public void testCreateSimpleTask() throws NotAuthorizedException { - registerBasicMocks(false); - Mockito.doNothing().when(workbasketServiceImpl).checkAuthorization(any(), any()); Mockito.doNothing().when(taskMapper).insert(any()); - Task task = new Task(); task.setName("Unit Test Task"); task.setWorkbasketId("1"); @@ -101,13 +118,17 @@ public class TaskServiceImplTest { @Test public void testTransferTaskZuDestinationWorkbasket() throws TaskNotFoundException, WorkbasketNotFoundException, NotAuthorizedException { - registerBasicMocks(false); Workbasket workbasket2 = createWorkbasket2(); - Mockito.when(workbasketServiceImpl.getWorkbasket("2")).thenReturn(workbasket2); + + Mockito.when(taskanaEngine.getWorkbasketService().getWorkbasket("2")).thenReturn(workbasket2); Task task = createUnitTestTask("1", "Unit Test Task 1", "1"); task.setRead(true); + // taskanaEngine.getConfiguration().isSecurityEnabled()) + Mockito.when(taskanaEngine.getConfiguration()).thenReturn(taskanaEngineConfiguration); + Mockito.when(taskanaEngineConfiguration.isSecurityEnabled()).thenReturn(false); + Assert.assertEquals(taskServiceImpl.getTaskById(task.getId()).getWorkbasketId(), "1"); taskServiceImpl.transfer(task.getId(), "2"); Assert.assertEquals(taskServiceImpl.getTaskById(task.getId()).getWorkbasketId(), "2"); @@ -119,8 +140,7 @@ public class TaskServiceImplTest { @Test(expected = WorkbasketNotFoundException.class) public void testTransferFailsIfDestinationWorkbasketDoesNotExist_withSecurityDisabled() throws TaskNotFoundException, WorkbasketNotFoundException, NotAuthorizedException { - registerBasicMocks(false); - Mockito.doThrow(WorkbasketNotFoundException.class).when(workbasketServiceImpl) + Mockito.doThrow(WorkbasketNotFoundException.class).when(workbasketService) .checkAuthorization(eq("invalidWorkbasketId"), any()); Task task = createUnitTestTask("1", "Unit Test Task 1", "1"); @@ -132,9 +152,7 @@ public class TaskServiceImplTest { @Test(expected = WorkbasketNotFoundException.class) public void testTransferFailsIfDestinationWorkbasketDoesNotExist_withSecurityEnabled() throws TaskNotFoundException, WorkbasketNotFoundException, NotAuthorizedException { - registerBasicMocks(true); - Mockito.doThrow(WorkbasketNotFoundException.class).when(workbasketServiceImpl) - .checkAuthorization(eq("invalidWorkbasketId"), any()); + Mockito.doThrow(WorkbasketNotFoundException.class).when(workbasketService).checkAuthorization(eq("invalidWorkbasketId"), any()); Task task = createUnitTestTask("1", "Unit Test Task 1", "1"); @@ -152,8 +170,6 @@ public class TaskServiceImplTest { @Test public void should_InsertObjectReference_when_TaskIsCreated() throws NotAuthorizedException { - Mockito.when(taskanaEngine.getWorkbasketService()).thenReturn(workbasketServiceImpl); - Mockito.doNothing().when(workbasketServiceImpl).checkAuthorization(any(), any()); Mockito.when(objectReferenceMapper.findByObjectReference(any())).thenReturn(null); Task task = createUnitTestTask("1", "Unit Test Task 1", "1"); @@ -169,9 +185,6 @@ public class TaskServiceImplTest { @Test public void should_LinkObjectReference_when_TaskIsCreated() throws NotAuthorizedException { - Mockito.when(taskanaEngine.getWorkbasketService()).thenReturn(workbasketServiceImpl); - Mockito.doNothing().when(workbasketServiceImpl).checkAuthorization(any(), any()); - Task task = createUnitTestTask("1", "Unit Test Task 1", "1"); ObjectReference primaryObjRef = new ObjectReference(); primaryObjRef.setSystem("Sol"); @@ -208,10 +221,4 @@ public class TaskServiceImplTest { return workbasket2; } - private void registerBasicMocks(boolean securityEnabled) { - Mockito.when(taskanaEngine.getConfiguration()).thenReturn(taskanaEngineConfiguration); - Mockito.when(taskanaEngineConfiguration.isSecurityEnabled()).thenReturn(securityEnabled); - Mockito.when(taskanaEngine.getWorkbasketService()).thenReturn(workbasketServiceImpl); - } - } diff --git a/lib/taskana-core/src/test/java/pro/taskana/impl/WorkbasketServiceImplTest.java b/lib/taskana-core/src/test/java/pro/taskana/impl/WorkbasketServiceImplTest.java index d044dbd6b..815b7695c 100644 --- a/lib/taskana-core/src/test/java/pro/taskana/impl/WorkbasketServiceImplTest.java +++ b/lib/taskana-core/src/test/java/pro/taskana/impl/WorkbasketServiceImplTest.java @@ -1,12 +1,15 @@ package pro.taskana.impl; +import static org.mockito.Mockito.times; import org.junit.Assert; +import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Mock; +import org.mockito.MockitoAnnotations; import org.mockito.junit.MockitoJUnitRunner; -import pro.taskana.TaskanaEngine; + import pro.taskana.configuration.TaskanaEngineConfiguration; import pro.taskana.exceptions.NotAuthorizedException; import pro.taskana.exceptions.WorkbasketNotFoundException; @@ -44,10 +47,16 @@ public class WorkbasketServiceImplTest { @Mock WorkbasketAccessMapper workbasketAccessMapper; @Mock - TaskanaEngine taskanaEngine; + TaskanaEngineImpl taskanaEngine; + @Mock + TaskanaEngineImpl taskanaEngineImpl; @Mock TaskanaEngineConfiguration taskanaEngineConfiguration; + @Before + public void setup() { + MockitoAnnotations.initMocks(this); + } @Test public void should_ReturnWorkbasket_when_WorkbasketIdExists() throws WorkbasketNotFoundException { when(workbasketMapper.findById(any())).thenReturn(new Workbasket()); diff --git a/lib/taskana-core/src/test/java/pro/taskana/impl/configuration/DBCleaner.java b/lib/taskana-core/src/test/java/pro/taskana/impl/configuration/DBCleaner.java index ed40376c2..c80b79cf3 100644 --- a/lib/taskana-core/src/test/java/pro/taskana/impl/configuration/DBCleaner.java +++ b/lib/taskana-core/src/test/java/pro/taskana/impl/configuration/DBCleaner.java @@ -3,6 +3,7 @@ package pro.taskana.impl.configuration; import java.io.InputStreamReader; import java.io.PrintWriter; import java.io.StringWriter; +import java.sql.Connection; import java.sql.SQLException; import javax.sql.DataSource; @@ -30,8 +31,9 @@ public class DBCleaner { * @throws SQLException */ public void clearDb(DataSource dataSource) throws SQLException { - ScriptRunner runner = new ScriptRunner(dataSource.getConnection()); - LOGGER.debug(dataSource.getConnection().getMetaData().toString()); + Connection connection = dataSource.getConnection(); + ScriptRunner runner = new ScriptRunner(connection); + LOGGER.debug(connection.getMetaData().toString()); runner.setStopOnError(true); runner.setLogWriter(logWriter); diff --git a/lib/taskana-core/src/test/java/pro/taskana/impl/configuration/TaskanaEngineConfigurationTest.java b/lib/taskana-core/src/test/java/pro/taskana/impl/configuration/TaskanaEngineConfigurationTest.java index e8f8a0c22..8eb5687fa 100644 --- a/lib/taskana-core/src/test/java/pro/taskana/impl/configuration/TaskanaEngineConfigurationTest.java +++ b/lib/taskana-core/src/test/java/pro/taskana/impl/configuration/TaskanaEngineConfigurationTest.java @@ -11,12 +11,12 @@ import java.util.Properties; import javax.security.auth.login.LoginException; import javax.sql.DataSource; -import org.apache.ibatis.datasource.unpooled.UnpooledDataSource; -import org.h2.jdbcx.JdbcDataSource; +import org.apache.ibatis.datasource.pooled.PooledDataSource; import org.junit.Assert; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; + import pro.taskana.TaskanaEngine; import pro.taskana.configuration.TaskanaEngineConfiguration; /** @@ -26,6 +26,7 @@ import pro.taskana.configuration.TaskanaEngineConfiguration; public class TaskanaEngineConfigurationTest { private static DataSource dataSource = null; private static final Logger LOGGER = LoggerFactory.getLogger(TaskanaEngineConfigurationTest.class); + private static final int POOL_TIME_TO_WAIT = 50; @Test public void testCreateTaskanaEngine() throws FileNotFoundException, SQLException, LoginException { @@ -71,10 +72,20 @@ public class TaskanaEngineConfigurationTest { * @return */ private static DataSource createDefaultDataSource() { - JdbcDataSource ds = new JdbcDataSource(); - ds.setURL("jdbc:h2:mem:taskana"); - ds.setPassword("sa"); - ds.setUser("sa"); +// JdbcDataSource ds = new JdbcDataSource(); +// ds.setURL("jdbc:h2:mem:taskana"); +// ds.setPassword("sa"); +// ds.setUser("sa"); + + String jdbcDriver = "org.h2.Driver"; + String jdbcUrl = "jdbc:h2:mem:taskana"; + String dbUserName = "sa"; + String dbPassword = "sa"; + DataSource ds = new PooledDataSource(Thread.currentThread().getContextClassLoader(), jdbcDriver, + jdbcUrl, dbUserName, dbPassword); + ((PooledDataSource) ds).setPoolTimeToWait(POOL_TIME_TO_WAIT); + ((PooledDataSource) ds).forceCloseAll(); // otherwise the MyBatis pool is not initialized correctly + return ds; } @@ -112,8 +123,9 @@ public class TaskanaEngineConfigurationTest { } if (propertiesFileIsComplete) { - ds = new UnpooledDataSource(Thread.currentThread().getContextClassLoader(), jdbcDriver, + ds = new PooledDataSource(Thread.currentThread().getContextClassLoader(), jdbcDriver, jdbcUrl, dbUserName, dbPassword); + ((PooledDataSource) ds).forceCloseAll(); // otherwise the MyBatis pool is not initialized correctly } else { LOGGER.warn("propertiesFile " + propertiesFileName + " is incomplete" + warningMessage); LOGGER.warn("Using default Datasource for Test"); diff --git a/lib/taskana-core/src/test/java/pro/taskana/impl/integration/ClassificationServiceImplIntTest.java b/lib/taskana-core/src/test/java/pro/taskana/impl/integration/ClassificationServiceImplIntAutoCommitTest.java similarity index 97% rename from lib/taskana-core/src/test/java/pro/taskana/impl/integration/ClassificationServiceImplIntTest.java rename to lib/taskana-core/src/test/java/pro/taskana/impl/integration/ClassificationServiceImplIntAutoCommitTest.java index 27562ce5e..b5f39487b 100644 --- a/lib/taskana-core/src/test/java/pro/taskana/impl/integration/ClassificationServiceImplIntTest.java +++ b/lib/taskana-core/src/test/java/pro/taskana/impl/integration/ClassificationServiceImplIntAutoCommitTest.java @@ -10,13 +10,14 @@ import javax.security.auth.login.LoginException; import javax.sql.DataSource; import org.h2.store.fs.FileUtils; -import org.junit.After; import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; import org.junit.Test; + import pro.taskana.ClassificationService; import pro.taskana.TaskanaEngine; +import pro.taskana.TaskanaEngine.ConnectionManagementMode; import pro.taskana.configuration.TaskanaEngineConfiguration; import pro.taskana.exceptions.NotAuthorizedException; import pro.taskana.impl.TaskanaEngineImpl; @@ -25,10 +26,10 @@ import pro.taskana.impl.configuration.TaskanaEngineConfigurationTest; import pro.taskana.model.Classification; /** - * Integration Test for ClassificationServiceImpl. + * Integration Test for ClassificationServiceImpl with connection management mode AUTOCOMMIT. * @author EH */ -public class ClassificationServiceImplIntTest { +public class ClassificationServiceImplIntAutoCommitTest { static int counter = 0; private DataSource dataSource; @@ -45,6 +46,7 @@ public class ClassificationServiceImplIntTest { taskanaEngine = taskanaEngineConfiguration.buildTaskanaEngine(); classificationService = taskanaEngine.getClassificationService(); taskanaEngineImpl = (TaskanaEngineImpl) taskanaEngine; + taskanaEngineImpl.setConnectionManagementMode(ConnectionManagementMode.AUTOCOMMIT); DBCleaner cleaner = new DBCleaner(); cleaner.clearDb(dataSource); } @@ -112,7 +114,7 @@ public class ClassificationServiceImplIntTest { System.out.println(classification.getParentClassificationId()); List allClassifications = classificationService.getClassificationTree(); - Assert.assertEquals(2, list.size()); + Assert.assertEquals(2, allClassifications.size()); } @Test @@ -262,11 +264,6 @@ public class ClassificationServiceImplIntTest { Assert.assertEquals(1, list.size()); } - @After - public void cleanUp() { - taskanaEngineImpl.closeSession(); - } - @AfterClass public static void cleanUpClass() { FileUtils.deleteRecursive("~/data", true); diff --git a/lib/taskana-core/src/test/java/pro/taskana/impl/integration/ClassificationServiceImplIntExplicitTest.java b/lib/taskana-core/src/test/java/pro/taskana/impl/integration/ClassificationServiceImplIntExplicitTest.java new file mode 100644 index 000000000..b7d099920 --- /dev/null +++ b/lib/taskana-core/src/test/java/pro/taskana/impl/integration/ClassificationServiceImplIntExplicitTest.java @@ -0,0 +1,311 @@ +package pro.taskana.impl.integration; + +import java.io.FileNotFoundException; +import java.sql.Connection; +import java.sql.Date; +import java.sql.SQLException; +import java.time.LocalDate; +import java.util.List; + +import javax.security.auth.login.LoginException; +import javax.sql.DataSource; + +import org.h2.store.fs.FileUtils; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import pro.taskana.ClassificationService; +import pro.taskana.TaskanaEngine; +import pro.taskana.TaskanaEngine.ConnectionManagementMode; +import pro.taskana.configuration.TaskanaEngineConfiguration; +import pro.taskana.exceptions.NotAuthorizedException; +import pro.taskana.impl.TaskanaEngineImpl; +import pro.taskana.impl.configuration.DBCleaner; +import pro.taskana.impl.configuration.TaskanaEngineConfigurationTest; +import pro.taskana.model.Classification; + +/** + * Integration Test for ClassificationServiceImpl with connection management mode EXPLICIT. + * @author BBR + */ + +public class ClassificationServiceImplIntExplicitTest { + static int counter = 0; + + private DataSource dataSource; + private ClassificationService classificationService; + private TaskanaEngineConfiguration taskanaEngineConfiguration; + private TaskanaEngine taskanaEngine; + private TaskanaEngineImpl taskanaEngineImpl; + + + @Before + public void setup() throws FileNotFoundException, SQLException, LoginException { + dataSource = TaskanaEngineConfigurationTest.getDataSource(); + taskanaEngineConfiguration = new TaskanaEngineConfiguration(dataSource, false); + taskanaEngine = taskanaEngineConfiguration.buildTaskanaEngine(); + classificationService = taskanaEngine.getClassificationService(); + taskanaEngineImpl = (TaskanaEngineImpl) taskanaEngine; + taskanaEngineImpl.setConnectionManagementMode(ConnectionManagementMode.EXPLICIT); + DBCleaner cleaner = new DBCleaner(); + cleaner.clearDb(dataSource); + } + + @Test + public void testInsertClassification() throws SQLException { + Connection connection = dataSource.getConnection(); + taskanaEngineImpl.setConnection(connection); + + Classification classification = new Classification(); + classificationService.addClassification(classification); + + Assert.assertNotNull(classificationService.getClassification(classification.getId(), "")); + connection.commit(); + } + + @Test + public void testFindAllClassifications() throws NotAuthorizedException, SQLException { + Connection connection = dataSource.getConnection(); + taskanaEngineImpl.setConnection(connection); + Classification classification0 = new Classification(); + classificationService.addClassification(classification0); + Classification classification1 = new Classification(); + classificationService.addClassification(classification1); + Classification classification2 = new Classification(); + classification2.setParentClassificationId(classification0.getId()); + classificationService.addClassification(classification2); + + Assert.assertEquals(2 + 1, classificationService.getClassificationTree().size()); + connection.commit(); + } + + @Test + public void testModifiedClassification() throws SQLException { + + Connection connection = dataSource.getConnection(); + taskanaEngineImpl.setConnection(connection); + Classification classification = new Classification(); + connection.commit(); + classificationService.addClassification(classification); + classification.setDescription("TEST SOMETHING"); + classificationService.updateClassification(classification); + connection.commit(); + Assert.assertEquals(classification.getValidFrom(), Date.valueOf(LocalDate.now())); + } + + @Test + public void testInsertAndClassificationMapper() throws NotAuthorizedException, SQLException { + Connection connection = dataSource.getConnection(); + taskanaEngineImpl.setConnection(connection); + Classification classification = new Classification(); + classificationService.addClassification(classification); + Date today = Date.valueOf(LocalDate.now()); + List list = classificationService.createClassificationQuery().validInDomain(Boolean.TRUE).created(today).validFrom(today).validUntil(Date.valueOf("9999-12-31")).list(); + Assert.assertEquals(1, list.size()); + } + + @Test + public void testUpdateAndClassificationMapper() throws NotAuthorizedException, SQLException { + Connection connection = dataSource.getConnection(); + taskanaEngineImpl.setConnection(connection); + Classification classification = new Classification(); + classificationService.addClassification(classification); + System.out.println(classification.getId()); + classification.setDescription("description"); + classificationService.updateClassification(classification); + + List list = classificationService.createClassificationQuery().validUntil(Date.valueOf("9999-12-31")).list(); + Assert.assertEquals(1, list.size()); + list = classificationService.createClassificationQuery().validInDomain(true).list(); + Assert.assertEquals(2, list.size()); + + classification.setDomain("domain"); + classificationService.updateClassification(classification); + System.out.println(classification.getId()); + list = classificationService.createClassificationQuery().validUntil(Date.valueOf("9999-12-31")).list(); + Assert.assertEquals(2, list.size()); + + System.out.println(classification.getParentClassificationId()); + + List allClassifications = classificationService.getClassificationTree(); + Assert.assertEquals(2, allClassifications.size()); + connection.commit(); + } + + @Test + public void testFindWithClassificationMapperDomainAndCategory() throws NotAuthorizedException, SQLException { + Connection connection = dataSource.getConnection(); + taskanaEngineImpl.setConnection(connection); + Classification classification1 = new Classification(); + classification1.setDomain("domain1"); + classification1.setCategory("category1"); + classificationService.addClassification(classification1); + Classification classification2 = new Classification(); + classification2.setDomain("domain2"); + classification2.setCategory("category1"); + classificationService.addClassification(classification2); + Classification classification3 = new Classification(); + classification3.setDomain("domain1"); + classification3.setCategory("category2"); + classificationService.addClassification(classification3); + + List list = classificationService.createClassificationQuery().category("category1").domain("domain1").list(); + Assert.assertEquals(1, list.size()); + list = classificationService.createClassificationQuery().domain("domain1", "domain3").list(); + Assert.assertEquals(2, list.size()); + connection.commit(); + } + + @Test + public void testFindWithClassificationMapperCustomAndCategory() throws NotAuthorizedException, SQLException { + Connection connection = dataSource.getConnection(); + taskanaEngineImpl.setConnection(connection); + Classification classification1 = new Classification(); + classification1.setDescription("DESC1"); + classification1.setCategory("category1"); + classificationService.addClassification(classification1); + Classification classification2 = new Classification(); + classification2.setDescription("DESC1"); + classification2.setCustom1("custom1"); + classification2.setCategory("category1"); + classificationService.addClassification(classification2); + Classification classification3 = new Classification(); + classification3.setCustom1("custom2"); + classification3.setCustom2("custom1"); + classification3.setCategory("category2"); + classificationService.addClassification(classification3); + Classification classification4 = new Classification(); + classification4.setDescription("description2"); + classification4.setCustom8("custom2"); + classification4.setCategory("category1"); + classificationService.addClassification(classification4); + + List list = classificationService.createClassificationQuery().descriptionLike("DESC1").customFields("custom1").list(); + Assert.assertEquals(1, list.size()); + list = classificationService.createClassificationQuery().customFields("custom2").list(); + Assert.assertEquals(2, list.size()); + list = classificationService.createClassificationQuery().descriptionLike("DESC1").category("category1").list(); + Assert.assertEquals(2, list.size()); + connection.commit(); + } + + @Test + public void testFindWithClassificationMapperPriorityTypeAndParent() throws NotAuthorizedException, SQLException { + Connection connection = dataSource.getConnection(); + taskanaEngineImpl.setConnection(connection); + Classification classification = new Classification(); + classification.setPriority(Integer.decode("5")); + classification.setType("type1"); + classificationService.addClassification(classification); + Classification classification1 = new Classification(); + classification1.setPriority(Integer.decode("3")); + classification1.setType("type1"); + classification1.setParentClassificationId(classification.getId()); + classificationService.addClassification(classification1); + Classification classification2 = new Classification(); + classification2.setPriority(Integer.decode("5")); + classification2.setType("type2"); + classification2.setParentClassificationId(classification.getId()); + classificationService.addClassification(classification2); + Classification classification3 = new Classification(); + classification3.setPriority(Integer.decode("5")); + classification3.setType("type1"); + classification3.setParentClassificationId(classification1.getId()); + classificationService.addClassification(classification3); + + List list = classificationService.createClassificationQuery().parentClassification(classification.getId()).list(); + Assert.assertEquals(2, list.size()); + list = classificationService.createClassificationQuery().type("type1").priority(Integer.decode("5")).list(); + Assert.assertEquals(2, list.size()); + list = classificationService.createClassificationQuery().priority(Integer.decode("5")).type("type1").parentClassification(classification1.getId()).list(); + Assert.assertEquals(1, list.size()); + connection.commit(); + } + + @Test + public void testFindWithClassificationMapperServiceLevelNameAndDescription() throws NotAuthorizedException, SQLException { + Connection connection = dataSource.getConnection(); + taskanaEngineImpl.setConnection(connection); + int all = 0; + Classification classification = new Classification(); + classification.setServiceLevel("P1D"); + classification.setName("name1"); + classification.setDescription("desc"); + classificationService.addClassification(classification); + all++; + Classification classification1 = new Classification(); + classification1.setServiceLevel("P1DT1H"); + classification1.setName("name1"); + classification1.setDescription("desc"); + classificationService.addClassification(classification1); + all++; + Classification classification2 = new Classification(); + classification2.setServiceLevel("P1D"); + classification2.setName("name"); + classification2.setDescription("desc"); + classificationService.addClassification(classification2); + all++; + Classification classification3 = new Classification(); + classification3.setName("name1"); + classification3.setDescription("description"); + classificationService.addClassification(classification3); + all++; + + List list = classificationService.createClassificationQuery().name("name").list(); + Assert.assertEquals(1, list.size()); + list = classificationService.createClassificationQuery().serviceLevel("P1D").descriptionLike("desc").list(); + Assert.assertEquals(2, list.size()); + list = classificationService.createClassificationQuery().serviceLevel("P1DT1H").name("name").list(); + Assert.assertEquals(0, list.size()); + list = classificationService.createClassificationQuery().descriptionLike("desc%").list(); + Assert.assertEquals(all, list.size()); + connection.commit(); + } + + @Test + public void testDefaultSettingsWithClassificationMapper() throws NotAuthorizedException, SQLException { + Connection connection = dataSource.getConnection(); + taskanaEngineImpl.setConnection(connection); + Classification classification = new Classification(); + Classification classification1 = new Classification(); + classificationService.addClassification(classification); + classificationService.addClassification(classification1); + classification1.setParentClassificationId(classification.getId()); + classificationService.updateClassification(classification1); + + List + list = classificationService.createClassificationQuery().parentClassification("").list(); + Assert.assertEquals(2, list.size()); + list = classificationService.createClassificationQuery().validUntil(Date.valueOf("9999-12-31")).list(); + Assert.assertEquals(2, list.size()); + connection.commit(); + + List listAll = classificationService.createClassificationQuery().list(); + list = classificationService.createClassificationQuery().validFrom(Date.valueOf(LocalDate.now())).list(); + Assert.assertEquals(listAll.size(), list.size()); + list = classificationService.createClassificationQuery().validInDomain(true).list(); + Assert.assertEquals(listAll.size(), list.size()); + list = classificationService.createClassificationQuery().created(Date.valueOf(LocalDate.now())).list(); + Assert.assertEquals(listAll.size(), list.size()); + + list = classificationService.createClassificationQuery().domain("domain1").validInDomain(false).list(); + Assert.assertEquals(0, list.size()); + list = classificationService.createClassificationQuery().validFrom(Date.valueOf((LocalDate.now()))).validUntil(Date.valueOf(LocalDate.now().minusDays(1))).list(); + Assert.assertEquals(1, list.size()); + connection.commit(); + } + + @After + public void cleanUp() { + taskanaEngineImpl.setConnection(null); + } + + @AfterClass + public static void cleanUpClass() { + FileUtils.deleteRecursive("~/data", true); + } + +} diff --git a/lib/taskana-core/src/test/java/pro/taskana/impl/integration/TaskServiceImplTransactionTest.java b/lib/taskana-core/src/test/java/pro/taskana/impl/integration/TaskServiceImplIntAutocommitTest.java similarity index 91% rename from lib/taskana-core/src/test/java/pro/taskana/impl/integration/TaskServiceImplTransactionTest.java rename to lib/taskana-core/src/test/java/pro/taskana/impl/integration/TaskServiceImplIntAutocommitTest.java index 8ce52c2ca..93884770c 100644 --- a/lib/taskana-core/src/test/java/pro/taskana/impl/integration/TaskServiceImplTransactionTest.java +++ b/lib/taskana-core/src/test/java/pro/taskana/impl/integration/TaskServiceImplIntAutocommitTest.java @@ -1,8 +1,20 @@ package pro.taskana.impl.integration; +import java.io.FileNotFoundException; +import java.sql.SQLException; +import java.util.List; + +import javax.security.auth.login.LoginException; +import javax.sql.DataSource; + import org.h2.store.fs.FileUtils; -import org.junit.*; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + import pro.taskana.TaskanaEngine; +import pro.taskana.TaskanaEngine.ConnectionManagementMode; import pro.taskana.configuration.TaskanaEngineConfiguration; import pro.taskana.exceptions.NotAuthorizedException; import pro.taskana.exceptions.TaskNotFoundException; @@ -18,17 +30,11 @@ import pro.taskana.model.TaskState; import pro.taskana.persistence.ClassificationQuery; import pro.taskana.persistence.ObjectReferenceQuery; -import javax.security.auth.login.LoginException; -import javax.sql.DataSource; -import java.io.FileNotFoundException; -import java.sql.SQLException; -import java.util.List; - /** - * Integration Test for TaskServiceImpl transactions. + * Integration Test for TaskServiceImpl transactions with connection management mode AUTOCOMMIT. * @author EH */ -public class TaskServiceImplTransactionTest { +public class TaskServiceImplIntAutocommitTest { private DataSource dataSource; private TaskServiceImpl taskServiceImpl; @@ -43,6 +49,7 @@ public class TaskServiceImplTransactionTest { taskanaEngine = taskanaEngineConfiguration.buildTaskanaEngine(); taskanaEngineImpl = (TaskanaEngineImpl) taskanaEngine; + taskanaEngineImpl.setConnectionManagementMode(ConnectionManagementMode.AUTOCOMMIT); taskServiceImpl = (TaskServiceImpl) taskanaEngine.getTaskService(); DBCleaner cleaner = new DBCleaner(); cleaner.clearDb(dataSource); @@ -50,13 +57,12 @@ public class TaskServiceImplTransactionTest { @Test public void testStart() throws FileNotFoundException, SQLException, TaskNotFoundException, NotAuthorizedException { - Task task = new Task(); task.setName("Unit Test Task"); String id1 = IdGenerator.generateWithPrefix("TWB"); task.setWorkbasketId(id1); task = taskServiceImpl.create(task); - taskanaEngineImpl.getSession().commit(); // needed so that the change is visible in the other session + //skanaEngineImpl.getSqlSession().commit(); // needed so that the change is visible in the other session TaskanaEngine te2 = taskanaEngineConfiguration.buildTaskanaEngine(); TaskServiceImpl taskServiceImpl2 = (TaskServiceImpl) te2.getTaskService(); @@ -67,7 +73,6 @@ public class TaskServiceImplTransactionTest { @Test(expected = TaskNotFoundException.class) public void testStartTransactionFail() throws FileNotFoundException, SQLException, TaskNotFoundException, NotAuthorizedException { - Task task = new Task(); task.setName("Unit Test Task"); String id1 = IdGenerator.generateWithPrefix("TWB"); @@ -99,7 +104,6 @@ public class TaskServiceImplTransactionTest { @Test public void should_ReturnList_when_BuilderIsUsed() throws SQLException, NotAuthorizedException { - Task task = new Task(); task.setName("Unit Test Task"); String id1 = IdGenerator.generateWithPrefix("TWB"); @@ -124,11 +128,6 @@ public class TaskServiceImplTransactionTest { } - @After - public void cleanUp() { - taskanaEngineImpl.closeSession(); - } - @AfterClass public static void cleanUpClass() { FileUtils.deleteRecursive("~/data", true); diff --git a/lib/taskana-core/src/test/java/pro/taskana/impl/integration/TaskServiceImplIntExplicitTest.java b/lib/taskana-core/src/test/java/pro/taskana/impl/integration/TaskServiceImplIntExplicitTest.java new file mode 100644 index 000000000..a64dfdb19 --- /dev/null +++ b/lib/taskana-core/src/test/java/pro/taskana/impl/integration/TaskServiceImplIntExplicitTest.java @@ -0,0 +1,158 @@ +package pro.taskana.impl.integration; + +import java.io.FileNotFoundException; +import java.sql.Connection; +import java.sql.SQLException; +import java.util.List; + +import javax.security.auth.login.LoginException; +import javax.sql.DataSource; + +import org.h2.store.fs.FileUtils; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import pro.taskana.TaskanaEngine; +import pro.taskana.TaskanaEngine.ConnectionManagementMode; +import pro.taskana.configuration.TaskanaEngineConfiguration; +import pro.taskana.exceptions.NotAuthorizedException; +import pro.taskana.exceptions.TaskNotFoundException; +import pro.taskana.impl.TaskServiceImpl; +import pro.taskana.impl.TaskanaEngineImpl; +import pro.taskana.impl.configuration.DBCleaner; +import pro.taskana.impl.configuration.TaskanaEngineConfigurationTest; +import pro.taskana.impl.persistence.ClassificationQueryImpl; +import pro.taskana.impl.persistence.ObjectReferenceQueryImpl; +import pro.taskana.impl.util.IdGenerator; +import pro.taskana.model.Task; +import pro.taskana.model.TaskState; +import pro.taskana.persistence.ClassificationQuery; +import pro.taskana.persistence.ObjectReferenceQuery; + +/** + * Integration Test for TaskServiceImpl transactions with connection management mode EXPLICIT. + * @author EH + */ +public class TaskServiceImplIntExplicitTest { + + private DataSource dataSource; + private TaskServiceImpl taskServiceImpl; + private TaskanaEngineConfiguration taskanaEngineConfiguration; + private TaskanaEngine taskanaEngine; + private TaskanaEngineImpl taskanaEngineImpl; + + @Before + public void setup() throws FileNotFoundException, SQLException, LoginException { + dataSource = TaskanaEngineConfigurationTest.getDataSource(); + taskanaEngineConfiguration = new TaskanaEngineConfiguration(dataSource, false, false); + taskanaEngine = taskanaEngineConfiguration.buildTaskanaEngine(); + taskServiceImpl = (TaskServiceImpl) taskanaEngine.getTaskService(); + taskanaEngineImpl = (TaskanaEngineImpl) taskanaEngine; + taskanaEngineImpl.setConnectionManagementMode(ConnectionManagementMode.EXPLICIT); + DBCleaner cleaner = new DBCleaner(); + cleaner.clearDb(dataSource); + } + + @Test + public void testStart() throws FileNotFoundException, SQLException, TaskNotFoundException, NotAuthorizedException { + Connection connection = dataSource.getConnection(); + taskanaEngineImpl.setConnection(connection); + Task task = new Task(); + task.setName("Unit Test Task"); + String id1 = IdGenerator.generateWithPrefix("TWB"); + task.setWorkbasketId(id1); + task = taskServiceImpl.create(task); + taskanaEngineImpl.getSqlSession().commit(); // needed so that the change is visible in the other session + + TaskanaEngine te2 = taskanaEngineConfiguration.buildTaskanaEngine(); + TaskServiceImpl taskServiceImpl2 = (TaskServiceImpl) te2.getTaskService(); + Task resultTask = taskServiceImpl2.getTaskById(task.getId()); + Assert.assertNotNull(resultTask); + connection.commit(); + } + + @Test(expected = TaskNotFoundException.class) + public void testStartTransactionFail() + throws FileNotFoundException, SQLException, TaskNotFoundException, NotAuthorizedException { + Connection connection = dataSource.getConnection(); + taskanaEngineImpl.setConnection(connection); +// taskServiceImpl = (TaskServiceImpl) taskanaEngine.getTaskService(); + + Task task = new Task(); + task.setName("Unit Test Task"); + String id1 = IdGenerator.generateWithPrefix("TWB"); + task.setWorkbasketId("id1"); + task = taskServiceImpl.create(task); + connection.commit(); + taskServiceImpl.getTaskById(id1); + + TaskanaEngineImpl te2 = (TaskanaEngineImpl) taskanaEngineConfiguration.buildTaskanaEngine(); + TaskServiceImpl taskServiceImpl2 = (TaskServiceImpl) te2.getTaskService(); + taskServiceImpl2.getTaskById(id1); + connection.commit(); + } + + @Test + public void testCreateTaskInTaskanaWithDefaultDb() + throws FileNotFoundException, SQLException, TaskNotFoundException, NotAuthorizedException { + DataSource ds = TaskanaEngineConfiguration.createDefaultDataSource(); + TaskanaEngineConfiguration taskanaEngineConfiguration = new TaskanaEngineConfiguration(ds, false, false); + TaskanaEngine te = taskanaEngineConfiguration.buildTaskanaEngine(); + Connection connection = ds.getConnection(); + te.setConnection(connection); + TaskServiceImpl taskServiceImpl = (TaskServiceImpl) te.getTaskService(); + + Task task = new Task(); + task.setName("Unit Test Task"); + String id1 = IdGenerator.generateWithPrefix("TWB"); + task.setWorkbasketId(id1); + task = taskServiceImpl.create(task); + + Assert.assertNotNull(task); + Assert.assertNotNull(task.getId()); + connection.commit(); + te.setConnection(null); + } + + @Test + public void should_ReturnList_when_BuilderIsUsed() throws SQLException, NotAuthorizedException { + + Connection connection = dataSource.getConnection(); + taskanaEngineImpl.setConnection(connection); + Task task = new Task(); + task.setName("Unit Test Task"); + String id1 = IdGenerator.generateWithPrefix("TWB"); + task.setWorkbasketId(id1); + task = taskServiceImpl.create(task); + + TaskanaEngineImpl taskanaEngineImpl = (TaskanaEngineImpl) taskanaEngine; + ClassificationQuery classificationQuery = new ClassificationQueryImpl(taskanaEngineImpl) + .parentClassification("pId1", "pId2").category("cat1", "cat2").type("oneType").name("1Name", "name2") + .descriptionLike("my desc").priority(1, 2, 1).serviceLevel("me", "and", "you"); + + ObjectReferenceQuery objectReferenceQuery = new ObjectReferenceQueryImpl(taskanaEngineImpl) + .company("first comp", "sonstwo gmbh").system("sys").type("type1", "type2") + .systemInstance("sysInst1", "sysInst2").value("val1", "val2", "val3"); + + List results = taskServiceImpl.createTaskQuery().name("bla", "test").descriptionLike("test") + .priority(1, 2, 2).state(TaskState.CLAIMED).workbasketId("asd", "asdasdasd") + .owner("test", "test2", "bla").customFields("test").classification(classificationQuery) + .objectReference(objectReferenceQuery).list(); + + Assert.assertEquals(0, results.size()); + connection.commit(); + } + + @After + public void cleanUp() { + taskanaEngineImpl.setConnection(null); + } + + @AfterClass + public static void cleanUpClass() { + FileUtils.deleteRecursive("~/data", true); + } +} diff --git a/lib/taskana-core/src/test/java/pro/taskana/impl/integration/WorkbasketServiceImplIntTest.java b/lib/taskana-core/src/test/java/pro/taskana/impl/integration/WorkbasketServiceImplIntAutocommitTest.java similarity index 96% rename from lib/taskana-core/src/test/java/pro/taskana/impl/integration/WorkbasketServiceImplIntTest.java rename to lib/taskana-core/src/test/java/pro/taskana/impl/integration/WorkbasketServiceImplIntAutocommitTest.java index 5cc04d4a3..34a948b3a 100644 --- a/lib/taskana-core/src/test/java/pro/taskana/impl/integration/WorkbasketServiceImplIntTest.java +++ b/lib/taskana-core/src/test/java/pro/taskana/impl/integration/WorkbasketServiceImplIntAutocommitTest.java @@ -2,7 +2,9 @@ package pro.taskana.impl.integration; import org.h2.store.fs.FileUtils; import org.junit.*; + import pro.taskana.TaskanaEngine; +import pro.taskana.TaskanaEngine.ConnectionManagementMode; import pro.taskana.WorkbasketService; import pro.taskana.configuration.TaskanaEngineConfiguration; import pro.taskana.exceptions.NotAuthorizedException; @@ -23,10 +25,10 @@ import java.util.List; /** - * Integration Test for workbasketServiceImpl. + * Integration Test for workbasketServiceImpl with connection management mode AUTOCOMMIT. * @author EH */ -public class WorkbasketServiceImplIntTest { +public class WorkbasketServiceImplIntAutocommitTest { private static final int SLEEP_TIME = 100; private static final int THREE = 3; @@ -45,6 +47,7 @@ public class WorkbasketServiceImplIntTest { taskanaEngineConfiguration = new TaskanaEngineConfiguration(dataSource, false); taskanaEngine = taskanaEngineConfiguration.buildTaskanaEngine(); taskanaEngineImpl = (TaskanaEngineImpl) taskanaEngine; + taskanaEngineImpl.setConnectionManagementMode(ConnectionManagementMode.AUTOCOMMIT); workBasketService = taskanaEngine.getWorkbasketService(); DBCleaner cleaner = new DBCleaner(); cleaner.clearDb(dataSource); @@ -205,7 +208,7 @@ public class WorkbasketServiceImplIntTest { @After public void cleanUp() { - taskanaEngineImpl.closeSession(); + taskanaEngineImpl.returnConnection(); } @AfterClass diff --git a/lib/taskana-core/src/test/java/pro/taskana/impl/integration/WorkbasketServiceImplIntExplicitTest.java b/lib/taskana-core/src/test/java/pro/taskana/impl/integration/WorkbasketServiceImplIntExplicitTest.java new file mode 100644 index 000000000..a954c69ce --- /dev/null +++ b/lib/taskana-core/src/test/java/pro/taskana/impl/integration/WorkbasketServiceImplIntExplicitTest.java @@ -0,0 +1,262 @@ +package pro.taskana.impl.integration; + +import java.io.FileNotFoundException; +import java.sql.Connection; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; + +import javax.security.auth.login.LoginException; +import javax.sql.DataSource; + +import org.h2.store.fs.FileUtils; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import pro.taskana.TaskanaEngine; +import pro.taskana.TaskanaEngine.ConnectionManagementMode; +import pro.taskana.WorkbasketService; +import pro.taskana.configuration.TaskanaEngineConfiguration; +import pro.taskana.exceptions.NotAuthorizedException; +import pro.taskana.exceptions.WorkbasketNotFoundException; +import pro.taskana.impl.TaskanaEngineImpl; +import pro.taskana.impl.configuration.DBCleaner; +import pro.taskana.impl.configuration.TaskanaEngineConfigurationTest; +import pro.taskana.impl.util.IdGenerator; +import pro.taskana.model.Workbasket; +import pro.taskana.model.WorkbasketAccessItem; + +/** + * Integration Test for workbasketServiceImpl with connection mode EXPLICIT. + * @author bbr + * + */ +public class WorkbasketServiceImplIntExplicitTest { + + private static final int SLEEP_TIME = 100; + private static final int THREE = 3; + + static int counter = 0; + + private DataSource dataSource; + private TaskanaEngineConfiguration taskanaEngineConfiguration; + private TaskanaEngine taskanaEngine; + private TaskanaEngineImpl taskanaEngineImpl; + private WorkbasketService workBasketService; + + @Before + public void setup() throws FileNotFoundException, SQLException, LoginException { + dataSource = TaskanaEngineConfigurationTest.getDataSource(); + taskanaEngineConfiguration = new TaskanaEngineConfiguration(dataSource, false); + taskanaEngine = taskanaEngineConfiguration.buildTaskanaEngine(); + taskanaEngineImpl = (TaskanaEngineImpl) taskanaEngine; + taskanaEngineImpl.setConnectionManagementMode(ConnectionManagementMode.EXPLICIT); + DBCleaner cleaner = new DBCleaner(); + cleaner.clearDb(dataSource); + } + + @Test + public void testInsertWorkbasket() throws NotAuthorizedException, SQLException { + Connection connection = dataSource.getConnection(); + taskanaEngineImpl.setConnection(connection); + workBasketService = taskanaEngine.getWorkbasketService(); + int before = workBasketService.getWorkbaskets().size(); + Workbasket workbasket = new Workbasket(); + String id1 = IdGenerator.generateWithPrefix("TWB"); + workbasket.setId(id1); + workbasket.setName("Megabasket"); + workBasketService.createWorkbasket(workbasket); + Assert.assertEquals(before + 1, workBasketService.getWorkbaskets().size()); + connection.close(); + } + + @Test + public void testSelectAllWorkbaskets() throws NotAuthorizedException, SQLException { + Connection connection = dataSource.getConnection(); + taskanaEngineImpl.setConnection(connection); + workBasketService = taskanaEngine.getWorkbasketService(); + int before = workBasketService.getWorkbaskets().size(); + Workbasket workbasket0 = new Workbasket(); + String id0 = IdGenerator.generateWithPrefix("TWB"); + workbasket0.setId(id0); + workbasket0.setName("Superbasket"); + workBasketService.createWorkbasket(workbasket0); + Workbasket workbasket1 = new Workbasket(); + String id1 = IdGenerator.generateWithPrefix("TWB"); + workbasket1.setId(id1); + workbasket1.setName("Megabasket"); + workBasketService.createWorkbasket(workbasket1); + Workbasket workbasket2 = new Workbasket(); + String id2 = IdGenerator.generateWithPrefix("TWB"); + workbasket2.setId(id2); + workbasket2.setName("Hyperbasket"); + workBasketService.createWorkbasket(workbasket2); + Assert.assertEquals(before + THREE, workBasketService.getWorkbaskets().size()); + connection.commit(); + connection.close(); + } + + @Test + public void testSelectWorkbasket() throws WorkbasketNotFoundException, NotAuthorizedException, SQLException { + Connection connection = dataSource.getConnection(); + taskanaEngineImpl.setConnection(connection); + workBasketService = taskanaEngine.getWorkbasketService(); + Workbasket workbasket0 = new Workbasket(); + String id0 = IdGenerator.generateWithPrefix("TWB"); + workbasket0.setId(id0); + workbasket0.setName("Superbasket"); + workBasketService.createWorkbasket(workbasket0); + Workbasket workbasket1 = new Workbasket(); + String id1 = IdGenerator.generateWithPrefix("TWB"); + workbasket1.setId(id1); + workbasket1.setName("Megabasket"); + workBasketService.createWorkbasket(workbasket1); + Workbasket workbasket2 = new Workbasket(); + String id2 = IdGenerator.generateWithPrefix("TWB"); + workbasket2.setId(id2); + workbasket2.setName("Hyperbasket"); + workBasketService.createWorkbasket(workbasket2); + Workbasket foundWorkbasket = workBasketService.getWorkbasket(id2); + Assert.assertEquals(id2, foundWorkbasket.getId()); + connection.commit(); + connection.close(); + } + + @Test(expected = WorkbasketNotFoundException.class) + public void testGetWorkbasketFail() throws WorkbasketNotFoundException, SQLException { + Connection connection = dataSource.getConnection(); + taskanaEngineImpl.setConnection(connection); + workBasketService = taskanaEngine.getWorkbasketService(); + workBasketService.getWorkbasket("fail"); + connection.commit(); + connection.close(); + } + + @Test + public void testSelectWorkbasketWithDistribution() throws WorkbasketNotFoundException, NotAuthorizedException, SQLException { + Connection connection = dataSource.getConnection(); + taskanaEngineImpl.setConnection(connection); + workBasketService = taskanaEngine.getWorkbasketService(); + Workbasket workbasket0 = new Workbasket(); + String id0 = IdGenerator.generateWithPrefix("TWB"); + workbasket0.setId(id0); + workbasket0.setName("Superbasket"); + Workbasket workbasket1 = new Workbasket(); + String id1 = IdGenerator.generateWithPrefix("TWB"); + workbasket1.setId(id1); + workbasket1.setName("Megabasket"); + Workbasket workbasket2 = new Workbasket(); + String id2 = IdGenerator.generateWithPrefix("TWB"); + workbasket2.setId(id2); + workbasket2.setName("Hyperbasket"); + workbasket2.setDistributionTargets(new ArrayList<>()); + workbasket2.getDistributionTargets().add(workbasket0); + workbasket2.getDistributionTargets().add(workbasket1); + workBasketService.createWorkbasket(workbasket2); + Workbasket foundWorkbasket = workBasketService.getWorkbasket(id2); + Assert.assertEquals(id2, foundWorkbasket.getId()); + Assert.assertEquals(2, foundWorkbasket.getDistributionTargets().size()); + connection.commit(); + connection.close(); + } + + @Test + public void testUpdateWorkbasket() throws Exception { + Connection connection = dataSource.getConnection(); + taskanaEngineImpl.setConnection(connection); + workBasketService = taskanaEngine.getWorkbasketService(); + Workbasket workbasket0 = new Workbasket(); + String id0 = IdGenerator.generateWithPrefix("TWB"); + workbasket0.setId(id0); + workbasket0.setName("Superbasket"); + Workbasket workbasket1 = new Workbasket(); + String id1 = IdGenerator.generateWithPrefix("TWB"); + workbasket1.setId(id1); + workbasket1.setName("Megabasket"); + Workbasket workbasket2 = new Workbasket(); + String id2 = IdGenerator.generateWithPrefix("TWB"); + workbasket2.setId(id2); + workbasket2.setName("Hyperbasket"); + workbasket2.getDistributionTargets().add(workbasket0); + workbasket2.getDistributionTargets().add(workbasket1); + workBasketService.createWorkbasket(workbasket2); + + Workbasket workbasket3 = new Workbasket(); + String id3 = IdGenerator.generateWithPrefix("TWB"); + workbasket3.setId(id3); + workbasket3.setName("hm ... irgend ein basket"); + workbasket2.getDistributionTargets().clear(); + workbasket2.getDistributionTargets().add(workbasket3); + Thread.sleep(SLEEP_TIME); + workBasketService.updateWorkbasket(workbasket2); + + Workbasket foundBasket = workBasketService.getWorkbasket(workbasket2.getId()); + + List distributionTargets = foundBasket.getDistributionTargets(); + Assert.assertEquals(1, distributionTargets.size()); + Assert.assertEquals(id3, distributionTargets.get(0).getId()); + Assert.assertNotEquals(workBasketService.getWorkbasket(id2).getCreated(), + workBasketService.getWorkbasket(id2).getModified()); + Assert.assertEquals(workBasketService.getWorkbasket(id1).getCreated(), + workBasketService.getWorkbasket(id1).getModified()); + Assert.assertEquals(workBasketService.getWorkbasket(id3).getCreated(), + workBasketService.getWorkbasket(id3).getModified()); + connection.commit(); + connection.close(); + } + + @Test + public void testInsertWorkbasketAccessUser() throws NotAuthorizedException, SQLException { + Connection connection = dataSource.getConnection(); + taskanaEngineImpl.setConnection(connection); + workBasketService = taskanaEngine.getWorkbasketService(); + WorkbasketAccessItem accessItem = new WorkbasketAccessItem(); + String id1 = IdGenerator.generateWithPrefix("TWB"); + accessItem.setWorkbasketId(id1); + accessItem.setAccessId("Arthur Dent"); + accessItem.setPermOpen(true); + accessItem.setPermRead(true); + workBasketService.createWorkbasketAuthorization(accessItem); + + Assert.assertEquals(1, workBasketService.getAllAuthorizations().size()); + connection.commit(); + connection.close(); + } + + @Test + public void testUpdateWorkbasketAccessUser() throws NotAuthorizedException, SQLException { + Connection connection = dataSource.getConnection(); + taskanaEngineImpl.setConnection(connection); + workBasketService = taskanaEngine.getWorkbasketService(); + WorkbasketAccessItem accessItem = new WorkbasketAccessItem(); + String id1 = IdGenerator.generateWithPrefix("TWB"); + accessItem.setWorkbasketId(id1); + accessItem.setAccessId("Arthur Dent"); + accessItem.setPermOpen(true); + accessItem.setPermRead(true); + workBasketService.createWorkbasketAuthorization(accessItem); + + Assert.assertEquals(1, workBasketService.getAllAuthorizations().size()); + + accessItem.setAccessId("Zaphod Beeblebrox"); + workBasketService.updateWorkbasketAuthorization(accessItem); + + Assert.assertEquals("Zaphod Beeblebrox", + workBasketService.getWorkbasketAuthorization(accessItem.getId()).getAccessId()); + connection.commit(); + connection.close(); + } + + @After + public void cleanUp() { + taskanaEngineImpl.setConnection(null); + } + + @AfterClass + public static void cleanUpClass() { + FileUtils.deleteRecursive("~/data", true); + } +} diff --git a/lib/taskana-core/src/test/java/pro/taskana/impl/persistence/ClassificationQueryImplTest.java b/lib/taskana-core/src/test/java/pro/taskana/impl/persistence/ClassificationQueryImplTest.java index 5319e42e2..40016d86b 100644 --- a/lib/taskana-core/src/test/java/pro/taskana/impl/persistence/ClassificationQueryImplTest.java +++ b/lib/taskana-core/src/test/java/pro/taskana/impl/persistence/ClassificationQueryImplTest.java @@ -39,7 +39,7 @@ public class ClassificationQueryImplTest { @Test public void should_ReturnList_when_BuilderIsUsed() throws NotAuthorizedException { - when(taskanaEngine.getSession()).thenReturn(sqlSession); + when(taskanaEngine.getSqlSession()).thenReturn(sqlSession); when(sqlSession.selectList(any(), any())).thenReturn(new ArrayList<>()); List result = classificationQueryImpl.name("test", "asd", "blubber").type("cool", "bla").priority(1, 2) @@ -49,7 +49,7 @@ public class ClassificationQueryImplTest { @Test public void should_ReturnListWithOffset_when_BuilderIsUsed() throws NotAuthorizedException { - when(taskanaEngine.getSession()).thenReturn(sqlSession); + when(taskanaEngine.getSqlSession()).thenReturn(sqlSession); when(sqlSession.selectList(any(), any(), any())).thenReturn(new ArrayList<>()); List result = classificationQueryImpl.name("test", "asd", "blubber").type("cool", "bla").priority(1, 2) @@ -59,7 +59,7 @@ public class ClassificationQueryImplTest { @Test public void should_ReturnOneItem_when_BuilderIsUsed() throws NotAuthorizedException { - when(taskanaEngine.getSession()).thenReturn(sqlSession); + when(taskanaEngine.getSqlSession()).thenReturn(sqlSession); when(sqlSession.selectOne(any(), any())).thenReturn(new Classification()); Classification result = classificationQueryImpl.name("test", "asd", "blubber").type("cool", "bla").priority(1, 2) diff --git a/lib/taskana-core/src/test/java/pro/taskana/impl/persistence/ObjectReferenceQueryImplTest.java b/lib/taskana-core/src/test/java/pro/taskana/impl/persistence/ObjectReferenceQueryImplTest.java index d535df54c..2538152bd 100644 --- a/lib/taskana-core/src/test/java/pro/taskana/impl/persistence/ObjectReferenceQueryImplTest.java +++ b/lib/taskana-core/src/test/java/pro/taskana/impl/persistence/ObjectReferenceQueryImplTest.java @@ -39,7 +39,7 @@ public class ObjectReferenceQueryImplTest { @Test public void should_ReturnList_when_BuilderIsUsed() throws NotAuthorizedException { - when(taskanaEngine.getSession()).thenReturn(sqlSession); + when(taskanaEngine.getSqlSession()).thenReturn(sqlSession); when(sqlSession.selectList(any(), any())).thenReturn(new ArrayList<>()); List result = objectReferenceQueryImpl.value("test", "asd", "blubber").type("cool", "bla") @@ -49,7 +49,7 @@ public class ObjectReferenceQueryImplTest { @Test public void should_ReturnListWithOffset_when_BuilderIsUsed() throws NotAuthorizedException { - when(taskanaEngine.getSession()).thenReturn(sqlSession); + when(taskanaEngine.getSqlSession()).thenReturn(sqlSession); when(sqlSession.selectList(any(), any(), any())).thenReturn(new ArrayList<>()); List result = objectReferenceQueryImpl.value("test", "asd", "blubber").type("cool", "bla") @@ -59,7 +59,7 @@ public class ObjectReferenceQueryImplTest { @Test public void should_ReturnOneItem_when_BuilderIsUsed() throws NotAuthorizedException { - when(taskanaEngine.getSession()).thenReturn(sqlSession); + when(taskanaEngine.getSqlSession()).thenReturn(sqlSession); when(sqlSession.selectOne(any(), any())).thenReturn(new ObjectReference()); ObjectReference result = objectReferenceQueryImpl.value("test", "asd", "blubber").type("cool", "bla") diff --git a/lib/taskana-core/src/test/java/pro/taskana/impl/persistence/TaskQueryImplTest.java b/lib/taskana-core/src/test/java/pro/taskana/impl/persistence/TaskQueryImplTest.java index 9ae0913f7..10eec9b11 100644 --- a/lib/taskana-core/src/test/java/pro/taskana/impl/persistence/TaskQueryImplTest.java +++ b/lib/taskana-core/src/test/java/pro/taskana/impl/persistence/TaskQueryImplTest.java @@ -40,7 +40,7 @@ public class TaskQueryImplTest { @Test public void should_ReturnList_when_BuilderIsUsed() throws NotAuthorizedException { - when(taskanaEngine.getSession()).thenReturn(sqlSession); + when(taskanaEngine.getSqlSession()).thenReturn(sqlSession); when(sqlSession.selectList(any(), any())).thenReturn(new ArrayList<>()); List result = taskQueryImpl.name("test", "asd", "blubber").customFields("cool", "bla").priority(1, 2) @@ -50,7 +50,7 @@ public class TaskQueryImplTest { @Test public void should_ReturnListWithOffset_when_BuilderIsUsed() throws NotAuthorizedException { - when(taskanaEngine.getSession()).thenReturn(sqlSession); + when(taskanaEngine.getSqlSession()).thenReturn(sqlSession); when(sqlSession.selectList(any(), any(), any())).thenReturn(new ArrayList<>()); List result = taskQueryImpl.name("test", "asd", "blubber").customFields("cool", "bla").priority(1, 2) @@ -60,7 +60,7 @@ public class TaskQueryImplTest { @Test public void should_ReturnOneItem_when_BuilderIsUsed() throws NotAuthorizedException { - when(taskanaEngine.getSession()).thenReturn(sqlSession); + when(taskanaEngine.getSqlSession()).thenReturn(sqlSession); when(sqlSession.selectOne(any(), any())).thenReturn(new Task()); Task result = taskQueryImpl.name("test", "asd", "blubber").customFields("cool", "bla").priority(1, 2)