diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/governance/workflows/WorkflowHandler.java b/openmetadata-service/src/main/java/org/openmetadata/service/governance/workflows/WorkflowHandler.java index 27341af9802..df904c8ef78 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/governance/workflows/WorkflowHandler.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/governance/workflows/WorkflowHandler.java @@ -47,6 +47,7 @@ import org.openmetadata.service.Entity; import org.openmetadata.service.OpenMetadataApplicationConfig; import org.openmetadata.service.clients.pipeline.PipelineServiceClientFactory; import org.openmetadata.service.exception.UnhandledServerException; +import org.openmetadata.service.governance.workflows.elements.nodes.userTask.UserTaskType; import org.openmetadata.service.governance.workflows.flowable.sql.SqlMapper; import org.openmetadata.service.governance.workflows.flowable.sql.UnlockExecutionSql; import org.openmetadata.service.governance.workflows.flowable.sql.UnlockJobSql; @@ -238,7 +239,7 @@ public class WorkflowHandler { public ProcessInstance triggerByKey( String processDefinitionKey, String businessKey, Map variables) { RuntimeService runtimeService = processEngine.getRuntimeService(); - LOG.info( + LOG.debug( "[WorkflowTrigger] START: processKey='{}' businessKey='{}' variables={}", processDefinitionKey, businessKey, @@ -246,7 +247,7 @@ public class WorkflowHandler { try { ProcessInstance instance = runtimeService.startProcessInstanceByKey(processDefinitionKey, businessKey, variables); - LOG.info( + LOG.debug( "[WorkflowTrigger] SUCCESS: processKey='{}' instanceId='{}' businessKey='{}'", processDefinitionKey, instance.getId(), @@ -394,12 +395,12 @@ public class WorkflowHandler { public void resolveTask(UUID customTaskId, Map variables) { TaskService taskService = processEngine.getTaskService(); - LOG.info("[WorkflowTask] RESOLVE: customTaskId='{}' variables={}", customTaskId, variables); + LOG.debug("[WorkflowTask] RESOLVE: customTaskId='{}' variables={}", customTaskId, variables); try { Optional oTask = Optional.ofNullable(getTaskFromCustomTaskId(customTaskId)); if (oTask.isPresent()) { Task task = oTask.get(); - LOG.info( + LOG.debug( "[WorkflowTask] Found task: flowableTaskId='{}' processInstanceId='{}' name='{}'", task.getId(), task.getProcessInstanceId(), @@ -416,11 +417,11 @@ public class WorkflowHandler { boolean taskCompleted = handleMultiApproval(task, variables, approvalThreshold, rejectionThreshold); if (taskCompleted) { - LOG.info( + LOG.debug( "[WorkflowTask] SUCCESS: Multi-approval task '{}' completed with threshold met", customTaskId); } else { - LOG.info( + LOG.debug( "[WorkflowTask] SUCCESS: Multi-approval task '{}' recorded vote, waiting for more votes", customTaskId); // Update the Thread entity to remove the task from the current voter's feed @@ -431,18 +432,18 @@ public class WorkflowHandler { Optional.ofNullable(variables) .ifPresentOrElse( variablesValue -> { - LOG.info( + LOG.debug( "[WorkflowTask] Completing with variables: taskId='{}' vars={}", task.getId(), variablesValue); taskService.complete(task.getId(), variablesValue); }, () -> { - LOG.info( + LOG.debug( "[WorkflowTask] Completing without variables: taskId='{}'", task.getId()); taskService.complete(task.getId()); }); - LOG.info("[WorkflowTask] SUCCESS: Task '{}' resolved", customTaskId); + LOG.debug("[WorkflowTask] SUCCESS: Task '{}' resolved", customTaskId); } } else { LOG.warn("[WorkflowTask] NOT_FOUND: No Flowable task for customTaskId='{}'", customTaskId); @@ -554,7 +555,7 @@ public class WorkflowHandler { if (!votedUsers.contains(currentUser)) { votedUsers.add(currentUser); taskService.setVariable(flowableTask.getId(), "votedUsers", votedUsers); - LOG.info( + LOG.debug( "[WorkflowTask] Added user '{}' to voted users list for Flowable task", currentUser); } @@ -564,7 +565,7 @@ public class WorkflowHandler { String currentAssignee = flowableTask.getAssignee(); if (currentUser.equals(currentAssignee)) { taskService.unclaim(flowableTask.getId()); - LOG.info( + LOG.debug( "[WorkflowTask] Unclaimed Flowable task '{}' from user '{}'", flowableTask.getId(), currentUser); @@ -572,7 +573,7 @@ public class WorkflowHandler { // Remove from candidate users if present taskService.deleteCandidateUser(flowableTask.getId(), currentUser); - LOG.info( + LOG.debug( "[WorkflowTask] Removed user '{}' from candidate users for Flowable task '{}'", currentUser, flowableTask.getId()); @@ -611,18 +612,6 @@ public class WorkflowHandler { return null; } - private Integer extractTaskIdFromCustomTaskId(UUID customTaskId) { - // The customTaskId might contain the integer task ID - // This is a fallback approach if direct UUID matching doesn't work - try { - // Check if we can extract an integer ID from somewhere - // This depends on how the task ID is generated and stored - return null; // Placeholder - actual implementation would depend on ID generation logic - } catch (Exception e) { - return null; - } - } - private boolean handleMultiApproval( Task task, Map variables, @@ -638,79 +627,53 @@ public class WorkflowHandler { rejectionThreshold = 1; } - // Get current approval tracking variables @SuppressWarnings("unchecked") - List> approvals = - (List>) taskService.getVariable(task.getId(), "approvals"); - if (approvals == null) { - approvals = new ArrayList<>(); + List approversList = + (List) taskService.getVariable(task.getId(), "approversList"); + if (approversList == null) { + approversList = new ArrayList<>(); } - Integer approvalCount = (Integer) taskService.getVariable(task.getId(), "approvalCount"); - if (approvalCount == null) { - approvalCount = 0; - } - - Integer rejectionCount = (Integer) taskService.getVariable(task.getId(), "rejectionCount"); - if (rejectionCount == null) { - rejectionCount = 0; + @SuppressWarnings("unchecked") + List rejectersList = + (List) taskService.getVariable(task.getId(), "rejectersList"); + if (rejectersList == null) { + rejectersList = new ArrayList<>(); } // Get the current user and approval decision - // Variables might be namespaced, so check both namespaced and global versions - String currentUser = (String) variables.get("updatedBy"); - if (currentUser == null) { - // Try to find namespaced updatedBy (e.g., "ApproveGlossaryTerm_updatedBy") - for (String key : variables.keySet()) { - if (key.endsWith("_updatedBy")) { - currentUser = (String) variables.get(key); - break; - } - } - } + String nodeName = getParentActivityId(task.getExecutionId()); + String updatedByVariable = getNamespacedVariableName(nodeName, "updatedBy"); + String resultVariable = getNamespacedVariableName(nodeName, "result"); + String currentUser = (String) variables.get(updatedByVariable); + Boolean approved = (Boolean) variables.get(resultVariable); - Boolean approved = (Boolean) variables.get("result"); - if (approved == null) { - // Try to find namespaced result (e.g., "ApproveGlossaryTerm_result") - for (String key : variables.keySet()) { - if (key.endsWith("_result")) { - approved = (Boolean) variables.get(key); - break; - } - } - } - - // Make variables final for lambda expression - final String finalCurrentUser = currentUser; - final Boolean finalApproved = approved; - - // Check if this user has already voted - boolean alreadyVoted = - approvals.stream() - .anyMatch(a -> finalCurrentUser != null && finalCurrentUser.equals(a.get("user"))); - - if (alreadyVoted) { - LOG.warn("[MultiApproval] User '{}' has already voted on this task", finalCurrentUser); + if (currentUser == null || approved == null) { + LOG.warn( + "[MultiApproval] Cannot process approval - missing required variables. " + + "updatedBy: {}, result: {}. Task remains open.", + currentUser, + approved); + // DON'T complete the task, DON'T increment counts return false; } - // Record the approval/rejection - Map approval = new HashMap<>(); - approval.put("user", finalCurrentUser); - approval.put("approved", finalApproved); - approval.put("timestamp", System.currentTimeMillis()); - approvals.add(approval); - - if (Boolean.TRUE.equals(finalApproved)) { - approvalCount++; - } else { - rejectionCount++; + if (approversList.contains(currentUser) || rejectersList.contains(currentUser)) { + LOG.warn("[MultiApproval] User '{}' has already voted on this task", currentUser); + return false; } - // Update task variables - taskService.setVariable(task.getId(), "approvals", approvals); - taskService.setVariable(task.getId(), "approvalCount", approvalCount); - taskService.setVariable(task.getId(), "rejectionCount", rejectionCount); + if (approved) { + approversList.add(currentUser); + } else { + rejectersList.add(currentUser); + } + + taskService.setVariable(task.getId(), "approversList", approversList); + taskService.setVariable(task.getId(), "rejectersList", rejectersList); + + int approvalCount = approversList.size(); + int rejectionCount = rejectersList.size(); LOG.debug( "[MultiApproval] Task '{}' - Approvals: {}/{}, Rejections: {}/{}", @@ -727,14 +690,7 @@ public class WorkflowHandler { rejectionCount, rejectionThreshold); // Set the final result - need to check if result is namespaced - String resultKey = "result"; - for (String key : variables.keySet()) { - if (key.endsWith("_result")) { - resultKey = key; - break; - } - } - variables.put(resultKey, false); + variables.put(resultVariable, false); taskService.complete(task.getId(), variables); return true; } @@ -746,14 +702,7 @@ public class WorkflowHandler { approvalCount, approvalThreshold); // Set the final result - need to check if result is namespaced - String resultKey = "result"; - for (String key : variables.keySet()) { - if (key.endsWith("_result")) { - resultKey = key; - break; - } - } - variables.put(resultKey, true); + variables.put(resultVariable, true); taskService.complete(task.getId(), variables); return true; } @@ -888,12 +837,8 @@ public class WorkflowHandler { LOG.debug( "Extracted subprocess ID: '{}' from task key '{}'", subProcessId, taskDefinitionKey); - // Try both possible termination message patterns - // UserApprovalTask uses: subProcessId_terminateProcess - // DetailedUserApprovalTask uses: subProcessId_terminateDetailedProcess - String[] messagePatterns = { - subProcessId + "_terminateProcess", subProcessId + "_terminateDetailedProcess" - }; + // Get all possible termination message patterns from the enum + List messagePatterns = UserTaskType.getAllTerminationPatterns(subProcessId); for (String messageName : messagePatterns) { LOG.debug("Checking for message subscription: {}", messageName); diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/governance/workflows/WorkflowUtils.java b/openmetadata-service/src/main/java/org/openmetadata/service/governance/workflows/WorkflowUtils.java deleted file mode 100644 index b1856b49731..00000000000 --- a/openmetadata-service/src/main/java/org/openmetadata/service/governance/workflows/WorkflowUtils.java +++ /dev/null @@ -1,132 +0,0 @@ -package org.openmetadata.service.governance.workflows; - -import static org.openmetadata.service.governance.workflows.elements.TriggerFactory.getMainWorkflowDefinitionNameFromTrigger; - -import java.util.List; -import lombok.extern.slf4j.Slf4j; -import org.flowable.engine.RuntimeService; -import org.flowable.engine.runtime.ProcessInstance; -import org.jdbi.v3.core.transaction.TransactionIsolationLevel; -import org.openmetadata.schema.governance.workflows.WorkflowInstance; -import org.openmetadata.schema.utils.ResultList; -import org.openmetadata.service.Entity; -import org.openmetadata.service.jdbi3.ListFilter; -import org.openmetadata.service.jdbi3.WorkflowDefinitionRepository; -import org.openmetadata.service.jdbi3.WorkflowInstanceRepository; -import org.openmetadata.service.jdbi3.WorkflowInstanceStateRepository; -import org.openmetadata.service.util.EntityUtil; - -@Slf4j -public class WorkflowUtils { - - /** - * Terminates conflicting workflow instances of a specific type for an entity. - * Orchestrates both Flowable termination and OpenMetadata database updates. - */ - public static void terminateConflictingInstances( - String triggerWorkflowDefinitionKey, String entityLink, String currentProcessInstanceId) { - try { - // Convert trigger name to main workflow name (e.g., "GlossaryTermApprovalWorkflowTrigger" → - // "GlossaryTermApprovalWorkflow") - String mainWorkflowDefinitionName = - getMainWorkflowDefinitionNameFromTrigger(triggerWorkflowDefinitionKey); - WorkflowInstanceRepository workflowInstanceRepository = - (WorkflowInstanceRepository) - Entity.getEntityTimeSeriesRepository(Entity.WORKFLOW_INSTANCE); - WorkflowInstanceStateRepository workflowInstanceStateRepository = - (WorkflowInstanceStateRepository) - Entity.getEntityTimeSeriesRepository(Entity.WORKFLOW_INSTANCE_STATE); - - // Query for running instances of this workflow type for this entity - ListFilter filter = new ListFilter(null); - filter.addQueryParam("entityLink", entityLink); - - long endTs = System.currentTimeMillis(); - long startTs = endTs - (7L * 24 * 60 * 60 * 1000); - - ResultList allInstances = - workflowInstanceRepository.list(null, startTs, endTs, 100, filter, false); - - // Filter to running instances of this specific workflow type - List candidateInstances = - allInstances.getData().stream() - .filter( - instance -> WorkflowInstance.WorkflowStatus.RUNNING.equals(instance.getStatus())) - .filter( - instance -> { - try { - WorkflowDefinitionRepository repo = - (WorkflowDefinitionRepository) - Entity.getEntityRepository(Entity.WORKFLOW_DEFINITION); - var def = - repo.get( - null, - instance.getWorkflowDefinitionId(), - EntityUtil.Fields.EMPTY_FIELDS); - return mainWorkflowDefinitionName.equals(def.getName()); - } catch (Exception e) { - return false; - } - }) - .toList(); - - // Check if there are multiple instances using Flowable's API - RuntimeService runtimeService = WorkflowHandler.getInstance().getRuntimeService(); - List runningProcessInstances = - runtimeService - .createProcessInstanceQuery() - .processDefinitionKey(mainWorkflowDefinitionName) - .list(); - // Find instances to terminate (exclude the current one by process instance ID) - List conflictingInstances = - candidateInstances.stream() - .filter( - instance -> { - // Check if this WorkflowInstance corresponds to a different process instance - return runningProcessInstances.stream() - .filter(pi -> !pi.getId().equals(currentProcessInstanceId)) - .anyMatch(pi -> pi.getBusinessKey().equals(instance.getId().toString())); - }) - .toList(); - - if (conflictingInstances.isEmpty()) { - LOG.debug("No conflicting instances found to terminate for {}", mainWorkflowDefinitionName); - return; - } - // Execute everything in a single transaction for atomicity - Entity.getJdbi() - .inTransaction( - TransactionIsolationLevel.READ_COMMITTED, - handle -> { - try { - // 1. Terminate Flowable processes using existing handler method - WorkflowHandler.getInstance().terminateWorkflow(mainWorkflowDefinitionName); - - // 2. Mark OpenMetadata instances and states as FAILURE - for (WorkflowInstance instance : conflictingInstances) { - workflowInstanceStateRepository.markInstanceStatesAsFailed( - instance.getId(), "Terminated due to conflicting workflow instance"); - workflowInstanceRepository.markInstanceAsFailed( - instance.getId(), "Terminated due to conflicting workflow instance"); - } - - return null; - } catch (Exception e) { - LOG.error( - "Failed to terminate conflicting instances in transaction: {}", - e.getMessage()); - throw e; - } - }); - - LOG.info( - "Terminated {} conflicting instances of {} for entity {}", - conflictingInstances.size(), - mainWorkflowDefinitionName, - entityLink); - - } catch (Exception e) { - LOG.warn("Failed to terminate conflicting instances: {}", e.getMessage()); - } - } -} diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/governance/workflows/elements/nodes/automatedTask/CheckEntityAttributesTask.java b/openmetadata-service/src/main/java/org/openmetadata/service/governance/workflows/elements/nodes/automatedTask/CheckEntityAttributesTask.java index ea2a4f0dd92..ccb8a0de5ad 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/governance/workflows/elements/nodes/automatedTask/CheckEntityAttributesTask.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/governance/workflows/elements/nodes/automatedTask/CheckEntityAttributesTask.java @@ -73,8 +73,8 @@ public class CheckEntityAttributesTask implements NodeInterface { private ServiceTask getCheckEntityAttributesServiceTask( String subProcessId, String rules, String inputNamespaceMap) { - LOG.info("CheckEntityAttributesTask: rules = {}", rules); - LOG.info("CheckEntityAttributesTask: inputNamespaceMap = {}", inputNamespaceMap); + LOG.debug("CheckEntityAttributesTask: rules = {}", rules); + LOG.debug("CheckEntityAttributesTask: inputNamespaceMap = {}", inputNamespaceMap); FieldExtension rulesExpr = new FieldExtensionBuilder().fieldName("rulesExpr").fieldValue(rules).build(); FieldExtension inputNamespaceMapExpr = diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/governance/workflows/elements/nodes/userTask/ChangeReviewTask.java b/openmetadata-service/src/main/java/org/openmetadata/service/governance/workflows/elements/nodes/userTask/ChangeReviewTask.java index 0e1c67945fb..5ba546af6c7 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/governance/workflows/elements/nodes/userTask/ChangeReviewTask.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/governance/workflows/elements/nodes/userTask/ChangeReviewTask.java @@ -197,10 +197,10 @@ public class ChangeReviewTask implements NodeInterface { } private BoundaryEvent getTerminationEvent(String subProcessId) { - // Use a consistent format that matches what getFlowableElementId produces - // This ensures uniqueness per node within the workflow definition - // ChangeReviewTask uses terminateChangeReviewProcess to distinguish from UserApprovalTask - String uniqueMessageName = getFlowableElementId(subProcessId, "terminateChangeReviewProcess"); + // Use the enum to get the termination message suffix for this task type + String uniqueMessageName = + getFlowableElementId( + subProcessId, UserTaskType.CHANGE_REVIEW_TASK.getTerminationMessageSuffix()); Message terminationMessage = new Message(); terminationMessage.setId(uniqueMessageName); diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/governance/workflows/elements/nodes/userTask/UserApprovalTask.java b/openmetadata-service/src/main/java/org/openmetadata/service/governance/workflows/elements/nodes/userTask/UserApprovalTask.java index f9dddf4642b..6c2e9e2dbee 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/governance/workflows/elements/nodes/userTask/UserApprovalTask.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/governance/workflows/elements/nodes/userTask/UserApprovalTask.java @@ -195,10 +195,10 @@ public class UserApprovalTask implements NodeInterface { } private BoundaryEvent getTerminationEvent(String subProcessId) { - // Use a consistent format that matches what getFlowableElementId produces - // This ensures uniqueness per node within the workflow definition - // Format: subProcessId.terminateProcess (where subProcessId is the node name) - String uniqueMessageName = getFlowableElementId(subProcessId, "terminateProcess"); + // Use the enum to get the termination message suffix for this task type + String uniqueMessageName = + getFlowableElementId( + subProcessId, UserTaskType.USER_APPROVAL_TASK.getTerminationMessageSuffix()); Message terminationMessage = new Message(); terminationMessage.setId(uniqueMessageName); diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/governance/workflows/elements/nodes/userTask/UserTaskType.java b/openmetadata-service/src/main/java/org/openmetadata/service/governance/workflows/elements/nodes/userTask/UserTaskType.java new file mode 100644 index 00000000000..669986b91a5 --- /dev/null +++ b/openmetadata-service/src/main/java/org/openmetadata/service/governance/workflows/elements/nodes/userTask/UserTaskType.java @@ -0,0 +1,39 @@ +package org.openmetadata.service.governance.workflows.elements.nodes.userTask; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +public enum UserTaskType { + USER_APPROVAL_TASK("terminateProcess"), + CHANGE_REVIEW_TASK("terminateChangeReviewProcess"); + + private final String terminationMessageSuffix; + + UserTaskType(String terminationMessageSuffix) { + this.terminationMessageSuffix = terminationMessageSuffix; + } + + public String getTerminationMessageSuffix() { + return terminationMessageSuffix; + } + + public String getTerminationMessageName(String subProcessId) { + return subProcessId + "_" + terminationMessageSuffix; + } + + public static List getAllTerminationPatterns(String subProcessId) { + return Arrays.stream(values()) + .map(type -> type.getTerminationMessageName(subProcessId)) + .collect(Collectors.toList()); + } + + public static String findTerminationPattern(String messageName) { + for (UserTaskType type : values()) { + if (messageName.endsWith("_" + type.getTerminationMessageSuffix())) { + return type.getTerminationMessageSuffix(); + } + } + return null; + } +} diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/governance/workflows/elements/nodes/userTask/impl/ApprovalTaskCompletionValidator.java b/openmetadata-service/src/main/java/org/openmetadata/service/governance/workflows/elements/nodes/userTask/impl/ApprovalTaskCompletionValidator.java index 865cdcab5f0..a6708024c90 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/governance/workflows/elements/nodes/userTask/impl/ApprovalTaskCompletionValidator.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/governance/workflows/elements/nodes/userTask/impl/ApprovalTaskCompletionValidator.java @@ -4,7 +4,6 @@ import static org.openmetadata.service.governance.workflows.WorkflowHandler.getP import java.util.ArrayList; import java.util.List; -import java.util.Map; import lombok.extern.slf4j.Slf4j; import org.flowable.engine.delegate.BpmnError; import org.flowable.engine.delegate.TaskListener; @@ -34,18 +33,21 @@ public class ApprovalTaskCompletionValidator implements TaskListener { return; // Single approval, allow completion } - // Get current vote counts + // Get current vote lists and calculate counts @SuppressWarnings("unchecked") - List> approvals = - (List>) delegateTask.getVariable("approvals"); - if (approvals == null) { - approvals = new ArrayList<>(); + List approversList = (List) delegateTask.getVariable("approversList"); + if (approversList == null) { + approversList = new ArrayList<>(); } - Integer approvalCount = (Integer) delegateTask.getVariable("approvalCount"); - Integer rejectionCount = (Integer) delegateTask.getVariable("rejectionCount"); - if (approvalCount == null) approvalCount = 0; - if (rejectionCount == null) rejectionCount = 0; + @SuppressWarnings("unchecked") + List rejectersList = (List) delegateTask.getVariable("rejectersList"); + if (rejectersList == null) { + rejectersList = new ArrayList<>(); + } + + int approvalCount = approversList.size(); + int rejectionCount = rejectersList.size(); // Check if thresholds are met boolean approvalThresholdMet = approvalCount >= approvalThreshold; diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/governance/workflows/elements/nodes/userTask/impl/CreateApprovalTaskImpl.java b/openmetadata-service/src/main/java/org/openmetadata/service/governance/workflows/elements/nodes/userTask/impl/CreateApprovalTaskImpl.java index 8f5483df752..f57f2d0eba1 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/governance/workflows/elements/nodes/userTask/impl/CreateApprovalTaskImpl.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/governance/workflows/elements/nodes/userTask/impl/CreateApprovalTaskImpl.java @@ -79,9 +79,9 @@ public class CreateApprovalTaskImpl implements TaskListener { // Store approval and rejection thresholds and initialize approval tracking in task variables delegateTask.setVariable("approvalThreshold", approvalThreshold); delegateTask.setVariable("rejectionThreshold", rejectionThreshold); - delegateTask.setVariable("approvals", new ArrayList>()); - delegateTask.setVariable("approvalCount", 0); - delegateTask.setVariable("rejectionCount", 0); + // Use separate lists for approvers and rejecters - simpler and cleaner + delegateTask.setVariable("approversList", new ArrayList()); + delegateTask.setVariable("rejectersList", new ArrayList()); } catch (Exception exc) { LOG.error( String.format( diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/governance/workflows/elements/nodes/userTask/impl/CreateChangeReviewTaskImpl.java b/openmetadata-service/src/main/java/org/openmetadata/service/governance/workflows/elements/nodes/userTask/impl/CreateChangeReviewTaskImpl.java index 01d0a7dfb48..9d79b244e53 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/governance/workflows/elements/nodes/userTask/impl/CreateChangeReviewTaskImpl.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/governance/workflows/elements/nodes/userTask/impl/CreateChangeReviewTaskImpl.java @@ -82,9 +82,9 @@ public class CreateChangeReviewTaskImpl implements TaskListener { // Store approval and rejection thresholds and initialize approval tracking in task variables delegateTask.setVariable("approvalThreshold", approvalThreshold); delegateTask.setVariable("rejectionThreshold", rejectionThreshold); - delegateTask.setVariable("approvals", new ArrayList>()); - delegateTask.setVariable("approvalCount", 0); - delegateTask.setVariable("rejectionCount", 0); + // Use separate lists for approvers and rejecters - simpler and cleaner + delegateTask.setVariable("approversList", new ArrayList()); + delegateTask.setVariable("rejectersList", new ArrayList()); } catch (Exception exc) { LOG.error( String.format( diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/governance/workflows/elements/triggers/impl/FilterEntityImpl.java b/openmetadata-service/src/main/java/org/openmetadata/service/governance/workflows/elements/triggers/impl/FilterEntityImpl.java index fe4aad28f7f..7549fc2a0af 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/governance/workflows/elements/triggers/impl/FilterEntityImpl.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/governance/workflows/elements/triggers/impl/FilterEntityImpl.java @@ -16,7 +16,6 @@ import org.openmetadata.schema.type.Include; import org.openmetadata.schema.utils.JsonUtils; import org.openmetadata.service.Entity; import org.openmetadata.service.governance.workflows.WorkflowHandler; -import org.openmetadata.service.governance.workflows.WorkflowUtils; import org.openmetadata.service.governance.workflows.WorkflowVariableHandler; import org.openmetadata.service.resources.feeds.MessageParser; import org.openmetadata.service.rules.RuleEngine; @@ -47,8 +46,9 @@ public class FilterEntityImpl implements JavaDelegate { String triggerWorkflowDefinitionKey = WorkflowHandler.getProcessDefinitionKeyFromId(execution.getProcessDefinitionId()); String currentProcessInstanceId = execution.getProcessInstanceId(); - WorkflowUtils.terminateConflictingInstances( - triggerWorkflowDefinitionKey, entityLinkStr, currentProcessInstanceId); + WorkflowHandler.getInstance() + .terminateDuplicateInstances( + triggerWorkflowDefinitionKey, entityLinkStr, currentProcessInstanceId); } log.debug("Trigger Glossary Term Approval Workflow: {}", passesFilter);