Skip to main content

Workflow scripting

Scripts are used to perform automatic actions and fine-tune the behavior of the workflow. There are two basic types of scripts:

  • Visibility scripts are executed to control the availability of the activity.
  • Regular scripts are executed when a certain action is performed or event takes place.

In addition, some elements and adornments have scripts with special purposes, as for example the decision script which determines the exit which a case takes when running through a decision node.

There are two ways of managing scripts:

  • Using embedded scripts: Embedded scripts are provided directly in the workflow editor, i.e., you open the script editor for the desired element, type the script content and save the script.
  • Using scripts of the type Workflow*: Workflow scripts are saved on the Scripts page of the Web Admin Suite, see Scripts of the type Workflow. They can be referenced in an embedded script, i.e., you create an embedded script which executes a workflow script:
    scriptExecutionService.execute("myscript.groovy")

The following table shows a comparison between both modes:

ModeDescriptionAdvantagesDisadvantages
Embedded scriptThe complete script content is provided in the workflow editor.
  • The whole process logic is stored in one place and can be checked in the workflow editor.
  • You can use workflowApi methods with all implicitly available objects.
  • You can benefit from strict versioning, as a workflow version contains all the related changes.
  • If the same logic is needed in several workflow elements, you need to duplicate the related code.
  • You need to activate the development mode for changes to become effective immediately.
Workflow scriptThe script is saved as a script of the type Workflow on the Scripts page. The embedded script references this workflow script.
  • The same script can be used in different places of the workflow.
  • Changes to the script become effective immediately, regardless of the selected deployment mode.
  • You need to check a second script to know the workflow logic.
  • Objects which are implicitly available in embedded scripts need to be passed as parameters to the script.
  • You need to do a scene export with both workflows and scripts to put a new workflow version into production.

Scripts are written in Groovy. Since Groovy code runs in the Java Virtual Machine, you can also write Java code. Groovy code allows you to use dynamic typing, and to omit getter and setter methods, thus providing a shorter syntax. The following table shows some examples of the differences between Groovy and Java:

GoalGroovyJava
Retrieve the subject of a casedef mysubject = ticket.subjectString mysubject = ticket.getSubject();
Retrieve the main contact of a casedef mymaincontact = ticket.mainContactUnit mymaincontact = ticket.getMainContact();
Retrieve the value of a certain case field from a casedef myprio = ticket.get("helpdesk_fields.prio")String myprio = ticket.get("helpdesk_fields", "prio");
Set the subject of a caseticket.subject = "asd"ticket.setSubject("asd");

ConSol CM API methods

The ConSol CM API provides various convenience interfaces and methods which make access to the most commonly used objects easy. Most of these convenience interfaces are part of the package com.consol.cmas.common.service and its sub-packages.

The implementing instance of the interface is always available by replacing the first letter, which is a capital letter, in the class name by a lower case one, e.g., use engineerService to call methods of the interface EngineerService. The only exception to this rule is the class WorkflowContextService whose object workflowApi provides many useful methods.

ConSol CM API documentation

Please refer to the ConSol CM API documentation for details about the available classes and methods.

Features of the script editor

