All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.cloudfoundry.multiapps.controller.process.flowable.FlowableFacade Maven / Gradle / Ivy

There is a newer version: 1.183.0
Show newest version
package org.cloudfoundry.multiapps.controller.process.flowable;

import static java.text.MessageFormat.format;

import java.text.MessageFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import jakarta.inject.Inject;
import jakarta.inject.Named;

import org.cloudfoundry.multiapps.controller.persistence.Constants;
import org.cloudfoundry.multiapps.controller.process.Messages;
import org.cloudfoundry.multiapps.controller.process.variables.Variables;
import org.flowable.common.engine.api.FlowableObjectNotFoundException;
import org.flowable.common.engine.api.FlowableOptimisticLockingException;
import org.flowable.engine.ProcessEngine;
import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.runtime.Execution;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.job.api.Job;
import org.flowable.job.service.impl.asyncexecutor.AsyncExecutor;
import org.flowable.variable.api.history.HistoricVariableInstance;
import org.flowable.variable.api.persistence.entity.VariableInstance;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Named
public class FlowableFacade {

    private static final Logger LOGGER = LoggerFactory.getLogger(FlowableFacade.class);

    private static final int DEFAULT_JOB_RETRIES = 0;
    private static final int DEFAULT_ABORT_TIMEOUT_MS = 30 * 1000;
    private static final int DEFAULT_ABORT_WAIT_TIMEOUT_MS = 60 * 1000;

    private final ProcessEngine processEngine;

    @Inject
    public FlowableFacade(ProcessEngine processEngine) {
        this.processEngine = processEngine;
    }

    public ProcessInstance startProcess(String processDefinitionKey, Map variables) {
        return processEngine.getRuntimeService()
                            .startProcessInstanceByKey(processDefinitionKey, variables);
    }

    public String getProcessInstanceId(String executionId) {
        return getVariable(executionId, Constants.CORRELATION_ID);
    }

    public String getSubprocessInstanceId(String executionId) {
        return getVariable(executionId, Variables.SUBPROCESS_ID.getName());
    }

    public String getCurrentTaskId(String executionId) {
        return getVariable(executionId, Constants.TASK_ID);
    }

    private String getVariable(String executionId, String variableName) {
        VariableInstance variableInstance = processEngine.getRuntimeService()
                                                         .getVariableInstance(executionId, variableName);

        if (variableInstance == null) {
            return getVariableFromHistoryService(executionId, variableName);
        }

        return variableInstance.getTextValue();
    }

    private String getVariableFromHistoryService(String executionId, String variableName) {
        HistoricVariableInstance historicVariableInstance = processEngine.getHistoryService()
                                                                         .createHistoricVariableInstanceQuery()
                                                                         .executionId(executionId)
                                                                         .variableName(variableName)
                                                                         .singleResult();

        if (historicVariableInstance == null) {
            return null;
        }

        return (String) historicVariableInstance.getValue();
    }

    public ProcessInstance getProcessInstance(String processId) {
        return processEngine.getRuntimeService()
                            .createProcessInstanceQuery()
                            .processInstanceId(processId)
                            .singleResult();
    }

    public boolean hasDeadLetterJobs(String processId) {
        return !getDeadLetterJobs(processId).isEmpty();
    }

    private List getDeadLetterJobs(String processId) {
        List allProcessExecutions = getAllProcessExecutions(processId);
        return allProcessExecutions.stream()
                                   .map(this::getDeadLetterJobsForExecution)
                                   .flatMap(List::stream)
                                   .collect(Collectors.toList());
    }

    private List getDeadLetterJobsForExecution(Execution execution) {
        return processEngine.getManagementService()
                            .createDeadLetterJobQuery()
                            .processInstanceId(execution.getProcessInstanceId())
                            .list();
    }

    public List getHistoricSubProcessIds(String correlationId) {
        List historicVariableInstances = retrieveVariablesByCorrelationId(correlationId);
        return historicVariableInstances.stream()
                                        .map(HistoricVariableInstance::getProcessInstanceId)
                                        .filter(id -> !id.equals(correlationId))
                                        .collect(Collectors.toList());
    }

    public HistoricProcessInstance getHistoricProcessById(String processInstanceId) {
        return processEngine.getHistoryService()
                            .createHistoricProcessInstanceQuery()
                            .processInstanceId(processInstanceId)
                            .singleResult();
    }

    private List retrieveVariablesByCorrelationId(String correlationId) {
        return processEngine.getHistoryService()
                            .createHistoricVariableInstanceQuery()
                            .variableValueEquals(Constants.CORRELATION_ID, correlationId)
                            .orderByProcessInstanceId()
                            .asc()
                            .list();
    }

    public HistoricVariableInstance getHistoricVariableInstance(String processInstanceId, String variableName) {
        return processEngine.getHistoryService()
                            .createHistoricVariableInstanceQuery()
                            .processInstanceId(processInstanceId)
                            .variableName(variableName)
                            .singleResult();
    }

    public List getActiveHistoricSubProcessIds(String correlationId) {
        return getHistoricSubProcessIds(correlationId).stream()
                                                      .filter(this::isActive)
                                                      .collect(Collectors.toCollection(LinkedList::new));
    }

    private boolean isActive(String processId) {
        HistoricProcessInstance processInstance = processEngine.getHistoryService()
                                                               .createHistoricProcessInstanceQuery()
                                                               .processInstanceId(processId)
                                                               .singleResult();
        return processInstance.getEndTime() == null;
    }

    public void executeJob(String processInstanceId) {
        List deadLetterJobsIds = getDeadLetterJobsDistinctIds(processInstanceId);
        if (deadLetterJobsIds.isEmpty()) {
            LOGGER.info(MessageFormat.format("No dead letter jobs found for process with id {0}", processInstanceId));
            return;
        }
        moveDeadLetterJobsToExecutableJobs(deadLetterJobsIds);
    }

    private List getDeadLetterJobsDistinctIds(String processInstanceId) {
        return getDeadLetterJobs(processInstanceId).stream()
                                                   .map(Job::getId)
                                                   .distinct()
                                                   .collect(Collectors.toList());
    }

    private void moveDeadLetterJobsToExecutableJobs(List deadLetterJobIds) {
        deadLetterJobIds.forEach(this::moveDeadLetterJobToExecutableJob);
    }

    private void moveDeadLetterJobToExecutableJob(String deadLetterJobId) {
        try {
            processEngine.getManagementService()
                         .moveDeadLetterJobToExecutableJob(deadLetterJobId, DEFAULT_JOB_RETRIES);
        } catch (FlowableObjectNotFoundException e) {
            LOGGER.error(e.getMessage(), e);
        }
    }

    public void trigger(String executionId, Map variables) {
        processEngine.getRuntimeService()
                     .trigger(executionId, variables);
    }

    public void deleteProcessInstance(String processInstanceId, String deleteReason) {
        long overallAbortDeadline = System.currentTimeMillis() + DEFAULT_ABORT_WAIT_TIMEOUT_MS + DEFAULT_ABORT_TIMEOUT_MS;
        while (true) {
            try {
                processEngine.getRuntimeService()
                             .deleteProcessInstance(processInstanceId, deleteReason);
                break;
            } catch (FlowableOptimisticLockingException e) {
                if (isPastDeadline(overallAbortDeadline)) {
                    throw new IllegalStateException(Messages.ABORT_OPERATION_TIMED_OUT, e);
                }
                LOGGER.warn(format(Messages.RETRYING_PROCESS_ABORT, processInstanceId));
            }
        }
    }

    protected boolean isPastDeadline(long deadline) {
        return System.currentTimeMillis() >= deadline;
    }

    public boolean isProcessInstanceAtReceiveTask(String processInstanceId) {
        List executionsAtReceiveTask = findExecutionsAtReceiveTask(processInstanceId);
        return !executionsAtReceiveTask.isEmpty();
    }

    public List findExecutionsAtReceiveTask(String processInstanceId) {
        List allProcessExecutions = getActiveProcessExecutions(processInstanceId);

        return allProcessExecutions.stream()
                                   .filter(execution -> !findCurrentActivitiesAtReceiveTask(execution).isEmpty())
                                   .collect(Collectors.toList());

    }

    public List getActiveProcessExecutions(String processInstanceId) {
        List allProcessExecutions = getAllProcessExecutions(processInstanceId);

        return allProcessExecutions.stream()
                                   .filter(e -> e.getActivityId() != null)
                                   .collect(Collectors.toList());
    }

    private List getAllProcessExecutions(String processInstanceId) {
        return processEngine.getRuntimeService()
                            .createExecutionQuery()
                            .rootProcessInstanceId(processInstanceId)
                            .list();
    }

    private List findCurrentActivitiesAtReceiveTask(Execution execution) {
        return processEngine.getHistoryService()
                            .createHistoricActivityInstanceQuery()
                            .activityId(execution.getActivityId())
                            .executionId(execution.getId())
                            .activityType("receiveTask")
                            .list();
    }

    public void suspendProcessInstance(String processInstanceId) {
        processEngine.getRuntimeService()
                     .suspendProcessInstanceById(processInstanceId);
    }

    public void shutdownJobExecutor() {
        LOGGER.info(Messages.SHUTTING_DOWN_FLOWABLE_JOB_EXECUTOR);
        AsyncExecutor asyncExecutor = processEngine.getProcessEngineConfiguration()
                                                   .getAsyncExecutor();
        asyncExecutor.shutdown();
    }

    public boolean isJobExecutorActive() {
        return processEngine.getProcessEngineConfiguration()
                            .getAsyncExecutor()
                            .isActive();
    }

    public ProcessEngine getProcessEngine() {
        return processEngine;
    }

    public List findAllRunningProcessInstanceStartedBefore(LocalDateTime startedBefore) {
        return processEngine.getRuntimeService()
                            .createProcessInstanceQuery()
                            .excludeSubprocesses(true)
                            .startedBefore(java.util.Date.from(startedBefore.atZone(ZoneId.systemDefault())
                                                                            .toInstant()))
                            .list();
    }

    public Execution getParentExecution(String parentId) {
        return processEngine.getRuntimeService()
                            .createExecutionQuery()
                            .executionId(parentId)
                            .singleResult();
    }

    public void setVariableInParentProcess(DelegateExecution execution, String variableName, Object value) {
        String parentProcessId = getParentExecution(execution.getParentId()).getSuperExecutionId();
        processEngine.getRuntimeService()
                     .setVariable(parentProcessId, variableName, value);
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy