diff options
Diffstat (limited to 'id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process')
5 files changed, 148 insertions, 145 deletions
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessEngine.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessEngine.java index 2d9dcff8e..535070107 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessEngine.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessEngine.java @@ -31,35 +31,35 @@ public interface ProcessEngine { void registerProcessDefinition(InputStream processDefinitionInputStream) throws ProcessDefinitionParserException; /** - * Creates a process instance according to the referenced process definition. + * Creates a process instance according to the referenced process definition, persists it into the database and returns it identifier. * <p/> - * Note that the method returns a process instance which will be needed in order to start a process or to continue - * process execution after asynchronous task execution (refer to {@link #start(ProcessInstance)} and - * {@link #signal(ProcessInstance)} for further information). + * Note that the method returns the identifier of a process instance which will be needed in order to start a process or to continue + * process execution after asynchronous task execution (refer to {@link #start(String)} and + * {@link #signal(String)} for further information). * * @param processDefinitionId * The identifier of the respective process definition. * @param executionContext The execution context (may be {@code null}). - * @return The newly created process instance (never {@code null}). + * @return The id of the newly created process instance (never {@code null}). * @throws ProcessExecutionException * Thrown in case of error, e.g. when a {@code processDefinitionId} is referenced that does not exist. */ - ProcessInstance createProcessInstance(String processDefinitionId, ExecutionContext executionContext) throws ProcessExecutionException; + String createProcessInstance(String processDefinitionId, ExecutionContext executionContext) throws ProcessExecutionException; /** - * Creates a process instance according to the referenced process definition. + * Creates a process instance according to the referenced process definition, persists it into the database and returns it identifier. * <p/> - * Note that the method returns a process instance which will be needed in order to start a process or to continue - * process execution after asynchronous task execution (refer to {@link #start(ProcessInstance)} and - * {@link #signal(ProcessInstance)} for further information). + * Note that the method returns the identifier of a process instance which will be needed in order to start a process or to continue + * process execution after asynchronous task execution (refer to {@link #start(String))} and + * {@link #signal(String)} for further information). * * @param processDefinitionId * The identifier of the respective process definition. - * @return The newly created process instance (never {@code null}). + * @return The id of the newly created process instance (never {@code null}). * @throws ProcessExecutionException * Thrown in case of error, e.g. when a {@code processDefinitionId} is referenced that does not exist. */ - ProcessInstance createProcessInstance(String processDefinitionId) throws ProcessExecutionException; + String createProcessInstance(String processDefinitionId) throws ProcessExecutionException; /** * Returns the process instance with a given {@code processInstanceId}. @@ -73,41 +73,24 @@ public interface ProcessEngine { ProcessInstance getProcessInstance(String processInstanceId); /** - * Starts the process using the given {@code processInstance}. + * Starts the process using the given {@code processInstanceId}. * - * @param processInstance - * The process instance. + * @param processInstanceId + * The process instance id. * @throws ProcessExecutionException * Thrown in case of error. */ - void start(ProcessInstance processInstance) throws ProcessExecutionException; + void start(String processInstanceId) throws ProcessExecutionException; + /** * Resumes process execution after an asynchronous task has been executed. * - * @param processInstance - * The process instance. + * @param processInstanceId + * The process instance id. * @throws ProcessExecutionException * Thrown in case of error. */ - void signal(ProcessInstance processInstance) throws ProcessExecutionException; - - /** - * Performs cleanup, removing all process instances that have not been used for a certain time. - * - * @see #setProcessInstanceMaxIdleTimeSeconds(long) - */ - void cleanup(); - - /** - * Returns the first process instance with a process context containing some {@code value} stored under key {@code key}. - * - * @param key - * The key. - * @param value - * The value that needs to match. - * @return The process instance or {@code null} in case no process instance was found. - */ - ProcessInstance findProcessInstanceWith(String key, Serializable value); + void signal(String processInstanceId) throws ProcessExecutionException; }
\ No newline at end of file diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessEngineImpl.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessEngineImpl.java index 3ba8fb9ed..8af9e1b69 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessEngineImpl.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessEngineImpl.java @@ -2,11 +2,8 @@ package at.gv.egovernment.moa.id.process; import java.io.InputStream; import java.io.Serializable; -import java.util.Date; -import java.util.Iterator; +import java.util.HashMap; import java.util.Map; -import java.util.Map.Entry; -import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; import org.apache.commons.collections4.CollectionUtils; @@ -16,10 +13,14 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.slf4j.MDC; +import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException; import at.gv.egovernment.moa.id.process.api.ExecutionContext; import at.gv.egovernment.moa.id.process.api.ExpressionEvaluationContext; import at.gv.egovernment.moa.id.process.api.ExpressionEvaluator; import at.gv.egovernment.moa.id.process.api.Task; +import at.gv.egovernment.moa.id.process.dao.ProcessInstanceStore; +import at.gv.egovernment.moa.id.process.dao.ProcessInstanceStoreDAO; +import at.gv.egovernment.moa.id.process.dao.ProcessInstanceStoreDAOImpl; import at.gv.egovernment.moa.id.process.model.EndEvent; import at.gv.egovernment.moa.id.process.model.ProcessDefinition; import at.gv.egovernment.moa.id.process.model.ProcessNode; @@ -33,21 +34,20 @@ import at.gv.egovernment.moa.id.process.model.Transition; * */ public class ProcessEngineImpl implements ProcessEngine { - + private Logger log = LoggerFactory.getLogger(getClass()); - + private ProcessDefinitionParser pdp = new ProcessDefinitionParser(); + ProcessInstanceStoreDAO piStoreDao = ProcessInstanceStoreDAOImpl.getInstance(); + private Map<String, ProcessDefinition> processDefinitions = new ConcurrentHashMap<String, ProcessDefinition>(); - private Map<String, ProcessInstance> processInstances = new ConcurrentHashMap<String, ProcessInstance>(); - + private final static String MDC_CTX_PI_NAME = "processInstanceId"; private final static String MDC_CTX_TASK_NAME = "taskId"; - - private static final long DEFAULT_PROCESS_INSTANCE_MAX_AGE_SECONDS = 3600; - private long processInstanceIdleTimeSeconds = DEFAULT_PROCESS_INSTANCE_MAX_AGE_SECONDS; + private ExpressionEvaluator transitionConditionExpressionEvaluator; - + @Override public void registerProcessDefinition(ProcessDefinition processDefinition) { log.info("Registering process definition '{}'.", processDefinition.getId()); @@ -61,7 +61,7 @@ public class ProcessEngineImpl implements ProcessEngine { /** * Sets the process definitions. - * + * * @param processDefinitions * The process definitions. * @throws IllegalArgumentException @@ -76,19 +76,6 @@ public class ProcessEngineImpl implements ProcessEngine { registerProcessDefinition(pd); } } - - /** - * Defines the time frame in seconds an idle process instance will be managed by the process engine. A process - * instance with an idle time larger than the given time will be removed. - * <p/> - * Note that {@link #cleanup()} needs to be called in order to remove expired process instances. - * - * @param processInstanceMaxIdleTimeSeconds - * The maximum idle time in seconds. - */ - public void setProcessInstanceMaxIdleTimeSeconds(long processInstanceMaxIdleTimeSeconds) { - this.processInstanceIdleTimeSeconds = processInstanceMaxIdleTimeSeconds; - } /** * Sets an expression evaluator that should be used to process transition condition expressions. @@ -98,10 +85,10 @@ public class ProcessEngineImpl implements ProcessEngine { ExpressionEvaluator transitionConditionExpressionEvaluator) { this.transitionConditionExpressionEvaluator = transitionConditionExpressionEvaluator; } - + @Override - public ProcessInstance createProcessInstance(String processDefinitionId, ExecutionContext executionContext) throws ProcessExecutionException { + public String createProcessInstance(String processDefinitionId, ExecutionContext executionContext) throws ProcessExecutionException { // look for respective process definition ProcessDefinition pd = processDefinitions.get(processDefinitionId); if (pd == null) { @@ -110,19 +97,32 @@ public class ProcessEngineImpl implements ProcessEngine { // create and keep process instance ProcessInstance pi = new ProcessInstance(pd, executionContext); log.info("Creating process instance from process definition '{}': {}", processDefinitionId, pi.getId()); - processInstances.put(pi.getId(), pi); - return pi; + + try { + saveProcessInstance(pi); + } catch (MOADatabaseException e) { + throw new ProcessExecutionException(e.getMessage(), e.getCause()); + } + + return pi.getId(); } @Override - public ProcessInstance createProcessInstance(String processDefinitionId) throws ProcessExecutionException { + public String createProcessInstance(String processDefinitionId) throws ProcessExecutionException { return createProcessInstance(processDefinitionId, null); } @Override - public void start(ProcessInstance pi) throws ProcessExecutionException { - MDC.put(MDC_CTX_PI_NAME, pi.getId()); + public void start(String processInstanceId) throws ProcessExecutionException { + + boolean mdcEntryAdded = false; + try { + ProcessInstance pi = loadProcessInstance(processInstanceId); + + MDC.put(MDC_CTX_PI_NAME, pi.getId()); + mdcEntryAdded = true; + if (!ProcessInstanceState.NOT_STARTED.equals(pi.getState())) { throw new ProcessExecutionException("Process instance '" + pi.getId() + "' has already been started (current state is " + pi.getState() + ")."); } @@ -130,45 +130,49 @@ public class ProcessEngineImpl implements ProcessEngine { // execute process pi.setState(ProcessInstanceState.STARTED); execute(pi); + + saveProcessInstance(pi); + } catch (MOADatabaseException e) { + throw new ProcessExecutionException(e.getMessage(), e.getCause()); + } finally { - MDC.remove(MDC_CTX_PI_NAME); + if (mdcEntryAdded) + MDC.remove(MDC_CTX_PI_NAME); } } @Override - public void signal(ProcessInstance pi) throws ProcessExecutionException { - MDC.put(MDC_CTX_PI_NAME, pi.getId()); + public void signal(String processInstanceId) throws ProcessExecutionException { + + boolean mdcEntryAdded = false; + try { + ProcessInstance pi = loadProcessInstance(processInstanceId); + + MDC.put(MDC_CTX_PI_NAME, pi.getId()); + mdcEntryAdded = true; + if (!ProcessInstanceState.SUSPENDED.equals(pi.getState())) { throw new ProcessExecutionException("Process instance '" + pi.getId() + "' has not been suspended (current state is " + pi.getState() + ")."); } + log.info("Waking up process instance '{}'.", pi.getId()); pi.setState(ProcessInstanceState.STARTED); execute(pi); + + saveProcessInstance(pi); + } catch (MOADatabaseException e) { + throw new ProcessExecutionException(e.getMessage(), e.getCause()); + } finally { - MDC.remove(MDC_CTX_PI_NAME); + if (mdcEntryAdded) + MDC.remove(MDC_CTX_PI_NAME); } } - @Override - public synchronized void cleanup() { - log.trace("Cleanup job started."); - Iterator<Entry<String, ProcessInstance>> it = processInstances.entrySet().iterator(); - while (it.hasNext()) { - Entry<String, ProcessInstance> entry = it.next(); - ProcessInstance pi = entry.getValue(); - log.trace("Checking process instance {}.", pi); - long ageMillis = new Date().getTime() - pi.getLru().getTime(); - if (ageMillis > processInstanceIdleTimeSeconds * 1000) { - log.info("Removing process instance '{}'.", pi.getId()); - processInstances.remove(entry.getKey()); - } - } - log.trace("Cleanup job completed."); - } /** - * Instantates a task implementation given by a {@link TaskInfo}. + * Instantiates a task implementation given by a {@link TaskInfo}. * @param ti The task info. * @return A Task implementation or {@code null} if the task info does not reference any task implementing classes. * @throws ProcessExecutionException Thrown in case of error (when the referenced class does not implement {@link Task} for instance). @@ -194,7 +198,7 @@ public class ProcessEngineImpl implements ProcessEngine { throw new ProcessExecutionException("Unable to instantiate class '" + clazz + "' associated with task '" + ti.getId() + "' .", e); } } - + return task; } @@ -239,7 +243,12 @@ public class ProcessEngineImpl implements ProcessEngine { } else if (processNode instanceof EndEvent) { log.info("Finishing process instance '{}'.", pi.getId()); - processInstances.remove(pi.getId()); + + try { + piStoreDao.remove(pi.getId()); + } catch (MOADatabaseException e) { + throw new ProcessExecutionException(e.getMessage(), e.getCause()); + } pi.setState(ProcessInstanceState.ENDED); log.debug("Final process context: {}", pi.getExecutionContext().keySet()); return; @@ -282,23 +291,73 @@ public class ProcessEngineImpl implements ProcessEngine { @Override public ProcessInstance getProcessInstance(String processInstanceId) { - ProcessInstance processInstance = processInstances.get(processInstanceId); + + ProcessInstance processInstance; + try { + processInstance = loadProcessInstance(processInstanceId); + + } catch (MOADatabaseException e) { + throw new IllegalArgumentException("The process instance '" + processInstanceId + "' could not be retrieved."); + } + if (processInstance == null) { throw new IllegalArgumentException("The process instance '" + processInstanceId + "' does not/no longer exist."); } + return processInstance; } - @Override - public ProcessInstance findProcessInstanceWith(String key, Serializable value) { - Iterator<ProcessInstance> it = processInstances.values().iterator(); - while (it.hasNext()) { - ProcessInstance pi = it.next(); - if (Objects.equals(pi.getExecutionContext().get(key), value)) { - return pi; - } + /** + * Persists a {@link ProcessInstance} to the database. + * @param processInstance The object to persist. + * @throws MOADatabaseException Thrown if an error occurs while accessing the database. + */ + private void saveProcessInstance(ProcessInstance processInstance) throws MOADatabaseException { + ProcessInstanceStore store = new ProcessInstanceStore(); + + ExecutionContext ctx = processInstance.getExecutionContext(); + + Map<String, Serializable> ctxData = new HashMap<String, Serializable>(); + for (String key : ctx.keySet()) { + ctxData.put(key, ctx.get(key)); + } + store.setExecutionContextData(ctxData); + + store.setNextTaskId(processInstance.getNextId()); + store.setProcessDefinitionId(processInstance.getProcessDefinition().getId()); + + store.setProcessInstanceId(processInstance.getId()); + store.setProcessState(processInstance.getState()); + + piStoreDao.save(store); + } + + /** + * Load a {@link ProcessInstance} with a certain id from the database. + * @param processInstanceId The process instance id + * @return The process instance corresponding to the id or {@code null} if no such object is found. + * @throws MOADatabaseException Thrown if an error occurs while accessing the database. + */ + private ProcessInstance loadProcessInstance(String processInstanceId) throws MOADatabaseException { + + ProcessInstanceStore piStore = piStoreDao.load(processInstanceId); + + if (piStore == null) { + return null; } - return null; + + ExecutionContext executionContext = new ExecutionContextImpl(piStore.getProcessInstanceId()); + + Map<String, Serializable> executionContextData = piStore.getExecutionContextData(); + for (String key : executionContextData.keySet()) { + executionContext.put(key, executionContextData.get(key)); + } + + ProcessInstance pi = new ProcessInstance(processDefinitions.get(piStore.getProcessDefinitionId()), executionContext); + pi.setNextId(piStore.getNextTaskId()); + pi.setState(piStore.getProcessState()); + + return pi; } } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/dao/ProcessInstanceStore.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/dao/ProcessInstanceStore.java index c94c95516..c86d0de3d 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/dao/ProcessInstanceStore.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/dao/ProcessInstanceStore.java @@ -32,7 +32,7 @@ public class ProcessInstanceStore { @Column(name = "processState", nullable = false) @Enumerated(value = EnumType.STRING) - private Enum<ProcessInstanceState> processState; + private ProcessInstanceState processState; @Column(name = "executionContextData", nullable = false) @Lob @@ -50,7 +50,7 @@ public class ProcessInstanceStore { return nextTaskId; } - public Enum<ProcessInstanceState> getProcessState() { + public ProcessInstanceState getProcessState() { return processState; } @@ -70,7 +70,7 @@ public class ProcessInstanceStore { this.nextTaskId = nextTaskId; } - public void setProcessState(Enum<ProcessInstanceState> processState) { + public void setProcessState(ProcessInstanceState processState) { this.processState = processState; } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/dao/ProcessInstanceStoreDAO.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/dao/ProcessInstanceStoreDAO.java index 0aa6f80cd..999a9b82b 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/dao/ProcessInstanceStoreDAO.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/dao/ProcessInstanceStoreDAO.java @@ -42,14 +42,4 @@ public interface ProcessInstanceStoreDAO { */ void remove(String processInstanceId) throws MOADatabaseException; - /** - * Returns all {@link ProcessInstanceStore} objects stored in the database. - * The returned list may be empty, but never {@code null}. - * - * @return a list of {@link ProcessInstanceStore} (never {@code null}). - * @throws MOADatabaseException - * is thrown if a problem occurs while accessing the database. - */ - List<ProcessInstanceStore> getAllProcessInstanceStores() throws MOADatabaseException; - } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/dao/ProcessInstanceStoreDAOImpl.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/dao/ProcessInstanceStoreDAOImpl.java index 4b7468013..e9e977d53 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/dao/ProcessInstanceStoreDAOImpl.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/dao/ProcessInstanceStoreDAOImpl.java @@ -84,33 +84,4 @@ public class ProcessInstanceStoreDAOImpl implements ProcessInstanceStoreDAO { } } - @SuppressWarnings("unchecked") - @Override - public List<ProcessInstanceStore> getAllProcessInstanceStores() throws MOADatabaseException { - log.debug("Retrieve a list with all ProcessInstanceStores from the database."); - Session session = MOASessionDBUtils.getCurrentSession(); - - List<ProcessInstanceStore> result = Collections.emptyList(); - Transaction tx = null; - synchronized (session) { - try { - - tx = session.beginTransaction(); - // select all - result = session.createCriteria(ProcessInstanceStore.class).list(); - tx.commit(); - - } catch (Exception e) { - log.error("A problem occured while retrieving all stored ProcessInstanceStores."); - if (tx != null) { - tx.rollback(); - } - throw e; - } finally { - MOASessionDBUtils.closeSession(); - } - } - return result; - } - } |