The script editor has the following features:

  • Text highlighting: You can double-click a word or mark some text to highlight all its occurrences within the script.

  • Syntax highlighting: The editor uses syntax highlighting for Groovy.

  • Code autocompletion: As soon as you type a dot, the methods for the current object are suggested. You can continue typing to narrow down the results. Only methods for explicitly declared variables are displayed.

    tip

    You can press CTRL + SPACE to display suggestions for service classes.

    If you call a script inside your script by using code like def utilityScript = scriptExecutionService.execute("utilityScript") or def utilityScript = workflowApi.runScript("utilityScript"), the public methods defined on the top level of the utility script are suggested when typing utilityScript followed by a dot. The utility script must include the statement return this.

  • Code validation: The code validation results are displayed when hovering the line with the error. There are three modes:

    • No validation: The code validation feature is turned off.
    • Simple validation: A simple code validation is performed.
    • Strict validation: A more detailed code validation, which also checks if the invoked methods exist for the objects, is performed.
  • Method and variable list: You can click the Show navigator icon to open a panel on the right which contains a list of the methods and global variables defined in the main scope of the script. Click a method or variable to jump to its definition in the script.

  • Referenced scripts: Scripts which are called from a script are underlined. You can click the script name to open it.

  • Code snippets: You can insert code snippets into your scripts by selecting the >> Insert code snippet option from the autocomplete suggestions, by clicking the Insert code snippet button in the toolbar, or by using the keyboard shortcut CTRL + J. The following snippets are available:

    • Script generators: generate and insert code for email or search scripts based on selections made in a modal window
    • Data fields: get and set values of case, contact and resource fields, get the technical and localized value of enum fields, iterate over list fields, add rows to list fields
    • Labels: insert a label with or without locale
    • Queues: insert a queue
    • Scripts: execute a script
    • System properties: insert a system property
    • Templates: insert a template with or without locale

    The Code snippets window includes a search field to search for the desired piece of code, e.g., search for a contact field to display the available snippets. You can apply additional filters by entering the type of object followed by a colon in the search field:

    • label: searches for labels
    • property: search for system properties
    • queue: searches for queues
    • resource: searches for resource fields
    • script: searches for scripts
    • template: searches for templates
    • ticket: searches for case fields
    • unit: searches for contact fields
  • Wrap text: Toggle between wrapping text, when a line of text exceeds the available space, and displaying a scrollbar.

  • Keyboard shortcuts: There are keyboard shortcuts for common operations. Examples:

    • Save: CTRL + S
    • Undo: CTRL + Z
    • Find: CTRL + F
    • Insert code snippet: CTRL + J
    • Autocompletion: CTRL + space
    • Jump to line: CTRL + L
    • Jump to the referenced script: CTRL + click
    • Open a preview of the referenced script: CTRL + ALT + click
    • Open a preview o the script template: ALT + T
    • Format code: ALT + F

Scripting examples

The following sections contain short descriptions of the most important aspects of scripting. Larger topics are covered in sub-pages:

Referencing workflow elements

Workflow elements are always referenced by their path. The path reflects the hierarchical structure of the workflow. It starts with defaultScope and contains the technical names of the scopes where the element is located and the technical name of the element.

Example: Activity information_received in the sub-scope on_hold of the scope work_in_progress:

defaultScope/work_in_progress/on_hold/information_received

You can copy the path using the Copy button in the details panel of the respective element.

Working with data fields

Data fields are always referenced by their technical names using the following pattern:

<ticket|unit|resource>.<get|set|add|remove>("<technical name of the field group>.<technical name of the field>")

The content of a data field depends on the data type, it can be either a value or an object.

Please see Using data fields in scripts for details about the available methods for different objects and field types.

Using data fields for variables

Sometimes you need variables which are required for workflow programming but should not be visible on the GUI of the Web Client and CM/Track. Depending on the object for which they are needed, you can use case, contact or resource fields for these variables.

  1. Create a data field with the required data type.
  2. Set Visibility to Never to hide the field from the GUI.

Working with user data

When working with user data, you need to distinguish between the current user, i.e., the user who is logged in and performs the action which leads to the execution of the script, and the assignee of a case.

  • Retrieve the current user:
    workflowApi.getCurrentEngineer()
    engineerService.getCurrent()
  • Retrieve the assignee of the current case:
    ticket.getEngineer()
  • Assign the current case to the current user:
    ticket.engineer = engineerService.current
  • Retrieve the users which have a certain role:
    engineerRoleRelationService.getEngineersWithRoles(roleService.getByName("Supervisor"))
  • Retrieve the roles of the current user:
    engineerRoleRelationService.getRolesForEngineer(engineerService.current)

Displaying messages

Messages are useful to provide dynamic information to the user regarding the process or the entered data. They can be displayed in a red box below the menu bar or next to a case field in an activity form. If the message should be localized, it is recommended to use labels, see Labels.

  • Display a localized message in a red box. The message text is based on the label defined for the locale of the current user.
    workflowApi.addValidationError("INFO", messageProviderService.getMessage("label key", engineerService.currentLocale))
  • Display a simple message next to a case field.
    workflowApi.addValidationError(ticket.getField("field group", "field"), "Message text")

Working with overlays

Overlays stay on the case icon according to the selected overlay range. You can remove an overlay by script using the following piece of code:

def si = ticket.scopeInfo
for (ov in si.getActivatedOverlays().toArray() ) {
if (ov.parent.name == "defaultScope/ServiceDeskTicketInProgressScope/Email_received") {
si.removeOverlay(ov)
}
}

The overlay is identified by the path of the activity where it was attached.

Working with system properties

You can use methods of the class ConfigurationService to retrieve the value of system properties.

configurationService.getValue("module name","property name")

