cancel
Showing results for 
Search instead for 
Did you mean: 

Cannot get process execution variables in latest state

dmitry_serdiuk
Champ in-the-making
Champ in-the-making
Hello.

I'm trying to write an integration test for my Activiti process, which contains a lot of Script tasks. I basically need a way to retrieve process execution variables. First I've tried placing a dummy Java Receive task at the process' end and then retrieve the variables using
runtimeService.getVariables(processInstance.getId());
, but only got the variables in their initial state (e.g. I've passed an empty array in the process and filled it inside my Script tasks, but get an empty array again as a result from calling getVariables(instanceId)).

After that I've set ProcessEngineConfiguration property 'history' to 'full' and tried querying for variableUpdates
historyService.createHistoricDetailQuery().variableUpdates().processInstanceId(processInstance.getId()).orderByTime().desc().list();
which, in turn, returned me variables as they were passed in the process.

Why does it happen and how can I check that process execution variables?

P. S. I'm testing with JUnit and Spring.

Thanks.
9 REPLIES 9

frederikherema1
Star Contributor
Star Contributor
From where do you exactly call runtimeService.getVariables(processInstance.getId());? is the process running than, or in a wait-state?

dmitry_serdiuk
Champ in-the-making
Champ in-the-making
I've called this when process reached Java Receive task (later I've replaced it with User Task with same effect), the execution returned. E.g.:

//…putting together initialVariables map

ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("p_verify", initialVariables);
//the process has been started

//this line gets executed when process reached User Task and, therefore, in wait state.
Map<String, Object> afterVariables = runtimeService.getVariables(processInstance.getId());

Inside script tasks I add elements to the array:
errorMsgs.add(stdMsgs.get(13011L));And I want to check that errorMsgs afterwards in JUnit.

frederikherema1
Star Contributor
Star Contributor
Thats really strange. Could you make simple testcase (junit test + process) that shows this behaviour, because that should just work Smiley Wink

dmitry_serdiuk
Champ in-the-making
Champ in-the-making
I've created a very simple test case. Plz see in attachments.

tidetom
Champ in-the-making
Champ in-the-making
Hi Dmitry,

I found a hack workaround for your issue, if you simply put:

errorMsgs = errorMsgs
Then the errorMsgs changes will be made.  Note that oddly enough you only have to do this one time somewhere in your process flow. This would indicate to me that Activiti must register changes to an execution variable only when it's set, and not when it's updated … therefore if it's set at least once, then all changes before and after will be logged.

I'm no Activiti expert (just starting myself) - maybe some of the Activiti folks can weigh in on this as to whether my assumption above is correct?

Thanks,
Tom

tidetom
Champ in-the-making
Champ in-the-making
More info on this issue, it would seem the "commit" is not a global one for the entire process.  All changes made to the execution variable prior to inserting the:

errorMsgs = errorMsgs
will be saved and can be retrieved, but any additional changes AFTER that call will still be lost.  Thus the solution seems to be to put in an additional scriptTask prior to the end of the script that re-sets each variable that got updated throughout the execution (not those that got set).

Also, as a little corollary to this, scriptTasks aren't the only items with this problem.  If you use a serviceTask with Spring integration, and invoke a bean method like this:

helloBean.doSomethingWithError(errorMsgs)
And if the doSomethingWithError method adds a new error message to the list of errorMsgs as part of the execution, that change will not get picked up on by Activiti in the same manner as it does not in the script task.  If you put a scriptTask after the serviceTask that has the:

errorMsgs = errorMsgs
inside of it, then the change will be recognized.  Very odd behavior.

frederikherema1
Star Contributor
Star Contributor
Hi,

Activiti has a built-in mechanism for saving serializable variables again, when they have changed once the command-context is being closed. Looks like the variables loaded from within a service/script-task aren't picked up by this, so the serializable value in't persisted to the DB. The workaround suggested by tidetom will explicitly do a "execution.setVariable" behind the screens, which stores the new value to the DB.

@see http://jira.codehaus.org/browse/ACT-820

dmitry_serdiuk
Champ in-the-making
Champ in-the-making
Ok, thanks for the clarifications.
Will use suggested workaround while waiting for the fix…

rahult
Champ in-the-making
Champ in-the-making
I m facing a similar issue. The scenario is a little different from one mentioned above.

Acitivi verision : 5.12.1

Here is my code snippet.

Map<String, Object> var = new HashMap<String, Object>();
            var.put("workorderrequest", payload);
            var.put("workOrderResponse", response);
ProcessInstance pi = runtime.startProcessInstanceByKey("getWorkOrder", var);
response = (GetWorkOrderDetailsResponseType) runtime.getVariable(pi.getProcessInstanceId(),"workOrderResponse");

At the time of runtime.getVariable, my process is already complete and successfull. I'm not able to access the process level parameters from it. I m running activiti on weblogic 10.3.4 with oracle 11g database with spring configuration.

It give me the following exception.

DFLTLOG> DEBUG 19:32:31 org.springframework.jdbc.datasource.SimpleDriverDataSource> Creating new JDBC Driver Connection to [jdbcSmiley Surprisedracle:thin:@10.100.10.207:1521:sidev11g]
07:32:31,503 [[ACTIVE] ExecuteThread: '1' for queue: 'weblogic.kernel.Default (self-tuning)'] ERROR org.activiti.engine.impl.interceptor.CommandContext  - Error while closing command context
org.activiti.engine.ActivitiObjectNotFoundException: execution 301 doesn't exist
at org.activiti.engine.impl.cmd.GetExecutionVariableCmd.execute(GetExecutionVariableCmd.java:54)
at org.activiti.engine.impl.interceptor.CommandExecutorImpl.execute(CommandExecutorImpl.java:24)
at org.activiti.engine.impl.interceptor.CommandContextInterceptor.execute(CommandContextInterceptor.java:61)
at org.activiti.spring.SpringTransactionInterceptor$1.doInTransaction(SpringTransactionInterceptor.java:42)
at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:130)
at org.activiti.spring.SpringTransactionInterceptor.execute(SpringTransactionInterceptor.java:40)
at org.activiti.engine.impl.interceptor.LogInterceptor.execute(LogInterceptor.java:31)
at org.activiti.engine.impl.RuntimeServiceImpl.getVariable(RuntimeServiceImpl.java:118)
at com.sigma.omp.extinterfaces.oms.WorkOrderOMSAmdocsV1PortTypeImpl.getWorkOrderDetails(WorkOrderOMSAmdocsV1PortTypeImpl.java:91)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at weblogic.wsee.jaxws.WLSInstanceResolver$WLSInvoker.invoke(WLSInstanceResolver.java:92)
at weblogic.wsee.jaxws.WLSInstanceResolver$WLSInvoker.invoke(WLSInstanceResolver.java:74)
at com.sun.xml.ws.server.InvokerTube$2.invoke(InvokerTube.java:151)
at com.sun.xml.ws.server.sei.EndpointMethodHandlerImpl.invoke(EndpointMethodHandlerImpl.java:268)
at com.sun.xml.ws.server.sei.SEIInvokerTube.processRequest(SEIInvokerTube.java:100)
at com.sun.xml.ws.api.pipe.Fiber.__doRun(Fiber.java:866)
at com.sun.xml.ws.api.pipe.Fiber._doRun(Fiber.java:815)
at com.sun.xml.ws.api.pipe.Fiber.doRun(Fiber.java:778)