Go to primary content
Agile Product Lifecycle Management Administrator Guide
Release 9.3.6
E71145-01
  Go To Table Of Contents
Contents

Previous
Previous
 
Next
Next
 

30 Scripting and Sample Event Subscriptions

This chapter provides an introduction to the Scripting capability, which permits scripted instructions of any length and complexity in Event Handlers.

30.1 Overview to Scripting in Agile PLM

The scripting capability is fully embedded in the Event Management framework, with a server-side scripting engine that runs inside the PLM server (Agile Application Server). The script code is stored in a Large Character field in the database. You have access to the Script APIs and the Agile SDK, so you can write SDK programs.

The use of the Agile SDK is a key aspect to exploiting the potential of automated Events. The SDK programmer will find technical information about PLM Events in the Agile PLM SDK Developer's Guide.

The sample Event Subscriptions later in this chapter are models for the administrator's understanding of configured Event Subscriptions; they can help a non-programming administrator become familiar with scripting in Groovy (however, the samples are not specific "tutorials" in script-writing). While it is not necessary that the Agile-system administrator be able to write scripts for Handlers, if you do have the assistance of a programmer, you must be able to describe to that person what you want to achieve with the Event Management framework in Agile PLM.

The source code should be available in the production system at runtime, so script code is delivered in plain text, not in object code.

Figure 30-1 Scripting in Agile PLM

Scripting in Agile PLM

30.2 Using Groovy Scripting Language

To contribute to Script PX Handler masks, the script-writer must know how to write scripts in Groovy, how to use the Script API, and how to use Agile Java SDK.

Ideally, the contributing programmer must understand the basics of Event Subscriptions and Handler masks. (A programmer who has not read the previous chapter, "Event Management", should start with "Handler Types." and "Working in Event Handlers Node").

A scripting language is an excellent means to write user-readable and user-modifiable programs that perform simple operations and control the execution of other programs.

Groovy is a dynamic language for the Java platform. Its many features are inspired by languages such as Python, Ruby, and Smalltalk, making them available to Java developers using a Java-like syntax. With Groovy's simplified syntax, your code becomes easy to read and maintain.

These and other factors led to the selection of Groovy as the supported scripting language for the Agile PLM Event Management framework. Groovy is the only scripting language that is supported in Agile PLM 9.3.x.

There are many resources for learning Groovy, both in print and electronic media.

30.2.1 Choosing Script-based Handlers

Scripts are normally dynamically typed (type checked at runtime) instead of statically typed (type checked while compiling). You should use or specify Script-based Handlers over Java-based Handlers in these cases:

  • whenever there is a premium on user- (that is, administrator)-readable programs,

  • cases where the business logic will need to be updated without explicit compiling or deploying,

  • and especially for rapid prototyping of business logic; once validated, you may want to convert a Script PX to Java PX for better performance.

30.2.2 Steps to Develop or Update Handler Masks

The steps that are needed to develop or update Handler masks is another factor to consider.

To develop a Script PX Handler Mask:

  1. Define requirements (see Checklists below).

  2. Write Groovy script.

  3. Associate completed Script PX Handler mask into an Event Subscription.

  4. Test the Handler.

To develop a Java PX Handler Mask:

  1. Define requirements (see Checklists below).

  2. Write Java code.

  3. Compile code and test PX.

  4. Deploy PX on Agile Application Server.

  5. Associate completed Java PX Handler mask into an Event Subscription.

To update a Script PX Handler Mask:

  1. Revise the Groovy script.

To update a Java PX Handler Mask:

  1. Update the Java process extension.

  2. Compile code and test PX.

  3. Deploy revised PX on Agile Application Server.

30.2.3 Editing Scripts in the Handler Mask

A Handler mask based on the Script PX handler type is an effective script editor.

On the General Information tab of a Handler mask, you can copy-and-paste your script for direct editing in Administrator.

Some editing features are available, particularly the Validate Script button, which performs a syntax check of script code, such as proper syntax with parentheses, "Equal" signs, and simple text errors.

The Where Used tab shows all Subscriber masks that use this script-based Handler mask.

The History tab displays the editing history of the script, such as its creation and instances of modification.

30.3 Logging of Scripts

There are several different types of logging of scripts, which are activated and logged differently.

  • Systems Logging

    • The systemwide Preference "Agile Script Log Level" controls the amount of information that is written to the Script PX log.

  • Object-related Scripts

    • Explicit logs are written into server-side LOG4J trace files.

    • There is one log file for each PLM user. The log file name resembles: <userID>_agileScript.Log.

    • Runtime error messages give information to the administrator.

    • Object-related script execution is logged in the object's History tab.

  • Event Handler Monitor

    • The Event Handler Monitor provides information about handlers being run. See "Event Handler Monitor."

    • The systemwide Preference "Event Monitor Log Level" controls the level of script logs to the Handler Monitor.

30.4 Checklist for Specifying Script-based Event Subscriptions

In the "Event Management" chapter, checklist questions were listed in the sections about creating Event masks, Handler masks, and Subscriber masks. Some of these questions are collected below for your use in describing desired Script PX handlers.

  • Event Mask:

    • From a given Event being triggered, what is the result that you want to automatically happen?

    • Will the Handler mask apply to a single subclass? Will the Handler apply to multiple subclasses from a single class, but not all of its subclasses?

    • If the event involves a Change, which Workflow(s) does it apply to? Does it apply to all workflows or a specific workflow?

    • Are there any Event Type-specific parameters to consider? For example, for the event type Delete Object Action, is the Handler mask going to handle soft deletes or hard deletes?

  • Handler Mask:

    • What broad outcome does the Handler need to accomplish? What kind of instructions must the system have to complete a successful automation?

    • If the Handler is to be a process extension, what is the proper handler type for this Handler mask?

    • Who is providing the Java code, SDK or Groovy script that will drive this Handler mask?

    • What Roles are needed to run the handler mask? Will the user performing the PLM action always have the right Roles?

  • Subscriber Mask:

    • What Handler mask is being named in this Subscriber mask? What Handler do you want invoked when the Event of interest is triggered?

    • Which Trigger Type should be used, Pre or Post? Why do you want the Handler to invoke Pre or Post?

    • Which Execution Mode should be used, Asynchronous or Synchronous?

    • What is the Order in which the Handler mask should be invoked?

    • What Error Handling Rule should be used?

30.5 Sample Event Subscriptions with Scripts

The following sample Event Subscriptions provide models of the various masks in several use cases. They demonstrate how a Groovy script drives certain Subscription outcomes.

Event Management has been deployed as a working "ready-to-use" feature, but It is not assumed that the PLM administrator knows or must learn how to write scripts in Groovy. There is more technical documentation, including samples, about Agile Events and Scripting in Agile PLM SDK Developer's Guide. The full potential of Events can be realized with the assistance of a programmer working with that manual.


Note:

The solution-based PLM user guides may contain information about how the solution can be enhanced by the Event framework. This would be in the administrator configuration chapter or appendix (for example, in the PG&C and PCM user guides).

These sample events and Groovy scripts have been tested, but they are not guaranteed to work "verbatim" in any customer system without scrutiny and modifications.

30.5.1 Update Item Description

In this case, when a user updates the Title Block of any business object from one of all the Items base-class (grandchild) subclasses, the item's Description field is updated. This can be done with the primary business objects of any of the PLM solutions, for instance, auto-updating the Content objects of a Project in PPM.

In this sample, the action that triggers this Event Subscription is when a user updates the Title Block of a part. If Description is set with, say, "Testing", and the user modifies Text07 to "SOA" and Text08 to "Project" and Saves, this Event Subscription replaces the existing Description value with "Testing SOA Project". The Handler's execution status can be verified from the Handler Monitor.

30.5.1.1 Event mask: [Update Title Block Items]

  • Event Type: Update Title Block

  • Object Type: Items

30.5.1.2 Handler mask: [Update Item Description]

  • Handler Type: Script PX

  • Script:

import com.agile.agileDSL.ScriptObj.IBaseScriptObj
// add other import statements here
import com.agile.api.ItemConstants
 
void invokeScript(IBaseScriptObj obj) {
   //script body starts here.
 
   // get old item description value
   oldItemDescription = obj.getValueByAttId(ItemConstants.ATT_TITLE_BLOCK_DESCRIPTION);
 
   // get the first field from pageTwo field1 =    obj.getValueByAttId(ItemConstants.ATT_PAGE_TWO_TEXT07);
 
   // get the second field from pageTwo field2 =    obj.getValueByAttId(ItemConstants.ATT_PAGE_TWO_TEXT08);
 
   // set the new description
   obj.setValueByAttId(ItemConstants.ATT_TITLE_BLOCK_DESCRIPTION, oldItemDescription + " " + field1 + " " + field2);
 
   // get the new description
   newItemDescription = obj.getValueByAttId(ItemConstants.ATT_TITLE_BLOCK_DESCRIPTION);
 
   // log to Event Handler Monitor
obj.logMonitor( "Old description: " + oldItemDescription + "| " + "New    description: " + newItemDescription);
}
 

30.5.1.3 Subscriber mask: [Update Title Block Items Update Item Description]

  • Event: [Update Title Block Items]

  • Event Handler: [Update Item Description]

  • Trigger Type: Post

  • Execution Mode: Synchronous

  • Order: 0

  • Error Handling Rule: Continue

30.5.2 Notify Create User when Item is Incorporated

