Action engine

Da itm wiki.

Action Engine Configuration

Action Engine enabled the user to configured an Action and the activation condition. An action is composed by:

  • General Information
  • Trigger and Activation condition
  • Parameters
  • Tasks to execute

General

The following images shown the action' user interface and provide some more detail about this functionality

Action Configuration

Parameters

TBC

Events Managed

Category / Class General Project Service Ticket
LDAP Events LDAP Message N/A N/A N/A
MB Scheduler Reporting distribution by mail

Resource on project association

Upload relations Resource-Projects

N/A N/A N/A
User Note Events User Note Created

User Note Updated

N/A N/A N/A
Internal System Events N/A Project Created

Project Updated

Service Created

Service Updated

Ticket Activity Created

Ticket Activity Updated

Ticket Created

Ticket Updated

Workflow Button

External System Events N/A N/A N/A Incoming Message
OCE Events N/A N/A N/A Trigger Value Reached
Company Events Process File Upload N/A N/A N/A
LDAP Message

This event is raised when MB sends an itmSUITE internal Message to PMSM with type "Ldap Synchronization".

Reporting distribution by mail

This is an External Event, it is raised when MB sends an itmSUITE internal Message to PMSM with type "Reporting distribution by Mail".

Resource on project association

This is an External Event, it is raised when MB sends an itmSUITE internal Message to PMSM with type "Resource on Project Associations".

Upload relations Resource-Projects

This is an External Event, it is raised when MB sends an itmSUITE internal Message to PMSM with type "Upload relations Resources-Projects".

User Note Created

This is an Internal Event: it is raised when a User Note is created on Ticket.

User Note Updated

This is an Internal Event: it is raised when a User Note is updated on Ticket.

Project Created

This is an Internal Event: it is raised when a Project is created.

Project Updated

This is an Internal Event: it is raised when a Project is updated.

Service Created

This is an Internal Event: it is raised when a Service is created.

Service Updated

This is an Internal Event: it is raised when a Service is updated.

Ticket Activity Created

This is an Internal Event: it is raised when a Ticket Activity is created.

Ticket Activity Updated

This is an Internal Event: it is raised when a Ticket Activity is updated.

Ticket Created

This is an Internal Event: it is raised when a Ticket is created.

Ticket Updated

This is an Internal Event: it is raised when a Ticket is updated.

Workflow Button

This is an Internal Event: it is raised when a Custom Field with type "Command button" on a Ticket is pressed.

Incoming Message

This is an External Event.

When the incoming message is validated by EEM, the informations are sent to MB (Message Bus) that dispatch it to the itmSUITE® Action engine and a configured Action is activated.

Trigger Value Reched

This is an Internal Event: it is raised when a OCE Objective reach a trigger.

VCE Condition

Condition'tab enable the user to define a Boolean condition that should be verify before activate the action' . Generally the conditions works on input Parameter.

Action Configuration

Task

Tasks tab enable the user to define one or more task that will be executed sequentially if the condition is valid. The system manage different type of task, the most flexible and powerful is Scripting task, based on Javascript framework, enable the user to call itmSUITE® primitive

Action Task Configuration

Basic Task

The following Task are predefined.

Create Ticket

Allows to create a new Ticket. In Tab Settings shall be selected the Service Request this Task will emulate. Fields "Project/Service" and "Ticket Type" will be used as filter to find the correct Service Request among the configured in SRCS.

Create Ticket Activity

Allows to create a new Ticket Activity. In Tab Parameters shall be mandatory set a collection of Tickets. The Ticket Activity will be created for all the Tickets in collection.

Execute Tickets Transition

Allows to move Ticket in another Workflow Status. In Tab Parameters shall be mandatory set a collection of Tickets. In Tab Settings shall be mandatory selected the Transition to be performed. The field "Ticket Type" will be used as filter to find the correct Transition. The Transition will be executed for all the Tickets in collection.

Find Tickets

Allows to find Tickets by filter. In Outcome Tab is possible to define an alias for the Tickets collection.

Find Ticket Activities

Allows to find Ticket Activities by filter. In Outcome Tab is possible to define an alias for the Ticket Activities collection.

Relate Tickets

Allows to relate a collection of Tickets to current Ticket. In Tab Parameters shall be mandatory set a collection of Tickets.

Usually this Task is used after Select Related Tickets or Select Tickets.

Select Related Tickets

Allows to select the collection of related Tickets from current Ticket. In Outcome Tab is possible to define an alias for the Tickets collection.

Select Related Ticket Activities

Allows to select the collection of related Ticket Activities from current Ticket. In Outcome Tab is possible to define an alias for the Ticket Activities collection.

Select Tickets

Allows to filter some Tickets from an input collection of Tickets. In Parameters Tab shall be mandatory set a collection of Tickets. In Conditions Tab set a condition to check if Tickets collection is not empty. In Outcome Tab is possible to define an alias for the Tickets collection.

Send Ticket Message

Allows to send a Ticket Message to some receivers.

Set Ticket Fields

Allows to insert/update values for Ticket fields. In Tab Settings shall be selected the Fields and inserted the values for them. Fields "Project/Service" and "Ticket Type" will be used as filter to find Fields available on corresponding WorkFlow.

Set Ticket Activity Fields

Allows to insert/update values for Ticket Activity fields.

Reporting distribution by mail

Allows to send a REP report result by mail to some receivers

Example: move related Tickets to another Status

In this example are listed the Tasks (and their configuration) required to perform following scenario:

  1. A "Change" Ticket (with eventually some related Tickets) is updated in "Completed" Status.
  2. Some of related Tickets could be "Incident".
  3. The "Incident" related Tickets (currently in Status "In Charge") shall be moved in "Completed" Status too.

Action Engine shall be configured as follow:

  • Add new Action with "Event Type" = Ticket Updated
  • In Action - Tab "Condition" add:
(Event.Data.ticketOpStatusName <> "Completed" AND Event.Ticket.ticketOpStatusName = "Completed")
  • In Tab Task add a new Task with Type "Select Related Tickets"
In Task Parameters Tab select Exent.Ticket in auto generated Parameter 
In Task Outcome Tab insert "Alias" = RelTickets in auto generated Parameter 
  • In Tab Task add a new Task with Type "Select Tickets"
In Task Parameters Tab select Task.id.RelatedTickets (or the Alias Action.RelTickets)
In Task Conditions Tab insert --> Task.id.RelatedTickets.size <> 0
(or the Alias Action.RelTickets.size <>0)
In Task Settings Tab insert --> Tickets.ticketType IN ("Incident") 
AND Tickets.ticketOpStatusName = "In Charge" 
In Task Outcome Tab (eventually) define an Alias for output Tickets collection
  • In Tab Task add a new Task with Type "Execute Tickets Transition"
In Task Parameters Tab select Task.id.SelectedTickets
In Task Conditions Tab insert --> Task.id.SelectedTickets.size <> 0
In Task Settings Tab select "Ticket Type" = Incident and the Transition "In Charge - Completed"

Scripting Task

Scripting Task in a JavaScript editor: it allows to use many methods to perform a large set of operations on itmSUITE entities (Ticket, Service, CI etc...)

Action Engine can also send information towards third parties software using scripting tasks. This can be performed:

  • Sending a preformatted mail
  • Calling a third parties web services
Action Task Configuration
Example: Update a Ticket Field

There are 3 way to update a Ticket Field

//1. Ticket Model Entity - time expensive and complete.
//Ticket Model refresh field values from DB at object instantiation and require a specific call to 
//update(....) to save field values.
//ticketService.update (model) method cascade/run following procedure:
//  - history: in Ticket Tab will be inserted new record(s)
//  - transition related logic: Check if transition is allowed, raise notification etc...
//  - new events: new Action Events will be evaluated
function main(event, incomeParameters)
{
var ticketId = 14543;
//STD Field "Short Description"
var ShortDescriptionId = 25;
var ticketService = taskRuntime.getService("TicketService");
var ticket = ticketService.findModelById(new java.lang.Integer(ticketId));
if (ticket == null)
{
taskRuntime.raiseError("ticket is null");
}
//single line
ticket.getCustomFieldValues().put(new java.lang.Integer(ShortDescriptionId), "single line");
//update ticket
ticketService.update(ticket);
}
function main(event, incomeParameters)
{
var ticketId = 14543;
//CF Text Single Line
var CfId = 1159;
var ticketService = taskRuntime.getService("TicketService");
var ticket = ticketService.findModelById(new java.lang.Integer(ticketId));
if (ticket == null)
{
taskRuntime.raiseError("ticket is null");
}
//single line
ticket.getCustomFieldValues().put(new java.lang.Integer(CfId), "single line");
//update ticket
ticketService.update(ticket);
}
//2. Ticket Entity
//Ticket works at hibernate level and is complex to be used for Custom Field.
//For Insert/Update events: an update of value for a STD field with Ticket entity requires a User 
//reload of Ticket to see the new value.
//For Event Button events: an update of value for a STD field doesn't require a User reload to see
//new value.
function main(event, incomeParameters)
{
var ticketId = 14543;
var ticketService = taskRuntime.getService("TicketService");
var ticket = ticketService.findEntityById(new java.lang.Integer(ticketId));
if (ticket == null)
{
taskRuntime.raiseError("ticket is null");
}
ticket.setShortDescription("single line");
}
//3. Ticket Meta Entity
//Ticket Meta wraps methods to manage both STD and Custom fields (standard way setValue(...) and
// getValue(...) methods). 
//Ticket Meta refresh field values from DB at object instantiation, doen't require a call to update
//(....) to save field values.

function main(event, incomeParameters)
{
var ticketId = 14543;
//STD Field "Short Description"
var ShortDescriptionId = 25;
var ticketService = taskRuntime.getService("TicketService");
var ticket = ticketService.findModelById(new java.lang.Integer(ticketId));
var ticket_ME = ticketService.getMetaEntity(ticket);
if (ticket_ME == null)
{
taskRuntime.raiseError("ticket is null");
}
//update ticket 
ticket_ME.setValue(new java.lang.Integer(ShortDescriptionId), "single line");
}
function main(event, incomeParameters)
{
var ticketId = 14543;
//CF Text Single Line
var CfId = 1159;
var ticketService = taskRuntime.getService("TicketService");
var ticket = ticketService.findModelById(new java.lang.Integer(ticketId));
var ticket_ME = ticketService.getMetaEntity(ticket);
if (ticket_ME == null)
{
taskRuntime.raiseError("ticket is null");
}
//update ticket 
ticket_ME.setValue(new java.lang.Integer(CfId), "single line");
}

Scripting Task Tutorial

Simple Event Handler

We need to define a function main, which accept two arguments:

* event
* incomeParameters
Empty Task Handler
/**
* @param event
* @param incomeParameters
*/
function main(event, incomeParameters)
{
}
incomeParameters usage
/**
* 1. print as warning event name and Task Income Parameters
* 2. accessing to income parameter by name
* @param event
* @param incomeParameters
*/
function main(event, incomeParameters)
{
var message = " event: " + event.getClass().getSimpleName();
var entries = incomeParameters.entrySet().toArray();
for each (var obj in entries)
{
message = message
+ "\n"
+ "key:" + obj.getKey() + "\n"
+ "value:" + (obj.getValue().getValue() != null ? obj.getValue().getValue() : "null");
}
//suppose we have parameter under "ticket" name
//lets retrieve it
var value = incomeParameters.getObjectValue("ticket");
message = message
+ "\n"
+ "ticket:" + value;
//lets retrieve type of incomeParameters.getObjectValue("ticket")
var type = incomeParameters.getParameterTypeModel("ticket");
message = message
+ "\n"
+ "ticket:" + type.getName();
taskRuntime.addWarning(message);
}
taskRuntime

taskRuntime Provide access to:

* securityContext
* entities and system services 
* system logger
* to user messages (warnings and errors messages)
/**
* print as warning resource full name and event name and dump the same 
* message as error and warning to system log
* @param event
* @param incomeParameters
*/
function main(event, incomeParameters)
{
var message = "user:" + taskRuntime.getSecurityContext().getResourceFullName()
+ " event: " + event.getClass().getSimpleName();
taskRuntime.addWarning(message);
taskRuntime.getLogger().error(message);
taskRuntime.getLogger().warn(message);
}
Services

SystemService - provide access to PMSM's email internal service

/**
* send an email to myEmail@host.com
* @param event
* @param incomeParameters
*/
function main(event, incomeParameters)
{
var systemService = taskRuntime.getService("SystemService");
var eventName = event.getClass().getSimpleName();
systemService.sendEmail("myEmail@host.com", "email send by scripting task:" + eventName, "TBD");
}

EntityFinderService - provide a set of finders for different entities

/**
* invoke EntityFinderService for all supported entities and print result as PMSM warnings
* @param event
* @param incomeParameters
*/
function main(event, incomeParameters)
{
invokeEntityFinderService("Area", "test");
invokeEntityFinderService("Functionality", "test");
invokeEntityFinderService("Product", "test");
invokeEntityFinderService("Project", "test");
invokeEntityFinderService("Resource", "test");
invokeEntityFinderService("ResolutionCause", "test");
invokeEntityFinderService("Service", "test");
invokeEntityFinderService("SolutionGroup", "test");
invokeEntityFinderService("TargetEnvironment", "test");
invokeEntityFinderService("TicketAdmStatus", "enumeration.ticketadminstatus.unbillable");
invokeEntityFinderService("TicketArea", "test");
invokeEntityFinderService("TicketCategory", "test");
invokeEntityFinderService("TicketImpact", "test");
invokeEntityFinderService("TicketTopic", "test");
invokeEntityFinderService("TicketUrgency", "test");
invokeEntityFinderService("TicketActivityStatus", "enumeration.ticketactivity.running");
}
function invokeEntityFinderService(entityName, name)
{
var service = taskRuntime.getService("EntityFinderService");
taskRuntime.addWarning("entityName:" + entityName+ " name:" + name+ " id:" + 
service.findIdByName entityName, name));
taskRuntime.addWarning("entityName:" + entityName + " name:" + name + " model:" +
service.findModelByName(entityName, name));
taskRuntime.addWarning("entityName:" + entityName + " name:" + name + " entity:" +
service.findEntityByName(entityName, name));
}

ResourceService - provide an extended finders for resource entity

var service = taskRuntime.getService("ResourceService");
/**
* Resource service example
* @param event
* @param incomeParameters
*/
function main(event, incomeParameters)
{
var id = service.findIdByFullName("test test");
var name;
if (id == null)
{
taskRuntime.addWarning("Resource not found");
}
taskRuntime.addWarning("Resource id:" + id + " found");
createResource("new resource");
// createResource("new resource"); the second attempt shall fail, due resource duplication with the 
// same login
}
function createResource(login)
{
var resource = new com.kv4.psm.core.domain.model.ResourceModel();
resource = service.prepareNew(resource).result;
resource.login = login;
resource.name = login;
resource.surname = login;
resource = service.create(resource).result;
taskRuntime.addWarning("Resource id:" + resource + " created");
}

TicketService - provide CRUD methods

Create:

/**
* create a new WF ticket
* @param event - any
* @param incomeParameters
*/
function main(event, incomeParameters)
{
var ticketService = taskRuntime.getService("TicketService");
//create an empty WfTicketModel
var ticket = new com.kv4.psm.core.domain.model.ticket.WFTicketModel();
//set required fields
ticket.setProjectId(579);
ticket.setTickettypeId(118);
//send to service to fill "default" values
ticket = ticketService.prepareNew(ticket).getResult();
//create an ticket
ticket = ticketService.create(ticket).getResult();
//report the ticket id to user as warning message
taskRuntime.addWarning("Ticket: " + ticket.getId() + " had been created");
}

Update:

importPackage(com.kv4.psm.core.domain.ticket);
/**
* Event:Ticket Updated
*
* update Ticket Priority to HIGH,
* we can't directly set Priority since its calculable field we can manage via Impact and Urgency 
* fields
* @param event
* @param incomeParameters
*/
function main(event, incomeParameters)
{
//ticket id
var ticketId = 14543;
//retrieve the EntityFinderService
var entityFinderService = taskRuntime.getService("EntityFinderService");
//retrieve ticket model
var ticket = taskRuntime.getService("TicketService").findModelById(ticketId);
if (ticket == null)
{
taskRuntime.raiseError("ticket is null");
}
var ticketImpactId = entityFinderService.findIdByName("TicketImpact", "1 - ALL users impacted on 1 or 
more VBF");
var ticketUrgencyId = entityFinderService.findIdByName("TicketUrgency", "1 - Service needed now AND 
WA NOT available");
if (ticketImpactId == null || ticketUrgencyId)
{
taskRuntime.raiseError("ticketUrgency or ticketImpact is null");
}
ticket.setTicketimpactId(ticketImpactId);
ticket.setTicketurgencyId(ticketUrgencyId);
//update ticket
taskRuntime.getService("TicketService").update(ticket);
taskRuntime.addWarning("Impact and Urgency had been updated by Action Engine");
}

Custom Fields

/**
* Ticket Custom Fields
*
* @param event
* @param incomeParameters
*/
function main(event, incomeParameters)
{
var ticketId = 14543;
var ticketService = taskRuntime.getService("TicketService");
var ticket = ticketService.findModelById(ticketId);
if (ticket == null)
{
taskRuntime.raiseError("ticket is null");
}
//simple/primitive types
//number type
//taskRuntime.addWarning(ticket.getCustomFieldValues().get(new java.lang.Integer(1168))); to read
need exactly define the Integer
ticket.getCustomFieldValues().put(new java.lang.Integer(1168), "2,0");
//date type
ticket.getCustomFieldValues().put(new java.lang.Integer(1163), "01-10-2012");
//datetime type
var dateTimeValue = new com.kv4.psm.core.domain.model.workflow.DateTimeValue();
dateTimeValue.setDateString("01-10-2012");
dateTimeValue.setTimeString("10:00");
// alternative way setup datetime its using java.util.Date, in this case the dateTimeValue will 
contains current system time
//var dateTimeValue = new com.kv4.psm.core.domain.model.workflow.DateTimeValue(new java.util.Date());
ticket.getCustomFieldValues().put(new java.lang.Integer(1165), dateTimeValue);
//time type
ticket.getCustomFieldValues().put(new java.lang.Integer(1164), "10:00");
//time text
//single line
ticket.getCustomFieldValues().put(new java.lang.Integer(1159), "single line");
//Multi Line
ticket.getCustomFieldValues().put(new java.lang.Integer(1160), "Multi Line\nsecond one");
//Rich Text
ticket.getCustomFieldValues().put(new java.lang.Integer(1161), "Multi Line
second one"); //check/radio/ boxes and Drop Down Tuple var ids = java.lang.reflect.Array.newInstance(java.lang.Integer, 2); //construct empty array with length 2 ids[0] = 196; ids[1] = 197; ticket.getCustomFieldValues().put(new java.lang.Integer(1162), ids); //Drop Down Plain ids = java.lang.reflect.Array.newInstance(java.lang.Integer, 1); //construct empty array with length 1 ids[0] = 196; ticket.getCustomFieldValues().put(new java.lang.Integer(1166), ids); //update ticket ticketService.update(ticket); }

Transition

/**
* Ticket Transition
*
* @param event
* @param incomeParameters
*/
function main(event, incomeParameters)
{
var ticketId = 14543;
var ticketService = taskRuntime.getService("TicketService");
var ticket = ticketService.findModelById(ticketId);
if (ticket == null)
{
taskRuntime.raiseError("ticket is null");
}
//lets suppose ticket in "Opened" and need to transition into "In charge"
var transitionRuleModel = ticketService.findTransitionRuleModelByName(ticket, "Take incident in 
charge");
if (ticket == null)
{
taskRuntime.raiseError("can't find transition \"Take incident in charge\"");
}
ticketService.transition(ticket, transitionRuleModel);
}