flowable-engine icon indicating copy to clipboard operation
flowable-engine copied to clipboard

Unexpected result when a HistoricProcessInstanceQuery is executed twice for the same processInstanceId in the same transaction.

Open billerby opened this issue 2 years ago • 0 comments

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?

billerby avatar Nov 08 '22 10:11 billerby