Global scripts

This topic explains the concept of HCL Compass global scripts.

You can use global scripts to define common functions that you can call from any hook in your schema. Global scripts are like a library of subroutines; HCL Compass software does not invoke them directly.

Global scripts are useful when you have multiple record types that call the same hook code. They enable you to centralize hook code maintenance and avoid copying the hook code into multiple places. For example, the global script included in the HCL Compass Email package allows multiple actions to send notification by calling one global script.

The only way to run a global script is to call it from another script. Ultimately, however, a call to a global script must be traced back to a call to a record-based hook such as a field hook, action hook, or record script. Because calls to a global script can always be traced to a record-based hook, each global script is provided with an implicit entity object that is passed to the record-based hook that originated the call.

You can write scripts using both VBScript and Perl, but one language type cannot call another language type. When writing a global script, write it in the same language as the script that calls it.

Use functions only in a global hook, because all code in a global script is run unless it is in a function.

For more information, see Writing scripts and Operating context for using scripts.

For examples of relevant scripts, see Global script example.

Using subroutines for global scripts

For Perl, the variables $entity and $session are global variables that become active when a hook is run. These variables are defined at run time and can be used in global script code. However, you do not use these variables to call Entity or Session object methods within the context of a global script.

If the global script code uses these variables to call a method (such as, $entity->GetSession), schema validation fails because $session and $entity are not defined until execution time. For example, this code outside of a global subroutine fails because you cannot call the method on an undefined value ($session).
$info = $session->GetProductInfo();
It is not enough to place the $session call in a global subroutine. For example, the following code fails for the same reason because it tries to resolve $productInfo at compile time:
$productInfo = GetProductInfo();
   sub GetProductInfo
   {
       return $session->GetProductInfo();
   }

Instead of using global variables such as $productInfo call GetProductInfo() to retrieve the value.

While executing Perl hooks, $session is always set to the current session. However, for best performance, avoid defining global variables that are sensitive to Session or Entity object data; instead, write global accessor functions (for example, GetUserLoginName()) to retrieve the values.

Global script cloning

Global scripts are intended to be used as a collection of subroutines that can be called from other hooks (such as access control hooks, initialization hooks, and validation hooks). To allow this, all global script code is included as part of the Perl code used for every hook execution. However, global script code can include statements that are outside of subroutine scope (at file scope).

Beginning in version 7.0.1, a new Perl hook enhancement that clones global scripts is available. When this enhancement is enabled, a Perl hook environment is created; all global script code is compiled and then cloned to create new hook environments. The cloning process avoids recompiling code and allows hook environments to share a parse tree. Cloning scripts saves time and memory for each Perl hook environment, which provides better performance (with significant improvements for HCL Compass Web).

Schema developers should consider how to use cloning when writing global scripts. If cloning is enabled for global hooks, file scope statements in global scripts are executed only once. The results are then cloned to subsequent Perl interpreters. If cloning is disabled, this code runs each time the hook environment is created (once per record action and once for each record script call).

To avoid confusion about running setup code in cloned global scripts, move setup code that is at file scope into a subroutine and use a specially scoped our global variable to check for setup status. You can ensure the setup code is always run at least once in each hook environment and avoid multiple executions. This setup subroutine cab called from any hook that requires the setup to be completed. For example:
  our $run_once;
   sub DoSetup
   {
       return if defined($run_once);
       $run_once = 1;
       # do setup here
   }
sub Defect_Initialization {
 DoSetup();
 # ...
 # ...
 #reset of Defect_Initialization code...
 # ...
 }

In this code example, the $run_once variable is not defined when the hook environment is created. When it is cloned, this variable is still undefined. When hooks first run and call DoSetup(), the setup code is executed.

Note: Perl global script cloning requires that any Perl libraries that are called by your code must be thread-safe. For example,
use Win32::OLE;
should not be used in cloned hook code (but can be used in non-cloned hook code, including action hooks, field hooks and record hooks). Win32::OLE is not thread safe but can be used outside of a HCL Compass Web multithreaded environment. For example, you can use
require Win32::OLE; import Win32::OLE;
within the global script to prevent the Win32::OLE module from being cloned, but the module should not be used in schemas that are used with HCL Compass Web.
Attention: HCL Compass cannot guarantee if a Perl module is thread-safe as Perl modules are outside the control of HCL Compass. For information on thread safety, see the Perl documentation available at http://www.perl.org.