In this case, when an item—an instance of any subclass in the Parts or Documents classes, and therefore of the Items base class—is incorporated, a notification is created and sent to the user who created that part or document.

More specifically, the action that triggers this Event Subscription is a user creates a part, and from the Actions menu selects Incorporate.

The item changes to Incorporated, and a notification is sent to the part's creator. The Handler's execution status can be verified from the Handler Monitor.

Note that this notification is generated by instructions from a script (a Script PX handler), rather than a Notification mask created by the administrator (as in last example in this set).

30.5.2.1 Event mask: [Incorporate Item]

  • Event Type: Incorporate Item

  • Object Type: Items

30.5.2.2 Handler mask: [Incorporated Item]

  • Handler Type: Script PX

  • Script:

import com.agile.agileDSL.ScriptObj.IBaseScriptObj
// add other import statements here
import com.agile.api.ItemConstants
 
void invokeScript(IBaseScriptObj obj) {
//script body starts here.
  
   // get create user
   createUser = obj.getValueByAttId(ItemConstants.ATT_PAGE_TWO_CREATE_USER)
 
   // send notification
   sendToList = [createUser];
   obj.sendNotification("Notify On Incorporate", false, sendToList, "Comments: send from Script handler");
 
   // log to Event Handler Monitor
   obj.logMonitor( "Notify On Incorporate sent to: " + sendToList);
}
 

30.5.2.3 Subscriber mask: [Incorporate Item Incorporated Item]

  • Event: [Incorporate Item]

  • Event Handler: [Incorporated Item]

  • Trigger Type: Post

  • Execution Mode: Synchronous

  • Order: 0

  • Error Handling Rule: Continue

30.5.3 Set Change Analyst

This Event Subscription is a model for automatically setting the Change Analyst when a workflow changes status.

More specifically, the action that triggers this Event Subscription is a user creates an ECO and sets the product lines to one from this list: Capricorn, Leo, Pisces, Scorpio, Taurus, Test, Virgo. The field for Change Analyst is left unfilled.

When the system (or a user manually) changes the status to Submitted, the Change Analyst for the ECO is set according to the product lines. The Handler's execution status can be verified from the Handler Monitor.

30.5.3.1 Event mask: [Change Analyst for Workflow]

  • Event Type: Change Status for Workflow

  • Workflow: Default Change Orders

  • Object Type: Change Orders

  • Status - From: Pending

  • Status - To: Submitted

30.5.3.2 Handler mask: [Set Change Analyst]

  • Handler Type: Script PX

  • Script:

import com.agile.agileDSL.ScriptObj.BaseScriptObj;
import com.agile.agileDSL.ScriptObj.AgileDSLException;
import com.agile.api.ChangeConstants;
 
/**
* Sets the change analyst upon setting an ECO to submitted.
*/
BaseScriptObj invokeScript(BaseScriptObj obj) {
 
   def PRODUCTLINES_ATTID =  ChangeConstants.ATT_COVER_PAGE_PRODUCT_LINES;
   def CHANGEANALYST_ATTID =  ChangeConstants.ATT_COVER_PAGE_CHANGE_ANALYST;
   def CAMap = [
      'Capricorn':'user1',
      'Leo':'user2',
      'Pisces':'user3',
      'Scorpio':'user4',
      'Taurus':'user5',
      'Test':'user6',
      'Virgo':'user7'
      ]
 
   def toStatus = obj.getToStatus();
   def workflow = obj.getWorkflow();
   def changeAnalyst = obj.getValueByAttId(CHANGEANALYST_ATTID);
 
   // update change analyst based on the product lines if the next status is CCB and CA list is not filled yet
   if(workflow == "Default Change Orders" && toStatus == "Submitted" &&
      (changeAnalyst == null || changeAnalyst == "") ){
 
      def productLines = obj.getValueByAttId(PRODUCTLINES_ATTID);
 
      if(productLines == null || productLines == "") throw new       AgileDSLException("Product Line cannot be null, please fill in!");
   else
      obj.logMonitor("Current productlines are " + productLines);
      def productLinesList = productLines.tokenize(";")
   // Set change analyst based on the product lines
 
   changeAnalyst = CAMap.subMap(productLinesList).values().min();
      obj.setValueByAttId(CHANGEANALYST_ATTID, changeAnalyst);
      obj.logMonitor("||Set change analyst to " + changeAnalyst);
   }
}
 
 

30.5.3.3 Subscriber mask: [Change Analyst for Workflow Set Change Analyst]

  • Event: [Change Analyst for Workflow]

  • Event Handler: [Set Change Analyst]

  • Trigger Type: Post

  • Execution Mode: Synchronous

  • Order: 0

  • Error Handling Rule: Continue

30.5.4 Add Document to New Part

This Event Subscription is a model for automatically creating a Document and adding it to the Assembly BOM any time a part is created. It could be set up for any single subclass from the Parts class, as it is here, or for any object in all the Parts-class subclasses (by populating Object Type field with Parts Class).

More specifically, the action that triggers this Event Subscription is a user creates a part in Web or Java client.

When you click the part's BOM tab, you see a document has been added to the part and the part has been changed to an assembly. The Handler's execution status can be verified from the Handler Monitor.

30.5.4.1 Event mask: [Create Parts]

  • Event Type: Create Object

  • Object Type: Parts

30.5.4.2 Handler mask: [Add Doc to New Part]

  • Handler Type: Script PX

  • Script:

import com.agile.agileDSL.ScriptObj.IBaseScriptObj;
import com.agile.agileDSL.ScriptObj.AgileDSLException;
import com.agile.api.IAdmin;
import com.agile.api.IAgileClass
import com.agile.api.IAgileSession;
import com.agile.api.IAutoNumber;
import com.agile.api.IItem;
import com.agile.api.INode;
import com.agile.api.ITable;
import com.agile.api.ItemConstants;
import com.agile.px.EventActionResult;
import com.agile.px.IEventAction;
import com.agile.px.IEventInfo;
import com.agile.px.ICreateEventInfo;
import com.agile.px.EventConstants;
import com.agile.px.ActionResult;
 
import java.text.SimpleDateFormat;
import java.util.*;
 
/**
*Post event of create item action, create document and add the document into BOM table of assembly.
* It's mainly using SDK
*
*/
 
void invokeScript(IBaseScriptObj obj) {
   IAgileSession session = obj.getAgileSDKSession();
   IEventInfo req = obj.getPXEventInfo();
 
   try {
      int eventType=req.getEventType();
      int triggerType=req.getEventTriggerType();
      if(eventType!=EventConstants.EVENT_CREATE_OBJECT &&       triggerType!=EventConstants.EVENT_TRIGGER_POST)
         throw new AgileDSLException("The PX is only applicable for  post create event");
      ICreateEventInfo info=(ICreateEventInfo)req;
      Integer newSubClassId=info.getNewSubclassId();
 
      IAdmin admin=session.getAdminInstance();
      IAgileClass partclass=admin.getAgileClass(newSubClassId);
      IAgileClass docclass=admin.getAgileClass(ItemConstants.CLASS_DOCUMENT);
 
      // get the part object
      IItem part = (IItem) session.getObject(partclass, info.getNewNumber());
      if(part==null)
         throw new AgileDSLException("The part is not created:"+info.getNewNumber());
 
      if(partclass.getSuperClass().getId().equals(ItemConstants.CLASS_PARTS_CLASS)){
      IAutoNumber docNumber = docclass.getAutoNumberSources()[0];
 
      //create a new document
      IItem doc = (IItem) session.createObject(docclass, docNumber);
 
      //add the document into BOM table of the new part.  ITable tab = part.getTable(ItemConstants.TABLE_BOM); tab.createRow(doc);
      obj.logMonitor("Succeed to add document '"+  doc.getName() +"' to assemlby '"+part.getName()+"'");
         }
      else
      obj.logMonitor("The PX is only applicable for creating part object.");
      } catch (Exception e) {
      e.printStackTrace();
      throw new AgileDSLException(e);
   }
}
 

30.5.4.3 Subscriber mask:

  • Event: [Create Parts]

  • Event Handler: [Add Doc to New Part]

  • Trigger Type: Post

  • Execution Mode: Synchronous

  • Order: 0

  • Error Handling Rule: Continue

30.5.5 Notify when Affected Items Table is Updated

This event is a model for automatically creating and sending a notification (the Notification mask has been created in the Notifications node) any time the Affected Items table of a Change is updated.

It could be set up for any single subclass from the Change Orders class, or for any object in all the Change Orders-class subclasses (by populating Object Type field with Change Orders Class), or for any object in all the Changes base class (by populating Object Type field with Changes Base Class).

In this case, when the system modifies the Affected Items table (this is always an automatic process) of an instance of the subclass (and object type) ECO, a notification is created and sent to the users named on it. The Notification's execution status can be verified from the Handler Monitor.

30.5.5.1 Event mask: [Update Table ECO]

  • Event Type: Update Table

  • Object Type: ECO

  • Table Name: Affected Items

30.5.5.2 Notification mask: [Notify ECO AffItem Change]

  • Object Type: Change Orders

  • Here is a screenshot of the Notification mask:

Figure 30-2 Notification mask

Notification mask

30.5.5.3 Subscriber mask: [Update Table ECO Notify Item ECO AffItem Change]

  • Event: [Update Table ECO]

  • Event Handler: [NotifyItemECOAffItemChange]

  • Trigger Type: Post

  • Execution Mode: Asynchronous

  • Order: -

  • Error Handling Rule: -