Closure of Work-items by rule

I’m working with SailPoint IdentityIQ 8.4 and closing aging work items through a rule. The work items close correctly, but the related access requests don’t update automatically. I want the access request to close as soon as its work item is closed, without any manual updates. Right now, the work item status updates immediately, but the access request only closes after I manually run the Identity Request Maintenance task, which I want to avoid. Please let me know if you have any suggestions.

Ps - I would like to avoid execution of the commented code at the end.

public autocloseLogic(WorkItem wi)
{
 if(wi != null)
 {
	wflower = new Workflower(context);
	term = new Terminator(context);
	WorkflowCase wfc = wi.getWorkflowCase();
	if(wfc!=null)
	{
	  if(wi.getType().equals(WorkItem.Type.Form))
	  {
		 wi.load();
		 wi.setState(WorkItem.State.Canceled);
		 String currentOwner = wi.getOwner()!=null?  wi.getOwner().getDisplayName():null;
		 wi.setCompletionComments("Form Auto-Rejected by SailPoint Administrator as no action was taken by "+currentOwner);
	  }
	  if(wi.getType().equals(WorkItem.Type.Approval))
	  {
		 // Auto Reject Individual Approval Items
		 ApprovalSet set = wi.getApprovalSet();
		 if (null != set)
		 {
			List appItems = set.getItems();
			if (null != appItems && appItems.size() > 0)
			{
			  for (ApprovalItem item : appItems) 
			  {
				 //item.reject();
				 //item.add(new Comment("Approval auto-rejected by SailPoint Administrator", "spadmin"));
				 item.setState(WorkItem.State.Rejected);
				 item.setApprover("spadmin");
			  }
			}
		 }	
		 wi.load();
		 wi.setState(WorkItem.State.Rejected);
		 //Setting the owner as Administrator if the owner.
		 String currentOwner = wi.getOwner()!=null?  wi.getOwner().getDisplayName():null;
		 Identity spadmin = context.getObjectByName(Identity.class,"spadmin");
		 wi.setOwner(spadmin);
		 wi.setCompletionComments("Approval workitem auto-rejected by SailPoint Administrator as no action was taken by " + currentOwner + " for more than " + threshold + " days");
	  }	
	  if(wi.getType().equals(WorkItem.Type.ManualAction))
	  {
		 // Auto Reject Individual Approval Items
		 ApprovalSet set = wi.getApprovalSet();
		 if (null != set)
		 {
			List appItems = set.getItems();
			if (null != appItems && appItems.size() > 0)
			{
			  for (ApprovalItem item : appItems) 
			  {
				 //item.reject();
				 //item.add(new Comment("Approval auto-rejected by SailPoint Administrator", "spadmin"));
				 item.setState(WorkItem.State.Rejected);
			  }
			}
		 }	
		 wi.load();
		 wi.setState(WorkItem.State.Finished);
		 //Setting the owner as Administrator if the owner.
		 String currentOwner = wi.getOwner()!=null?  wi.getOwner().getDisplayName():null;
		 Identity spadmin = context.getObjectByName(Identity.class,"spadmin");
		 wi.setOwner(spadmin);
		 wi.setCompletionComments("Approval workitem auto-rejected by SailPoint Administrator as no action was taken by " + currentOwner + " for more than " + threshold + " days");
	  }	
	  if(wi.getType().equals(WorkItem.Type.ViolationReview))
	  {
		 // Auto Reject Individual Approval Items
		 ApprovalSet set = wi.getApprovalSet();
		 if (null != set)
		 {
			List appItems = set.getItems();
			if (null != appItems && appItems.size() > 0)
			{
			  for (ApprovalItem item : appItems) 
			  {
				 //item.reject();
				 //item.add(new Comment("Approval auto-rejected by SailPoint Administrator", "spadmin"));
				 item.setState(WorkItem.State.Rejected);
			  }
			}
		 }	
		 wi.load();
			  Identity spadmin = context.getObjectByName(Identity.class,"spadmin");
			  String currentOwner = wi.getOwner()!=null?  wi.getOwner().getDisplayName():null;
			  wi.setState(WorkItem.State.Canceled);
			  wi.setCompletionComments("Policy Violation auto-cancelled by SailPoint Administrator as no action was taken by "+currentOwner);
	  }	

	  /*wflower.reject(wi);	
	  wfc = wi.getWorkflowCase();
	  String idntReqID = wi.getIdentityRequestId();
	  if(idntReqID==null)
	  {
		 Workflow wf = wfc.getWorkflow();
		 ProvisioningPlan plan = wf.get("plan");
		 Attributes atr = plan.getArguments();
		 idntReqID = atr.get("identityRequestId");
	  }
	  idntReqID = null;
	  if(idntReqID != null){
		 log.error("idntReqID: "+idntReqID);
		 IdentityRequest ir = null;
		 ir = context.getObjectByName(IdentityRequest.class, idntReqID);
		 String cm = "Test cancellation";
		 Message message=new Message(Message.Type.Warn,cm,null);
		 List requestComent=new ArrayList();
		 requestComent.add(message);
		 ir.setMessages(requestComent);
		 ir.setExecutionStatus(IdentityRequest.ExecutionStatus.Terminated);
		 ir.setCompletionStatus(IdentityRequest.CompletionStatus.Success);  
		 ir.setEndDate(new Date());		
		 context.saveObject(ir);
			  context.commitTransaction();				
	  }
	  wfc = null;
	  if(wfc!=null)
	  {
		 log.error("Workflowcase - "+wfc);
		 term.deleteObject(wfc);
	  }*/				
	}
 }
}

for (String wiId:wiList) //wiList has list of workitem ids in String format
{
 
 WorkItem wi = context.getObjectById(WorkItem.class, wiId); 
 log.error("Workitem: "+wi.getName());
 autocloseLogic(wi);    
}

return "Done workitem processing";

@Spoorthy_M1198 Try to process the workitem using workflower to move the workflow to next step once set required attributes like state, comment, etc..

Workflower.process(workItemObj, false);

ex:

wi.setCompletionComments(“comment if needed”);
wi.setCompleter(“username”);
wi.setState(WorkItem.State.Finished);
context.saveObject(wi);
Workflower wflower = new Workflower(context);
wflower.process(wi,false);
context.commitTransaction();

I’ve always run something like this to close it out:

Workflower wf = new Workflower(context); // Used to complete work items

WorkItem wi = context.getObjectByName(WorkItem.class, "00002315");

for (ApprovalItem item : wi.getApprovalSet().getItems()) {
  item.reject();
  item.setState(WorkItem.State.Rejected);
}

wi.addComment("Auto rejected by this rule");
wi.setState(WorkItem.State.Rejected);
wf.finish(wi)

context.commitTransaction();

@Spoorthy_M1198 Have you tried launching the PIRM task at the end of your rule? You can launch it as soon as you are done closing the workitems.

Note: Found a fix?Help the community by marking the comment as solution. Feel free to react(:heart:,:+1:, etc.)with an emoji to show your appreciation or message me directly if your problem requires a deeper dive.

@neel193 Its working on running a task after the rule execution. But we’re looking for alternative methods to handle it in the rule.

@sunny_tsang I’m doing something similar. The workitem is processing fine after execution of wf.finish(), but it’s not updating the access request.

@SivaprakashRNTBCI Will try this out, thanks

@Spoorthy_M1198 I meant running the task via code, not manually or scheduled. In that way you don’t need any additional customization to close the requests.

@neel193 Got it, Let me try it out. Thanks

1 Like

You can always add some code to close out the IdentityRequest object:

// Assuming you have WorkItem delcared as wi

// Close this out in the IdentityRequest
IdentityRequest ir = context.getObjectByName(IdentityRequest.class, wi.getIdentityRequestId());

if (ir != null) {
  ir.setCompletionStatus(IdentityRequest.CompletionStatus.Success);
  ir.setEndDate(new Date());
  ir.setExecutionStatus(IdentityRequest.ExecutionStatus.Completed);
  
  context.commitTransaction();
}

I don’t think so that could be the right approach, perform task is already a background task, which is scheduled in every organisation, and it takes lot of time to complete, depending on the environment configuration.

I would suggest @Spoorthy you to try updating it via code, you already have a rule, just add few lines of the code, as suggested by otherand you should be able to achieve your requirement

@naveenkumar3 Perform Identity Request Maintenance task is a scheduled task and runs independently. However in the usecases where we are handling the access request and work items via code (scheduled rule runner task) we can trigger the same PIRM task via code. No need to schedule the task separately.

Instead of scheduling PIRM directly, this rule runner could be a scheduled which can process the work item and then launch the PIRM task at the end of the rule. By doing this, it’ll process the requests whose workitems are closed via rule + it’ll process remaining access requests waiting for closures. We can avoid updating access request via code with this process.

Even you can execute PIRM multiple times a day or can have multiple versions by creating new task from the template: Identity Request Maintenance.

I understand, but he already has a workitem rule, and can directly write the code to complete the identityrequest directly , instead of calling the perform task. It all depends on what spoorthy wants to go ahead.

Thank you all for your valuable inputs. Using “workflower.process(workitem,false)” as suggested by @SivaprakashRNTBCI is working for me.