cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Scheduling a workflow to run in the future from BeanShell/rule code

Scheduling a workflow to run in the future from BeanShell/rule code

One strategy for carrying out actions like LDAP account re-names or other account provisioning actions that depend on prerequisite data is to have IdentityIQ schedule the action to be carried out in a workflow at a future date.  This is called "scheduling a workflow event".  Under the hood  what happens is a new Request object is created and committed to the database.  The Request object is of type "Workflow Request", and it carries all of the arguments required to launch the workflow at a future date.  Every five seconds the request processor polls the database for new requests that need to be processed.  When the "eventDate" of the workflow matches or is behind the current time the request processor will launch the workflow and carry out whatever logic it contains.  When the workflow is launched it is is launched in a clean context that is separate from the thread that scheduled the workflow event.

Attached are two example artifacts: an example "hello world" workflow that simply logs the arguments passed to it and stops and the rule that demonstrates how to configure a workflow to be launched at a future date.  You can import both of these artifacts into your environment and then run the rule from either the debug page or the console.  Five seconds after the rule is executed the request scheduler will launch the workflow.  You should see the workflow logs printed in your Identity IQ logs under your application server.

The following illustrates the boilerplate code required to schedule the future launch a Workflow from any block of BeanShell or Rule code.  The import statements required are provided in the attached example files.  The strings in the example below are designed to be easily edited in the field so you can modify them to substitute in your own variables.

 

 

// This rule demonstrates launching a workflow using the Request Scheduler

// features of IdentityIQ 6.2+.  This places a Request in the queue to launch

// the specified workflow with the specified arguments.  This feature allows

// architects to schedule events to immediately follow Identity refresh

// operations.  This takes processing out of Identity refresh tasks and allows

// for more use of the parallelism features in the request processor.



String workflowName = "Hello World Example";

String identityName = "john.doe";

String argumentVal  = "CN=john.doe,DC=corp,DC=acme,DC=com";

String caseName     = "Run '" + workflowName + "' for: " + identityName;

String requesterId  = "spadmin";



Workflow eventWorkflow = context.getObject(Workflow.class, workflowName);

if (null == eventWorkflow) {

   log.error("Could not find a workflow named: " + workflowName);

   throw new GeneralException("Invalid worklfow: " + workflowName);

}



// Simulate the request being submitted by a user. Default: spadmin.

Identity id = context.getObjectByName(Identity.class, requesterId);

if (null == id) {

   log.error("Could not find a requester Identity: " + requesterId);

   throw new GeneralException("Invalid identity: " + requesterId);

}



// Ask the Request Processor to start the workflow 5 seconds from now.

// Append the time stamp to the workflow case name to ensure it's unique.

long launchTime = System.currentTimeMillis() + 5000;

caseName = caseName + "(" + launchTime + ")";



// Build out a map of arguments to pass to the Request Scheduler.

Attributes reqArgs = new Attributes();

reqArgs.put(StandardWorkflowHandler.ARG_REQUEST_DEFINITION,

            sailpoint.request.WorkflowRequestExecutor.DEFINITION_NAME);

reqArgs.put(sailpoint.workflow.StandardWorkflowHandler.ARG_WORKFLOW,

            workflowName);

reqArgs.put(sailpoint.workflow.StandardWorkflowHandler.ARG_REQUEST_NAME,

            caseName);

reqArgs.put( "requestName", caseName );          



// Build a map of arguments to pass to the Workflow case when it launches.

Attributes wfArgs = new Attributes();

wfArgs.put("identityName",    identityName);

wfArgs.put("exampleArgument", argumentVal);

wfArgs.put("workflow",        eventWorkflow.getId());



reqArgs.putAll(wfArgs);



// Use the Request Launcher to schedule the workflow reqeust.  This requires

// a Request object to store the properties of the request item.

Request req = new Request();

RequestDefinition reqdef = context.getObject(RequestDefinition.class, "Workflow Request");

req.setDefinition(reqdef);

req.setEventDate( new Date( launchTime ) );

req.setOwner(id);

req.setName(caseName);

req.setAttributes( reqdef, reqArgs );



// Schedule the work flow via the request manager.

RequestManager.addRequest(context, req);

 

 

 

Please see the attached example files for more details.  When run from the console the rule produces no output unless there is an exception during execution.

 

In the log file for the application server you an see the following messages from the workflow when it gets launched:

 

 

Starting workflow Hello World Example

Variable initialized with launch input: identityName

--> john.doe

Variable initialized with launch input: exampleArgument

--> CN=john.doe,DC=corp,DC=acme,DC=com

Initial case variables:

<?xml version='1.0' encoding='UTF-8'?>

<!DOCTYPE Attributes PUBLIC "sailpoint.dtd" "sailpoint.dtd">

<Attributes>

  <Map>

    <entry key="exampleArgument" value="CN=john.doe,DC=corp,DC=acme,DC=com"/>

    <entry key="identityName" value="john.doe"/>

    <entry key="launcher" value="RequestHandler"/>

    <entry key="maxThreads" value="12"/>

    <entry key="requestDefinition" value="Workflow Request"/>

    <entry key="requestName" value="Run &apos;Hello World Example&apos; for: john.doe(1412087864210)"/>

    <entry key="sessionOwner" value="RequestHandler"/>

    <entry key="trace" value="true"/>

    <entry key="transient" value="false"/>

  </Map>

</Attributes>



Starting step Start

Ending step Start

Starting step Middle

2014-09-30 09:37:45,685 DEBUG Thread-8 services.workflow.helloWorld.example:? - Hello World! id:john.doe arg:CN=john.doe,DC=corp,DC=acme,DC=com

Ending step Middle

Starting step End

Ending step End

Ending workflow Hello World Example

 

 

 

Starting in IdentityIQ releases 6.4 and newer, this feature can be exploited to ensure that specific workflow code runs on a specific application server.  This mechanism bypasses the concept of "restricted" request processors that was introduced in these versions of IdentityIQ.  Request objects can be targeted to a specific Request Scheduler host by specifying the case-sensitive host name of the application server host to run the request on.   An example of that API looks like the following:

 

 

Request req = new Request();

// ....

// Specify the request get handled by a specific target host.

req.setHost("iiq-ui-server-01.acme.com");

// ...

// continue submitting the request as shown in the example above.

 

 

Labels (2)
Attachments
Comments
Sally_Newton

And in pre 6.2 installs make sure you tune the requestProcessorPoolSize setting in the SystemConfiguration object to match your requirements.   In 6.2 and newer versions use the RequestDefinition objects to tune the number of threads.

Hi,

Attempted this in 6.4 and I am successful in launching new workflow as long as there is no approval step.  However, when I attempt to do so with a workflow that has an approval step I receive the following error when it gets to that step:

2015-09-18 10:55:04,574 ERROR Thread-6 sailpoint.api.Workflower:4407 - An unexpected error occurred: Unknown object: RequestHandler

If I trigger the same workflow from a quick link it runs without error.

Any thoughts?

Thanks,

Scott Ditzenberger

Scott D, got any more of the stack trace you can share there?

Here's my hunch:  The RequestHandler is not a serialize-able java object.  Every object that ends up in the Workflow's variables set must be serialize-able in the Java API sense (see BSDG 16 - Workflow Step Bean Shell Best Practices for details).  That's why you can't reference all object types and few sailpoint.object.* type objects in workflow variables without inviting trouble.  Does your "wfArgs" map include a reference to a RequestHandler instance?

A RequestHandler is an extension of Java's Thread class that processes request objects that have been submitted to the queue in the back-end database.  Can you turn on trace on sailpoint.api.Workflower or show us more of the stack trace to tell us which workflow step is unable to find/reference the RequestHandler?

--Adam

Hi Adam,

Attaching more of trace.  Tracing Workflower next. 

To be random I created an Identity object and named it 'RequestHandler'.  This resolved the error.  heh.

The work item generated has the RequesterHandler defined as the Owner and Requester.  Looking deeper into work item arguments soon.

2Ex015-09-18 10:55:04,574 ERROR Thread-6 sailpoint.api.Workflower:4407 - An unexpected error occurred: Unknown object: RequestHandler

sailpoint.tools.GeneralException: Unknown object: RequestHandler

  at sailpoint.api.ObjectUtil.getObjects(ObjectUtil.java:929)

  at sailpoint.api.ObjectUtil.getObjects(ObjectUtil.java:825)

  at sailpoint.api.ObjectUtil.getObjects(ObjectUtil.java:812)

  at sailpoint.api.ObjectUtil.getObjects(ObjectUtil.java:959)

  at sailpoint.api.Workflower.expandApprovalScriptResult(Workflower.java:6359)

  at sailpoint.api.Workflower.expandApproval(Workflower.java:6275)

  at sailpoint.api.Workflower.start(Workflower.java:6150)

  at sailpoint.api.Workflower.advanceApproval(Workflower.java:5935)

  at sailpoint.api.Workflower.advanceStep(Workflower.java:4914)

  at sailpoint.api.Workflower.advance(Workflower.java:4373)

  at sailpoint.api.Workflower.startCase(Workflower.java:2975)

  at sailpoint.api.Workflower.launchInner(Workflower.java:2644)

  at sailpoint.api.Workflower.launch(Workflower.java:2517)

  at sailpoint.api.Workflower.launch(Workflower.java:2281)

  at sailpoint.request.WorkflowRequestExecutor.execute(WorkflowRequestecutor.java:147)

  at sailpoint.request.RequestHandler.run(RequestHandler.java:143)

Hi Experts,

How to schedule a workflow that runs daily(every 24 hours) from today ?

Thanks

Shashank H.

Hi shashank.hule ,

How is your workflow triggered? If it is from

Task - Schedule that task.

Rule - Then add that rule to Run Rule task and schedule it.

- Jagadeep

How to invoke a workflow from task and schedule it ?

Use this example to create a Task that is scheduled every day.  That task runs a Rule and that Rule uses the code example above to launch the workflow:

--Adam

Excellent, that's what I need. Is there a way I can return a value ( or a list of values ) from the workflow to my rule once the launched workflow is finished ( completed all steps ) ?

This is brilliant. Thanks for sharing.

Version history
Revision #:
3 of 3
Last update:
‎Jul 25, 2023 06:18 PM
Updated by: