summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Lenz <thomas.lenz@egiz.gv.at>2019-11-21 08:59:34 +0100
committerThomas Lenz <thomas.lenz@egiz.gv.at>2019-11-21 08:59:34 +0100
commit05835c051b57d3231e3ddf8dc160f1477a6494ca (patch)
tree257f1b31329d2783e333bd4223e56f5bd64799ee
parent2ba634720fd8ce44f6322f3b8ee3e930e67631b6 (diff)
downloadEAAF-Components-05835c051b57d3231e3ddf8dc160f1477a6494ca.tar.gz
EAAF-Components-05835c051b57d3231e3ddf8dc160f1477a6494ca.tar.bz2
EAAF-Components-05835c051b57d3231e3ddf8dc160f1477a6494ca.zip
add stop condition to process-flow engine that can be set dynamically by tasks
-rw-r--r--eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/ExecutionContextImpl.java16
-rw-r--r--eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/ProcessEngineImpl.java117
-rw-r--r--eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/ProcessInstance.java10
-rw-r--r--eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/process/test/HalloWeltTask.java2
-rw-r--r--eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/process/test/HelloWorldTask.java2
-rw-r--r--eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/process/test/ProcessEngineTest.java96
-rw-r--r--eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/process/test/StopProcessFlagTask.java52
-rw-r--r--eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/process/test/ThrowExceptionTask.java52
-rw-r--r--eaaf_core/src/test/resources/process/spring/test/SpringExpressionAwareProcessEngineTest-context.xml6
-rw-r--r--eaaf_core/src/test/resources/process/test/SampleProcessDefinition4.xml24
-rw-r--r--eaaf_core/src/test/resources/process/test/SampleProcessDefinition5.xml24
-rw-r--r--eaaf_core_api/src/main/java/at/gv/egiz/eaaf/core/api/idp/process/ExecutionContext.java15
12 files changed, 334 insertions, 82 deletions
diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/ExecutionContextImpl.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/ExecutionContextImpl.java
index 88a95795..3cd696df 100644
--- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/ExecutionContextImpl.java
+++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/ExecutionContextImpl.java
@@ -44,9 +44,10 @@ public class ExecutionContextImpl implements ExecutionContext {
private static final long serialVersionUID = 1L;
- private Map<String, Serializable> ctxData = Collections.synchronizedMap(new HashMap<String, Serializable>());
+ private final Map<String, Serializable> ctxData = Collections.synchronizedMap(new HashMap<String, Serializable>());
private String processInstanceId;
+ private boolean markedAsCancelled = false;
/**
* Creates a new instance.
@@ -93,7 +94,7 @@ public class ExecutionContextImpl implements ExecutionContext {
@Override
public String toString() {
- StringBuilder builder = new StringBuilder();
+ final StringBuilder builder = new StringBuilder();
builder.append("ExecutionContextImpl [");
builder.append("id=").append(processInstanceId);
builder.append(", variables=");
@@ -102,4 +103,15 @@ public class ExecutionContextImpl implements ExecutionContext {
return builder.toString();
}
+ @Override
+ public boolean isProcessCancelled() {
+ return markedAsCancelled;
+ }
+
+ @Override
+ public void setCanceleProcessFlag() {
+ markedAsCancelled = true;
+
+ }
+
}
diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/ProcessEngineImpl.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/ProcessEngineImpl.java
index b6b42850..53f50e1f 100644
--- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/ProcessEngineImpl.java
+++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/ProcessEngineImpl.java
@@ -64,14 +64,14 @@ import at.gv.egiz.eaaf.core.impl.idp.process.model.Transition;
*/
public class ProcessEngineImpl implements ProcessEngine {
- private Logger log = LoggerFactory.getLogger(getClass());
+ private final Logger log = LoggerFactory.getLogger(getClass());
@Autowired ProcessInstanceStoreDAO piStoreDao;
@Autowired ApplicationContext context;
- private ProcessDefinitionParser pdp = new ProcessDefinitionParser();
+ private final ProcessDefinitionParser pdp = new ProcessDefinitionParser();
- private Map<String, ProcessDefinition> processDefinitions = new ConcurrentHashMap<String, ProcessDefinition>();
+ private final Map<String, ProcessDefinition> processDefinitions = new ConcurrentHashMap<String, ProcessDefinition>();
private final static String MDC_CTX_PI_NAME = "processInstanceId";
private final static String MDC_CTX_TASK_NAME = "taskId";
@@ -86,7 +86,7 @@ public class ProcessEngineImpl implements ProcessEngine {
@Override
public String registerProcessDefinition(InputStream processDefinitionInputStream) throws ProcessDefinitionParserException{
- ProcessDefinition pd = pdp.parse(processDefinitionInputStream);
+ final ProcessDefinition pd = pdp.parse(processDefinitionInputStream);
postValidationOfProcessDefintion(pd);
@@ -104,7 +104,7 @@ public class ProcessEngineImpl implements ProcessEngine {
*/
public void setProcessDefinitions(Iterable<ProcessDefinition> processDefinitions) {
this.processDefinitions.clear();
- for (ProcessDefinition pd : processDefinitions) {
+ for (final ProcessDefinition pd : processDefinitions) {
if (this.processDefinitions.containsKey(pd.getId())) {
throw new IllegalArgumentException("Duplicate process definition identifier '" + pd.getId() + "'.");
}
@@ -125,18 +125,18 @@ public class ProcessEngineImpl implements ProcessEngine {
@Override
public String createProcessInstance(String processDefinitionId, ExecutionContext executionContext) throws ProcessExecutionException {
// look for respective process definition
- ProcessDefinition pd = processDefinitions.get(processDefinitionId);
+ final ProcessDefinition pd = processDefinitions.get(processDefinitionId);
if (pd == null) {
throw new ProcessExecutionException("Unable to find process definition for process '" + processDefinitionId + "'.");
}
// create and keep process instance
- ProcessInstance pi = new ProcessInstance(pd, executionContext);
+ final ProcessInstance pi = new ProcessInstance(pd, executionContext);
log.info("Creating process instance from process definition '{}': {}", processDefinitionId, pi.getId());
try {
saveOrUpdateProcessInstance(pi);
- } catch (EAAFException e) {
+ } catch (final EAAFException e) {
throw new ProcessExecutionException("Unable to persist process instance.", e);
}
@@ -158,7 +158,7 @@ public class ProcessEngineImpl implements ProcessEngine {
+ " includes NO 'ProcessInstanceId'");
}
- ProcessInstance pi = loadProcessInstance(pendingReq.getProcessInstanceId());
+ final ProcessInstance pi = loadProcessInstance(pendingReq.getProcessInstanceId());
if (pi == null ) {
throw new ProcessExecutionException("Process instance '" + pendingReq.getProcessInstanceId() + "' does not exist.");
@@ -179,7 +179,7 @@ public class ProcessEngineImpl implements ProcessEngine {
if (!ProcessInstanceState.ENDED.equals(pi.getState()))
saveOrUpdateProcessInstance(pi);
- } catch (EAAFException e) {
+ } catch (final EAAFException e) {
throw new ProcessExecutionException("Unable to load/save process instance.", e);
} finally {
@@ -198,7 +198,7 @@ public class ProcessEngineImpl implements ProcessEngine {
+ " includes NO 'ProcessInstanceId'");
}
- ProcessInstance pi = loadProcessInstance(pendingReq.getProcessInstanceId());
+ final ProcessInstance pi = loadProcessInstance(pendingReq.getProcessInstanceId());
if (pi == null ) {
throw new ProcessExecutionException("Process instance '" + pendingReq.getProcessInstanceId() + "' does not exist.");
@@ -223,7 +223,7 @@ public class ProcessEngineImpl implements ProcessEngine {
if (!ProcessInstanceState.ENDED.equals(pi.getState()))
saveOrUpdateProcessInstance(pi);
- } catch (EAAFException e) {
+ } catch (final EAAFException e) {
throw new ProcessExecutionException("Unable to load/save process instance.", e);
} finally {
@@ -239,7 +239,7 @@ public class ProcessEngineImpl implements ProcessEngine {
* @throws ProcessExecutionException Thrown in case of error (when the referenced class does not implement {@link Task} for instance).
*/
private Task createTaskInstance(TaskInfo ti) throws ProcessExecutionException {
- String clazz = StringUtils.trimToNull(ti.getTaskImplementingClass());
+ final String clazz = StringUtils.trimToNull(ti.getTaskImplementingClass());
Task task = null;
if (clazz != null) {
@@ -248,7 +248,7 @@ public class ProcessEngineImpl implements ProcessEngine {
try {
instanceClass = context.getBean(clazz);
- } catch (Exception e) {
+ } catch (final Exception e) {
throw new ProcessExecutionException("Unable to get class '" + clazz + "' associated with task '" + ti.getId() + "' .", e);
}
@@ -259,7 +259,7 @@ public class ProcessEngineImpl implements ProcessEngine {
try {
task = (Task) instanceClass;
- } catch (Exception e) {
+ } catch (final Exception e) {
throw new ProcessExecutionException("Unable to instantiate class '" + clazz + "' associated with task '" + ti.getId() + "' .", e);
}
}
@@ -277,19 +277,19 @@ public class ProcessEngineImpl implements ProcessEngine {
if (ProcessInstanceState.ENDED.equals(pi.getState())) {
throw new ProcessExecutionException("Process for instance '" + pi.getId() + "' has already been ended.");
}
- ProcessDefinition pd = pi.getProcessDefinition();
- ProcessNode processNode = pd.getProcessNode(pi.getNextId());
+ final ProcessDefinition pd = pi.getProcessDefinition();
+ final ProcessNode processNode = pd.getProcessNode(pi.getNextId());
log.debug("Processing node '{}'.", processNode.getId());
// distinguish process node types StartEvent, TaskInfo and EndEvent
if (processNode instanceof TaskInfo) {
// TaskInfo types need to be executed
- TaskInfo ti = (TaskInfo) processNode;
+ final TaskInfo ti = (TaskInfo) processNode;
MDC.put(MDC_CTX_TASK_NAME, ti.getId());
try {
log.debug("Processing task '{}'.", ti.getId());
- Task task = createTaskInstance(ti);
+ final Task task = createTaskInstance(ti);
if (task != null) {
try {
log.debug("Executing task implementation for task '{}'.", ti.getId());
@@ -297,35 +297,39 @@ public class ProcessEngineImpl implements ProcessEngine {
pendingReq = task.execute(pendingReq, pi.getExecutionContext());
log.debug("Returned from execution of task '{}'.", ti.getId());
log.trace("Execution context after task execution: {}", pi.getExecutionContext().keySet());
- } catch (Throwable t) {
+
+ } catch (final Throwable t) {
throw new ProcessExecutionException("Error executing task '" + ti.getId() + "'.", t);
+
+ }
+
+ //check if process was cancelled dynamically by task
+ if (pi.getExecutionContext().isProcessCancelled()) {
+ log.debug("Processing task '{}' was cancelled by Task: '{}'.", pi.getId(), ti.getId());
+ processFinishEvent(pi);
+ return;
+
}
+
} else {
log.debug("No task implementing class set.");
+
}
} finally {
MDC.remove(MDC_CTX_TASK_NAME);
+
}
} else if (processNode instanceof EndEvent) {
- log.info("Finishing process instance '{}'.", pi.getId());
-
- try {
- piStoreDao.remove(pi.getId());
-
- } catch (EAAFException e) {
- throw new ProcessExecutionException("Unable to remove process instance.", e);
-
- }
- pi.setState(ProcessInstanceState.ENDED);
- log.debug("Final process context: {}", pi.getExecutionContext().keySet());
+ processFinishEvent(pi);
return;
+
}
final ExpressionEvaluationContext expressionContext = new ExpressionEvaluationContextImpl(pi);
// traverse pointer
- Transition t = IterableUtils.find(processNode.getOutgoingTransitions(), new Predicate<Transition>() {
+ final Transition t = IterableUtils.find(processNode.getOutgoingTransitions(), new Predicate<Transition>() {
@Override
public boolean evaluate(Transition transition) {
if (transitionConditionExpressionEvaluator != null && transition.getConditionExpression() != null) {
@@ -356,7 +360,7 @@ public class ProcessEngineImpl implements ProcessEngine {
execute(pi, pendingReq);
}
}
-
+
@Override
public ProcessInstance getProcessInstance(String processInstanceId) {
@@ -364,7 +368,7 @@ public class ProcessEngineImpl implements ProcessEngine {
try {
processInstance = loadProcessInstance(processInstanceId);
- } catch (EAAFException e) {
+ } catch (final EAAFException e) {
throw new RuntimeException("The process instance '" + processInstanceId + "' could not be retrieved.", e);
}
@@ -381,12 +385,12 @@ public class ProcessEngineImpl implements ProcessEngine {
* @throws MOADatabaseException Thrown if an error occurs while accessing the database.
*/
private void saveOrUpdateProcessInstance(ProcessInstance processInstance) throws EAAFException {
- ProcessInstanceStore store = new ProcessInstanceStore();
+ final ProcessInstanceStore store = new ProcessInstanceStore();
- ExecutionContext ctx = processInstance.getExecutionContext();
+ final ExecutionContext ctx = processInstance.getExecutionContext();
- Map<String, Serializable> ctxData = new HashMap<String, Serializable>();
- for (String key : ctx.keySet()) {
+ final Map<String, Serializable> ctxData = new HashMap<String, Serializable>();
+ for (final String key : ctx.keySet()) {
ctxData.put(key, ctx.get(key));
}
store.setExecutionContextData(ctxData);
@@ -408,20 +412,20 @@ public class ProcessEngineImpl implements ProcessEngine {
*/
private ProcessInstance loadProcessInstance(String processInstanceId) throws EAAFException {
- ProcessInstanceStore piStore = piStoreDao.load(processInstanceId);
+ final ProcessInstanceStore piStore = piStoreDao.load(processInstanceId);
if (piStore == null) {
return null;
}
- ExecutionContext executionContext = new ExecutionContextImpl(piStore.getProcessInstanceId());
+ final ExecutionContext executionContext = new ExecutionContextImpl(piStore.getProcessInstanceId());
- Map<String, Serializable> executionContextData = piStore.getExecutionContextData();
- for (String key : executionContextData.keySet()) {
+ final Map<String, Serializable> executionContextData = piStore.getExecutionContextData();
+ for (final String key : executionContextData.keySet()) {
executionContext.put(key, executionContextData.get(key));
}
- ProcessInstance pi = new ProcessInstance(processDefinitions.get(piStore.getProcessDefinitionId()), executionContext);
+ final ProcessInstance pi = new ProcessInstance(processDefinitions.get(piStore.getProcessDefinitionId()), executionContext);
pi.setNextId(piStore.getNextTaskId());
pi.setState(piStore.getProcessState());
@@ -441,10 +445,31 @@ public class ProcessEngineImpl implements ProcessEngine {
try {
piStoreDao.remove(processInstanceId);
- } catch (EAAFException e) {
+ } catch (final EAAFException e) {
+ throw new ProcessExecutionException("Unable to remove process instance.", e);
+
+ }
+
+ }
+
+ /**
+ * Finish a process-flow and remove any process-flow related information
+ *
+ * @param pi
+ * @throws ProcessExecutionException
+ */
+ private void processFinishEvent(ProcessInstance pi) throws ProcessExecutionException {
+ log.info("Finishing process instance '{}'.", pi.getId());
+
+ try {
+ piStoreDao.remove(pi.getId());
+
+ } catch (final EAAFException e) {
throw new ProcessExecutionException("Unable to remove process instance.", e);
}
+ pi.setState(ProcessInstanceState.ENDED);
+ log.debug("Final process context: {}", pi.getExecutionContext().keySet());
}
@@ -458,11 +483,11 @@ public class ProcessEngineImpl implements ProcessEngine {
*/
private void postValidationOfProcessDefintion(ProcessDefinition pd) throws ProcessDefinitionParserException{
try {
- for(TaskInfo task : pd.getTaskInfos().values()) {
+ for(final TaskInfo task : pd.getTaskInfos().values()) {
createTaskInstance(task);
}
- } catch (ProcessExecutionException e) {
+ } catch (final ProcessExecutionException e) {
log.error("Post-validation of process definition: {} find an error: {}", pd.getId(), e.getMessage());
throw new ProcessDefinitionParserException("Post-validation find an error in process definition:" + pd.getId(), e);
diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/ProcessInstance.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/ProcessInstance.java
index 17d8ea8f..6db1dc7d 100644
--- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/ProcessInstance.java
+++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/process/ProcessInstance.java
@@ -49,13 +49,13 @@ public class ProcessInstance implements Serializable {
private static final long serialVersionUID = 1L;
private static final int RND_ID_LENGTH = 22;
- private ProcessDefinition processDefinition;
+ private final ProcessDefinition processDefinition;
private String nextId;
private Date lru;
- private ExecutionContext executionContext;
+ private final ExecutionContext executionContext;
private ProcessInstanceState state = ProcessInstanceState.NOT_STARTED;
- private Logger log = LoggerFactory.getLogger(getClass());
+ private final Logger log = LoggerFactory.getLogger(getClass());
/**
* Creates a new process instance, based on a given process definition and a
@@ -74,7 +74,7 @@ public class ProcessInstance implements Serializable {
executionContext = new ExecutionContextImpl();
}
if (executionContext.getProcessInstanceId() == null) {
- String pdIdLocalPart = RandomStringUtils.random(RND_ID_LENGTH, 0, 0, true, true, null,
+ final String pdIdLocalPart = RandomStringUtils.random(RND_ID_LENGTH, 0, 0, true, true, null,
SecureRandomHolder.getInstance());
executionContext.setProcessInstanceId(this.processDefinition.getId() + "-" + pdIdLocalPart);
} else {
@@ -169,7 +169,7 @@ public class ProcessInstance implements Serializable {
@Override
public String toString() {
- StringBuilder builder = new StringBuilder();
+ final StringBuilder builder = new StringBuilder();
builder.append("ProcessInstance [");
builder.append("id=").append(executionContext.getProcessInstanceId());
builder.append(", idle since=").append(
diff --git a/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/process/test/HalloWeltTask.java b/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/process/test/HalloWeltTask.java
index 40399e58..743a61da 100644
--- a/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/process/test/HalloWeltTask.java
+++ b/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/process/test/HalloWeltTask.java
@@ -44,7 +44,7 @@ public class HalloWeltTask implements Task {
@Override
public IRequest execute(IRequest pendingReq, ExecutionContext executionContext) {
System.out.println("Hallo Welt");
- return null;
+ return pendingReq;
}
}
diff --git a/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/process/test/HelloWorldTask.java b/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/process/test/HelloWorldTask.java
index a2d8b3fb..c6da16b4 100644
--- a/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/process/test/HelloWorldTask.java
+++ b/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/process/test/HelloWorldTask.java
@@ -44,7 +44,7 @@ public class HelloWorldTask implements Task {
@Override
public IRequest execute(IRequest pendingReq, ExecutionContext executionContext) {
System.out.println("Hello World");
- return null;
+ return pendingReq;
}
}
diff --git a/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/process/test/ProcessEngineTest.java b/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/process/test/ProcessEngineTest.java
index 78fdde61..dc45534e 100644
--- a/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/process/test/ProcessEngineTest.java
+++ b/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/process/test/ProcessEngineTest.java
@@ -33,6 +33,7 @@ import static org.junit.Assert.assertEquals;
import java.io.IOException;
import java.io.InputStream;
+import org.apache.commons.lang3.RandomStringUtils;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
@@ -44,6 +45,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import at.gv.egiz.eaaf.core.api.idp.process.ProcessEngine;
import at.gv.egiz.eaaf.core.exceptions.ProcessExecutionException;
+import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException;
import at.gv.egiz.eaaf.core.impl.idp.module.test.TestRequestImpl;
import at.gv.egiz.eaaf.core.impl.idp.process.ProcessDefinitionParser;
import at.gv.egiz.eaaf.core.impl.idp.process.ProcessDefinitionParserException;
@@ -64,7 +66,7 @@ public class ProcessEngineTest {
public void init() throws IOException, ProcessDefinitionParserException {
if (!isInitialized) {
- ProcessDefinitionParser pdp = new ProcessDefinitionParser();
+ final ProcessDefinitionParser pdp = new ProcessDefinitionParser();
if (pe == null) {
pe = applicationContext.getBean("processEngine", ProcessEngine.class);
@@ -79,29 +81,19 @@ public class ProcessEngineTest {
((ProcessEngineImpl) pe).registerProcessDefinition(pdp.parse(in));
}
+ try (InputStream in = ProcessEngineTest.class.getResourceAsStream("/process/test/SampleProcessDefinition4.xml")) {
+ ((ProcessEngineImpl) pe).registerProcessDefinition(pdp.parse(in));
+ }
+
+ try (InputStream in = ProcessEngineTest.class.getResourceAsStream("/process/test/SampleProcessDefinition5.xml")) {
+ ((ProcessEngineImpl) pe).registerProcessDefinition(pdp.parse(in));
+ }
+
//initHibernateForTesting();
isInitialized = true;
}
}
- private static void initHibernateForTesting() throws IOException{
-
-// InputStream in = ProcessEngineTest.class.getResourceAsStream("/at/gv/egovernment/moa/id/process/hibernate.configuration.test.properties");
-// Properties props = new Properties();
-// props.load(in);
-//
-// try {
-// //ConfigurationDBUtils.initHibernate(props);
-// Configuration config = new Configuration();
-// config.addProperties(props);
-// //config.addAnnotatedClass(ProcessInstanceStore.class);
-// config.addAnnotatedClass(AssertionStore.class);
-// //MOASessionDBUtils.initHibernate(config, props);
-// } catch (Exception e) {
-// e.printStackTrace();
-// }
- }
-
@Test
public void wrongProcessDefinition() throws IOException {
try (InputStream in = ProcessEngineTest.class.getResourceAsStream("/process/test/SampleProcessDefinition3.xml")) {
@@ -109,7 +101,7 @@ public class ProcessEngineTest {
((ProcessEngineImpl) pe).registerProcessDefinition(in);
Assert.fail();
- } catch (ProcessDefinitionParserException e) {
+ } catch (final ProcessDefinitionParserException e) {
Assert.assertTrue(e.getMessage().contains("Post-validation find an error in process definition"));
}
}
@@ -119,9 +111,9 @@ public class ProcessEngineTest {
@Test
public void testSampleProcess1() throws IOException, ProcessDefinitionParserException, ProcessExecutionException {
- TestRequestImpl testReq = new TestRequestImpl();
+ final TestRequestImpl testReq = new TestRequestImpl();
- String piId = pe.createProcessInstance("SampleProcess1");
+ final String piId = pe.createProcessInstance("SampleProcess1");
ProcessInstance pi = pe.getProcessInstance(piId);
assertEquals(NOT_STARTED, pi.getState());
@@ -139,7 +131,7 @@ public class ProcessEngineTest {
throw new ProcessExecutionException("ProcessInstance should be removed already, but it was found.");
//assertEquals(ENDED, pi.getState());
- } catch (IllegalArgumentException e) {
+ } catch (final IllegalArgumentException e) {
// do nothing because processInstance should be already removed
}
@@ -148,9 +140,9 @@ public class ProcessEngineTest {
@Test
public void testSampleProcess2() throws IOException, ProcessDefinitionParserException, ProcessExecutionException {
- TestRequestImpl testReq = new TestRequestImpl();
+ final TestRequestImpl testReq = new TestRequestImpl();
- String piId = pe.createProcessInstance("SampleProcess2");
+ final String piId = pe.createProcessInstance("SampleProcess2");
ProcessInstance pi = pe.getProcessInstance(piId);
assertEquals(NOT_STARTED, pi.getState());
@@ -168,14 +160,64 @@ public class ProcessEngineTest {
throw new ProcessExecutionException("ProcessInstance should be removed already, but it was found.");
//assertEquals(ENDED, pi.getState());
- } catch (IllegalArgumentException e) {
+ } catch (final IllegalArgumentException e) {
// do nothing because processInstance should be already removed
}
+
+ }
+
+ @Test
+ public void testSampleProcess4() throws IOException, ProcessDefinitionParserException, ProcessExecutionException {
+
+ final TestRequestImpl testReq = new TestRequestImpl();
+ testReq.setPendingReqId(RandomStringUtils.randomAlphanumeric(5));
-
+ final String piId = pe.createProcessInstance("SampleProcess4");
+ final ProcessInstance pi = pe.getProcessInstance(piId);
+ assertEquals(NOT_STARTED, pi.getState());
+
+ // start process
+ testReq.setProcessInstanceID(piId);
+ try {
+ pe.start(testReq);
+ Assert.fail("Task exception not handled");
+
+ } catch (final ProcessExecutionException e1) {
+ org.springframework.util.Assert.isInstanceOf(TaskExecutionException.class, e1.getCause(), "No TaskExecutionException");
+ Assert.assertEquals("Wrong error-msg", "jUnit Test", e1.getCause().getMessage());
+ Assert.assertEquals("Wrong pendingReqId", testReq.getPendingRequestId(), ((TaskExecutionException) e1.getCause()).getPendingRequestID());
+ org.springframework.util.Assert.isInstanceOf(RuntimeException.class, e1.getCause().getCause(), "Wrong Exception in TaskExecutionException");
+ }
+
+
}
+
+ @Test
+ public void testSampleProcess5() throws IOException, ProcessDefinitionParserException, ProcessExecutionException {
+ final TestRequestImpl testReq = new TestRequestImpl();
+
+ final String piId = pe.createProcessInstance("SampleProcess5");
+ ProcessInstance pi = pe.getProcessInstance(piId);
+ assertEquals(NOT_STARTED, pi.getState());
+
+ // start process
+ testReq.setProcessInstanceID(piId);
+ pe.start(testReq);
+
+ try {
+ pi = pe.getProcessInstance(piId);
+
+ } catch (final IllegalArgumentException e) {
+ Assert.assertTrue("wrong error-msg", e.getMessage().contains("does not/no longer exist."));
+ Assert.assertTrue("wrong process-instance-id", e.getMessage().contains(piId));
+
+ }
+
+
+ }
+
@Test(expected = IllegalArgumentException.class)
public void testProcessInstanceDoesNotExist() {
pe.getProcessInstance("does not exist");
diff --git a/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/process/test/StopProcessFlagTask.java b/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/process/test/StopProcessFlagTask.java
new file mode 100644
index 00000000..8cd76eaa
--- /dev/null
+++ b/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/process/test/StopProcessFlagTask.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright 2017 Graz University of Technology
+ * EAAF-Core Components has been developed in a cooperation between EGIZ,
+ * A-SIT Plus, A-SIT, and Graz University of Technology.
+ *
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * https://joinup.ec.europa.eu/news/understanding-eupl-v12
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *******************************************************************************/
+/*******************************************************************************
+ *******************************************************************************/
+/*******************************************************************************
+ *******************************************************************************/
+package at.gv.egiz.eaaf.core.impl.idp.process.test;
+
+import org.springframework.stereotype.Service;
+
+import at.gv.egiz.eaaf.core.api.IRequest;
+import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext;
+import at.gv.egiz.eaaf.core.api.idp.process.Task;
+
+/**
+ * Simple task that just outputs a "Hello World" text to the console.
+ *
+ * @author tknall
+ *
+ */
+@Service("HelloWorldTask")
+public class StopProcessFlagTask implements Task {
+
+ @Override
+ public IRequest execute(IRequest pendingReq, ExecutionContext executionContext) {
+ System.out.println("Stop process-flow dynamically from task");
+ executionContext.setCanceleProcessFlag();
+
+ return pendingReq;
+ }
+
+}
diff --git a/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/process/test/ThrowExceptionTask.java b/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/process/test/ThrowExceptionTask.java
new file mode 100644
index 00000000..ecd139c8
--- /dev/null
+++ b/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/process/test/ThrowExceptionTask.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright 2017 Graz University of Technology
+ * EAAF-Core Components has been developed in a cooperation between EGIZ,
+ * A-SIT Plus, A-SIT, and Graz University of Technology.
+ *
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * https://joinup.ec.europa.eu/news/understanding-eupl-v12
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *******************************************************************************/
+/*******************************************************************************
+ *******************************************************************************/
+/*******************************************************************************
+ *******************************************************************************/
+package at.gv.egiz.eaaf.core.impl.idp.process.test;
+
+import org.springframework.stereotype.Service;
+
+import at.gv.egiz.eaaf.core.api.IRequest;
+import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext;
+import at.gv.egiz.eaaf.core.api.idp.process.Task;
+import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException;
+
+/**
+ * Simple task that just outputs a "Hello World" text to the console.
+ *
+ * @author tknall
+ *
+ */
+@Service("HelloWorldTask")
+public class ThrowExceptionTask implements Task {
+
+ @Override
+ public IRequest execute(IRequest pendingReq, ExecutionContext executionContext) throws TaskExecutionException {
+ System.out.println("Stop process-flow dynamically from task");
+ throw new TaskExecutionException(pendingReq, "jUnit Test", new RuntimeException("jUnit test exception handling"));
+
+ }
+
+}
diff --git a/eaaf_core/src/test/resources/process/spring/test/SpringExpressionAwareProcessEngineTest-context.xml b/eaaf_core/src/test/resources/process/spring/test/SpringExpressionAwareProcessEngineTest-context.xml
index ad94c6d4..ebbd89e9 100644
--- a/eaaf_core/src/test/resources/process/spring/test/SpringExpressionAwareProcessEngineTest-context.xml
+++ b/eaaf_core/src/test/resources/process/spring/test/SpringExpressionAwareProcessEngineTest-context.xml
@@ -30,6 +30,12 @@
<bean id="HalloWeltTask"
class="at.gv.egiz.eaaf.core.impl.idp.process.test.HalloWeltTask"/>
+ <bean id="StopProcessFlagTask"
+ class="at.gv.egiz.eaaf.core.impl.idp.process.test.StopProcessFlagTask"/>
+
+ <bean id="ThrowExceptionTask"
+ class="at.gv.egiz.eaaf.core.impl.idp.process.test.ThrowExceptionTask"/>
+
<bean id="SelectBKUTask"
class="at.gv.egiz.eaaf.core.impl.idp.process.spring.test.task.SelectBKUTask"/>
diff --git a/eaaf_core/src/test/resources/process/test/SampleProcessDefinition4.xml b/eaaf_core/src/test/resources/process/test/SampleProcessDefinition4.xml
new file mode 100644
index 00000000..c88afd05
--- /dev/null
+++ b/eaaf_core/src/test/resources/process/test/SampleProcessDefinition4.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ -->
+
+<tns:ProcessDefinition
+ id="SampleProcess4"
+ xmlns:tns="http://reference.e-government.gv.at/namespace/moa/process/definition/v1"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://reference.e-government.gv.at/namespace/moa/process/definition/v1 ../../main/resources/process/ProcessDefinition.xsd ">
+
+ <tns:StartEvent id="start" />
+
+ <tns:Task id="task1" class="HelloWorldTask" />
+ <tns:Task id="task2" class="ThrowExceptionTask" />
+ <tns:Task id="task3" />
+
+ <tns:EndEvent id="end" />
+
+ <tns:Transition id="fromStart" from="start" to="task1" conditionExpression="true" />
+ <tns:Transition from="task1" to="task2" />
+ <tns:Transition from="task2" to="task3" />
+ <tns:Transition from="task3" to="end" />
+
+</tns:ProcessDefinition>
diff --git a/eaaf_core/src/test/resources/process/test/SampleProcessDefinition5.xml b/eaaf_core/src/test/resources/process/test/SampleProcessDefinition5.xml
new file mode 100644
index 00000000..e0072e62
--- /dev/null
+++ b/eaaf_core/src/test/resources/process/test/SampleProcessDefinition5.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ -->
+
+<tns:ProcessDefinition
+ id="SampleProcess5"
+ xmlns:tns="http://reference.e-government.gv.at/namespace/moa/process/definition/v1"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://reference.e-government.gv.at/namespace/moa/process/definition/v1 ../../main/resources/process/ProcessDefinition.xsd ">
+
+ <tns:StartEvent id="start" />
+
+ <tns:Task id="task1" class="HelloWorldTask" />
+ <tns:Task id="task2" class="StopProcessFlagTask" />
+ <tns:Task id="task3" class="ThrowExceptionTask" />
+
+ <tns:EndEvent id="end" />
+
+ <tns:Transition id="fromStart" from="start" to="task1" conditionExpression="true" />
+ <tns:Transition from="task1" to="task2" />
+ <tns:Transition from="task2" to="task3" />
+ <tns:Transition from="task3" to="end" />
+
+</tns:ProcessDefinition>
diff --git a/eaaf_core_api/src/main/java/at/gv/egiz/eaaf/core/api/idp/process/ExecutionContext.java b/eaaf_core_api/src/main/java/at/gv/egiz/eaaf/core/api/idp/process/ExecutionContext.java
index 38a66d4c..319db027 100644
--- a/eaaf_core_api/src/main/java/at/gv/egiz/eaaf/core/api/idp/process/ExecutionContext.java
+++ b/eaaf_core_api/src/main/java/at/gv/egiz/eaaf/core/api/idp/process/ExecutionContext.java
@@ -38,6 +38,21 @@ import java.util.Set;
public interface ExecutionContext extends Serializable {
/**
+ * Flag that indicates that a Task canceled the current {@link ExecutionContext}
+ *
+ * @return true if the process-flow was marked as canceled, otherwise false
+ */
+ boolean isProcessCancelled();
+
+ /**
+ * Mark this {@link ExecutionContext} as cancelled
+ *
+ * The process-flow engine will stop execution when the task that sets this flag is finished
+ *
+ */
+ void setCanceleProcessFlag();
+
+ /**
* Returns the identifier of underlying process instance.
*
* @return The identifier of the process instance.