STAX Service User's Guide

STAf eXecution engine
Version 3.5.17

June 27, 2016

Document Owner: Sharon Lucas


Table of Contents

Overview

Concepts

Using XML to Define STAX Jobs

Using Python for Expression Evaluation

Element Syntax and Usage

  • Root Element
  • stax
  • Python Code Execution
  • script: Run Python Code
  • Actions
  • process: Run a Process
  • stafcmd: Run a STAF Command
  • job: Execute a STAX Sub-Job
  • nop: Perform No Operation
  • Sequential Execution
  • sequence: Run Tasks In Sequence
  • Parallel Execution
  • parallel: Run Tasks in Parallel
  • paralleliterate: Run a Task for Each Entry in a List in Parallel
  • Functions
  • function: Define a Named Task
  • call: Call a Function
  • call-with-list: Call a Function with a Argument List
  • call-with-map: Call a Function with a Argument Map
  • defaultcall: Specify Default Starting Function To Call
  • return: Return From a Function
  • import: Import Functions From Another STAX XML Job File
  • Loops
  • loop: Run a Task Repeatedly
  • iterate: Iterate a List and Run Each Iteration In Sequence
  • break: Jump out of the Closest Enclosing Loop or Iterate
  • continue: Jump to the Top of the Closest Enclosing Loop or Iterate
  • Conditional
  • if / elseif / else: Select a Task To Perform
  • Wrappers
  • block: Define a Task for which Execution Control is Provided
  • testcase / tcstatus: Define a Testcase and Record Status
  • timer: Define a Task for which Time Control is Provided
  • Directives
  • hold: Hold a Block
  • release: Release a Block
  • terminate: Terminate a Block
  • Exceptions
  • try / catch / finally: Run a Task, Catch Exceptions and/or Run a Finalization Task
  • throw: Throw an Exception
  • rethrow: Rethrow an Exception
  • Example of Nested Try Blocks
  • Signals
  • raise: Raise a Signal
  • signalhandler: Handle a Signal
  • How to Perform Cleanup Before Job Termination
  • Logging / Messages
  • log: Log a Message in the STAX Job User Log
  • message: Send a Message to the STAX Monitor
  • Breakpoints
  • breakpoint: Settings Breakpoints in a STAX Job
  • System Requirements

  • Software Requirements
  • Hardware Requirements
  • Installation and Configuration

  • STAX Service Machine
  • Requesting Machine
  • Execution Machine
  • Monitoring Machine
  • Request Syntax

  • EXECUTE
  • GET RESULT
  • GET DTD
  • HELP
  • HOLD
  • LIST
  • LOG MESSAGE
  • QUERY
  • RELEASE
  • SEND MESSAGE
  • STOP PROCESS
  • ADD BREAKPOINT
  • REMOVE BREAKPOINT
  • RESUME THREAD
  • STEP THREAD
  • STOP THREAD
  • PYEXEC
  • SET
  • START TESTCASE
  • STOP TESTCASE
  • TERMINATE
  • UPDATE
  • NOTIFY REGISTER/UNREGISTER
  • NOTIFY LIST
  • PURGE <FILECACHE | MACHINECACHE>
  • VERSION
  • STAX Monitoring

  • Starting the STAX Monitor
  • Setting STAX Monitor Properties
  • Displaying a List of Active Jobs
  • Submitting a New Job for Execution
  • Using the Job Wizard
  • Monitoring a Job
  • Displaying a Job Log
  • Displaying a JVM Log
  • STAX Logging

  • Listing/Querying STAX Service Logs
  • Querying STAX Job Logs
  • Querying STAX Job User Logs
  • Displaying STAX Logs via a GUI
  • Formatting a STAX Log as Html or Text
  • Enabling/Disabling Testcase Logging
  • STAX Variables

    STAXGlobal Class

    STAX Python Interfaces (STAFMarshalling)

    STAF Java Classes (STAFUtil, STAFRC, STAFVersion, etc)

    STAX File and Machine Caching

    STAX Extensions

  • Registering STAX Service Extensions
  • Creating a STAX Extensions XML File
  • Registering STAX Monitor Extensions
  • Generating STAX Function Documentation

  • Using STAXDoc
  • Using StyleSheet FunctionList.xsl
  • Debugging

    Using Breakpoints to Debug STAX Jobs

    Events Generated by STAX that Provide Job Status

    Support Information

  • Known Problems
  • History of Changes
  • Appendix A: STAX XML Document Examples

  • STAX Libraries Containing Common Utility Functions
  • STAF Upgrade Functions
  • STAX Utility Functions
  • Sample STAX Jobs
  • Sample STAX Job 1 - Basic Example How to Run Processes and STAF Commands
  • Sample STAX Job 2 - Executing Tests in Parallel on Multiple Machines
  • Sample STAX Job 3 - Creating a STAF Handle and Using it's Queue
  • Appendix B: STAX Error Code Reference

    Appendix C: STAX Document Type Definition (DTD)

    Appendix D: STAX Extensions Document Type Definition (DTD)

    Appendix E: References

    Appendix F: Jython and CPython Differences

    Appendix G: Licenses and Acknowledgements


    Overview

    STAX (STAf eXecution engine) is an XML-based execution engine implemented as an external STAF service. STAX was designed to make it significantly easier to automate the workflow of your tests and test environments.

    STAX accepts job definitions, in the form of XML documents. Fundamentally, these job definitions allow you to specify the processes and STAF commands necessary to perform the job. STAX provides a wealth of expressive functionality on top of this, making it easy to implement, manage, track, and monitor your jobs.

    STAX uses the Python scripting language for variable and expression evaluation. The Python code is executed by Jython, a version of Python written entirely in Java. This allows STAX to take advantage of the powerful and easy-to-use features of Python.

    The sections that follow describe the basic concepts behind STAX, explain the STAX XML language used to define your jobs, and detail the commands externalized by the STAX service. Read on to find out more about the exciting new world of STAX.
     

    Concepts

    STAX Elements

    A STAX Element is a node in a STAX XML document. Some of the items that STAX Elements can represent are:  data to be used during the job, commands/processes to be executed, definitions of the logic and control flow within the job, exceptions and signals, and wrappers such as functions and blocks that encompass other STAX Elements.

    Processes and Commands

    A STAX job definition describes the execution flow for processes and STAF commands.

    Processes and stafcmds may be put into sequential and/or parallel wrappers which can be nested.

    Expression Evaluation via Python

    STAX allows you to avoid hard-coding information in your job definition by using Python to assign values to variables and then using Python scripting language to evaluate expressions and to execute Python code. STAX also sets some variables in Python that provide runtime information about the job definition's execution.

    For example, instead of hardcoding the name of the machines where processes and commands are executed during the job, a Python variable can be assigned the name of the machine and specified for the location element. Python variables also be provided at the time the job is requested to be executed. A Python variable may also be assigned a list of machine names.

    After STAX processes some elements (e.g. process and stafcmd), the return code and result (if applicable) are accessible via STAX variables. These variables can be referenced by other STAX elements (e.g. via the if element's expression attribute) to determine logic flow within the job.

    Groups

    STAX can execute groups of STAX Elements sequentially or in parallel.  When Elements are executed in parallel, STAX will run each of the Elements on a separate thread.

    Loops

    Loop Elements are available which allow a STAX Element to be executed repeatedly.  Additionally, there are Iterate Elements which allow a STAX Element to be executed repeatedly while stepping through a list of data for each iteration (this could be used, for example, to execute a sequence of commands for each machine in a list).

    STAX-Threads

    When the STAX Service executes elements in parallel, rather than using real system threads (and thereby potentially creating an overabundance of system threads), the STAX Service will simulate the threading capabilities via a thread pool which will utilize a manageable number of real system threads.  These simulated threads are called STAX-Threads.

    Whenever a new STAX-Thread is created, existing variables are cloned from the parent STAX-Thread. To create a global variable that can be accessed across STAX-Threads, use the STAXGlobal class described in "STAXGlobal Class" section. STAX elements that can create STAX-Threads include the following: <parallel>, <paralleliterate>, <process-action>, <job-action>, and <function> elements with a local scope.

    Wrappers

    STAX has several Wrapper Elements which simply provide additional functionality to another STAX Element.  These Wrapper Elements can denote Testcases (with testcase status), Blocks (for which execution control can be manipulated), Timers (for time-based execution control), and Functions (which provide a unique name that can be called from other STAX Elements in the Job Definition.

    Functions

    Functions are a nearly universal program-structuring device. Functions serve two primary development roles: code reuse and procedural decomposition. Functions are the simplest way to package logic you may wish to use in more than one place and more than one time. Functions allow us to group and parameterize chunks of XML to be used arbitrarily many times later. Functions also provide a tool for splitting jobs into pieces that have a well-defined role. STAX allows functions to be imported from other XML files so that you can build up libraries of STAX functions that can be reused by many different STAX jobs.

    Sub-Jobs

    STAX provides a "job" element so that sub-jobs can be executed within a parent job with synchronized completion as well as providing access to the sub-job result.

    Logic Flow

    STAX provides an "if" element which can evaluate conditions using Python (for example, a return code) to determine logic flow within the STAX Job Definition, thus allowing job flow to branch dynamically.

    Exceptions and Signals

    The STAX Service provides exception and signal handling capabilities.  STAX exception handlers, as well as finally blocks, alter the execution flow of the job. STAX signal handlers provide asynchronous error handling of raised signals.  The STAX execution engine may also raise signals or throw exceptions for errors which occur during job execution.

    Monitoring STAX Jobs

    A STAX Monitor application is available for the STAX Service.  This application displays a graphical representation of the currently running elements of a given Job. The STAX Monitor makes it easy to see which processes and STAF commands are currently running as well as the blocks which contain them. You may select a process or STAF command to get more detailed information about it. You may also select a block and then control the execution of the job by choosing to hold, release, or terminate the block. The STAX Monitor also displays a list of testcases that have been run and the number of passes and fails for each. Also, a messages panel displays any messages that are sent by the job. This can help make debugging a job definition easy.

    Logging

    The STAX Service maintains a service log which records high level information about all jobs that have been submitted.

    The STAX Service also maintains an individual job log for each submitted job.  These job-specific logs record information such as testcase status and job execution tracing. If the "log" element is used within the STAX Job Definition, then a user log is also created for the submitted job.

    Queues

    The STAX Service uses the STAF QUEUE service for sending messages. Each STAF handle has a queue (see the STAF User's Guide for more information on STAF handles, queues, and the QUEUE service). Each STAX job has a handle associated with it (and, thus, a queue). A STAX job uses it's STAF Queue for lots of things, so you should not use the STAX job handle's queue (e.g. don't get try to get data off a STAX job handle's queue) as that can interfere with the use of the queue by the STAX service.

    Alternatively, if you want your STAX job to use a queue on the STAX service side to send and receive messages, you can create your own STAF handle and use it's queue. Refer to Sample STAX Job 3 - Creating a STAF Handle and Using it's Queue for an example of how to create a STAF handle within a STAX job and use it's queue to get messages.
     


    Using XML to Define STAX Jobs

    STAX uses XML (Extensible Markup Language) to describe STAX job definitions. XML is a language defined by the World Wide Web Consortium (W3C), the body that sets the standards for the Web. It is called extensible because it is not a fixed format like HTML (a single, predefined markup language). Instead, XML is actually a 'metalanguage' -- a language for describing other languages -- which lets you design your own customized markup languages for limitless different types of documents. This section reviews some XML fundamentals. Refer to the "References" section for where to get more information about XML.

    Both markup and text in an XML document are case-sensitive. All XML processing instructions start with <? and end with ?>. XML comments start with <!-- and end with -->. In XML, tags always start with < and end with >. The names that can be used for a tag are defined by the DTD (Document Type Definition).

    XML documents are made up of XML elements. Much like in HTML, you create XML elements with an opening tag, such as <stax>, followed by the element content (if any), such as text or other elements, and ending with the matching closing tag that starts with </, such as </stax>. It's necessary to enclose the entire document, except for processing instructions, in one element, called the root element -- that's the <stax> element here:

    <?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <!DOCTYPE stax SYSTEM "stax.dtd">
    <stax>
       .
       .
       .
    </stax>
    

    Empty Elements

    Empty elements have only one tag, not a start and end tag. In XML, you close an empty element with />. For example, nop is an empty element:
    <nop/>
    

    Attributes

    Attributes in XML are name-value pairs that let you specify additional data in start and empty tags. To assign a value to an attribute, you use an equal sign. Because markup is always text, attributes are also text. Even if you're assigning a number to an attribute, you treat that number as a text string and enclose it in quotes. In XML, you must enclose attribute values in quotation marks. Usually, you use double quotes, but if the attribute value itself contains double quotes, you can use single quotes to surround the text.

    If the attribute value contains both single and double quotes, you can use the XML-defined entity &apos; for a single quote and &quot; for double quotes.

    An example of a defaultcall element with a function attribute is:

    <defaultcall function="MainFunction"/>
    

    Creating a STAX XML document

    The root element can contain other elements, of course. Here, I added elements for three functions to the document and added one element that defines the function to call first by default. Note that the function element has an attribute called name and the defaultcall element is empty and has an attribute called function.
    <?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <!DOCTYPE stax SYSTEM "stax.dtd">
    <stax>
      <defaultcall function="FunctionA"/>
    
      <function name="FunctionA">
          ...
      </function>
    
      <function name="FunctionB">
          ...
      </function>
    
      <function name="FunctionC">
          ...
      </function>
    </stax>
    

    The function element can contain a single task element as defined by the STAX DTD. Here, I added a process element to FunctionA, a stafcmd element to FunctionB, and a log element to functionC. A process element can contain other elements. In this case I added location, command, and parms. A stafcmd element can contain other elements. In this case I added location, service, and request.

    <?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <!DOCTYPE stax SYSTEM "stax.dtd">
    <stax>
      <defaultcall function="FunctionA"/>
    
      <function name="FunctionA">
          <process>
            <location>'local'</location>
            <command>'java'</command>
            <parms>'com.ibm.staf.service.stax.TestProcess 2 4 0'</parms>
          </process>
      </function>
    
      <function name="FunctionB">
          <stafcmd>
            <location>'local'</location>
            <service>'misc'</service>
            <request>'version'</request>
          </stafcmd>
      </function>
    
      <function name="FunctionC">
          <log>'This function logs this message'</log>
      </function>
    </stax>
    

    Document Type Definition (DTD)

    The STAX DTD specifies the correct syntax of the document. A STAX XML document is valid if it complies with the STAX DTD. A DTD is a formal description in XML Declaration Syntax of a particular type of document. It defines what names are to be used for the different types of elements, where they may occur, and how they all fit together. Refer to the "STAX Document Type Definition (DTD)" section to see the entire STAX DTD.

    For example, the STAX DTD allows you to describe a STAF Command which has a name attribute and contains location, service, and request elements. The relevant part of the STAX DTD contains:

                <!ELEMENT stafcmd   (location, service, request)>
                <!ATTLIST stafcmd
                          name      CDATA    #IMPLIED
                >
                <!ELEMENT location  (#PCDATA)>
                <!ELEMENT service   (#PCDATA)>
                <!ELEMENT request   (#PCDATA)>
    
    This defines a stafcmd as an element type containing location, service, and request elements; and it defines location, service, and request as element types containing just plain text (Parsed Character Data or PCDATA) and defines name as an attribute type containing just plain text (Character Data or CDATA). Validating parsers read the DTD before they read your document so that they can identify where every element type ought to come and how each relates to the other, so that applications which need to know this in advance (such as the STAX service) can set themselves up correctly. The example above lets you create STAF commands like:
                <stafcmd name="'Delay'">
                  <location>'local'</location>
                  <service>'delay'</service>
                  <request>'delay 5000'</request>
                </stafcmd>
    
    A DTD provides applications with advance notice of what names and structures can be used in a particular document type. Using a DTD when editing files means you can be certain that all documents which belong to a particular type will be constructed and named in a consistent and conformant manner. The STAX service parses an XML document to break it down into its component parts and then handles the resulting data. STAX uses the XML Parser for Java which is a validating XML parser.

    Refer to the References section for where to get more information about the XML Parser for Java.

    You can use your favorite text editor to create a STAX XML document, or you can use an XML editor such as Cooktop. If you use an XML editor, you'll probably want to get the STAX DTD file so that the XML editor can use it to validate the XML syntax by updating the DOCTYPE statement in the xml file so that the SYSTEM value is the location of the stax.dtd file you created. The stax.dtd file is not provided with the STAX service because its contents can vary because you can extend it by registering STAX service extensions. You can get the stax.dtd file by running the following from a command prompt on your STAX service machine:

      set STAF_QUIET_MODE=1               (or if on Unix:  export STAF_QUIET_MODE=1)
      STAF local STAX GET DTD > stax.dtd
      set STAF_QUIET_MODE=                (or if on Unix:  unset STAF_QUIET_MODE)
    
    This creates a stax.dtd file in the current directory. Or, see Appendix D: STAX Extensions Document Type Definition (DTD) for the contents of the STAX DTD (without any extensions).
     


    Using Python for Expression Evaluation

    STAX uses the Python for variable and expression evaluation. STAX uses Jython to execute the Python code. Jython is an implementation of the Python scripting language written in 100% pure Java that runs under any compliant Java Virtual Machine (JVM). Using Jython, you can write Python code that interacts with any Java code.

    STAX variable names must follow the Python variable naming conventions. In Python, variable names come into existence when you assign values to them, but there are a few rules to follow when picking names for variables.

    Python string constants can be enclosed in single or double quotes, which allows embedded quotes of the opposite flavor.

    For example, the following two lines do exactly the same thing in a STAX XML document.  They assign a string constant (literal) "CoolTest" to the value of a variable named testName.

    <script>testName = "CoolTest1"</script>
    <script>testName = 'CoolTest1'</script>
    However, the following line is not the same.  It assigns the value of a variable named CoolTest1 to the value of a variable named testName. If this was not what you intended and a variable named CoolTest1 does not exist, a STAXPythonEvaluationError signal is raised.
    <script>testName = CoolTest1</script>

    For elements and attributes whose values are evaluated via Python, we need to distinguish between literals and variables.

    For example, the following request element's value contains a string constant which is concatenated with the value of a variable named machName.  So, if the value of variable machName is 'testA.austin.ibm.com', after being evaluated by Python, the request element's value would be:  'RELEASE POOL ClientMachPool ENTRY testA.austin.ibm.com'.

    <request>'RELEASE POOL ClientMachPool ENTRY ' + machName</request>
    Another way to do this is:
    <request>'RELEASE POOL ClientMachPool ENTRY %s' % (machName)</request>
    where the %s indicates a String format (and can also be used for decimal format, etc.), and where the value of the machName variable would replace the %s marker.

    Also, note that the following two lines do exactly the same thing in a STAX XML document.  They assign a string constant (literal) "VerifyRC" to the function attribute's value.

    <call function="'VerifyRC'"/>
    <call function='"VerifyRC"'/>
    However, the following line is not the same.  It assigns the value of a variable named VerifyRC to the function attribute's value. If a variable named VerifyRC does not exist, a STAXPythonEvaluationError signal is raised.
    <call function="VerifyRC"/>
    Also, note that XML processors assume that < always starts a tag and that & always starts an entity reference, so you should avoid using those characters for anything else. You must use the entity reference &lt; instead of < and entity reference &amp; instead of & or else you'll get an XML parsing error. This can be difficult sometimes as the < character is used as the less-than operator in Python, as in this example, where RC < 0 is being assigned to the expression attribute.
    <if expr="RC &lt; 0">
    Here's another example that shows a <script> element that contains Python code using the regular expression (re) module to look for pattern '<pass>' anywhere in the STAFResult string variable and must use the entity reference &lt; instead of <.
    <script>
      import re
      matchstr = r'.*?&lt;pass>.*?'
      matchFlag = re.match(matchstr, STAFResult)
    </script>

    Refer to the "References" section for where to get more information about Jython and Python.

    If you are already a CPython programmer, or are hoping to use CPython code under Jython, refer to the "Jython and CPython Differences" section for information about differences in the two implementations of Python.
     


    Element Syntax and Usage

    A job to be executed by the STAX Service is described by an XML document. The XML document must comply with the STAX document type definition (DTD) shown in "STAX Document Type Definition (DTD)". The function of the STAX XML document is to describe STAF command and process execution.

    The first line in an XML document should start with an XML declaration. This indicates the document is written in XML and specifies the XML version, the language encoding for the document, and indicates that the document refers to an external DTD (standalone="no").

    The second line in an XML document should be the document type declaration. This is used to indicate the DTD used for the document. It defines the name of the root element (stax), and the DTD to be used. STAX checks the syntax of XML documents using a validating XML parser to verify that the document complies with the DTD. Note that DTDs are all about specifying the structure and syntax of XML documents (not their content).

    So, the first two lines in a STAX XML document should look like:

    <?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <!DOCTYPE stax SYSTEM "stax.dtd">
    

    The DOCTYPE statement's value for SYSTEM must end in stax.dtd (not case-sensitive) or a STAXXMLParseException error will be returned when executing the STAX XML document.

    Note that references to external entities in a STAX XML document are not supported. If a STAX XML document references an external entity (other than the stax.dtd in the DOCTYPE statement), a STAXXMLParseException error will be returned when executing the STAX XML document.

    This section describes the elements that can be used in a STAX XML document.

    To ease the description of the elements, some elements will be grouped as follows so that they can be referenced as a group and will be shown in bold italics:

       Reference       Elements
       task              process | stafcmd | nop |
                         sequence | parallel | paralleliterate |
                         call | call-with-list | call-with-map | return | import |
                         if | loop | iterate | break | continue |
                         try | throw | rethrow |
                         signalhandler | raise |
                         hold | release | terminate |
                         testcase | tcstatus | script |
                         block | timer | log | message
    Notes:

    Also, some examples of the usage of elements use "..." for brevity to represent that additional XML would be included in place of the "...".

    Root Element

    An XML document must contain a root element which contains all other elements in the document. The root element of a STAX XML document is stax.

    stax

    The stax element consists of any number of function, script, and/or signalhandler elements and an optional defaultcall element.

    Usage:

    <?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <!DOCTYPE stax SYSTEM "stax.dtd">
    
    <stax>
    
      <defaultcall function="FunctionA"/>
      <script>machName = "test1.austin.ibm.com"</script>
    
      <function name="FunctionA">
        ...
      </function>
    
      <function name="FunctionB">
        ...
      </function>
      ...
    
    </stax>

    Python Code Execution

    STAX uses Python, which is an object-oriented scripting language. To specify Python code to be executed, you can use the script element. The Python code can include any Python statements such as variable assignments, importing and running Python modules, accessing Java libraries, and running built-in Python tools.

    All script elements contained in the root stax element are initialized at the beginning of the job, as each is encountered in sequential order, regardless of their placement within the stax element, and are accessible throughout the job (like global variables).  All script elements contained in elements other than the stax element (e.g. such as the sequence element) are assigned as each is encountered and are accessible within their scope and are inherited from parent STAX-Threads.

    Whenever a new STAX-Thread is created, existing variables are cloned from the parent STAX-Thread. To create a global variable that can be accessed across STAX-Threads, use the STAXGlobal class described in "STAXGlobal Class" section. STAX elements that can create STAX-Threads include the following: parallel, paralleliterate, process-action, job-action, and function elements with a local scope.

    script: Run Python Code

    The script element is used to specify Python code to be executed. For example, the script element can be used to define STAX variables which are utilized during the parsing of the XML document and the subsequent execution of the STAX job. Note that a STAX variable is used solely by the STAX job and is not associated with STAF variables. You can also use the script element to import and run Python modules and built-in Python tools.

    Usage:

    Goal: Create a variable named testName and assign it value "CoolTest1"
    <script>testName = "CoolTest1"</script>
    Goal: Create a variable named machName and assign it the value of the STAFResult variable.
    <script>machName = STAFResult</script>
    Goal: Create a list called machList containing 10 machine names by running the STAF Resource Pool Request command in a loop ten times, each time adding the STAF Result value from the RESPOOL REQUEST POOL command (which contains a machine name) to the list. Note that this example first creates an empty list and then adds a machine name to the list 10 times.
    <script>machList = []</script>
    <script>clientPool = 'ClientMachinePool'</script>
    <loop var="i" from="1" to="10">
      <sequence>
        <stafcmd>
          <location>'server1.austin.ibm.com'</location>
          <service>'RESPOOL'</service>
          <request>'REQUEST POOL %s' % (clientPool)</request>
        </stafcmd>
        <script>machList.append(STAFResult)</script>
      </sequence>
    </loop>
    Goal: Create a list called allMachList by combining lists named unallocMachList and allocMachList. New list allMachList contains ['MachA','MachB','MachC','MachD','AllocMachA','AllocMachB'].
    <script>unallocMachList = ['MachA','MachB','MachC','MachD']</script>
    <script>allocMachList = ['AllocMachA','AllocMachB']</script>
    <script>allMachList = unallocMachList + allocMachList</script>
    Goal: Generate a random number (which could be used to randomly select which function to call) using the random module provided by Python. Note that in Python, you can use a semicolon to separate multiple statements on the same line.
    <script>from random import random; r=random()*100</script>
    Goal: Use a Java class, com.ibm.staf.STAFUtil (provided in JSTAF.jar), and it's wrapData() method to turn strings containing spaces into the colon-length-colon form needed for submitting a STAF Notify request. For more information on the STAFUtil Java class, see the STAF Java Classes (STAFUtil, STAFRC, STAFVersion, etc) section. This example also shows that for statements that are too long to fit on one line, Python lets you continue typing the statement on the next line, if you're coding something enclosed in (), {}, or [] pairs. Continuation lines can start at any indentation level.
    <script>
      NotifyProfile = 'Jane Smith'
      Message = 'STAX Job ID %s failed.' % (STAXJobID)
      Request = ('NOTIFY PROFILE %s LEVEL NORMAL MESSAGE %s' %
                (STAFUtil.wrapData(NotifyProfile), STAFUtil.wrapData(Message)))
    </script>
    
    <message>NotifyRequest</message>
    
    The message element would display something like:
    NOTIFY PROFILE :10:Jane Smith LEVEL NORMAL MESSAGE :21:STAX Job ID 6 failed.
    
    Goal: Create a Python class object, Server, and generate three instance objects from the class and create a list of these Server objects. Then iterate through the server list, logging information about each server object in the server list.
    <script>
      # Define Server class
      class Server:
        def __init__(self, hostname, dir):
          self.hostname = hostname
          self.dir      = dir
        def __repr__(self):
          return "<Server: hostname=%s, directory=%s>" % (self.hostname, self.dir)
        def getHostname(self):
          return self.hostname
        def getDir(self):
          return self.dir
    
      # Create an array of 3 Server objects
      serverList = [
                     Server('myServer.austin.ibm.com', 'C:/install'),
                     Server('serverA.portland.ibm.com', 'D:/install'),
                     Server('linuxServer.austin.ibm.com', '/usr/local/install')
                   ]
    </script>
    
    <iterate var="server" in="serverList" indexvar="i">
      <log>
        'Server #%s: hostname=%s, directory=%s' % (i+1, server.getHostname(), server.getDir())
      </log>
    </iterate>
    
    Goal: Get the current date/time. Since STAX uses Jython to execute Python code, you can also import and use Python modules or Java classes to perform date/time functions such as getting the current date/time. Here are some ways to get the current date/time:


    Actions

    The process, stafcmd, job, and nop elements perform actions.

    process: Run a process

    The process element represents a STAF process which will be executed on a specified machine. It submits a START request to the STAF PROCESS service to run the specified command on the specified machine and waits for the process to complete running before continuing to the next element in the STAX job. You should use the process element instead of a stafcmd element if you want to start a process and wait for it to complete.

    After a process has completed (or if it could not be started) the following variables are set and can be referenced by the job:

    The process element has one optional attribute:

    The process element contains two required elements (location and command) with many optional elements. The location element must be specified first, followed by the command element. The rest of the elements are optional.

    Note that the process elements are equivalent to the options allowed for the STAF Process Service's START request (except where noted), so see the STAF User's Guide for more information.

    Required process elements:

    Optional process elements:

    Here are some important notes about optional process elements:

    1. If specified, these optional process elements must be specified in the order listed below (with some variations). Refer to the "STAX Document Type Definition (DTD)" section to see the DTD for the process element and to see the variations in process element order that are allowed.

    2. Each of these optional elements may specify an if attribute. The if attribute must evaluate via Python to a true or false value. If it does not evaluate to a true value, the element is ignored. The default value for the if attribute is 1, a true value. Note that in Python, true means any nonzero number or nonempty object; false means not true, such as a zero number, an empty object, or None. Comparisons and equality tests return 1 or 0 (true or false).

      Using the if attribute provides a convenient shortcut to deal with many variations of optional process elements that, otherwise, would have to be specified using the if/elseif elements and multiple different process elements.

    The process element may contain any of the following optional elements in the order listed (with some variations):

    Options allowed for the STAF Process Service which are not allowed for the STAX process element are as follows. These options should not be put in the other element.

    Notes:

    1. See the timer element section for special considerations regarding accessing stdout/stderr data when using a <timer> element to terminate a process that runs continously. An example is also provided in the timer's "Usage" section.

    2. You can use the <stdout> and/or <stderr> elements to stream a process's standard output and standard error, respectively, into a specified file. The contents of the file won't be returned to the user (e.g. via the STAXResult variable if using the <returnstdout> and/or <returnstderr> elements) until the process has completed. But, you could look at the contents of the stdout/stderr file while the process is still running by using a <parallel> or <process-action> element to do this in parallel with the process running.

    3. After you obtain the content of a file created by the <stdout> or <stderr> element, if you no longer need the file, you can delete it using a <stafcmd> element to run the FS service's DELETE ENTRY command. Or, if you didn't need the file deleted immediately, you could create the stdout/stderr file in the {STAF/DataDir}/tmp directory. All contents of the {STAF/DataDir}/tmp directory are deleted when STAFProc is restarted.

    Usage:

    In the following example of a process element, a Java program is executed. When the process completes, the if element is run which checks the return code from the process.
    <sequence>
    
      <process name="'TestProcess'">
        <location>'local'</location>
        <command>'java'</command>
        <parms>'com.ibm.staf.service.stax.TestProcess 5 1 0'</parms>
        <title>'Test Process'</title>
      </process>
    
      <if expr="RC != 0">
        <raise signal="'NonZeroRCError'"/>
      </if>
    
    </sequence>
    In the following example of a process element, a ping command is executed as though you were at a shell prompt. The ping is executed within a loop contained within a timer. If the ping command does not complete successfully (indicated by RC 0) within 30 seconds, a failure message is sent.
    <sequence>
    
      <timer duration="'30s'">
        <loop until="RC == 0">
          <process name="'Ping'">
            <location>'local'</location>
            <command mode="'shell'">'ping -n 1 -w 1 %s' % machName</command>
          </process>
        </loop>
      </timer>
    
      <if expr="RC != 0">
        <message>'Ping of machine %s failed' % machName</message>
      </if>
    
    </sequence>
    
    The following example of a process element shows many of the optional elements that a process can contain and shows the use of the if element to specify whether an optional element should be used based on an expression evaluated while the job is running.
    <script>
      machName = 'local'
      opSys = 'Win32'
      className = 'com.ibm.staf.service.stax.TestProcess'
      commonEnvVarList = ['COMMON_ENV_VAR_1=value1','COMMON_ENV_VAR_2=value2']
    </script>
    
    <process name="'aProcess'">
      <location>machName</location>
      <command>'java'</command>
    
      <parms if="opSys != 'Linux'">
        '%s 2 15 100' % className
      </parms>
    
      <title>'Title example for process with many elements'</title>
    
      <vars if="opSys == 'Win32'">
        ['tempPath=C:/temp', 'winRunPath=C:/temp/processa']
      </vars>
    
      <vars if="opSys == 'Linux'">
        ['tempPath=/test/temp']
      </vars>
    
      <var>
        'commonMachName=%s' % (machName)
      </var>
    
      <envs if="opSys == 'Win32'">
        ['TEMP_DIR=C:/temp']
      </envs>
    
      <envs>commonEnvVarList</envs>
    
      <useprocessvars if="opSys == 'Win32'"/>
    
      <disabledauth if="opSys == 'Win32'" action="'ignore'"/>
    
      <stdout mode="'replace'">
        'c:/temp/aProcess.out'
      </stdout>
    
      <stderr mode="'append'">
        'c:/temp/aProcess.err'
      </stderr>
    
      <console if="opSys == 'Win32'" use="'same'"/>
    
      <focus if="opSys == 'Win32'" mode="'minimized'"/>
    
    </process>
    
    In the following example of a process element, a command which writes to stdout and stderr and produces a couple of files (C:\process1.inf and C:\process2.inf) is run. The contents of the stdout file and the two additional files are returned in STAXResult when the process completes. Note that the stdout file also contains stderr output because <stderr> specified mode 'stdout' instead of specifying a different file name. Then the contents all returned files are written to one central place, the STAX Job User Log.
    <sequence>
    
      <process>
        <location>machName</location>
        <command>cmd</command>
        <stdout>'C:/temp.out'</stdout>
        <stderr mode="'stdout'"/>
        <returnstdout/>
        <returnfiles>['C:/process1.inf', 'C:/process2.inf']</returnfiles>
      </process>
    
      <if expr="RC != 0">
        <log level="'error'">
          'Process failed with RC=%s, Result=%s' % (RC, STAFResult)
        </log>
    
        <elseif expr="STAXResult != None">
          <iterate var="fileInfo" in="STAXResult" indexvar="i">
            <if expr="fileInfo[0] == 0">
              <sequence>
                <log level="'info'">fileInfo[1]</log>
              </sequence>
              <else>
                <log level="'error'">
                  'Retrieval of file %s contents failed with RC=%s' % (i, fileInfo[0])
                </log>
              </else>
            </if>
          </iterate>
        </elseif>
    
        <else>
          <log level="'info'">'STAXResult is None'</log>
        </else>
    
      </if>
    
    </sequence>
    
    In the following example of a process element, the following shell-style command is executed, "grep 'Node Count = ' /tests/cli.out | awk '{print $8}'" redirecting its standard output and standard error to /tests/awk.out and returning the output. Note the use of the caret (^) as an escape character for "{" so that it doesn't try to resolve a variable named "print $8".
    <process name="'Grep_and_awk_numClustNodes'">
      <location>machName</location>
      <command mode="'shell'">
        "/bin/grep 'Node Count = '  /tests/cli.out | awk '{print $8}'"
      </command>
      <stdout mode="'replace'" >'tests/awk.out'</stdout>
      <stderr mode="'stdout'"/>
      <returnstdout/>
    </process>
    
    In the following example of a process element, the command is started in a separate Cygwin shell on Windows, redirecting its standard output and standard error to D:/temp/copy.out and returning the output (if any).
    <process name="'copyFiles'">
      <location>machName</location>
      <command mode="'shell'" shell="'D:/Cygwin/bin/bash -c %C'">
        'cp -fr D:/tests/test1/*.java D:/output/test1'
      </command>
      <stdout mode="'replace'" >'D:/temp/copy.out'</stdout>
      <stderr mode="'stdout'"/>
      <returnstdout/>
    </process>
    
    In the following examples of a process element, a process-action element is specified. The process-action task will be executed after the process starts and will send several messages via the QUEUE service to the process. Here is the Java application used in these examples:
    import com.ibm.staf.*;
    import java.util.*;
    
    public class QueueListener implements Runnable
    {
        private STAFHandle fHandle;
        private Thread fQueueThread;
        private static String delimiter = "";
    
        public static void main(String[] args)
        {
            QueueListener queueListener = new QueueListener();
            return;
        }
    
        public QueueListener()
        {
            try
            {
                fHandle = new STAFHandle("QueueListener");
                System.out.println("QueueListener's handle is: " +
                    fHandle.getHandle() + ". Send a \"QueueListenerExit\" message" +
                    " to terminate the program.");
            }
            catch (STAFException e)
            {
                System.out.println(e);
            }
    
            char[] delimiterArray = new char[80];
            Arrays.fill(delimiterArray, '=');
            delimiter = new String(delimiterArray);
    
            fQueueThread = new Thread(this);
            fQueueThread.start();
        }
    
        public void run()
        {
            STAFResult queueGetResult;
    
            while (true)
            {
                queueGetResult = fHandle.submit2("local", "QUEUE", "GET WAIT");
    
                STAFMarshallingContext mc =
                    STAFMarshallingContext.unmarshall(queueGetResult.result);
    
                Map queueMap = (Map)mc.getRootObject();
                String message = (String)queueMap.get("message");
    
                System.out.println(delimiter);
                System.out.println(message);
    
                // is this a special exit message to tell the program to terminate?
                if (queueGetResult .result.indexOf("QueueListenerExit") >  -1)
                {
                    System.out.println(delimiter);
                    System.out.println("Exiting");
                    System.exit(0);
                 }
            }
        }
    }
    
    In the following example, since the mode="'shell'" attribute is not specified for the <command> element, the queued messages can be sent using the STAXProcessHandle variable.
    <script>
      machName = 'local'
      messages = [
                   STAFUtil.wrapData('First message'),
                   STAFUtil.wrapData('Second message'),
                   STAFUtil.wrapData('QueueListenerExit')
                 ]
    </script>
    
    <process>
      <location>machName</location>
      <command>'java'</command>
      <parms>'QueueListener'</parms>
      <stderr mode="'stdout'"/>
      <returnstdout/>
      <process-action>
        <sequence>
          <iterate var="message" in="messages">
            <stafcmd>
              <location>'local'</location>
              <service>'QUEUE'</service>
              <request>'QUEUE HANDLE %s MESSAGE %s' % (STAXProcessHandle, message)</request>
            </stafcmd>
          </iterate>
        </sequence>
      </process-action>
    </process>
    
    In the following example, since the mode="'shell'" attribute is specified for the <command> element, the queued messages must be sent using the handle name.
    <script>
      machName = 'local'
      messages = [
                   STAFUtil.wrapData('First message'),
                   STAFUtil.wrapData('Second message'),
                   STAFUtil.wrapData('QueueListenerExit')
                 ]
      processHandleName = 'QueueListener'
    </script>
    
    <process>
      <location>machName</location>
      <command mode="'shell'">'java QueueListener'</command>
      <stderr mode="'stdout'"/>
      <returnstdout/>
      <process-action>
        <sequence>
          <iterate var="message" in="messages">
            <stafcmd>
              <location>'local'</location>
              <service>'QUEUE'</service>
              <request>'QUEUE NAME %s MESSAGE %s' % (processHandleName, message)</request>
            </stafcmd>
          </iterate>
        </sequence>
      </process-action>
    </process>
    

    stafcmd: Run a STAF Command

    The stafcmd element represents a STAF command which will be executed on a specified machine.

    Note: If you want to start a process and wait for it to complete (e.g. if you want to submit a START request to the PROCESS service and wait for the process to complete), you should use the process element instead of the stafcmd element.

    After the STAF command has completed, the following variables are set and can be referenced by the job:

    The stafcmd element has one optional attribute:

    The stafcmd element contains the following required elements. These elements must be specified in the order listed here:

    Usage:

    This is an example of a stafcmd element that submits a PING request to the PING service on machine server1.company.com to see if STAFProc is running on that machine. When the STAF command completes, the if element checks the return code variable (RC) set by the STAF command. If the return code is not 0, the PING request failed and a message is logged.

    <sequence>
    
      <stafcmd>
        <location>'server1.company.com'</location>
        <service>'PING'</service>
        <request>'PING'</request>
      </stafcmd>
    
      <if expr="RC != 0">
        <log>
          'STAF %s PING PING request failed with RC: %s, Result: %s' % (RC, STAFResult)
        </log>
      </if>
    
    </sequence>

    This is an example of a stafcmd element that submits a request to the RESPOOL (Resource Pool) service on a machine specified by a variable named resPoolServer. The STAF RESPOOL request is requesting a machine name from a pool specified by a variable named clientPool. When the STAF command completes, the if element checks the return code variable set by the STAF command. If the return code is 0 (aka STAFRC.Ok), the value of the STAFResult variable is stored to another variable named machName, otherwise, the RC and error message are logged. For more information on the STAFRC alias for the com.ibm.staf.STAFResult Java class, see the STAF Java Classes (STAFUtil, STAFRC, STAFVersion, etc) section.

    <sequence>
    
      <script>resPoolServer = "server1.austin.ibm.com"</script>
      <script>clientPool = "clientMachinePool"</script>
    
      <stafcmd name="'Respool Request Pool'">
        <location>resPoolServer</location>
        <service>'RESPOOL'</service>
        <request>'REQUEST POOL %s' % (clientPool)</request>
      </stafcmd>
    
      <if expr="RC == STAFRC.Ok">
        <script>machName = STAFResult</script>
        <else>
          <log message="1">'RC=%s STAFResult=%s' % (RC, STAFResult)</log>
        </else>
      </if>
    
    </sequence>

    If you want to submit a START request to the PROCESS service and wait for the process to complete, you should use the process element, not the stafcmd element. However, if you want to submit a START request to the PROCESS service and not wait for it to complete (e.g. start the process asynchronously) before continuing to the next element in the STAX job, then you can use the stafcmd element. Here's an example of starting notepad on a Windows machine:

    <sequence>
    
      <stafcmd name="'Start Notepad'">
        <location>'client1.company.com'</location>
        <service>'PROCESS'</service>
        <request>'START COMMAND notepad'</request>
      </stafcmd>
    
      <if expr="RC != STAFRC.Ok">
        <log message="1">
          'Starting Notepad failed with RC=%s STAFResult=%s' % (RC, STAFResult)
        </log>
      </if>
    
    </sequence>
    

    In the following example of a stafcmd element, a "SEND MESSAGE" request is submitted to the Email service on machine server1.company.com to send message "STAX Job ID 6 failed" to Jane Smith@company.com.

    Note that STAFUtil's wrapData() method is used to turn strings containing spaces into the colon-length-colon form needed for submitting a SEND MESSAGE request to the Email service. For more information on the STAFUtil Java class, see the STAF Java Classes (STAFUtil, STAFRC, STAFVersion, etc) section.

    <sequence>
    
      <script>
        emailServiceMachine = 'server1.company.com'
        message = 'STAX Job ID %s failed.' % (STAXJobID)
        subject = 'STAX Job Failed'
        address = 'JaneSmith@company.com'
        request = 'SEND MESSAGE %s' % (STAFUtil.wrapData(message))
        request += ' SUBJECT %s' % (STAFUtil.wrapData(subject))
        request += ' TO %s' % (address)
      </script>
    
      <stafcmd>
        <location>emailServiceMachine</location>
        <service>'Email'</service>
        <request>request</request>
      </stafcmd>
    
      <if expr="RC != 0">
        <log message="1">
          'Email request failed with RC=%s STAFResult=%s' % (RC, STAFResult)
        </log>
      </if>
    
    </sequence>

    In the following example of a stafcmd element which executes a FS QUERY ENTRY request on the local machine. A FS QUERY ENTRY request returns a PyDictionary (aka Map) if successful containing information about the file such as its name, type, size, and timestamp that it was last modified. Log the file information in a verbose format by specifying the STAFResultContext variable:

    <sequence>
    
      <stafcmd>
        <location>'local'</location>
        <service>'FS'</service>
        <request>'QUERY ENTRY C:/tmp/testA.exe'</request>
      </stafcmd>
    
      <if expr="RC == STAFRC.Ok">
        <log message="1">STAFResultContext</log>
        <else>
          <log message="1">'FS QUERY failed with RC=%s STAFResult=%s' % (RC, STAFResult)</log>
        </else> 
      </if>
    
    </sequence>

    The message logged in verbose mode could look like:

    {
      Name              : C:/tmp/testA.exe
      Type              : F
      Upper 32-bit Size : 0
      Lower 32-bit Size : 12505
      Modified Date-Time: 20030506-19:14:40
    }

    In the following example of a stafcmd element which executes a FS LIST DIRECTORY LONG DETAILS request on the local machine. A FS LIST DIRECTORY LONG DETAILS request returns a PyList of PyDictionary (aka Map) if successful, where each PyDictionary represents an entry in the specified directory and has keys such as 'name', 'lowerSize', 'type', and 'lastModifiedTimestamp'. It then checks for entries in the directory which are files with a size > 500000 bytes and logs a message containing the names of all the files meeting this criteria, along with their size and the timestamp that they were last modified.

    <sequence>
    
      <stafcmd>
        <location>'local'</location>
        <service>'FS'</service>
        <request>'LIST DIRECTORY C:/tmp LONG DETAILS'</request>
      </stafcmd>
    
      <script>
        msg = ''
    
        if RC == STAFRC.Ok:
          for entryMap in STAFResult:
            # Check if the entry is a file whose size is greater than 500000 bytes
            if entryMap['type'] == 'F' and int(entryMap['lowerSize']) > 500000:
              # Print the name, size, and last Modified Timestamp for the entry:
              msg += 'Name: %s, Size: %s, Timestamp: %s\n' % \
                   (entryMap['name'], entryMap['lowerSize'], entryMap['lastModifiedTimestamp'])
        else:
          msg = 'FS LIST ENTRY failed with RC=%s Result=%s' % (RC, STAFResult)
      </script>
     
      <log message="1">msg</log>
    
    </sequence>

    The message logged could look like:

    Name: en_platformsdk_win2003.exe, Size: 340488704, Timestamp: 20040512-18:07:52
    Name: project-docs.tar, Size: 1239040, Timestamp: 20040517-11:57:10

    job: Execute a STAX Sub-Job

    The job element represents a sub-job which will be executed within the parent job.

    Notes:

    After a sub-job has completed (or if it could not be started) the following variables are set and can be referenced by the job:

    The job element has the following optional attributes:

    The job element contains the following elements in the order listed (with some variations). Refer to the "STAX Document Type Definition (DTD)" section to see the DTD for the job element.

    Note that these elements are equivalent to the options allowed for the EXECUTE request (except where noted), so refer to the "EXECUTE" section for more information.

    The job element must contain either a job-file or job-data element as follows:

    The job element has the following optional elements. Each of these optional elements may specify an if attribute. The if attribute must evaluate via Python to a true or false value. If it does not evaluate to a true value, the element is ignored. The default value for the if attribute is 1, a true value. Note that in Python, true means any nonzero number or nonempty object; false means not true, such as a zero number, an empty object, or None. Comparisons and equality tests return 1 or 0 (true or false).

    Options allowed for the EXECUTE command which are not allowed for the job element are as follows.

    Usage:

    In the following example of a job element, a sub-job defined by an XML file named C:/stax/xml/myJob2.xml (located on the machine specified by STAXJobXMLMachine) is executed and given a job name of "MyJob". Since the monitor attribute is set to a true value, if the current job is being monitored by the STAX Monitor, and the "Automatically monitor recommended sub-jobs" option has been selected in the STAX Job Monitor Properties, a STAX Monitor window will be opened automatically for the sub-job. Also, since the <job-hold> element is specified, the sub-job will be held for up to 1 minute. If the current job is being monitored when the sub-job starts execution, the STAX Monitor will automatically start monitoring the sub-job and release it so that the sub-job is monitored from the beginning.
      <job name="'Job 2'" monitor="1">
        <job-file>'C:/stax/xml/myJob2.xml'</job-file>
        <job-hold timeout="'1m'"/>
      </job>
    
    In the following example of a job element, a sub-job defined by an XML file named tests/testB/xml located on machine myMachine is executed and given a job name of 'Test B'. The job is started by calling function 'Main' and passing this function an argument list of [1, 'server']. In addition, two scriptfiles are specified as well as a couple of script elements. This sub-job is similar to the following STAX EXECUTE request:
      EXECUTE FILE /tests/testB.xml MACHINE myMachine JOBNAME "Test B" CLEARLOGS
              FUNCTION Main ARGS "[1, 'server1']" SCRIPTFILEMACHINE myMachine
              SCRIPTFILE /tests/testB1.py SCRIPTFILE /tests/testB2.py
              SCRIPT "MachineList = ['machA', 'machB'] SCRIPT "maxTime = '1h'"
              WAIT RETURNRESULT
    
    In addition, a job-action element is run in parallel with the sub-job after the sub-job has been started. In this example, it simply logs a message containing the job ID for the sub-job being executed. When the sub-job completes, the return code (RC) set when starting the sub-job is checked so that either a message is logged providing information about the sub-job that run (e.g. it's job ID, status, and result) or a message is logged providing information about why the sub-job could not be started. Checking the RC after a <job> element and logging an error message if the RC is not 0, is highly recommended.
    <job name="'Test B'" clearlogs="'Enabled'">
      <job-file machine="'myMachine'">'/tests/testB.xml'</job-file>
      <job-function>'Main'</job-function>
      <job-function-args>[1, 'server1']</job-function-args>
      <job-scriptfiles machine="'myMachine'">['/tests/testB1.py', '/tests/testB2.py']</job-scriptfiles>
      <job-script>machineList = ['machA', 'machB']<job-script>
      <job-script>maxTime = '1h'</job-script>
      <job-action>
        <log>'Started sub-job %s' % (STAXSubJobID)</log>
      </job-action>
    </job>
    
    <if expr="RC == 0">
      <log message="1">
        'Sub-job %s completed.  Status: %s  Result: %s' % (STAXSubJobID, STAXSubJobStatus, STAXResult)
      </log>
      <else>
        <log message="1" level="'Error'">
          'Sub-job could not be started. RC: %s  Result: %s' % (RC, STAFResult)
        </log>
      </else>
    </if>
    
    In the following example of a job element, a sub-job defined by an XML file named C:/tests/Scenario01.xml located on machine myMachine is executed and given a job name of 'Scenario 01'. The option to clear the job logs is enabled, and all of the testcase logging options are enabled as well, and the python output is being redirected to both the STAX Job User Log and to the STAX Monitor's Messages panel and Python stdout is logged to the STAX Job User Log using logging level 'User1'.
      EXECUTE FILE C:/tests/Scenario01.xml MACHINE myMachine JOBNAME "Scenario 01"
              CLEARLOGS Enabled LOGTCELAPSEDTIME Enabled LOGTCNUMSTARTS Enabled
              LOGTCSTARTSTOP Enabled PYTHONOUTPUT JobUserLogAndMsg PYTHONLOGLEVEL User1
    
    <job name="'Scenario 01'" clearlogs="'Enabled'"
         logtcelapsedtime="'Enabled'" logtcnumstarts="'Enabled'" logtcstartstop="'Enabled'"
         pythonoutput="'JobUserLogAndMsg'" pythonloglevel="'User'">
      <job-file machine="'myMachine'">'C:/tests/Scenario01.xml'</job-file>
    </job>
    
    This example of a job element uses the job-data sub-element instead of the job-file sub-element to define the STAX XML job to be run and evaluates it via Python to a string in the parent job.
      <script>
        machine = 'myMachine'
    
        xml = '&lt;?xml version="1.0" encoding="UTF-8" standalone="no"?>\n'
        xml = xml + '&lt;!DOCTYPE stax SYSTEM "stax.dtd">\n'
        xml = xml + '&lt;stax>\n'
        xml = xml + '  &lt;defaultcall function="Main"/>\n'
        xml = xml + '  &lt;function name="Main">\n'
        xml = xml + '    &lt;function-single-arg>\n'
        xml = xml + '      &lt;function-required-arg name="machList"/>\n'
        xml = xml + '    &lt;/function-single-arg>\n'
        xml = xml + '    &lt;sequence>\n'
        xml = xml + '      &lt;log message="1">\'machList=%s\' % (machList)&lt;/log>\n'
        xml = xml + '      &lt;return>machList&lt;/return>\n'
        xml = xml + '    &lt;/sequence>\n'
        xml = xml + '  &lt;/function>\n'
        xml = xml + '&lt;/stax>'
      </script>
    
      <job name="'My Sub Job'">
        <job-data eval="1">xml</job-data>
        <job-function-args eval="1">[ machine ]</job-function-args>
      </job>
    
      <if expr="RC == 0">
        <log message="1">
          'Sub-job %s completed.  Status: %s  Result: %s' % (STAXSubJobID, STAXSubJobStatus, STAXResult)
        </log>
        <else>
          <log message="1" level="'Error'">
            'Sub-job could not be started. RC: %s  Result: %s' % (RC, STAFResult)
          </log>
        </else>
      </if>
    
    This example of a job element uses the job-data sub-element instead of the job-file sub-element to define the STAX XML job to be run and does not evaluate the value in the job-data sub-element via Python.
      <job name="'My Job'">
        <job-data eval="0">
          &lt;?xml version="1.0" encoding="UTF-8" standalone="no"?>
          &lt;!DOCTYPE stax SYSTEM "stax.dtd">
          &lt;stax>
            &lt;defaultcall function="Main"/>
            &lt;function name="Main">
              &lt;function-single-arg>
                &lt;function-required-arg name="machList"/>
              &lt;/function-single-arg>
              &lt;sequence>
                &lt;log message="1">'machList=%s' % (machList)&lt;/log>
                &lt;return>machList&lt;/return>
              &lt;/sequence>
            &lt;/function>
          &lt;/stax>
        </job-data>
        <job-function-args eval="0">[ 'myMachine' ]</job-function-args>
      </job>
    
      <if expr="RC == 0">
        <log message="1">
          'Sub-job %s completed.  Status: %s  Result: %s' % (STAXSubJobID, STAXSubJobStatus, STAXResult)
        </log>
        <else>
          <log message="1" level="'Error'">
            'Sub-job could not be started. RC: %s  Result: %s' % (RC, STAFResult)
          </log>
        </else>
      </if>
    

    nop: Perform No Operation

    The nop element indicates that no operation should be performed.  This element is typically used in conjunction with the if, elseif, and else elements.

    The nop element is an empty element and no attributes.

    Usage:

    In the following example of a nop element, if an expression is true, then use the nop element to do nothing; else perform function "ErrorRoutine".
    <if expr="RC == 0">
      <nop/>
      <else>
        <call function="'ErrorRoutine'"/>
      </else>
    </if>

    Sequential Execution

    The sequence element may contain any number of STAX elements and executes them serially.

    sequence: Run Tasks In Sequence

    The sequence element represents a container of STAX elements which will be executed serially, in the order in which the contained elements are listed in the sequence.  A sequence element may contain any number of task elements. You may nest sequence elements.

    Usage:

    In the following example of a sequence element, a variable is created. Then the stafcmd element is executed. When the stafcmd element completes, the process element is executed. When the process element completes, the call element is executed. When the call element completes, the sequence element is complete.
    <sequence>
    
      <script>server1 = "machine1.test.austin.ibm.com"</script>
    
      <stafcmd>
        ...
      </stafcmd>
    
      <process> 
        ...  
      </process>
    
      <call function="'VerifyRC'"/>
    
    </sequence>

    Parallel Execution

    The parallel and paralleliterate elements execute tasks in parallel.

    parallel: Run Tasks In Parallel

    The parallel element represents a container of task elements which will be executed in parallel.  Each task element it contains will be executed on a separate STAX-Thread and existing variables are cloned for each thread. The parallel element is considered to be complete when each of its contained task elements has completed.  A parallel element may contain any number of task elements.  You may nest parallel elements.

    Note: To create a global variable that can be accessed across STAX-Threads, use the STAXGlobal class described in "STAXGlobal Class" section.

    Usage:

    In the following example of a parallel element, the stafcmd, process, and call elements are executed at the same time. When all three tasks are complete, the parallel element is complete and processing will continue on to the next element defined after the </parallel> element.
    <parallel>
    
      <stafcmd>
        ...
      </stafcmd>
    
      <process> 
        ...  
      </process>
    
      <call function="'VerifyRC'"/>
    
    </parallel>

    paralleliterate: Run a Task for Each Entry in a List in Parallel

    The paralleliterate element contains a single task element.  The paralleliterate element performs the task for each value in a list. The iterations of the contained task element are executed in parallel (unlike the iterate element whose tasks are performed serially).  Each iteration will be executed on a separate STAX-Thread and existing variables are cloned for each thread.  The paralleliterate element is considered to be complete when all its iterations of the task element have completed.

    Notes:

    1. To create a global variable that can be accessed across STAX-Threads, use the STAXGlobal class described in "STAXGlobal Class" section.
    2. If the list being iterated can contain a large number of items, you may want to specify the maxthreads attribute to perform the task in parallel for a subset of the list so that you don't exceed available memory if too many STAX-Threads are running concurrently.

    The paralleliterate element has the following attributes:

    Usage:

    The following example of a paralleliterate element runs ProcessA simultaneously on a group of machines whose names are contained in a list. The paralleliterate element is not complete until "ProcessA" has completed on all of the machines whose names are contained in the list.
    <script>machList = ['machA','machB','machC','machD']</script>
    <paralleliterate var="machName" in="machList">
      <process>
        <location>machName</location>
        <command>'ProcessA'</command>
      </process>
    </paralleliterate>
    The following example of a paralleliterate element submits a STAF request to the PING service to ping each machine in a list. If the ping fails, the name of the machine which could not be pinged is added to a list. The STAXGlobal class was used to store this list so that it can be accessed across STAX-Threads that are running in parallel.
    <script>
      machineList = ['machA', 'machB', 'machC' ]
      gPingFailList = STAXGlobal([])
    </script>
    
    <paralleliterate var="machName" in="machineList">
      <sequence>
    
        <stafcmd>
          <location>machName</location>
          <service>'PING'</service>
          <request>'PING'</request>
        </stafcmd>
    
        <if expr="RC != 0">
          <script>gPingFailList.append(machName)</script>
        </if>
    
      </sequence>
    </paralleliterate>
    
    <if expr="len(gPingFailList) != 0">
      <message>
        'Could not ping the following machines: %s' % (gPingFailList.get())
      </message>
    </if>
    
    The following example of a paralleliterate element calls a function to run a test on each machine in an input list of machines. Since this machine list could contain hundreds of machines, the maxthreads attribute is being specified to run the test in parallel on a subset (20) of the machines at a time since running hundreds of STAX-Threads simultaneously could cause the STAX JVM to run out of memory.
    <paralleliterate var="machine" indexvar="i" in="machineList" maxthreads="20">
      <block name="'#%s: %s' % (i + 1, machine)">
        <call function="'RunTest'">machine</call>
      </block> 
    </paralleliterate>
    

    Functions

    The function, call, call-with-list, call-with-map, defaultcall, return, and import elements deal with functions and how they are invoked.

    function: Define a Named Task

    To understand how to use the function element, you need to understand the following concepts:

    The function element defines a named task and contains a single task element.  A function element may only be defined within the root stax element.

    The first function called when a job is started is determined by the defaultcall element or by the FUNCTION parameter of an EXECUTE request. Functions are called within a job definition file using the call, call-with-list, or call-with-map elements.

    The function element has the following attributes:

    The function element can also optionally contain the following elements, in the order listed, before the task element:

    The function argument elements are defined as follows:

    A function that does not define its arguments is implicitly defined as:

    <function-single-arg>
      <function-optional-arg name="STAXArg" default="None"/>
    </function-single-arg>
    Note that the function argument elements (function-required-arg, function-optional-arg, and function-other-args) can contain a description of the argument. This information, along with the values of the function-prolog element (or the deprecated function-description element) and the function-epilog element, can be used in conjunction with an XSLT stylesheet to generate a nicely formatted HTML file documenting functions and their associated arguments specified in a STAX job. Refer to the "Generating STAX Function Documentation" section for more information on how to generate HTML documentation for your STAX functions.

    The function-arg-def element can also optionally contain the following elements, in the order listed:

    The function-arg-property element has the following required attributes:

    The function-arg-property element can also optionally contain the following elements, in the order listed:

    The function-arg-property-data element has the following required attributes:

    Usage:

    Goal: Define a simple function containing a sequence element (which can then contain any number of other elements).

    <function name="FunctionA">
      <sequence>
        ...
      </sequence>
    </function>
    Goal: Define a function which you intend to import into other STAX XML job files. The requires attribute defines the two additional functions it requires so that they will be automatically imported as well when FunctionB is imported.
    <function name="FunctionB" requires="FunctionC FunctionD">
      <sequence>
        ...
        <call function="'FunctionC'"/>
        ...
        <call function="'FunctionD'"/>
        ...
      </sequence>
    </function>
    Goal: Illustrate the use of local function scope and the STAXGlobal class. Note that only changes to globalVar (which is an instance of the STAXGlobal class) are visible after function Bar completes. Also, all existing variables are visible inside functions with "local" scope. Thus, variables localVar and globalVar are visible inside function Bar, even though function Bar has "local" scope and had not defined them. The following messages are displayed in the STAX Monitor when this example is run:
    Before Bar: localVar=[1, 2], globalVar=[1, 2]
    After  Bar: localVar=[1, 2], globalVar=[1, 2, 3]
    <stax>
    
      <script>
        localVar = [1, 2]
        globalVar = STAXGlobal([1, 2])
      </script>
    
      <defaultcall function="Main"/>
    
      <function name="Main" scope="local">
    
        <sequence>
    
          <message>
            'Before Bar: localVar=%s, globalVar=%s' % (localVar, globalVar)
          </message>
    
          <call function="'Bar'"/>
    
          <message>
            'After  Bar: localVar=%s, globalVar=%s' % (localVar, globalVar)
          </message>
    
        </sequence>
    
      </function>
    
      <function name="Bar" scope="local">
    
        <script>
          localVar.append(3)
          globalVar.append(3)
        </script>
    
      </function>
    
    </stax>
    Goal: Illustrate the use of the function-import element using an absolute paths and specifying the machine attribute.

    The following imports all functions from file C:/stax/baseFunctions.xml that resides on machine server1.company.com:

      <function-import file="C:/stax/commonFunctions.xml" machine="server1.company.com"/>
    
    The following only imports functions FunctionA, FunctionB, and FunctionC from this file:
      <function-import file="C:/stax/commonFunctions.xml" machine="server1.company.com">
        FunctionA FunctionB FunctionC
      </function-import>
    
    The following imports all xml files from directory C:/stax/libraries that resides on machine server1.company.com:
      <function-import directory="C:/stax/libraries" machine="server1.company.com"/>
    
    Goal: Illustrate the use of the function-import element using relative file names. Assume the following STAX XML files reside on the same machine:
      /stax/MyApp/job1.xml
      /stax/MyApp/commonLib.xml
      /stax/libraries/library1.xml
      /stax/libraries/library2.xml
    
    and you wanted function "Main" in the /stax/MyApp/job1.xml file to import all functions from files /stax/MyApp/commonLib.xml, /stax/libraries/library1.xml and /stax/libraries/library2.xml so that it could call functions from these imported files. You could do this as follows:
      <function name="Main"/>
        <function-import file="commonLib.xml"/>
        <function-import file="../libraries/library1.xml"/>
        <function-import file="../libraries/library2.xml"/>
        
        <sequence>
          ...
        </sequence>
    
      </function>
    
    Instead of specifying two function-import elements to import the two xml files for /stax/libraries, you could use the directory attribute and do it as follows:
      <function name="Main"/>
        <function-import file="commonLib.xml"/>
        <function-import directory="../libraries"/>
        
        <sequence>
          ...
        </sequence>
    
      </function>
    
    Goal: Illustrate the specification of a function which does not allow any arguments to be passed to it. If any arguments are passed to it when called, a STAXFunctionArgValidate signal is raised and the function is not run.
      <function name="NoArgsFunction">
        <function-no-args/>
    
        <sequence>
          ...
        </sequence>
    
      </function>
    
    Goal: Illustrate the specification of a function which requires one argument, duration, to be passed to it. If zero or more than one argument is passed to it when called, a STAXFunctionArgValidate signal is raised and the function is not run.
      <function name="OneRequiredArgFunction" scope="local">
    
        <function-single-arg>
          <function-required-arg name="duration"/>
        </function-single-arg>
    
        <timer duration="duration">
          <loop>
            ...
          </loop>
        </timer>
    
      </function>
    
      This function could be called in any of the following ways with the same result:
    
      <call function="'OneRequiredArgFunction'">'24h'</call>
    
      <call-with-list function="'OneRequiredArgFunction'">
        <call-list-arg>'24h'</call-list-arg>
      </call-with-list>
    
    Goal: Illustrate the specification of a function which requires two map arguments (returnCode and result) and has one optional argument (msg). If the two required arguments are not passed to it when called, a STAXFunctionArgValidate signal is raised and the function is not run. A function prolog element is provided to describe what this function does and descriptions of the arguments passed to the function are also provided.
      <function name="Check-STAFCmd-RC" scope="local">
    
        <function-prolog>
          Checks if a STAFCmd was successful and updates testcase status
        </function-prolog>
    
        <function-map-args>
    
          <function-required-arg name="returnCode">
            Return Code from a STAF Command
          </function-required-arg>
    
          <function-required-arg name="result">
            Result from a STAF Command
          </function-required-arg>
    
          <function-optional-arg name="msg" default="''">
            Message to display if an error occurs
          </function-optional-arg>
    
        </function-map-args>
    
        <if expr="RC == 0">
          <tcstatus result="'pass'"/>
          <else>
            <tcstatus result="'fail'">
              '%s; RC=%s, Result=%s' % (msg, returnCode, result)
            </tcstatus>
          </else>
        </if>
    
      </function>
    
      This function could be called in any of the following ways with the same result:
    
      <call function="'Check-STAFCmd-RC'">
        { 'returnCode': RC, 'result': STAFResult, 'msg': 'This is the error message' }
      </call>
    
      <call-with-map function="'Check-STAFCmd-RC'">
        <call-map-arg name="'result'">STAFResult</call-map-arg>
        <call-map-arg name="'returnCode'">RC</call-map-arg>
        <call-map-arg name="'msg'">'This is the error message'<call-map-arg>
      </call-with-map>
    
    Goal: Illustrate the specification of a function which requires a list argument (machName) and may have any number of additional arguments which will be stored in a list called testList. This example also shows the use of a STAXGlobal variable which is updated across STAX-Threads.
    <function name="RunTests" scope="local">
    
        <function-list-args>
          <function-required-arg name="machName"/>
          <function-other-args name="testList"/>
        </function-list-args>
    
        <sequence>
    
          <script>
            testsRun = STAXGlobal([0])   # Number of tests run
          </script>
    
          <paralleliterate var="testName" in="testList">
    
            <sequence>
    
              <process>
                <location>machName</location>
                <command mode="'shell'">testName</command>
              </process>
    
              <script>testsRun[0] += 1</script>
    
            </sequence>
    
          </paralleliterate>
    
          <message>'Ran %s tests' % testsRun[0]</message>
    
        </sequence>
    
      </function>
    
      This function could be called in any of the following ways with the same result:
    
      <call function="'RunTests'">
        'local', 'ping machineA', 'dir C:\ > C:\out'
      </call>
    
      <call function="'RunTests'">
        [ 'local', 'ping machineA', 'dir C:\ > C:\out' ]
      </call>
    
      <call-with-list function="'RunTests'">
        <call-list-arg>'local'</call-list-arg>
        <call-list-arg>'ping machineA'</call-list-arg>
        <call-list-arg>'dir C:\ > C:\out'<call-list-arg>
      </call-with-list>
    
    Goal: Illustrate the specification of a function that includes a complete desription of the function using the function-prolog and function-epilog elements. These elements utilize a CDATA section so that the text can include standard HTML markup so that when transformed via an XSLT processor (or by using the STAXDoc tool), the text is easily readable. Note this function is actually provided in the sample STAXUtil.xml file provides in the STAX zip/tar file.
      <function name="STAXUtilLogAndMsg" scope="local">
    
        <function-prolog>
          <![CDATA[
          <p>
            Logs a message and sends the message to the STAX Monitor.
            It's a shortcut for specifying the <message> and <log> elements
            for the same message.
          </p>
          ]]>
        </function-prolog>
    
        <function-epilog>
          <![CDATA[
          <h4>Returns:</h4>
          <p>Nothing.  That is, STAXResult = None.</p>
          <h4>Example:</h4>
          <pre>
      <call function="'STAXUtilLogAndMsg'">'Here is my message'</call></pre>
          ]]>
        </function-epilog>
    
        <function-list-args>
    
          <function-required-arg name="message">
            The message you want to log in the STAX Job User log and to send to
            the STAX Monitor.
          </function-required-arg>
    
          <function-optional-arg name="level" default="'info'">
            The level of the message to be logged in the STAX Job User log.
          </function-optional-arg>
    
        </function-list-args>
    
        <sequence>
    
          <message>message</message>
    
          <log level="level">message</log>
    
        </sequence>
    
      </function>
    
    Goal: Illustrate the specification of a function that accepts a map of <function-arg-def> elements. It also demonstrates how function arguments can be denoted as containing private data, as well as defining an enumerated list of values for a function argument. This example includes an argument named "color" that allows values of "red" (which would be the default selection in any form of graphical selection), "blue", and "green".
      <function name="RunCommand">
      
        <function-map-args>
          
          <function-arg-def name="command">
            <function-arg-description>
               A command to execute
            </function-arg-description>
          </function-arg-def>
    
          <function-arg-def name="user" type="optional" default="'anonymous'">
            <function-arg-description>
              The user id to run the command under
            </function-arg-description>
          </function-arg-def>
    
          <function-arg-def name="password" type="optional">
            <function-arg-description>
              The password for the user id
            </function-arg-description>
            <function-arg-private/>
          </function-arg-def>
    
          <function-arg-def name="numTimes" type="optional" default="1">
            <function-arg-description>
              The number of times to run the command
            </function-arg-description>
            <function-arg-property name="type" value="int"/>
          </function-arg-def>
    
          <function-arg-def name="color" type="required">
            <function-arg-description>
              This is the color of the entity
            </function-arg-description>
            <function-arg-property name="type" value="enum">
              <function-arg-property-description>
                This defines this argument as an enumeration
              </function-arg-property-description>
              <function-arg-property-data type="choice" value="'red'">
                <function-arg-property-data type="default"/>
              </function-arg-property-data>
              <function-arg-property-data type="choice" value="'blue'"/>
              <function-arg-property-data type="choice" value="'green'"/>
            </function-arg-property>
          </function-arg-def>
    
        </function-map-args>
      
      <function>
      
      Here is an example of calling this function:
    
      
      <call function="'RunCommand'">
        {
          'command' : 'TestA', 
          'user'    : 'test',
          'password': 'secret',
          'numTimes': 5,
          'color'   : 'red'
        }
      </call>
    

    call: Call a Function

    The call element specifies the name of a function element to be executed. When a call element is executed during the job execution, the function referred to is executed. The call element has the following required attribute:

    Optionally, arguments may be passed when calling a function. The arguments are evaluated via Python in the caller's namespace. If no argument data is specified, then special Python object None is passed to the function. Any kind of argument data can be passed to functions using the <call> element and all of the types of function arguments (<function-no-args>, <function-single-arg>, <function-list-args>, or <function-map-args>) may be specified via this mechanism.

    Usage:

    Goal: Call a function named 'FunctionA', passing no arguments.
      <call function="'FunctionA'"/>
    Goal: Serially call each function (passing no arguments) whose name is in a list.
      <iterate var="funcName" in="['FuncA','FuncB','FuncC','FuncD']">
        <call function="funcName"/>
      </iterate>
    Goal: Call a function which expects one argument.
      <call function="'FunctionWithOneArg'">'Hi'</call>
    Goal: Call a function which expects a list of three arguments.
      <call function="'FunctionWithThreeArgs'">
        5, 'This is a message', ['test1', 'test2']
      </call>
    or
      <call function="'FunctionWithThreeArgs'">
        [ 5, 'This is a message', ['test1', 'test2'] ]
      </call>
    Goal: Call a function which expects a map of two required values named "testList" and "machineList":
      <call function="'Foo'">
        {
          'testList' : ['test1', 'test2'],
          'machineList' : ['machine1', 'machine2']
        }
      </call>

    call-with-list: Call a Function with a Argument List

    The call-with-list element specifies the name of a function element to be executed. When a call-with-list element is executed during the job execution, the function referred to is executed.The call-with-list element has the following required attribute:

    The call-with-list element can contain any number of call-list-arg elements. Each call-list-arg element contains a value for an argument which is evaluated via Python in the caller's namespace and will be passed to the function in the form of a list.

    Usage:

    Goal: Call a function named 'FunctionWithArgs' passing it three arguments in the form of a list.
      <call-with-list function="'FunctionWithArgs'">
        <call-list-arg>5</call-list-arg>
        <call-list-arg>'This is a message'</call-list-arg>
        <call-list-arg>['test1', 'test2']</call-list-arg>
      </call-with-list>
    Note that this is equivalent to the following examples which use the call element instead:
      <call function="'FunctionWithArgs'">
        5, 'This is a message', ['test1', 'test2']
      </call>
    
      <call function="'FunctionWithArgs'">
        [ 5, 'This is a message', ['test1', 'test2'] ]
      </call>

    call-with-map: Call a Function with a Argument Map

    The call-with-map element specifies the name of a function element to be executed. When a call-with-map element is executed during the job execution, the function referred to is executed. The call-with-map element has the following required attribute:

    The call-with-map element can contain any number of call-map-arg elements. Each call-map-arg element has a required name attribute and contains an argument value. Both the name attribute and the argument value are evaluated via Python in the caller's namespace. The arguments are passed to the function in the form of a map of name/value pairs (also known as a dictionary in Python).

    Usage:

    Goal: Call a function named 'FunctionWithArgs' passing it three arguments in the form of a map (Python dictionary).
      <call-with-map function="'FunctionWithArgs'">
        <call-map-arg name="'size'">5</call-map-arg>
        <call-map-arg name="'msg'">'This is a message'</call-map-arg>
        <call-map-arg name="'testList'">['test1', 'test2']</call-map-arg>
      </call-with-map>
    Note that this is equivalent to the following example which uses the call element instead:
      <call function="'FunctionWithArgs'">
        {'size' : 5, 'msg' : 'This is a message', 'testList' : ['test1', 'test2'] }
      </call>

    defaultcall: Specify Default Starting Function To Call

    The defaultcall element specifies the name of the function to call to start the job if no FUNCTION parameter is specified when the job is started using an EXECUTE request. The defaultcall element has the following required attribute:

    Optionally, arguments may be passed via the defaultcall element. The arguments are evaluated via Python. If no argument data is specified, then special Python object None is passed to the function. Any kind of argument data can be passed to functions using the defaultcall element and all of the types of function arguments (function-no-args, function-single-arg, function-list-args, or function-map-args) may be specified via this mechanism.

    A defaultcall element may only be defined within the root stax element, but it is not required.  If a defaultcall element is not specified, a FUNCTION parameter on the STAX EXECUTE request must be specified.

    Usage:

    Goal: Call FunctionA by default to start the STAX job. No arguments are passed to FunctionA.
    <stax>
     
      <defaultcall function="FunctionA"/>
    
      <function name="FunctionA">
        ...
      </function>
      ...
     
    </stax>
    Goal: Call FunctionA by default to start the STAX job. Pass a list of 2 arguments (duration and testList) to FunctionA.
    <stax>
     
      <defaultcall function="FunctionA">[ '24h', ['machA', 'machB'] ]</defaultcall>
    
      <function name="FunctionA">
        <function-list-args>
          <function-required-arg name="duration"/>
          <function-optional-arg name="testList" default="['local']"/>
        </function-list-args>
        ...
      </function>
      ...
    
    </stax>

    return: Return from a Function

    The return element ends the function call and sends a result back to the caller. The return element is optional; if it's not present, a function exits when control flow falls off the end of the function body.

    After the call of a function has completed, the STAXResult variable contains the result sent back from the call. It can be set to any type of object. For example, an integer, a list, a string, etc. This can be especially useful when the function called is defined with a local scope.

    If no return element is specified within a function, or if no value is specified for the result object, STAXResult is set to the special Python None object. If an error occurred calling the function (e.g. invalid arguments, Python Evaluation error), STAXResult is set to a result object called STAXFunctionError.

    Note that because the return sends back any sort of object, it can return multiple values, by packaging them as a tuple. Thus, call by reference can be simulated by returning tuples and assigning back to the original argument names in the caller. See the last example in the Usage section.

    If a value is specified for the return element, it is evaluated via Python.

    The return element has no attributes.

    Usage:

    Goal: Return control to the caller with STAXResult set to RC (e.g. an integer value set by a process or STAF command).
      <return>RC</return>
    
    Goal: Return control to the caller with STAXResult set to None.
      <return/>
    
    Goal: Return control to the caller with STAXResult set to a list. The caller can access the RC by specifying STAXResult[0] and the message by specifying STAXResult[1].
      <return>[RC, 'A descriptive message']</return>
    
    Goal: Simulate call by reference by returning new values in a tuple and assigning the results to the caller's names. After the call, A = 3 and B = ['test1', 'test2', 'test3']
    <function name="FunctionPassByReference" scope="local">
    
      <function-list-args>
        <function-required-arg name="x"/>
        <function-required-arg name="y"/>
      </function-list-args>
    
      <sequence>
        <script>
          x = x + 2
          y.append('test3')
        </script>
        <return>x, y</return>
      </sequence>
    
    </function>
    
    The above function is called from another function as follows:
    
    <script>
      A = 1
      B = ['test1', 'test2']
    </script>
    
    <call function="'FunctionPassByReference'">A, B</call>
    
    <script>
      A, B = STAXResult
    </script>
    

    import: Import Functions From Other STAX XML Job Files

    The import element specifies a set of functions to be imported from other STAX XML file(s). The import element has the following attributes:

    The import element contains the following optional elements:

    If <import-include> is not present, then all functions will be imported (bound by any exclude list). If <import-exclude> is not present, then no functions will be excluded.

    The <import-include> and <import-exclude> elements support grep matching.

    After executing an import element, the STAXResult variable will be set as follows: