From eaa269feec4f3c0575c920e80d72ea9598c6077c Mon Sep 17 00:00:00 2001 From: meyerd Date: Wed, 20 Jul 2011 15:46:54 +0000 Subject: [PATCH] ACT-773 Adding configurable interceptor for client code --- .../MultiInstanceActivityBehavior.java | 6 ++- ...askDelegateExpressionActivityBehavior.java | 11 +++- ...rviceTaskJavaDelegateActivityBehavior.java | 8 ++- .../impl/bpmn/helper/ClassDelegate.java | 20 +++++--- .../DelegateExpressionExecutionListener.java | 11 +++- .../DelegateExpressionTaskListener.java | 10 +++- .../cfg/ProcessEngineConfigurationImpl.java | 20 ++++++++ .../delegate/ActivityBehaviorInvocation.java | 25 +++++++++ .../delegate/DefaultDelegateInterceptor.java | 16 ++++++ .../impl/delegate/DelegateInvocation.java | 46 +++++++++++++++++ .../delegate/ExecutionListenerInvocation.java | 25 +++++++++ .../delegate/ExpressionGetInvocation.java | 25 +++++++++ .../impl/delegate/ExpressionInvocation.java | 18 +++++++ .../delegate/ExpressionSetInvocation.java | 28 ++++++++++ .../impl/delegate/JavaDelegateInvocation.java | 25 +++++++++ .../impl/delegate/TaskListenerInvocation.java | 25 +++++++++ .../impl/delegate/UserCodeInvocation.java | 51 +++++++++++++++++++ .../engine/impl/el/JuelExpression.java | 20 +++++++- .../impl/interceptor/DelegateInterceptor.java | 26 ++++++++++ .../impl/persistence/entity/TaskEntity.java | 9 +++- 20 files changed, 408 insertions(+), 17 deletions(-) create mode 100644 modules/activiti-engine/src/main/java/org/activiti/engine/impl/delegate/ActivityBehaviorInvocation.java create mode 100644 modules/activiti-engine/src/main/java/org/activiti/engine/impl/delegate/DefaultDelegateInterceptor.java create mode 100644 modules/activiti-engine/src/main/java/org/activiti/engine/impl/delegate/DelegateInvocation.java create mode 100644 modules/activiti-engine/src/main/java/org/activiti/engine/impl/delegate/ExecutionListenerInvocation.java create mode 100644 modules/activiti-engine/src/main/java/org/activiti/engine/impl/delegate/ExpressionGetInvocation.java create mode 100644 modules/activiti-engine/src/main/java/org/activiti/engine/impl/delegate/ExpressionInvocation.java create mode 100644 modules/activiti-engine/src/main/java/org/activiti/engine/impl/delegate/ExpressionSetInvocation.java create mode 100644 modules/activiti-engine/src/main/java/org/activiti/engine/impl/delegate/JavaDelegateInvocation.java create mode 100644 modules/activiti-engine/src/main/java/org/activiti/engine/impl/delegate/TaskListenerInvocation.java create mode 100644 modules/activiti-engine/src/main/java/org/activiti/engine/impl/delegate/UserCodeInvocation.java create mode 100644 modules/activiti-engine/src/main/java/org/activiti/engine/impl/interceptor/DelegateInterceptor.java diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/behavior/MultiInstanceActivityBehavior.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/behavior/MultiInstanceActivityBehavior.java index f515584b7c..f6c9841835 100644 --- a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/behavior/MultiInstanceActivityBehavior.java +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/behavior/MultiInstanceActivityBehavior.java @@ -23,6 +23,8 @@ import org.activiti.engine.ActivitiException; import org.activiti.engine.delegate.DelegateExecution; import org.activiti.engine.delegate.ExecutionListener; import org.activiti.engine.delegate.Expression; +import org.activiti.engine.impl.context.Context; +import org.activiti.engine.impl.delegate.ExecutionListenerInvocation; import org.activiti.engine.impl.pvm.delegate.ActivityBehavior; import org.activiti.engine.impl.pvm.delegate.ActivityExecution; import org.activiti.engine.impl.pvm.delegate.CompositeActivityBehavior; @@ -221,7 +223,9 @@ public abstract class MultiInstanceActivityBehavior extends FlowNodeActivityBeha List listeners = activity.getExecutionListeners(org.activiti.engine.impl.pvm.PvmEvent.EVENTNAME_END); for (ExecutionListener executionListener : listeners) { try { - executionListener.notify((ExecutionListenerExecution) execution); + Context.getProcessEngineConfiguration() + .getDelegateInterceptor() + .handleInvocation(new ExecutionListenerInvocation(executionListener, execution)); } catch (Exception e) { throw new ActivitiException("Couldn't execute end listener", e); } diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/behavior/ServiceTaskDelegateExpressionActivityBehavior.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/behavior/ServiceTaskDelegateExpressionActivityBehavior.java index e78a33e6ff..479c5648fd 100644 --- a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/behavior/ServiceTaskDelegateExpressionActivityBehavior.java +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/behavior/ServiceTaskDelegateExpressionActivityBehavior.java @@ -15,6 +15,9 @@ package org.activiti.engine.impl.bpmn.behavior; import org.activiti.engine.ActivitiException; import org.activiti.engine.delegate.Expression; import org.activiti.engine.delegate.JavaDelegate; +import org.activiti.engine.impl.context.Context; +import org.activiti.engine.impl.delegate.ActivityBehaviorInvocation; +import org.activiti.engine.impl.delegate.JavaDelegateInvocation; import org.activiti.engine.impl.pvm.delegate.ActivityBehavior; import org.activiti.engine.impl.pvm.delegate.ActivityExecution; import org.activiti.engine.impl.pvm.delegate.SignallableActivityBehavior; @@ -50,10 +53,14 @@ public class ServiceTaskDelegateExpressionActivityBehavior extends TaskActivityB Object delegate = expression.getValue(execution); if (delegate instanceof ActivityBehavior) { - ((ActivityBehavior) delegate).execute(execution); + Context.getProcessEngineConfiguration() + .getDelegateInterceptor() + .handleInvocation(new ActivityBehaviorInvocation((ActivityBehavior) delegate, execution)); } else if (delegate instanceof JavaDelegate) { - ((JavaDelegate) delegate).execute(execution); + Context.getProcessEngineConfiguration() + .getDelegateInterceptor() + .handleInvocation(new JavaDelegateInvocation((JavaDelegate) delegate, execution)); leave(execution); } else { diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/behavior/ServiceTaskJavaDelegateActivityBehavior.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/behavior/ServiceTaskJavaDelegateActivityBehavior.java index e6ec56078a..19e54d1d3e 100644 --- a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/behavior/ServiceTaskJavaDelegateActivityBehavior.java +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/behavior/ServiceTaskJavaDelegateActivityBehavior.java @@ -13,9 +13,11 @@ package org.activiti.engine.impl.bpmn.behavior; +import org.activiti.engine.delegate.DelegateExecution; import org.activiti.engine.delegate.ExecutionListener; import org.activiti.engine.delegate.JavaDelegate; -import org.activiti.engine.delegate.DelegateExecution; +import org.activiti.engine.impl.context.Context; +import org.activiti.engine.impl.delegate.JavaDelegateInvocation; import org.activiti.engine.impl.pvm.delegate.ActivityBehavior; import org.activiti.engine.impl.pvm.delegate.ActivityExecution; @@ -44,6 +46,8 @@ public class ServiceTaskJavaDelegateActivityBehavior extends TaskActivityBehavio } public void execute(DelegateExecution execution) throws Exception { - javaDelegate.execute(execution); + Context.getProcessEngineConfiguration() + .getDelegateInterceptor() + .handleInvocation(new JavaDelegateInvocation(javaDelegate, execution)); } } diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/helper/ClassDelegate.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/helper/ClassDelegate.java index 4026631d92..a57477dae8 100644 --- a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/helper/ClassDelegate.java +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/helper/ClassDelegate.java @@ -25,14 +25,14 @@ import org.activiti.engine.delegate.ExecutionListener; import org.activiti.engine.delegate.JavaDelegate; import org.activiti.engine.delegate.TaskListener; import org.activiti.engine.impl.bpmn.behavior.AbstractBpmnActivityBehavior; -import org.activiti.engine.impl.bpmn.behavior.ParallelMultiInstanceBehavior; -import org.activiti.engine.impl.bpmn.behavior.SequentialMultiInstanceBehavior; import org.activiti.engine.impl.bpmn.behavior.ServiceTaskJavaDelegateActivityBehavior; import org.activiti.engine.impl.bpmn.parser.FieldDeclaration; +import org.activiti.engine.impl.context.Context; +import org.activiti.engine.impl.delegate.ExecutionListenerInvocation; +import org.activiti.engine.impl.delegate.TaskListenerInvocation; import org.activiti.engine.impl.pvm.delegate.ActivityBehavior; import org.activiti.engine.impl.pvm.delegate.ActivityExecution; import org.activiti.engine.impl.pvm.delegate.SignallableActivityBehavior; -import org.activiti.engine.impl.pvm.process.ActivityImpl; import org.activiti.engine.impl.util.ReflectUtil; @@ -64,8 +64,10 @@ public class ClassDelegate extends AbstractBpmnActivityBehavior implements TaskL public void notify(DelegateExecution execution) throws Exception { if (executionListenerInstance == null) { executionListenerInstance = getExecutionListenerInstance(); - } - executionListenerInstance.notify(execution); + } + Context.getProcessEngineConfiguration() + .getDelegateInterceptor() + .handleInvocation(new ExecutionListenerInvocation(executionListenerInstance, execution)); } protected ExecutionListener getExecutionListenerInstance() { @@ -84,7 +86,13 @@ public class ClassDelegate extends AbstractBpmnActivityBehavior implements TaskL if (taskListenerInstance == null) { taskListenerInstance = getTaskListenerInstance(); } - taskListenerInstance.notify(delegateTask); + try { + Context.getProcessEngineConfiguration() + .getDelegateInterceptor() + .handleInvocation(new TaskListenerInvocation(taskListenerInstance, delegateTask)); + }catch (Exception e) { + throw new ActivitiException("Exception while invoking TaskListener: "+e.getMessage(), e); + } } protected TaskListener getTaskListenerInstance() { diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/listener/DelegateExpressionExecutionListener.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/listener/DelegateExpressionExecutionListener.java index 95e72fa46b..575b16f351 100644 --- a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/listener/DelegateExpressionExecutionListener.java +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/listener/DelegateExpressionExecutionListener.java @@ -17,6 +17,9 @@ import org.activiti.engine.delegate.DelegateExecution; import org.activiti.engine.delegate.ExecutionListener; import org.activiti.engine.delegate.Expression; import org.activiti.engine.delegate.JavaDelegate; +import org.activiti.engine.impl.context.Context; +import org.activiti.engine.impl.delegate.ExecutionListenerInvocation; +import org.activiti.engine.impl.delegate.JavaDelegateInvocation; /** @@ -36,9 +39,13 @@ public class DelegateExpressionExecutionListener implements ExecutionListener { Object delegate = expression.getValue(execution); if (delegate instanceof ExecutionListener) { - ((ExecutionListener) delegate).notify(execution); + Context.getProcessEngineConfiguration() + .getDelegateInterceptor() + .handleInvocation(new ExecutionListenerInvocation((ExecutionListener) delegate, execution)); } else if (delegate instanceof JavaDelegate) { - ((JavaDelegate) delegate).execute(execution); + Context.getProcessEngineConfiguration() + .getDelegateInterceptor() + .handleInvocation(new JavaDelegateInvocation((JavaDelegate) delegate, execution)); } else { throw new ActivitiException("Delegate expression " + expression + " did not resolve to an implementation of " + ExecutionListener.class diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/listener/DelegateExpressionTaskListener.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/listener/DelegateExpressionTaskListener.java index f9a0ffd731..0be0a73c10 100644 --- a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/listener/DelegateExpressionTaskListener.java +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/listener/DelegateExpressionTaskListener.java @@ -16,6 +16,8 @@ import org.activiti.engine.ActivitiException; import org.activiti.engine.delegate.DelegateTask; import org.activiti.engine.delegate.Expression; import org.activiti.engine.delegate.TaskListener; +import org.activiti.engine.impl.context.Context; +import org.activiti.engine.impl.delegate.TaskListenerInvocation; /** @@ -35,7 +37,13 @@ public class DelegateExpressionTaskListener implements TaskListener { Object delegate = expression.getValue(delegateTask.getExecution()); if (delegate instanceof TaskListener) { - ((TaskListener) delegate).notify(delegateTask); + try { + Context.getProcessEngineConfiguration() + .getDelegateInterceptor() + .handleInvocation(new TaskListenerInvocation((TaskListener)delegate, delegateTask)); + }catch (Exception e) { + throw new ActivitiException("Exception while invoking TaskListener: "+e.getMessage(), e); + } } else { throw new ActivitiException("Delegate expression " + expression + " did not resolve to an implementation of " + TaskListener.class ); diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/cfg/ProcessEngineConfigurationImpl.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/cfg/ProcessEngineConfigurationImpl.java index b6a6860862..c1a4ca8772 100644 --- a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/cfg/ProcessEngineConfigurationImpl.java +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/cfg/ProcessEngineConfigurationImpl.java @@ -63,6 +63,7 @@ import org.activiti.engine.impl.cfg.standalone.StandaloneMybatisTransactionConte import org.activiti.engine.impl.db.DbIdGenerator; import org.activiti.engine.impl.db.DbSqlSessionFactory; import org.activiti.engine.impl.db.IbatisVariableTypeHandler; +import org.activiti.engine.impl.delegate.DefaultDelegateInterceptor; import org.activiti.engine.impl.el.ExpressionManager; import org.activiti.engine.impl.form.AbstractFormType; import org.activiti.engine.impl.form.BooleanFormType; @@ -76,6 +77,7 @@ import org.activiti.engine.impl.history.handler.HistoryParseListener; import org.activiti.engine.impl.interceptor.CommandContextFactory; import org.activiti.engine.impl.interceptor.CommandExecutor; import org.activiti.engine.impl.interceptor.CommandInterceptor; +import org.activiti.engine.impl.interceptor.DelegateInterceptor; import org.activiti.engine.impl.interceptor.SessionFactory; import org.activiti.engine.impl.jobexecutor.JobExecutor; import org.activiti.engine.impl.jobexecutor.JobHandler; @@ -256,6 +258,8 @@ public abstract class ProcessEngineConfigurationImpl extends ProcessEngineConfig protected boolean isDbHistoryUsed = true; protected boolean isDbCycleUsed = false; + protected DelegateInterceptor delegateInterceptor; + // buildProcessEngine /////////////////////////////////////////////////////// public ProcessEngine buildProcessEngine() { @@ -287,6 +291,7 @@ public abstract class ProcessEngineConfigurationImpl extends ProcessEngineConfig initSqlSessionFactory(); initSessionFactories(); initJpa(); + initDelegateInterceptor(); } // command executors //////////////////////////////////////////////////////// @@ -783,6 +788,12 @@ public abstract class ProcessEngineConfigurationImpl extends ProcessEngineConfig } } + protected void initDelegateInterceptor() { + if(delegateInterceptor == null) { + delegateInterceptor = new DefaultDelegateInterceptor(); + } + } + // JPA ////////////////////////////////////////////////////////////////////// protected void initJpa() { @@ -1470,5 +1481,14 @@ public abstract class ProcessEngineConfigurationImpl extends ProcessEngineConfig public void setDeploymentCache(DeploymentCache deploymentCache) { this.deploymentCache = deploymentCache; } + + public ProcessEngineConfigurationImpl setDelegateInterceptor(DelegateInterceptor delegateInterceptor) { + this.delegateInterceptor = delegateInterceptor; + return this; + } + + public DelegateInterceptor getDelegateInterceptor() { + return delegateInterceptor; + } } \ No newline at end of file diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/delegate/ActivityBehaviorInvocation.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/delegate/ActivityBehaviorInvocation.java new file mode 100644 index 0000000000..3114a9e275 --- /dev/null +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/delegate/ActivityBehaviorInvocation.java @@ -0,0 +1,25 @@ +package org.activiti.engine.impl.delegate; + +import org.activiti.engine.impl.pvm.delegate.ActivityBehavior; +import org.activiti.engine.impl.pvm.delegate.ActivityExecution; + +/** + * + * @author Daniel Meyer + */ +public class ActivityBehaviorInvocation extends DelegateInvocation { + + protected final ActivityBehavior behaviorInstance; + + protected final ActivityExecution execution; + + public ActivityBehaviorInvocation(ActivityBehavior behaviorInstance, ActivityExecution execution) { + this.behaviorInstance = behaviorInstance; + this.execution = execution; + } + + protected void invoke() throws Exception { + behaviorInstance.execute(execution); + } + +} diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/delegate/DefaultDelegateInterceptor.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/delegate/DefaultDelegateInterceptor.java new file mode 100644 index 0000000000..b4bab99f17 --- /dev/null +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/delegate/DefaultDelegateInterceptor.java @@ -0,0 +1,16 @@ +package org.activiti.engine.impl.delegate; + +import org.activiti.engine.impl.interceptor.DelegateInterceptor; + +/** + * Default implementation, simply proceeding the call. + * + * @author Daniel Meyer + */ +public class DefaultDelegateInterceptor implements DelegateInterceptor { + + public void handleInvocation(DelegateInvocation invocation) throws Exception { + invocation.proceed(); + } + +} diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/delegate/DelegateInvocation.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/delegate/DelegateInvocation.java new file mode 100644 index 0000000000..0b79eb557a --- /dev/null +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/delegate/DelegateInvocation.java @@ -0,0 +1,46 @@ +package org.activiti.engine.impl.delegate; + +import org.activiti.engine.impl.interceptor.DelegateInterceptor; + +/** + * Provides context about the invocation of usercode and handles the actual + * invocation + * + * @author Daniel Meyer + * @see DelegateInterceptor + */ +public abstract class DelegateInvocation { + + protected Object invocationResult; + protected Object[] invocationParameters; + + /** + * make the invocation proceed, performing the actual invocation of the user + * code. + * + * @throws Exception + * the exception thrown by the user code + */ + public void proceed() throws Exception { + invoke(); + } + + protected abstract void invoke() throws Exception; + + /** + * @return the result of the invocation (can be null if the invocation does + * not return a result) + */ + public Object getInvocationResult() { + return invocationResult; + } + + /** + * @return an array of invocation parameters (null if the invocation takes no + * parameters) + */ + public Object[] getInvocationParameters() { + return invocationParameters; + } + +} diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/delegate/ExecutionListenerInvocation.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/delegate/ExecutionListenerInvocation.java new file mode 100644 index 0000000000..a1fa4963bf --- /dev/null +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/delegate/ExecutionListenerInvocation.java @@ -0,0 +1,25 @@ +package org.activiti.engine.impl.delegate; + +import org.activiti.engine.delegate.DelegateExecution; +import org.activiti.engine.delegate.ExecutionListener; + +/** + * Class handling invocations of ExecutionListeners + * + * @author Daniel Meyer + */ +public class ExecutionListenerInvocation extends DelegateInvocation { + + protected final ExecutionListener executionListenerInstance; + protected final DelegateExecution execution; + + public ExecutionListenerInvocation(ExecutionListener executionListenerInstance, DelegateExecution execution) { + this.executionListenerInstance = executionListenerInstance; + this.execution = execution; + } + + protected void invoke() throws Exception { + executionListenerInstance.notify(execution); + } + +} diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/delegate/ExpressionGetInvocation.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/delegate/ExpressionGetInvocation.java new file mode 100644 index 0000000000..65f6d0a70f --- /dev/null +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/delegate/ExpressionGetInvocation.java @@ -0,0 +1,25 @@ +package org.activiti.engine.impl.delegate; + +import org.activiti.engine.impl.javax.el.ELContext; +import org.activiti.engine.impl.javax.el.ValueExpression; + +/** + * Class responsible for handling Expression.getValue invocations + * + * @author Daniel Meyer + */ +public class ExpressionGetInvocation extends ExpressionInvocation { + + protected final ELContext elContext; + + public ExpressionGetInvocation(ValueExpression valueExpression, ELContext elContext) { + super(valueExpression); + this.elContext = elContext; + } + + @Override + protected void invoke() throws Exception { + invocationResult = valueExpression.getValue(elContext); + } + +} diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/delegate/ExpressionInvocation.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/delegate/ExpressionInvocation.java new file mode 100644 index 0000000000..08c34eab0a --- /dev/null +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/delegate/ExpressionInvocation.java @@ -0,0 +1,18 @@ +package org.activiti.engine.impl.delegate; + +import org.activiti.engine.impl.javax.el.ValueExpression; + +/** + * Baseclass responsible for handling invocations of Expressions + * + * @author Daniel Meyer + */ +public abstract class ExpressionInvocation extends DelegateInvocation { + + protected final ValueExpression valueExpression; + + public ExpressionInvocation(ValueExpression valueExpression) { + this.valueExpression = valueExpression; + } + +} diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/delegate/ExpressionSetInvocation.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/delegate/ExpressionSetInvocation.java new file mode 100644 index 0000000000..c8ee546c0e --- /dev/null +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/delegate/ExpressionSetInvocation.java @@ -0,0 +1,28 @@ +package org.activiti.engine.impl.delegate; + +import org.activiti.engine.impl.javax.el.ELContext; +import org.activiti.engine.impl.javax.el.ValueExpression; + +/** + * Class responsible for handling Expression.setValue() invocations. + * + * @author Daniel Meyer + */ +public class ExpressionSetInvocation extends ExpressionInvocation { + + protected final Object value; + protected ELContext elContext; + + public ExpressionSetInvocation(ValueExpression valueExpression, ELContext elContext, Object value) { + super(valueExpression); + this.value = value; + this.elContext = elContext; + this.invocationParameters = new Object[] {value}; + } + + @Override + protected void invoke() throws Exception { + valueExpression.setValue(elContext, value); + } + +} diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/delegate/JavaDelegateInvocation.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/delegate/JavaDelegateInvocation.java new file mode 100644 index 0000000000..ebc570e222 --- /dev/null +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/delegate/JavaDelegateInvocation.java @@ -0,0 +1,25 @@ +package org.activiti.engine.impl.delegate; + +import org.activiti.engine.delegate.DelegateExecution; +import org.activiti.engine.delegate.JavaDelegate; + +/** + * Class handling invocations of JavaDelegates + * + * @author Daniel Meyer + */ +public class JavaDelegateInvocation extends DelegateInvocation { + + protected final JavaDelegate delegateInstance; + protected final DelegateExecution execution; + + public JavaDelegateInvocation(JavaDelegate delegateInstance, DelegateExecution execution) { + this.delegateInstance = delegateInstance; + this.execution = execution; + } + + protected void invoke() throws Exception { + delegateInstance.execute((DelegateExecution) execution); + } + +} diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/delegate/TaskListenerInvocation.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/delegate/TaskListenerInvocation.java new file mode 100644 index 0000000000..c831dcc234 --- /dev/null +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/delegate/TaskListenerInvocation.java @@ -0,0 +1,25 @@ +package org.activiti.engine.impl.delegate; + +import org.activiti.engine.delegate.DelegateTask; +import org.activiti.engine.delegate.TaskListener; + +/** + * Class handling invocations of {@link TaskListener TaskListeners} + * + * @author Daniel Meyer + */ +public class TaskListenerInvocation extends DelegateInvocation { + + protected final TaskListener executionListenerInstance; + protected final DelegateTask delegateTask; + + public TaskListenerInvocation(TaskListener executionListenerInstance, DelegateTask delegateTask) { + this.executionListenerInstance = executionListenerInstance; + this.delegateTask = delegateTask; + } + + protected void invoke() throws Exception { + executionListenerInstance.notify(delegateTask); + } + +} diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/delegate/UserCodeInvocation.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/delegate/UserCodeInvocation.java new file mode 100644 index 0000000000..1605d51de3 --- /dev/null +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/delegate/UserCodeInvocation.java @@ -0,0 +1,51 @@ +package org.activiti.engine.impl.delegate; + +import org.activiti.engine.impl.interceptor.DelegateInterceptor; +import org.activiti.engine.impl.persistence.entity.ExecutionEntity; +import org.activiti.engine.runtime.Execution; + +/** + * Provides context about the invocation of usercode and handles the actual + * invocation + * + * @author Daniel Meyer + * @see DelegateInterceptor + */ +public abstract class UserCodeInvocation { + + protected Object invocationResult; + + protected final ExecutionEntity execution; + + public UserCodeInvocation(ExecutionEntity execution) { + this.execution = execution; + } + + /** + * make the invocation proceed, performing the actual invocation of the user + * code. + * + * @throws Exception + * the exception thrown by the user code + */ + public void proceed() throws Exception { + handleInvocation(); + } + + protected abstract void handleInvocation() throws Exception; + + /** + * return the result of the invocation + */ + public Object getInvocationResult() { + return invocationResult; + } + + /** + * @return the current {@link Execution} + */ + public ExecutionEntity getExecution() { + return execution; + } + +} diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/el/JuelExpression.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/el/JuelExpression.java index ff9e7a8a44..d4537fab7f 100644 --- a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/el/JuelExpression.java +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/el/JuelExpression.java @@ -15,6 +15,9 @@ package org.activiti.engine.impl.el; import org.activiti.engine.ActivitiException; import org.activiti.engine.delegate.VariableScope; +import org.activiti.engine.impl.context.Context; +import org.activiti.engine.impl.delegate.ExpressionGetInvocation; +import org.activiti.engine.impl.delegate.ExpressionSetInvocation; import org.activiti.engine.impl.javax.el.ELContext; import org.activiti.engine.impl.javax.el.ELException; import org.activiti.engine.impl.javax.el.MethodNotFoundException; @@ -43,19 +46,32 @@ public class JuelExpression implements Expression { public Object getValue(VariableScope variableScope) { ELContext elContext = expressionManager.getElContext(variableScope); try { - return valueExpression.getValue(elContext); + ExpressionGetInvocation invocation = new ExpressionGetInvocation(valueExpression, elContext); + Context.getProcessEngineConfiguration() + .getDelegateInterceptor() + .handleInvocation(invocation); + return invocation.getInvocationResult(); } catch (PropertyNotFoundException pnfe) { throw new ActivitiException("Unknown property used in expression", pnfe); } catch (MethodNotFoundException mnfe) { throw new ActivitiException("Unknown method used in expression", mnfe); } catch(ELException ele) { throw new ActivitiException("Error while evalutaing expression", ele); + } catch (Exception e) { + throw new ActivitiException("Error while evalutaing expression", e); } } public void setValue(Object value, VariableScope variableScope) { ELContext elContext = expressionManager.getElContext(variableScope); - valueExpression.setValue(elContext, value); + try { + ExpressionSetInvocation invocation = new ExpressionSetInvocation(valueExpression, elContext, value); + Context.getProcessEngineConfiguration() + .getDelegateInterceptor() + .handleInvocation(invocation); + }catch (Exception e) { + throw new ActivitiException("Error while evalutaing expression", e); + } } @Override diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/interceptor/DelegateInterceptor.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/interceptor/DelegateInterceptor.java new file mode 100644 index 0000000000..e8985c9657 --- /dev/null +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/interceptor/DelegateInterceptor.java @@ -0,0 +1,26 @@ +package org.activiti.engine.impl.interceptor; + +import org.activiti.engine.impl.delegate.DelegateInvocation; + +/** + * Interceptor responsible for handling calls to 'user code'. User code + * represents external Java code (e.g. services and listeners). The following is + * a list of classes that represent user code: + * + * + * The interceptor is passed in an instance of {@link DelegateInvocation}. + * Implementations are responsible for calling + * {@link DelegateInvocation#proceed()} to make the call to the usercode. + * + * @author Daniel Meyer + */ +public interface DelegateInterceptor { + + public void handleInvocation(DelegateInvocation invocation) throws Exception; + +} diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/persistence/entity/TaskEntity.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/persistence/entity/TaskEntity.java index a3ca95bb1c..347c6dc75c 100644 --- a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/persistence/entity/TaskEntity.java +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/persistence/entity/TaskEntity.java @@ -31,6 +31,7 @@ import org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl; import org.activiti.engine.impl.context.Context; import org.activiti.engine.impl.db.DbSqlSession; import org.activiti.engine.impl.db.PersistentObject; +import org.activiti.engine.impl.delegate.TaskListenerInvocation; import org.activiti.engine.impl.interceptor.CommandContext; import org.activiti.engine.impl.pvm.delegate.ActivityExecution; import org.activiti.engine.impl.task.TaskDefinition; @@ -504,7 +505,13 @@ public class TaskEntity extends VariableScopeImpl implements Task, DelegateTask, if (execution != null) { setEventName(taskEventName); } - taskListener.notify(this); + try { + Context.getProcessEngineConfiguration() + .getDelegateInterceptor() + .handleInvocation(new TaskListenerInvocation(taskListener, (DelegateTask)this)); + }catch (Exception e) { + throw new ActivitiException("Exception while invoking TaskListener: "+e.getMessage(), e); + } } } } -- GitLab