How to retrieve the the return value of the last serviceTask

Options
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
02-23-2012 10:48 AM
Hi, is there a way to retrieve the return value of the serviceTask at the end of the process ?
My BPMN file is as below
And my Java serviceTask is as below
and here is my main code, which is the one who started the process.
i've been trying to retrieve the return value of the java service task, after the startProcessInstanceByKey() finishes executing. but no luck so far, any suggestion on how to do this ?
My BPMN file is as below
<definitions id="definitions" targetNamespace="http://activiti.org/bpmn20" xmlns:activiti="http://activiti.org/bpmn" xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"> <process id="testProcess" name="Test process"> <startEvent id="theStart" /> <sequenceFlow id='flow1' sourceRef='theStart' targetRef='javaService' /> <serviceTask id="javaService" name="My Java Service Task" activiti:expression="#{myServiceTask.execute(name)}" activiti:resultVariableName="myResult" /> <sequenceFlow id='flow2' sourceRef='javaService' targetRef='theEnd' /> <endEvent id="theEnd" /> </process></definitions>
And my Java serviceTask is as below
@Componentpublic class MyServiceTask { @Transactional public String execute(String name) throws Exception { List<MyTable> myTables = myTableMapper.selectByExample(null); int maxId = -1; for (MyTable myTable : myTables) { maxId = maxId < myTable.getId() ? myTable.getId() : maxId; } MyTable newMyTable = new MyTable(); newMyTable.setId(maxId + 1); newMyTable.setName(name); myTableMapper.insert(newMyTable); return "Halo " + name + " !"; } @Autowired private MyTableMapper myTableMapper;}
and here is my main code, which is the one who started the process.
Map<String, Object> input = new HashMap<String, Object>();input.put("name", "Peter");ProcessInstance pi = runtimeService.startProcessInstanceByKey("testProcess", input);
i've been trying to retrieve the return value of the java service task, after the startProcessInstanceByKey() finishes executing. but no luck so far, any suggestion on how to do this ?
Labels:
- Labels:
-
Archive
8 REPLIES 8
Options
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
02-23-2012 11:52 AM
As your process is completely ended, the result (in the process variable 'myResult') is gone too, unless you set the Activiti History Level to FULL (performance impact) and use the history to retrieve the value.
For synchronous process models, you can add a receive task (named 'receiveTask', see example below) right after your service task or better before your endTask. The process will afterwards wait in this receive task. Then you can query the process using the runtime service for the variable, for example:
Hope it helped,
Heiko
For synchronous process models, you can add a receive task (named 'receiveTask', see example below) right after your service task or better before your endTask. The process will afterwards wait in this receive task. Then you can query the process using the runtime service for the variable, for example:
ProcessInstance pi = runtimeService.startProcessInstanceByKey("testProcess", input);
String myResult = runtimeService.getVariable(processInstance.getId(), "myResult");
But do not forget to signal the process afterwards to continue and finally end:
Execution execution = runtimeService.createExecutionQuery()
.processInstanceId(pi.getId())
.activityId("receiveTask")
.singleResult();
runtimeService.signal(execution.getId());
Now the process really ended.Hope it helped,
Heiko

Options
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
02-23-2012 06:59 PM
Hi Heiko,
Thanks for the reply, it worked as you suggested.
i guest this is the workaround for it.
Just wondering if there's a way to get the result variable at the end of the process (something like a return value of a method in java), because by using the receive task, we're actually 'pausing' the process so the variables get saved into DB, and when we try to retrieve the variable using the RuntimeService, this is actually making an sql call to DB which is i think a bit of an 'overhead' process just to get the result value of a process.
Thanks for the reply, it worked as you suggested.
i guest this is the workaround for it.
Just wondering if there's a way to get the result variable at the end of the process (something like a return value of a method in java), because by using the receive task, we're actually 'pausing' the process so the variables get saved into DB, and when we try to retrieve the variable using the RuntimeService, this is actually making an sql call to DB which is i think a bit of an 'overhead' process just to get the result value of a process.
Options
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
02-24-2012 12:32 PM
Hey Peter,
actually there is not, cause a process does by its design not have a result. It simply ends, either positively, with an error or with a cancellation. A "return" value is simply not modeled by BPMN. Only while the process itself is still running, you may send messages or update databases.
actually there is not, cause a process does by its design not have a result. It simply ends, either positively, with an error or with a cancellation. A "return" value is simply not modeled by BPMN. Only while the process itself is still running, you may send messages or update databases.

Options
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
08-27-2012 06:03 PM
I'm coming up against this now. I've not decided on an implementation.
One interim idead i had that should work within some constraints is to have a java service task that will take the 'result' variable and set it in a thread local.
That same thread local would be accessible by the calling code. So imagine:
// your BPMN
<serviceTask id="exposeReturnValue" activiti:delegateExpression="${ p.d.x.ActivitiReturnValue.getInstance().set(myResult)}"/>
Map<String,Object> args = new HashMap<String,Object>();
runtimeserviice.startProcessBykey("key", args);
// process runs and returns
Object result = ActivitiReturnValue.getInstance().get();
ActivitiReturnValue.getInstance().remove()
This has limitations in that it will only work for synchronous processes with ONE return value.
Also, your calling code MUST clear out the ActivitiReturnValue (a custom class by the way).
I'll post again once i determine my final solution that i plan on using. I don't care for this myself. I'm working on using the historyService to pull the value via variableUpdates(). This way i'm not adding any weird behavior and i can support multiple return values (like for multiInstance sub processes).
One interim idead i had that should work within some constraints is to have a java service task that will take the 'result' variable and set it in a thread local.
That same thread local would be accessible by the calling code. So imagine:
// your BPMN
<serviceTask id="exposeReturnValue" activiti:delegateExpression="${ p.d.x.ActivitiReturnValue.getInstance().set(myResult)}"/>
Map<String,Object> args = new HashMap<String,Object>();
runtimeserviice.startProcessBykey("key", args);
// process runs and returns
Object result = ActivitiReturnValue.getInstance().get();
ActivitiReturnValue.getInstance().remove()
This has limitations in that it will only work for synchronous processes with ONE return value.
Also, your calling code MUST clear out the ActivitiReturnValue (a custom class by the way).
I'll post again once i determine my final solution that i plan on using. I don't care for this myself. I'm working on using the historyService to pull the value via variableUpdates(). This way i'm not adding any weird behavior and i can support multiple return values (like for multiInstance sub processes).
Options
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
08-28-2012 01:38 AM
I am not sure I am understanding the problem correctly, but couldn't you simply get the value from the history service?
Note that we are currently introducing a new history level in activiti 5.11 which allows you to record only the "last" value of a process variable in history.
Note that we are currently introducing a new history level in activiti 5.11 which allows you to record only the "last" value of a process variable in history.
Options
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
08-29-2012 07:49 PM
Hi,
Returning something from an Activiti process is a requirement for us (for an automated flow) and the workarounds that were mentioned above would help. But, are there any plans to do this more naturally which is to optionally allow processes to return 1 or more values? This would be very useful for us through the REST API where we start a process by sending some variables & expect a response with the results from the flow back.
1.) Are there any future plans to include this feature in Activiti?
2.) Has someone extended or embedded Activiti to achieve this? One approach that comes to my mind right now, would be to define a custom task "EndTaskWithResult" which will add the result variables to the Process (by extending Process to add the result variables field) which will be returned to the callee (somehow). I would love to know if someone has done this or has any ideas around this or why this isn't a good idea to begin with if that's the case.
Thanks,
Jeegar Maru
Returning something from an Activiti process is a requirement for us (for an automated flow) and the workarounds that were mentioned above would help. But, are there any plans to do this more naturally which is to optionally allow processes to return 1 or more values? This would be very useful for us through the REST API where we start a process by sending some variables & expect a response with the results from the flow back.
1.) Are there any future plans to include this feature in Activiti?
2.) Has someone extended or embedded Activiti to achieve this? One approach that comes to my mind right now, would be to define a custom task "EndTaskWithResult" which will add the result variables to the Process (by extending Process to add the result variables field) which will be returned to the callee (somehow). I would love to know if someone has done this or has any ideas around this or why this isn't a good idea to begin with if that's the case.
Thanks,
Jeegar Maru

Options
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
08-30-2012 02:55 AM
Hi,
As Daniel already pointed out, it would be a good solution to define your own REST/Web service that starts the process instance, then retrieves the value of the process variable via the history service and give the response back. We don't have plans to support this in the REST API.
Best regards,
As Daniel already pointed out, it would be a good solution to define your own REST/Web service that starts the process instance, then retrieves the value of the process variable via the history service and give the response back. We don't have plans to support this in the REST API.
Best regards,
Options
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
07-15-2016 05:55 AM
Hi there,
One of the clean way to do it is using the Context (Wrapper classes). Pass these wrapper/context class object as an argument to the Service task. Service task will generate the result it and set it on this object which is available even after the life cycle of the process.
Class WorkflowContext{
RequestParamClass reqParameters;
ResponseParamClass resParameters;
}
- Manoj
One of the clean way to do it is using the Context (Wrapper classes). Pass these wrapper/context class object as an argument to the Service task. Service task will generate the result it and set it on this object which is available even after the life cycle of the process.
Class WorkflowContext{
RequestParamClass reqParameters;
ResponseParamClass resParameters;
}
- Manoj