Working with text classes

You can retrieve and set text classes for case history entries.

  • Retrieve the text class of a history entry:
    ContentEntry.getContentEntryClass()
  • Modify the text class of a history entry:
    ticketContentService.updateContentEntryClass(ContentEntry pContentEntry, ContentEntryClass pContentEntryClass)

Working with attachments

You can add and retrieve attachments with the following methods:

  • Retrieve all attachments:
    workflowApi.getAttachmentList()
  • Retrieve attachments from incoming emails:
    ticketContentService.getAttachmentEntries(ticket, ContentEntryCategory.INCOMING_MAIL)
  • Retrieve attachments from outgoing emails:
    ticketContentService.getAttachmentEntries(ticket, ContentEntryCategory.OUTGOING_MAIL)
  • Add an attachment:
      def filePath = "/home/hotline/fileToAdd.xml"
    def file = new File(filePath)
    def stream = new ByteArrayInputStream(file.readBytes() );
    def content = new ContentFile("newFileName.xml", "application/xml", stream, file.length());
    def attachment = new AttachmentEntry();
    attachment.setMimeType ("application/xml")
    attachment.setFile(content)

    // in workflow context
    workflowApi.addAttachment(attachment);

    // in non-workflow context
    ticketContentService.createContentEntry(ticket, attachment)

Modifying the visibility of data field groups

You can control the display of data field groups with the setting Visible. A common use case is to hide field groups initially by setting false, implement activity forms where the data is filled in, and show the field groups on the GUI afterwards. This helps to keep the case data concise by displaying certain fields only when they are needed in the process.

The following methods can be used for controlling the visibility of case field groups:

  • Show a case field group:
    workflowApi.setGroupProperty("ticket field group",GroupPropertyType.VISIBLE,"true")
  • Hide a case field group:
    workflowApi.setGroupProperty("ticket field group",GroupPropertyType.VISIBLE,"false")
  • Show a contact field group:
    def fieldGroupDefinition = fieldDefinitionService.getGroupByName("field group")
    unit.getGroupsConfiguration().setProperty(fieldGroupDefinition, GroupPropertyType.VISIBLE, "true")
  • Show a resource field group:
    def fieldGroupDefinition = fieldDefinitionService.getGroupByName("field group")
    resource.getGroupsConfiguration().setProperty(fieldGroupDefinition, GroupPropertyType.VISIBLE, "true")

Searching for objects

You can search for cases, contacts and resources using criteria objects.

  • Search for cases:
    ticketService.getByCriteria(TicketCriteria pTicketCriteria)
  • Search for contacts:
    unit.Service.getByCriteria(UnitCriteria pUnitCriteria)
  • Search for resources:
    resourceService.getByCriteria(ResourceCriteria pResourceCriteria)

The criteria object is configured by using the provided methods to add one or several criteria. If you use a data field as a search criterion, the respective data field must be indexed.

Memory consumption

The search methods return the complete objects, so they can consume a lot of memory if you perform a search. If you only need the number of objects matching certain criteria, you can use the methods getCountByCriteria() of the same classes instead. Use the methods getIdsByCriteria() to retrieve only the IDs of the matching objects.

Considering case update events

Certain methods cause so called update events (class TicketUpdateEvent). These events can decrease the system performance. Therefore, they should be avoided as long as they are not necessary for the business process.

Example: Assigning a user to a case

  • workflowApi.assignEngineer(workflowApi.currentEngineer) throws an update event.
  • ticket.setEngineer(workflowApi.currentEngineer) does not throw an update event.

In addition, update events occur after a workflow element is executed. If there is a chain of elements, you should avoid triggering an update event after every single element. Select the Skip update event checkbox for all elements except for the last one to update the case only once, after the last workflow element.

Adding log output

You can add log output to your scripts by using the following syntax:

log.info "This is my debug message."

You can log messages at other log levels by using log.debug, log.warn, or log.error. The log messages are written to the server.log file.

See Log files for details about the available log files and their configuration.

Modifying the execution flow

You can treat a trigger execution with automatic activities as an exception instead of an interrupt by using the method skipInterruptRestore() of the class ScopeInfo. This method can be used only in automatic activities connected to triggers. If you add it to the script of such an activity, the case does not return to the original activity where it was located before the trigger fired, but stays in the flow of the activity where this method is called.

This allows for example to implement workflows where the case is moved to a waiting scope by a trigger and remains there until another trigger fires.