Hi,
I’m confused as to why I would be getting different results from querying the process Instance.
METHOD #1 (REST API HTTP CALL):
https://host:port/engine-rest/process-instance/9572f4e6-13d5-11e7-ba1e-685b357b8867
returns:
{
links: [ ],
id: “9572f4e6-13d5-11e7-ba1e-685b357b8867”,
definitionId: “sleeps:1:5f029a2e-13d4-11e7-ae90-685b357b8867”,
businessKey: “d76ba883-1be2-437f-a1b9-b884f2bfbc1f”,
caseInstanceId: null,
ended: false,
suspended: true
}
METHOD #2 (Java API):
ProcessInstance processInstance =
runtimeService.createProcessInstanceQuery()
.processInstanceId(execution.getProcessInstanceId()).singleResult();
processInstance.isSuspended()
returns false.
I would expect both of these methods to return suspended = true. (The process instance is suspended).
METHOD #2 is called from inside an ExecutionListener class…
Thanks,
Galen
Hi @Galen_Hollins,
you have less filter criteria on second query so I assume your first result is just a different process instance. I think you might also add sorting to achieve more predictable results.
Cheers,
Askar
Hi Askar,
I went back and re-ran to double check this. In my test, I only have exactly one process instance in the whole system. I verified the instance ID is the same. Here are the results, which also log the instance ID:
METHOD #1:
https://host:port/engine-rest/process-instance/0e17ba60-1498-11e7-84db-c8e0eb180225
RESPONSE:
{
links: ,
id: “0e17ba60-1498-11e7-84db-c8e0eb180225”,
definitionId: “sleeps:1:fd150623-1497-11e7-856c-c8e0eb180225”,
businessKey: “7d4160b1-14bc-406f-bb7d-8e00a82c2cf0”,
caseInstanceId: null,
ended: false,
suspended: true
}
METHOD #2:
ProcessInstance processInstance =
runtimeService.createProcessInstanceQuery()
.processInstanceId(execution.getProcessInstanceId()).singleResult();
log.debug("processInstance (id = "+execution.getProcessInstanceId()+").isSuspended = " + processInstance.isSuspended());
OUTPUT:
processInstance (id = 0e17ba60-1498-11e7-84db-c8e0eb180225).isSuspended = false
So it seems like I’m doing something wrong, or not understanding if the API call actually goes to the database to get the actual current state, or whether it gets some cached state on the worker…
Thanks,
Galen
I created a JIRA issue for this here:
https://app.camunda.com/jira/browse/CAM-7575
I also verified that at the time of the queries, the “ACT_RU_EXECUTION.SUSPENSION_STATE_” field has a value of “2”.
Thanks,
Galen
Hi Galen,
Where do you perform this query? Is this part of a Java delegate? Could it be that the transaction that executes this delegate begins before you suspend the process instance (based on our discussion earlier this week)?
Cheers,
Thorben
Hi Thorben,
This Java API query is performed inside of ExecutionListener in my process application. The query gets executed when an end event triggers the listener. It is not part of the Java Delegate (well I guess it gets passed the DelegateExecution object). It does seem like this could be not going to the database, but instead looking at a transaction, or some local state… Is there a way to force the API call to go to the database?
Here’s some truncated code showing where it is
/**
* Process Application exposing this application's resources the process engine.
*/
@ProcessApplication
public class MyEngineProcessApplication extends SpringProcessApplication implements InitializingBean {
...
...
/**
* Custom ExecutionListener callback implementation
*
*/
public ExecutionListener getExecutionListener() {
return new ExecutionListener() {
@Override
public void notify(final DelegateExecution execution) throws Exception {
...
// -------------------------
// RUNNING ---> COMPLETE
// -------------------------
else if (elementName.equals("EndEventImpl")) {
try {
if (execution.getEventName().equals("end")) {
ProcessInstance processInstance =
runtimeService.createProcessInstanceQuery()
.processInstanceId(execution.getProcessInstanceId()).singleResult();
log.debug("processInstance (id = "+execution.getProcessInstanceId()+").isSuspended = " + processInstance.isSuspended());
...
...
}
Thanks,
Galen
Hi Galen,
Pretty much. While the query does hit the database, it updates the result with any state that was changed in the current engine command based on an entity cache. This is intended to avoid inconsistencies in process execution. There is no public API way to force the process engine to ignore the cached state.
Using internal API, this should work:
final RuntimeService runtimeService = ...;
Context.getProcessEngineConfiguration().getCommandExecutorTxRequiresNew().execute(new Command<ProcessInstance>() {
@Override
public ProcessInstance execute(CommandContext commandContext) {
return runtimeService.createProcessInstanceQuery().singleResult();
}
});
This command will be executed with a fresh cache and a separate transaction. Note that internal API can change with any future version.
I’ll close the JIRA ticket you raised, as all this is expected behavior.
Cheers,
Thorben
Hi Thorben,
Thanks. I think I see that the transaction only uses information from the database to fill in the gaps of what it doesn’t have. It uses what it already has, as the “truth” (even though it might not be the real truth). I think most people, when calling the public APIs would not think this deeply. They would just expect to get back whatever the absolute truth is in the database. I now understand (somewhat) the motivations behind modifying the results from the database on-the-fly though…
In any case, I’m just trying to detect whether the process is suspended or not when it reaches the end state. If it’s suspended, and it’s reach the end state, there no way to prevent it from going back and running activities again (Suspended processes continue to run, and can’t keep track of their progress). So, I want to see if it’s really suspended, to avoid doing certain cleanup activities twice…
Thanks,
Galen
I also think that fundamentally, calling the Java API call a “query” is misleading.
Now understanding the above logic, it’s more of a “getTransactionState”…
The Java API “query” is fundamentally different than the REST API “query”!
Perhaps there’s a way to clarify the distinction between the two in the docs?
Thanks again for the help,
Galen