flowable-engine
flowable-engine copied to clipboard
Unexpected result when a HistoricProcessInstanceQuery is executed twice for the same processInstanceId in the same transaction.
Describe the bug When a HistoricProcessInstanceQueryImpl executes (using singleResult()) it finds a HistoricProcessInstance and puts it in its cache. A later executed query in the same transaction with the same processInstanceId does not take any extra clauses into account.
This bug potentially exists in a lot of different query-implementations in flowable. (for example the HistoricTaskInstaceQueryImpl.
We stumbled upon this in a service task delegate which did a permission check by querying a processInstance with an or().involvedUser(username). Got completely lost when the query returned a processInstance when I expected null since no HistoricIdentityLinks existed for the involved user.
When debugging I found the following code:
public List queryWithRawParameter(String statement, CacheAwareQuery parameter, Class entityClass, boolean cacheLoadAndStore) {
if (parameter.getId() != null && !parameter.getId().isEmpty()) {
Object entity = entityCache.findInCache(entityClass, parameter.getId());
if (entity != null) {
List resultList = new ArrayList<>();
// enhance the cached entity
parameter.enhanceCachedValue(entity);
resultList.add(entity);
return resultList;
}
}
return selectListWithRawParameter(statement, parameter, cacheLoadAndStore);
}
The parameter that comes in is the HistoricProcessInstanceQuery, and the implementation of CacheAwareQuery.getId() is the following:
@Override
public String getId() {
return processInstanceId;
}
So basically whats happening here is that the second time we issue a HistoricProcessInstanceQuery in the same transaction but with a totally different (except for the processInstanceId) query object, the clauses in the query is completely ignored. :(
Expected behavior I would have expected to not get null back from my query since the involvedUser is not having any HistoricIdentityLinks connected to the HistoricProcessInstance.
Code
public boolean hasPermissionToViewProcess(String processInstanceId, String userId) {
List<String> groups = candidateManager.getGroupsForCandidateUser(userId);
HistoricProcessInstanceQuery query = historyService.createHistoricProcessInstanceQuery()
.processInstanceId(processInstanceId)
.or()
.involvedUser(userId);
if (!groups.isEmpty()) {
query.involvedGroups(new HashSet<>(groups));
}
query.endOr();
HistoricProcessInstance processInstance = query.singleResult();
return processInstance != null;
}
Additional context Flowable 6.7.2 Postgres 11 SpringBoot-application.
How do we disable this cache?