Skip to content

Conversation

@sadilchamishka
Copy link
Contributor

@sadilchamishka sadilchamishka commented Jul 4, 2025

@sadilchamishka sadilchamishka marked this pull request as draft July 4, 2025 16:54
String tenantDomain = CarbonContext.getThreadLocalCarbonContext().getTenantDomain();
List<String> roleIds = getAssignedRoleIds(userId, tenantDomain);
List<String> roleRequestsList;
List<String> lst = new ArrayList<>();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
List<String> lst = new ArrayList<>();
List<String> combinedList = new ArrayList<>();

WDYT?

Copy link
Contributor Author

@sadilchamishka sadilchamishka Jul 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we remove this method and use the method getAllAssignedTasks It looks both methods do the same logic. Need to have close look. We may able to re use the same method passing a specific status.

Comment on lines +651 to +660
public List<WorkflowAssociation> getAssociations(WorkflowRequest workflowRequest) {

List<WorkflowAssociation> associations = null;
WorkflowRequestAssociationDAO requestAssociationDAO = new WorkflowRequestAssociationDAO();
try {
associations = requestAssociationDAO.getWorkflowAssociationsForRequest(
workflowRequest.getEventType(), workflowRequest.getTenantId());
} catch (InternalWorkflowException e) {
}
return associations;
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method need to check whether it's logic is correct. For a give workflow request it should return one workflow association.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When we have multiple workflows with the same association, eg: ADD_USER in workflow1 and workflow2 this will return multiple associations and therefore it is possible to return multiple associations.

public String getWorkflowId(WorkflowRequest request) {

WorkflowManagementService workflowManagementService = new WorkflowManagementServiceImpl();
List<WorkflowAssociation> associations = getAssociations(request);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Related the comment. https://github.com/wso2-extensions/identity-workflow/pull/13/files#r2186705368

Below for loop should not be necessary.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In here we are iterating through the all the associations we have for the same operation like ADD_USER. Only chance to have the multiple associations here is 2 workflows have same operation configured.

Still with the current logic this only the last workflow id will be picked up. That means all other workflows are neglected. IMO, we should not support to have same operation in 2 workflows as it creates conflicts like this.
cc: @sadilchamishka

@sadilchamishka sadilchamishka force-pushed the Refactor-workflow-engine branch from 905287e to a28f6ba Compare July 5, 2025 05:24
@CLAassistant
Copy link

CLAassistant commented Jul 5, 2025

CLA assistant check
All committers have signed the CLA.

@sadilchamishka sadilchamishka force-pushed the Refactor-workflow-engine branch 2 times, most recently from 16dff73 to 8fdb7a3 Compare July 5, 2025 05:28
@sadilchamishka sadilchamishka force-pushed the Refactor-workflow-engine branch from 8fdb7a3 to d740cd1 Compare July 5, 2025 05:29
@Malith-19 Malith-19 requested a review from Copilot July 5, 2025 11:26
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Refactors the workflow engine by removing legacy approval event code and migrating to a new approval task service API, cleaning up dependencies, and streamlining SQL constants.

  • Removes old test classes and Powermock setup in favor of a shared test utility.
  • Updates project POMs to drop internal WSO2 plugin repositories and obsolete dependencies.
  • Introduces ApprovalTaskDAO/WorkflowRequestDAO and ApprovalTaskServiceImpl; updates SQL constants.

Reviewed Changes

Copilot reviewed 21 out of 22 changed files in this pull request and generated no comments.

Show a summary per file
File Description
pom.xml Removed internal plugin/repository blocks; updated framework & testutil versions
components/.../pom.xml Swapped out Powermock for shared org.wso2.carbon.identity.testutil and cleaned test deps
components/.../util/WorkflowEngineConstants.java Refactored SQL templates (e.g., ADD_CURRENT_STEP_FOR_EVENT) and renamed error messages
components/.../internal/dao/ApprovalTaskDAO.java & DAOImpl.java New DAO interface/implementation for approval tasks; dropped deprecated methods
components/.../ApprovalTaskServiceImpl.java Core service overhaul to list, retrieve, and update approval tasks
Comments suppressed due to low confidence (3)

components/org.wso2.carbon.identity.workflow.engine/src/main/java/org/wso2/carbon/identity/workflow/engine/ApprovalTaskServiceImpl.java:1

  • The new ApprovalTaskServiceImpl and its DAO lack accompanying unit or integration tests; consider adding tests to cover core methods like listing tasks, updating statuses, and step progression.
/*

components/org.wso2.carbon.identity.workflow.engine/src/main/java/org/wso2/carbon/identity/workflow/engine/util/WorkflowEngineConstants.java:57

  • Hardcoding the step value to '1' in the INSERT will ignore any dynamic currentStep; switch back to a placeholder (?,?,?) so the bound parameter is used.
                "(EVENT_ID,WORKFLOW_ID, CURRENT_STEP) VALUES (?,?,1)";

components/org.wso2.carbon.identity.workflow.engine/src/main/java/org/wso2/carbon/identity/workflow/engine/ApprovalTaskServiceImpl.java:247

  • The method 'updateStateOfRequest(...)' isn't declared in ApprovalTaskDAO; add this signature to the DAO interface and implement it, or call the correct method, to avoid compilation errors.
            approvalTaskDAO.updateStateOfRequest(workflowRequestId, workflowId, currentStep);

@sadilchamishka sadilchamishka marked this pull request as ready for review July 7, 2025 04:29

String userId = CarbonContext.getThreadLocalCarbonContext().getUserId();

List<ApprovalTaskSummaryDTO> approvalTaskSummaryDTOS = getAllAssignedTasks(status, userId);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Try to improve getAllAssignedTasks to remove duplicated workflow requests, preserve reserved tasks etc..

approvalTaskSummaryDTO.setApprovalStatus(approvalTaskSummaryDTO.getApprovalStatus());
}

if (limit == null || limit < 0) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pagination improvements. Here or at the getAllAssignedTasks method level.

taskId = taskArray[0];
String requestId = approvalTaskDAO.getWorkflowRequestIdByApprovalTaskId(taskId);
WorkflowRequest request = getWorkflowRequest(requestId);
TaskDetails taskDetails = getTaskDetails(request);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can comment at this moment.

TaskDetails taskDetails = getTaskDetails(request);
String initiator = workflowRequestDAO.getInitiatedUser(requestId);
List<String> approvers = approvalTaskDAO.listApprovers(taskId);
Map<String, String> assigneeMap = null;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We may not need this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if approval task is blocked, share who has got assigned.

String statusValue = approvalTaskDAO.getApprovalTaskStatus(taskId);
approvalTaskDTO.setApprovalStatus(statusValue);
approvalTaskDTO.setInitiator(WorkflowEngineConstants.ParameterName.INITIATED_BY + initiator);
approvalTaskDTO.setPriority(WorkflowEngineConstants.ParameterName.PRIORITY);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can remove this if no use case.

isAssignedApprovalTask = true;
}
} else {
List<String> roleIds = getAssignedRoleIds(userId, tenantDomain);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rename the method
userAssignedRoleIds

update get the method name of approverDTO. ex: getApproverId()

}
}

private void validateApprovers(String taskId) throws WorkflowEngineException {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggest good method name.

maxStep = step;
}
} catch (NumberFormatException e) {
throw new RuntimeException(e);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't return runtime exceptions.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Improve the algorithm.


private void handleApproval(String taskId) throws WorkflowEngineServerException {

String requestID = approvalTaskDAO.getWorkflowRequestIdByApprovalTaskId(taskId);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check whether we can pass the request id.

private void handleApproval(String taskId) throws WorkflowEngineServerException {

String requestID = approvalTaskDAO.getWorkflowRequestIdByApprovalTaskId(taskId);
List<String> taskIds = approvalTaskDAO.getApprovalTasksByWorkflowRequestId(requestID);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Improve update the status by one database query.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the completing step is the final step, clean the records in this table also.

Image

}
}

private void handleRelease(String taskId) throws WorkflowEngineServerException {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

String reservedStatus = WorkflowEngineConstants.TaskStatus.RESERVED.toString();
String blockedStatus = WorkflowEngineConstants.TaskStatus.BLOCKED.toString();

if (blockedStatus.equals(approvalTaskDAO.getApprovalTaskStatus(updatedApprovalTaskId))) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As we validate Approvers at the begining, we may not need this again.

private void handleClaim(String updatedApprovalTaskId) throws WorkflowEngineException {

String userId = CarbonContext.getThreadLocalCarbonContext().getUserId();
String reservedStatus = WorkflowEngineConstants.TaskStatus.RESERVED.toString();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use getValue, getName and no need to assign to a variable.

String newTaskId = UUID.randomUUID().toString();
approvalTaskDAO.addApproversOfRequest(newTaskId, workflowRequestID, workflowId,
ENTITY_TYPE_CLAIMED_USERS, userId, reservedStatus);
approvalTaskDAO.updateApprovalTaskStatus(newTaskId, reservedStatus);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check whether this is needed. As the add operation should do the same.

if (existingApprovalTaskId.equals(updatedApprovalTaskId)) {
if (WorkflowEngineConstants.APPROVER_TYPE_USERS.equals(approverType)) {
approvalTaskDAO.updateApprovalTaskStatus(updatedApprovalTaskId, reservedStatus);
} else if (WorkflowEngineConstants.APPROVER_TYPE_ROLES.equals(approverType)) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a comment explaining the business logic.

approvalTaskDAO.addApproversOfRequest(newTaskId, workflowRequestID, workflowId,
ENTITY_TYPE_CLAIMED_USERS, userId, reservedStatus);
approvalTaskDAO.updateApprovalTaskStatus(newTaskId, reservedStatus);
approvalTaskDAO.updateApprovalTaskStatus(updatedApprovalTaskId, blockedStatus);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check whether we need to improve the logic to improve the performance.

wsWorkflowCallBackService.onCallback(wsWorkflowResponse);
}

private TaskDetails getTaskDetails(WorkflowRequest workflowRequest) throws WorkflowEngineException {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't have a use case for TASK_SUBJECT, TASK_DESCRIPTION at the moment.

return taskDetails;
}

private List<Parameter> getParameterList(WorkflowRequest request) throws WorkflowEngineException {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to check this logic. There should be bug.

List<RequestParameter> requestParameter;
for (int i = 0; i < request.getRequestParameters().size(); i++) {
requestParameter = request.getRequestParameters();
if (requestParameter.get(i).getName().equals(WorkflowEngineConstants.ParameterName.REQUEST_ID)) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use constant first.


public String getWorkflowId(WorkflowRequest request) throws WorkflowEngineException {

WorkflowManagementService workflowManagementService = new WorkflowManagementServiceImpl();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Get the service from the dataholder.

Comment on lines +589 to +601
for (WorkflowAssociation association : associations) {
try {
Workflow workflow = workflowManagementService.getWorkflow(association.getWorkflowId());
workflowId = workflow.getWorkflowId();
} catch (WorkflowClientException e) {
throw new WorkflowEngineClientException(
WorkflowEngineConstants.ErrorMessages.WORKFLOW_ID_NOT_FOUND.getCode(),
WorkflowEngineConstants.ErrorMessages.WORKFLOW_ID_NOT_FOUND.getDescription());
} catch (WorkflowException e) {
throw new WorkflowEngineServerException(e.getErrorCode(), e.getMessage());
}
}
return workflowId;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check the logic.

Comment on lines +611 to +612
} catch (InternalWorkflowException e) {
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Handle exception.

long cal = calendar.getTimeInMillis();
setCreatedTime(cal);
approvalTaskSummaryDTO.setId(approvalTaskSummaryDTO.getId());
approvalTaskSummaryDTO.setName(WorkflowEngineConstants.ParameterName.APPROVAL_TASK);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this line.

String eventType = request.getEventType();

String workflowID = approvalTaskDAO.getWorkflowID(approvalTaskSummaryDTO.getId());
String workflowAssociationName = findAssociationNameByWorkflowAndEvent(workflowID, eventType);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This may not need now.

@jenkins-is-staging
Copy link

PR builder started
Link: https://github.com/wso2/product-is/actions/runs/16112970873

@jenkins-is-staging
Copy link

PR builder completed
Link: https://github.com/wso2/product-is/actions/runs/16112970873
Status: failure

@jenkins-is-staging
Copy link

PR builder started
Link: https://github.com/wso2/product-is/actions/runs/16135035038

@jenkins-is-staging
Copy link

PR builder completed
Link: https://github.com/wso2/product-is/actions/runs/16135035038
Status: failure

@sadilchamishka sadilchamishka merged commit 3c23732 into wso2-extensions:main Jul 8, 2025
2 checks passed
@sadilchamishka
Copy link
Contributor Author

sadilchamishka commented Jul 8, 2025

The comments will be addressed by a different PR.

The integration test was failed due to dependency with

The integration test will be run with both PRs merged. As we haven't onboard integration tests for the workflow approval, the code refactoring should not affect the integration tests.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants