cancel
Showing results for 
Search instead for 
Did you mean: 

Out Variables from a Primary Process - A Proposal

tidetom
Champ in-the-making
Champ in-the-making
One of the primary areas that has been a source of difficulty for my group in working with Activiti is the inability to specify "out" variables from a primary process.  Mainly, we're working with Activiti using Spring integration, and we typically have a Spring Bean that kicks off a new Activiti process, using something like this:

       Map<String,Object> variableMap = new HashMap<String,Object>();
        … populate variableMap with inputs from the client-tier …

        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("myprocess",variableMap);

        // Check the after variables to see if any errors occurred, etc.
        Map<String, Object> afterVariables = runtimeService.getVariables(pi.getId());
        … check the after variables for error messages that have stacked up, send the error messages back to the user …

However, in order to invoke runtimeService.getVariables(pi.getId()) to get the variables out of the process, the process itself needs to be unfinished.  This means that prior to the end of our process, we need to stick a Java Receive Task on there to stop the process from finishing in order for the above code to work.  Then, after we grab the afterVariables and check them in the segment above, we signal the process itself to complete:

        // Finish the process by triggering the "finishProcessReceiveTask"
        Execution finishProcessTaskExecution = runtimeService.createExecutionQuery().processInstanceId(
                processInstance.getId()).activityId("finishProcessReceiveTask").singleResult();
        runtimeService.signal(finishProcessTaskExecution.getId());

While it works, it seems a little bit like a hack having to put a Java Receive Task before the end of every primary process just to check variables that were set in the process execution flow.

I know that one of the responses to this is that you can simply set the history value to full in the process engine configuration, however this means (in our scenario at least) that megabytes of data would get saved in the database for every process, when all we care about is a few kilobytes of "out" data.

    <bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
        …
        <property name="history" value="audit" />
        …
    </bean>

My question is:  How are other people handling "out" variables like these? Am I missing something critical that I'm not thinking about?

Lastly (assuming I'm handling things properly given my use case), I'm wondering if the Activiti developers out there might consider this proposal:

Activiti already allows you to specify "in" and "out" variables when invoking a sub-process via the CallActivity task.  Yet, when invoking a primary process, we currently only get the capability of specifying "in" variables (via the variableMap specified in the runtimeService.startProcessInstanceByKey(processKey,variableMap) method defined above).  Would there be a way that you could add the ability to register for out variables, or pass in a simple map that will contain all of the out variables in a process, without being dependent on a currently executing process?

Thanks in advance for your time.
Tom
5 REPLIES 5

ronald_van_kuij
Champ on-the-rise
Champ on-the-rise
My question is:  How are other people handling "out" variables like these? Am I missing something critical that I'm not thinking about?

What we use is *not* storing all domain data in the engine, just references (e.g. see the jpa example but you can also do that yourself). What goes into the engine is just needed for the flow and the process updates domain data where needed. Works great (for us).

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

Thanks for your response!

What goes into the engine is just needed for the flow and the process updates domain data where needed

I see, thanks.  I should mention that we have similar processes … domain objects get updated for the primary purpose of being updated in the database … however the tricky part is that our processes are typically invoked in the context of a request/response type of flow.

For example:
    User submits request (async @ the client)
    Middle-tier receives the request, starts a process flow.
    Activiti process either succeeds or fails based upon many rules, database calls, etc.
    Upon failure (of which there may be many listed) we want to show the user the list of errors as the response to the request.
I suppose the list of errors could be written to a database to be retrieved via a separate DAO call after the process executes, but it just seems like overkill for our scenario, especially given that we already have the variables set in the process domain, we just need to get them out  Smiley Happy

I should mention that I love the product, just thought I'd propose something and see if others might want something similar … or if they have found other solutions that I wasn't considering.

Thanks again,
Tom

ronald_van_kuij
Champ on-the-rise
Champ on-the-rise
What goes into the engine is just needed for the flow and the process updates domain data where needed

I see, thanks.  I should mention that we have similar processes … domain objects get updated for the primary purpose of being updated in the database … however the tricky part is that our processes are typically invoked in the context of a request/response type of flow.
So are ours…
For example:
    User submits request (async @ the client)
    Middle-tier receives the request, starts a process flow.
    Activiti process either succeeds or fails based upon many rules, database calls, etc.
    Upon failure (of which there may be many listed) we want to show the user the list of errors as the response to the request.
Ahhh.. .but that will never be the megabyts of data then like you mentioned will it? If so I still miss something…
I suppose the list of errors could be written to a database to be retrieved via a separate DAO call after the process executes, but it just seems like overkill for our scenario, especially given that we already have the variables set in the process domain, we just need to get them out  Smiley Happy
In relation to the previous statement, if there are no megabytes anymore, why not retrieve them from the history? Or use a tasklistener for the process end event and do something with them then (e.g. copy them to some other place…
I should mention that I love the product
Me to 🙂

tidetom
Champ in-the-making
Champ in-the-making
Hmm, maybe we've hit one source of my confusion:

In relation to the previous statement, if there are no megabytes anymore, why not retrieve them from the history?
I thought when I specify "full" history, it will save all process execution variables … is there a way to only specify certain variables? (This was the megabytes that I was concerned about … you're very correct in that the error messages themselves are very small, but the remaining variables may be large.  I suppose I could null out all other variables prior to the end of the process.)

Or use a tasklistener for the process end event and do something with them then (e.g. copy them to some other place…
I'll look into sticking a task listener on the end event, I hadn't considered that option and it definitely seems viable.  Would just need to find a place that could be referenced from the Spring bean that kicked the process off in the first place.

Thanks again for your time.

ronald_van_kuij
Champ on-the-rise
Champ on-the-rise
is there a way to only specify certain variables?

Not yet afaik… maybe the bpmn history attribute will be used for this at one moment in time…

you're very correct in that the error messages themselves are very small, but the remaining variables may be large.
So you do have megabytes of processvariables PER instance? Wow… are you sure you cannot 'refactor' that?