cancel
Showing results for 
Search instead for 
Did you mean: 

Tasklistener on complete has no Execution Context

pfeiffer
Champ in-the-making
Champ in-the-making
Hi,

I stubled upon a problem when executing a task listener on the 'complete' event. It seems that when that listener is executed, no execution context is initialized. This has as a consequence that no process scoped beans are usable. Also when looking in the stack of org.activiti.engine.impl.context.Context no execution context is present.

I moved the same tasklistener to the create event and that worked. Making it a executionlistener on the end event made it possible for me to circumvent the problem. But this would prevent us from using any tasklisteners on the complete event. Is this a known bug ?
8 REPLIES 8

jbarrez
Star Contributor
Star Contributor
Is this a task which is part of a workflow? Ie it is not a standalone task?
In that case, it should have an execution. If it hasn't got one, then that's a bug.

Can you create a unit test demonstrating the issue and file an issue with it?

pfeiffer
Champ in-the-making
Champ in-the-making
Hi,

It is indeed during the execution of a workflow. I filed a issue for it:

http://jira.codehaus.org/browse/ACT-1437

Testcase is included.

Regards

frederikherema1
Star Contributor
Star Contributor
I think we were confused. Execution-context is something else that the Execution (or DelegateExecution). When writing a task-listener, the DelegateTask is the object you SHOULD use. The code you execute uses INTERNAL Context.getExecutionContext(). This is not the way to do this (extract from your code):


try {
   ExecutionContext execution = Context.getExecutionContext();
   delegateTask.setVariable("storedExecutionId", execution.getExecution().getId());
  } catch (EmptyStackException ese) {
   //This should not happen
   delegateTask.setVariable("storedExecutionId", null);
  }

Rather, DelegateTask exposes executionId and allows setting variables on the execution or local on the task…

pfeiffer
Champ in-the-making
Champ in-the-making
Ok, I could use the delegate Task to get and set variables. However:

1) not having a execution context has as a consequence that no "Process-scoped" beans can be retrieved at this moment as they internally rely on the Context.getExecutionContext() to be set.
2) I was using the Context.getExecutionContext() for a different reason. When logic in our application is executed started from the workflow, everything is allowed. To check if logic is executed from a workflow, I use that Context. If something is not executed form the workflow, a user should be logged in with the correct authorization. Also we need to do some logging. When changes are made through the workflow, we want to log the changes made together with which process and execution did the change. For this also the Context seemed like a good solution. If the on complete event for tasklisteners doesn't support this, we are dealing with a hole and I need to search for another solution.

1 - So I understand you say I should use the delegateTask, however The first point nevertheless makes it required that a proper executionContext is set in the Context or I'm I mistaken ? Process scoped beans not being present only on certain events doesn't seem like a good idea ?
2 - Is there any other way that I can make sure that code called from workflow, (using an expression in the workflow calling a spring bean OR using spring beans from the tasklisteners or service tasks) has all authorizations and information about the workflow currently executing ?

Regards,

Kristof

frederikherema1
Star Contributor
Star Contributor
I see where you're coming from…

"Process-scoped" beans can be retrieved at this moment as they internally rely on the Context.getExecutionContext() to be set
I suppose you're using CDI?

we want to log the changes made together with which process and execution did the change
Have you looked into adding a custom interceptor to the interceptor-stack? This is good for intercepting all commands that are executed and allows inspecting execution and command-context, I guess…

The way it currently works, is that only atomic operations are performed inside of a Context that is aware of an ExecutionContext. At the time of "completing" a task (and when the listener is called) there hasn't been any interaction to the process-state yet (apart from possibly setting variables), so NO ExecutionContext is available. Right after a task is completed, the outgoing flow is taken (using an AtomicOperation) and a ExecutionContext becomes available.

If you REALLY want to be sure the ExecutionContext is available in your java-code, either use a service-task OR use an ExecutionListener on the sequence-flow AFTER the task (event=take), this is run inside ExecutionContext.

pfeiffer
Champ in-the-making
Champ in-the-making
I'm using the org.activiti.spring.components.scope.ProcessScope provided by Josh long to create process scoped beans and to be able to use them in tasklisteners, service tasks or any other spring bean that needs information from the current running workflow.

That ProcessScope relies on the Context to retrieve it's information. This means it won't work in tasklisteners on the complete event in user tasks, which is kind of a pity. That was the mean reason why I felt the Context should be present also in this case. Perhaps the way the ProcessScoped variables are fetched should be changed ? The following code is present in the process scope class:

public Object resolveContextualObject(String key) {
  if ("executionId".equalsIgnoreCase(key))
   return Context.getExecutionContext().getExecution().getId();
  if ("processInstance".equalsIgnoreCase(key))
   return Context.getExecutionContext().getProcessInstance();
  if ("processInstanceId".equalsIgnoreCase(key))
   return Context.getExecutionContext().getProcessInstance().getId();
  return null;
}

I really like the idea of spring beans that contain variables from the current running process. It makes the code look much nicer and you can abstract a lot of stuff in those beans. Perhaps the intent of those processscoped beans is not for which I am using it? Is it actually only to be used in the workflow itself and not in the tasklisteners and other beans ?

jbarrez
Star Contributor
Star Contributor
Well, the thing is that the code that Josh Long added was meant to be 'stabilized' and fixed, but it really didn't come to that yet so far … but it is something which I'd like to see fixed in a future version

frederikherema1
Star Contributor
Star Contributor
As I said earlier, it's safest to use the "Context" when you're sure you're in a process-context, so in a service-task or execution-listener.. So if you convert your task-listeners to execution-listeners, it will work for you.