0% found this document useful (0 votes)
292 views

Java and Activities

The document discusses activities in Process Commander, which are similar to programs in traditional programming languages. Activities can perform computations, retrieve and update data, and call other activities. The document also covers libraries and functions, key features of activities like steps and methods, and important terminology related to activities.

Uploaded by

Kamesh Anand
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
292 views

Java and Activities

The document discusses activities in Process Commander, which are similar to programs in traditional programming languages. Activities can perform computations, retrieve and update data, and call other activities. The document also covers libraries and functions, key features of activities like steps and methods, and important terminology related to activities.

Uploaded by

Kamesh Anand
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 58

Java and Activities

An activity is a rule that corresponds in many ways to a traditional, procedural program in any
programming language. When learning Process Commander, application designers who have
programming experience often find activity rules easy to learn and understand. However, by design,
Process Commander activities have some important restrictions and constraints that help to prevent
some of the complexity and maintainability issues of conventional programming languages. Activity
rules are important to understand and use when appropriate, but activities are not the dominant or
primary rule type used in an application. Process Commander includes dozens of rule types that can
provide more focus and structure, and may be easier to maintain, than resorting to activity rules.
Activity rules are similar to programs in traditional programming languages in these ways:

contain a sequence of procedural, atomic steps that are by default executed top down
reference a specific instruction (known as a method) in each step
can perform calculations
can retrieve, update and save data
can call other activities
can contain loops or iterations

Java and Activities Overview


The Activities and Java topic category covers information about three types of rules; activity rules,
library rules and function rules.

What are activities? ​


What are libraries and functions? ​
Key features of activities
Important terminology ​

What are activities?


An activity rule can perform computations, create, update, or delete objects, or support user
interactions. Activity rules are most like traditional computer programs, in that they consist of a
sequence of steps that are typically performed in order. Each step contains a primitive operation known
as a method. For example, an activity can fetch a work item from the database, compute new values for
some of the properties in the work item, and save the updated work item back into the database.

Activities are popular with many Process Commander application designers who have previous
programming experience. However, activities are only one of dozens of useful rule types. By design,
activities have limitations and restrictions that improve maintainability and performance, but are
important to understand.

What are libraries and functions?


Process Commander, like Microsoft Excel and many other software products, includes libraries of
functions that can be called to perform various useful calculations. For example, the
DateTimeDifference( ) function computes the days, hours, minutes and seconds between two
moments in time. Functions support a wide variety of processing needs, including date and time
calculations, manipulation of text strings, operations with HTML styles, importing data from files, and
exporting data to Excel. Each library holds a group of related functions.

No knowledge of Java programming is required to use a function (or to execute an activity). Internally,
Process Commander automatically produces Java code from these rules that implements the required
function. (To create a custom function — one not found among the hundreds of standard functions
provided — does require a developer with Java skills.)

Key features of activities


Activities consist of one or a few dozen numbered steps, that are ordinarily executed in order from the
top one listed on the activity rule form to the bottom one. Each step contains an atomic operation
known as a method. For example, the Property-Set method sets the value of one or more properties to
a literal constant value, or to the value of a different property, or to the result of a computation. (This
method is the Process Commander equivalent of an assignment statement such as Area = Width *
Height.)
Many methods add, update, or delete values on the clipboard, a private memory area for each user.
Other methods save clipboard contents into the PegaRULES database. Other methods send an HTML or
XML document to a user's browser.

Most activities contain no more than 20 steps. Within the sequence of steps, processing can jump ahead
to a later-numbered step, identified by a label, based on a conditional test. (Jumping back to an earlier
step, to cause execution to loop, is not allowed. However, limited "repeat-until" loops are supported. ).
The example below has five steps, executed in sequence. Since the Label column is blank, none of these
steps is ever reached by a jump.

Activities can call other activities, which can call


other activities, and so on. This capability promotes modularity and reuse (sharing of common
capabilities) and allows activities that might require many steps to be structured as a set of interrelated
but shorter activities. The Show Calls button presents a display of activity calling relationships; an
example appears at the right.

Like other rules, activities belong to a RuleSet and version. When activity Alpha calls activity Beta, the
system uses rule resolution (in the context of a particular user's RuleSet list) to search for the right Beta
activity to run.

Most methods examine, update or create properties on a clipboard


page. Each user's clipboard is a private temporary memory area, consisting of a collection of named
pages in a tree structure. Each page holds property-value pairs. For example, the Page-New method
adds a new page to the clipboard, specifying its name. The new page may initially be empty. The
Property-Set method adds or updates the value of a property on a clipboard page. The Clipboard tool, a
debugging aid, lets application designers see and interact with a snapshot of their current clipboard.

While activities provide power and flexibility, designers must determine when and how they execute. In
contrast, declarative rules execute automatically whenever certain conditions are met, and so are the
alternative to activities and the recommended "best practice" in many situations.

Restrictions on the size and power of activity rules do not, in practice, limit what application designers
can achieve with activity rules. The restrictions encourage good practices and help prevent difficult-to-
analyze issues like infinite loops, deadlocks, and difficult-to-maintain "spaghetti" code.

Important terminology
Function rule — A rule that performs a computation or other useful operation, based on the value of
input parameters. Function rules are grouped into libraries. The name of the library is part of the formal
name of each member function.

Library — A named collection of function rules, typically all relating to one general theme, such as
calendar dates.

Local variables — A named text value, number or date that is used only temporarily during the
execution of an activity. When the activity completes, the local variables are no longer defined.

Method — One of about 70 atomic operations that can happen in a single activity step. For example,
the Property-Set method updates the value of one or more properties. The Obj-Open method retrieves a
single row of a table in the PegaRULES database and converts it to a clipboard page or pages.

Parameter — An input value to a specific execution of an activity that can affect the behavior and
operation of the activity. For example, if an activity is designed to change the status of a work item, one
of the input parameters is the key of the work item. (Other parameter values can be "return" values,
available to a calling activity after the called activity completes.)

Page — A named, structured collection of property name and property value pairs. The clipboard is a
collection of named pages, organized into a tree structure.

Primary page — A clipboard page that is the default page for the operations of an activity. While one
activity may update multiple pages, if no page is explicitly identified in a step, the method in the step
typically operates on the primary page.

Tracer tool — An interactive debugging tool that lets you display each step of activity execution, pause
or restart execution, and display clipboard values.

Introduction to the Collections feature in the Pega 7 Platform


Modeling complex business logic often involves evaluating several rules under different conditions and
contexts. Running and maintaining the logic under dynamic conditions, such as evaluating a loan
application in the context of fluctuating interest rates and organization policies, present many
challenges. The Collections feature in the Pega 7 Platform helps to overcome these challenges.

Collections enable you to define a set of rules that are referenced in sequence under the specified
conditions and contexts. Collections are business-friendly because they let you use function aliases and
track the rules that bring out the final outcome of the collection.

You use the Collection rule form to create the collection. To create a collection, right-click your
application and click Decision > Collection.

Composing business logic


Each step that you add on the Rules tab is evaluated under the condition and context that you specify.
Additionally, you can trigger a response action based on the outcome of the evaluation.
Collections execute the rules in the specified order along with the response actions

Embedding Java functions


Complex Java functions can be embedded within Collections to create powerful business logic. You can
use function aliases to reference functions:

1. Select Function in the Action drop-down list, and click the down arrow below the Type field to
select from the available function aliases.
2. Enter values in the parameter prompts for the selected function alias. You can pass additional
parameter values when the Get params button is available.
3. Click Copy return value to the field to store the value of param.pxReturnValue in the specified
property.

The list of referenced rules is updated when the underlying function has parameters that are mapped to
rule types.
You can identify the rules that are executed as part of the collection

Adding intermediate logic


Complete the fields on the Pre/Post Actions tab to define pre-actions and post-actions that are evaluated
before and after the collection is processed.

You can specify the set of tasks that you want the Collection to execute before and after it is run

Defining parameters
You can use the Parameters tab to define a list of named data types that can be passed to the
collection. At run time, the values of these parameters are referenced by the fields on the Rules tab and
the Pre/Post Actions tab of the form.

Not every Collection has parameters.

Linking specifications
Use the Specifications tab to create a link between a specification and this Collection. Rules that are
linked to a specification are known as implementations.

Viewing history
Use the History tab of a rule form to define custom fields, review or restore history snapshots, and
maintain usage details. History snapshots are instances of the History-Rule class.

Benefits
Collections can be very useful in Business Rules Engine (BRE) projects or in the BRE portion of a BPM
project. Potential uses include:

Defining and maintaining a list of adjustments that determine the cost of a loan or insurance policy
Defining and maintaining a list of decision rules that qualify or disqualify a loan dynamically,
determining which rule caused the disqualification

While activities sometimes appear to be a natural, general-purpose and flexible way to create business
logic, activities can quickly become complex to analyze, debug, and maintain. The Collections feature
provides a better way to model the orchestration and process behind both simple and complex business
rule logic.

Nine tactics to reduce your need for custom activities (PRPC


6.2 SP2)
Summary
Activity rules allow you to automate work using a procedural, programming-like approach. Some
activities do not require Java skills or the need to manually enter Java code. Because of their power and
flexibility, activities are often customized or created to perform a wide range of specialized and
advanced tasks. While this might seem like an effective approach at first, this technique:

Requires programming skills that only some of the development team members may possess.
May result in complex solutions that are difficult for system architects or business analysts to
understand, implement, and change.
Is an obstacle to reuse, particularly if an activity is designed to accomplish more than one purpose.
Conflicts with the business-maintained, rule-based logic inherent in the PRPC model.
Costs valuable time to develop, debug, and maintain.
May create security vulnerabilities due to hand-crafted JavaScript or Java that might not be tested
or analyzed by PRPC facilities.

A large array of facilities are included in V6.2 and have been augmented in subsequent releases that
provide you with guardrail-compliant and easy-to-use alternatives to activities. This article describes the
enhanced capabilities that are available as of V6.2 SP2, plus a few long-established techniques.

Suggested Approach
Use a data transform rule
Introduced in V6.2, the data transform rule (or simply "data transform") quickly transforms and maps
clipboard data without using activities. In general, the data transform defines how target data (such as
properties and pages) is mapped from and transformed by source data. The data transform rule form is
easy to use and understand — it has only two contexts (target and source), presents an intuitive tree
grid of the actions, and uses contextual prompting that helps guide you through configuration. See
Introduction to Data Transform rules.

Data transforms have been implemented in many areas of the product such as:

User interface elements, which include:


The Client Event Editor's Refresh This Section action
Refresh When conditions used in included sections and harness panels.
On-click control rule and navigation rule actions such as Run Data Transform, Landing Page, Refresh
Section, Show Harness, Harness, and Open URL In Window

Starter flow rules that use the data transform to set initial properties for the work item.
Flow action rules that apply the data transform before or after displaying the flow action user
interface to the user. See Using a data transform rule in a flow action.
Connector flow shapes that apply the data transform before the item reaches the next flow shape.
For example, an Integrator shape connector uses a data transform to map PRPC properties to and
from data in the target external system. Previously, this action was performed using property set
steps in an activity.
Activities generated by the connector and metadata accelerator now reference data transforms to
setup the request parameters and to map the response back to the work object.

Change work item status on the flow diagram settings


As of V6.2 SP2, the Properties panel on every flow shape contains a work status field. The field enables
you to easily change the status at every point in the process. Previously, you had to add Utility shapes
and reference activities in those shapes to invoke a status change. For example, you can quickly define
work status settings when creating a stage presentation on user forms. See How to use stages to
present the chevron view of work item status.

Use linked properties


A special form of property, know as a linked property, can be used to present data from data objects in
a harness, section, or flow action form. Linked properties hold the value of a key to Operator ID,
Organization, Access Group, or other data objects

Using linked properties eliminates the need for an activity to retrieve this data. In some situations, they
improve performance through caching. For example, you can use a linked property to present an
Operator ID directly in a section rule rather than use a Utility shape in the flow to fetch the Operator ID
record, make it available on the clipboard, and have the section access the Operator ID page. See Use
linked properties to display data from related objects

Configure case type dependencies


In hierarchical case management applications, complex activity networks are no longer required to
define when cases, across multiple subcase types, can be automatically completed or instantiated.
These capabilities were introduced in 6.2 SP2:

Mid-flow dependencies — Use a Dependent workbasket assignment shape to instruct the


system to complete a case and advance the flow only when another case type instance reaches a
specified work status. See When and how to use mid-process dependencies.
Instantiation dependencies — Use the Case Designer ( > Process & Rules > Case
Management > Case Designer ) to create instantiation dependencies among subcase types. The
system instantiates a case type when another case type instance starts, completes, or reaches a
specified work status. See When and how to use instantiation dependencies.

Use reports to support user interface displays


As of V6.2, repeating grids, tree grids, and controls all can use report definitions to retrieve data. This
can significantly reduce the need for activities to create and populate top-level pages. See Using a
report definition rule as a grid layout data source.

Declare pages rules now allow you to source data directly from a report definition instead of using a
load activity to create and update declarative pages.

Call Process Engine API activities


The number of process engine APIs has been greatly expanded, reducing the need to create custom
activities. For example, there are now APIs for transferring assignments, transferring cases between
workbaskets and worklists, linking attachments, creating subcases, and many more. To see a complete
list of the APIs, go to > Process & Rules > Process > APIs.

Use State-based validation


As of V6.2, you can use the validate rule to associate sets of validation conditions for each work item
status. The flow actions list the validate rule and the proposed work status, which is passed to the
validation rule so that it can execute the correct validation column. When validation passes, you set the
status on any shape's Properties panel Status tab. See How to set up validation that depends on work
item status.

Use declarative rules


While not a new idea, declarative rules are a proven technique to reduce the need for activities:

Declare Expression rules can ensure that computations involving property values are performed exactly
when and as needed. Unlike activities, you don't need to alter flow rules or other rules to explicitly call
Declare Expression rules. The contents of Declare Pages rules can be based upon a report definition
rule, and the page can be refreshed automatically whenever a value is fetched from the page (or
according to a schedule).

Call an existing, standard rule


Before you create a custom activity, check to see whether an existing standard, out-of-the-box rule
meets your needs. While the Process Engine API activities are specifically provided to support work item
processing, hundreds of other standard rules are available.

Using existing rules reduces your effort and the size of your application.

Additional information
Ten Guardrails to Success

Best practices to avoid cross-site scripting (XSS) vulnerabilities

Introduction to activities

Introduction to activities
Activity rules are one way to automate the processing of work by using a procedural, program-like
approach, without requiring Java skills or manually entering Java code. An activity is presented as a
series of steps, with some of the features of an object-oriented programming language, such as
iterations and conditions.

If you have programming experience, activities appear to be a natural and flexible way to create
rules; however, activities can quickly become complex to analyze, debug, and maintain. Use activities
only when there are no other more appropriate rule types. For example, instead of using a series of
activity steps, use a declare expression rule to calculate declaratively, rather than procedurally.
Similarly, use a when rule, decision table, map value rule, decision tree rule, or parse rule whenever
these rule types capture the business requirements well.

If you decide that an activity rule is appropriate, review the standard activities that Pega Platform™
includes. These activities apply to the @baseclass, Work-, Assign-, and History- classes. When possible,
call a standard activity and avoid writing custom activities.

When you write activities, keep the following best practices in mind:

Keep activities short. Limit your activities to fewer than 25 steps.


Limit hand-coded Java. Avoid Java steps in activities when standard or custom rule types, library
functions, or activity methods are available.

The following sections describe the activity rule form, methods, and give an example activity:

The activity rule form


Methods
Example activity

The activity rule form


The main tab on the activity rule form is the Steps tab. Steps are performed in sequence starting at step
1, unless you define conditions for skipping steps.

Each step contains the columns shown below:

The Steps tab

Column Description
Label Optional. Provide an identifier for the step that can be referred to from other steps.

Optional. Loops through the elements of a value list, page list, value group, or page group
and performs the provided activity method on each value or each embedded page.
Loop
If you define a loop, you can also create nested (child) steps. To add a nested step, right-
click the step number and click Add child.

Optional. Before the step is run, a condition is evaluated. Based on the result, the step is
When
either performed or skipped.
> (Expand
After you enter the Method, click the button to enter the method parameters.
method)
Method Optional. Select the method that this step will perform.
Optional. Identify a page to be used as the context for referenced properties within the
Step page
step. Define the page on the Pages & Classes tab.
Description Enter text that explains to other developers the action that the step is performing.
Optional. After the step is run, a condition is evaluated. Based on the result, the activity
Jump
can jump ahead to a higher-numbered step, or end.

The steps in an activity roughly correspond to statements in a traditional programming language. The
three control structures in activities — iteration, precondition, and transition — are intentionally limited.

Parameters tab
Define variables that input data to, or return data from, an activity. Parameter names and values are
held on a special clipboard page, known as the parameter page, which is not visible with the Clipboard
tool.
Use the notation param.<ParamName> to reference a parameter value.

Pages & Classes tab


Define the pages to be used as step pages for the steps of the activity. Enter a page name and
associate each name with a class.

At run time, the system uses this information to find properties that are referenced on the Steps tab by
using the notation .<propertyname>, where the page name is identified in the Step page field. The leading
period (or dot) is required.

The system also uses information on this tab to interpret property references of the form <pagename>.
<propertyname>, which might appear in various fields on the Steps tab.

Security tab
Specify the type of activity and optionally restrict how this activity can be started.

Note: The most common activity type is Utility.

back to top

Methods
A method is an operation that is performed in one step of an activity. This section describes
some frequently used methods. For additional details and descriptions of other methods, see Methods
and instructions by name.

Property-Set
The Property-Set method sets the value of one or more properties.

Usage

Specify the property in the PropertiesName field and the desired value in the PropertiesValue field.
Click Add item to enter more properties.

Call
The Call method instructs the current activity to find and run another activity by using rule resolution.
After the called activity completes, the calling activity resumes processing. The called activity can use
its own parameter page or share the parameter page of the calling activity. Configure this by selecting
the Pass current parameter page check box in the method parameters.

The main advantage of calling an activity is reuse. You can reference the activity and call it from other
rules instead of including all the steps in one activity.

Usage

Identify the activity you are calling by typing Call in the Method field, followed by a space, and the
activity name; for example, Call UpdateRecords. After you type or select the method Call, you can press the
Down Arrow key to select an activity.

Branch
Similar to the Call method, the Branch method runs another activity. The original activity ends when the
branched activity is complete.

Usage

The usage of the Branch method is similar to the Call method.

Obj-Browse
The Obj-Browse method searches for instances of one class and copies specified properties onto the
clipboard, creating a list of instances, each on an embedded page.

Usage

At a minimum, complete the PageName and ObjClass fields, and in the Field field, specify the properties
to return or to use as filters. Click Add item to add more fields.

Obj-Browse parameters

The Condition value (other than Value Only) filters the records that are returned, similar to using a
WHERE statement in an SQL command. The following conditions are available.

Obj-Browse conditions

The conditions highlighted in yellow do not need an entry in the Value field. For other conditions, enter
a property name or a regular expression in the Value field.

A completed Obj-Browse method is similar to an SQL statement of this form:

Select <FIELDS> from the <OBJCLASS> where <CONDITIONS = A VALUE> and place them on the <PAGENAME> page.

Note: Filter fields must be exposed as database columns. However, the method can retrieve values of
properties that are not exposed, including embedded properties.

Obj-Open
The Obj-Open method returns a single instance that is stored in the Pega Platform database or in an
external database table that is linked to an external class. The returned instance is converted to a
clipboard page. This method differs from the Obj-Browse method because it does not use search
conditions; it requires you to identify the key of the instance.

Usage

In the OpenClass field, enter the name of the class where the system should start searching for the
instance. The search continues up through the class hierarchy until the instance is found. Use the
PropertyName and PropertyValue fields to specify the key of the instance. Click Add item to specify
more key property names and values.

If your application updates and saves the instance, select the Lock check box to prevent other
requestors from updating the instance while your requestor is using it.

Obj-Open parameters

Data from the returned instance is placed on the Step page.

Page-Copy
The Page-Copy method copies the entire contents (all properties and embedded properties) of an
existing clipboard page to a new or existing clipboard page.

Usage

In the CopyFrom field, enter the name of the page to be copied. In the CopyInto field, enter the
destination page.

Page-Copy parameters

You can apply a model to the destination page before the page is populated with data by entering a
value in the Data Transform field. Rule resolution finds the model.

You can save the name of the new page as the final element in a value list by entering the list name in
the PageList field.

Page-Remove
The Page-Remove method deletes one or more pages from the clipboard.

Page-Remove parameters

To remove a page, enter one or more page names in the Page field, or enter the page name in the Step
page field.

To reduce system overhead and improve performance, remove clipboard pages when they are no
longer needed.

Show-Page
The Show-Page method sends an XML representation of the Step page to your browser window. This
method is primarily used for debugging.

Example activity
A simple activity can update a property for one Operator ID instance by opening the instance, updating
the clipboard page, saving the updated clipboard page, and committing the result to the database. This
example shows how methods work together and does not cover security, validation, locking, error
handling, or performance considerations.

First, the activity opens an Operator ID record, based on the value of a parameter, and copies the data
from the database to a clipboard page. Next, the activity updates the user locale, update time, and
name of the user who updated the record. Finally, the activity saves the updated page back to the Pega
Platform database, making the updates permanent.

Each step of the activity and its corresponding method are described below.

1. On the Parameters tab, define the parameters that identify the Operator ID to be updated and the
new locale value.

Parameters tab

2. On the Pages & Classes tab, enter the name of a page that holds the contents of the Operator ID
record that is returned by the Obj-Open method.

Pages & Classes tab

3. On the Steps tab, do the following.


1. Add an Obj-Open method. This method opens a single record from the database and copies it
to a clipboard page. Enter the values shown below to specify that the value of the
.pyUserIdentifier property on the Operator record equals the value of the parameter that is
defined on the Parameters tab.

Example: Obj-Open

Note: Methods that return data from an object (such as Obj-Browse and Obj-Open) put the
returned data on the Step page.

2. Add a Property-Set method to update the pyUseLocale property and two other properties. List
the Step page again. This provides context for the properties that are selected so you do not
need to provide the page name before the period that precedes the property name.

Example: Property-Set

Note: @CurrentDateTime() is a standard function rule that returns the current system date
and time.

3. Save the updated record and commit it to the database using two separate methods.

Example: Obj-Save and Commit

Note: For activities that are used in flow processing, do not include a Commit step. Built-in
activities contain Commit methods at the appropriate places.

4. Remove the Operator page from the clipboard by adding a Page-Remove method. This frees
up memory that is no longer needed. In the Step page field, enter the name of the page to be
removed.

Example: Page-Remove

At this point, you can test the activity. After you run the activity, you can see the updated data on the
Operator ID rule form. To help with testing, include a Show-Page method to display the Operator page
contents before or after the Property-Set step.

Example: Show-Page

Testing the example

To test the activity, do the following steps:

1. Click Actions > Run.


2. Notice the parameter names; these are the names that you defined on the Parameters tab.
3. Enter a value for each parameter.
4. Click Run to start the activity.
Run parameters

When the processing reaches the Show-Page step, the page contents appear as an XML document in a
browser window.

The page output appears as shown below. Notice the pyUserIdentifier and the updated pyUseLocale
values.

Show-Page output

For more complex activities, the Clipboard tool and Tracer tool are valuable debugging aids.

Contrasting PRThread objects and Java threads


Question
A developer asks: Are the threads in Process Commander like the operating system's threads? How can
separate threads run under the one requestor?

How should I think about threads and requestors when considering background processes I want to run?

Response
The terms threads and Threads mean different things in Process Commander.

The separate "threads" that can run under the same requestor (created, for example, through
launching a separate Process Commander portal) are PRThread objects used inside the system.

Informally, these are frequently referred to as "Capital T threads." They are not the "small t threads"
that commonly identify the operating system's execution contexts..

A PRThread, or Thread, is a data structure used in the system to allow a requestor to have separate
clipboard page name spaces that do not interact with each other. This allows a single requestor to run
multiple copies of a workflow near-simultaneously (at least in the user's perspective), so users can
process two work objects on one workstation, in two browser windows.
A requestor can have multiple Threads, but the Threads are guaranteed to never run concurrently.
Attempting to run them concurrently causes one to run and the others to block until the first
completes. These Threads are assumed to be usable only as cooperating parts of the online
environment. They are each really nothing more than a page name scope.

When attempting to perform processing in background, do not attempt to create Threads from an
interactive process. They won't provide the desired results, since only one Thread can be interacted
with by a user at any moment. To perform background processing, you need to use a separate
requestor.

In an interactive workflow environment, your application includes processing that can occur in the
background (so that users do not have to wait for it), you can create a new requestor using Public API
calls. The new requestor is provided an activity to run and a reference to a clipboard page. A copy of
this page becomes the called activity's primary page. The new requestor then processes in a new,
separate, operating system thread.

In a services-oriented environment, or a batch processing environment, each new arriving request can
create a new requestor automatically. Service requests then each proceed independently; Process
Commander may return responses in an order other than the order that the requests arrived.

As an alternative, you can perform background processing with agents. Agents are available in both
interactive and service environments. An agent (Rule-Agent-Queue rule type)is a RuleSet-based list of
activities that each run periodically to handle background tasks, with no user intervention. Process
Commander includes three standard agents.

For details, review the PublicAPI Javadocs for:

Package com.pega.pegarules.pub.context
Interface PRRequestor
Methods java.lang.Object queueBatchActivity, stopBatchActivity, and waitOnBatchActivity.

How to compare Java string values


Summary
Java provides two ways to compare objects:

1. Using the == operator to directly compare the objects.

2. Using the .equals() method to compare either the objects or the object values.

When comparing String objects, it is important to use the String.equals() method instead of the ==
operator, since you want to compare the values of the objects, not the actual references involved.

In Process Commander V5.1, some internal handling of clipboard property values and other string
objects were changed, so that using the == operator may not work the same way as it did in Process
Commander V4.2.

Below are two small pieces of Java code which exhibit different behavior.

The first example prints out the result "the same", but only because the references s1 and s2 are the
same:

String str1 = "foo";


String str2 = "foo";

if (str1 == str2) System.out.println("the same");

This second example does not print out the result "the same", because even though the values are the
same, it's comparing the references themselves:

String str1 = "foo";


String str2 = "fo";
str2 += "o";
if (str1 == str2) System.out.println("the same");

For the second example to work, the equals() method should be used to compare the values of the two
objects. This third example does successfully print out the result "the same":

String str1 = "foo";


String str2 = "fo";
str2 += "o";
if (str1 .equals( str2 ) ) System.out.println("the same");

Suggested Approach
Always use the String.equals() or String.equalsIgnoreCase() Java methods to compare the values of two java String
objects -- not the == operator.

How to use drag and drop operations on the Activity form


Summary
To speed the development of activities, you can use drag and drop to reorder steps within an activity or
drag a step to a different activity in the same or another RuleSet version. You can also cut (or copy) and
paste these elements within or across activities in the same or different RuleSet versions.

Additionally, you can reorder these elements:

Parameters and local variables on the Parameters tab


Pages on the Pages & Classes tab
Security privileges on the Security tab

(Ordering these elements does not affect the operation of the activity, but may improve the readability
and clarity of the rule.)

Suggested Approach
In this example, you create steps for setting properties related to car, truck, and SUV manufacturers.
Each step contains Property-Sets for ten different manufacturers of the vehicle styles.

Drag and drop within an activity


If you discover that a step must be moved to another location within the activity, use drag and drop. To
move Car Manufacturer List, for example, place your cursor over step number 1.. Your cursor will
change to a pointing finger. Left-click the 1., and drag the step to its new location. The result is shown
below.

Drag and drop to another activity


You can move steps from one activity to another. Each activity must be open in a separate window.
When you click the toolbar Launch button ( ) , a new window containing the activity will open. In the
example below, two activities, GetVehicles and GetMotorcyles, are open in one window.
When you click Launch ( ), the GetMotorcyles activity opens in a separate window. Position the two
windows so that you can access the step numbers. This will enable you to click a step, such as Truck
Manufacturer List, in one activity and drag a copy to another activity.

The Truck Manufacturer List step from the GetVehicles activity was successfully dragged to the
GetMotorcycles activity, where it can be used or modified.

Copy (or Cut) and Paste


You can leverage work you already completed by using Copy (or Cut) and Paste. For example, if a new
step is required for listing tractor manufacturers in this or another activity, you can copy the Car
Manufacturer List step, paste it into the new location, then modify Description, Step Page, and
Property-Sets of the newly copied step for the tractor manufacturer list.

1. Right-click the number of the step you want to copy.


2. Select Copy from the pop-up menu.
3. Position the cursor on the numbered step in the activity where you would like to place the copy,
then right-click.
4. Choose from the pop-up menu:

Paste - replaces the step with the contents of the copied step
Insert Above - inserts the copied step above the current step
Insert Below - inserts the copied step below the current step

5. Make any required modifications to the the copied step.

The Car Manufacturer List step from the GetVehicles activity was copied to the GetTractors
activity, then modified for tractor manufacturer information.

Methods
When to set the WriteNow parameter in the Obj-Sav and Obj-
Delete methods
Summary
The WriteNow option to the Obj-Save and Obj-Delete methods is useful in a few very specific scenarios
only. System Architects should take care to use this option only in places where it will not interfere with
standard flow processing. Standard flow processing already saves and commits work information, and
an interceding Obj-Save with the WriteNow option can cause information to become inconsistent.

Explanation
The WriteNow option instructs the PRPC engine to immediately save and commit the page specified,
and includes several ramifications. The Obj-Save WriteNow transaction:

Can be overwritten by a previous deferred Save (for example, in the case of flow processing)
Prevents rollback when there are errors with the statement
Does NOT represent the end of a transaction in and of itself
Does NOT release a lock or terminate other deferred saves

Suggested approach
Use the Obj-Save method with the WriteNow option primarily outside of flow processing.

Here are some examples of when to use Obj-Save with the WriteNow option selected:

In a rule called by a SOAP service, you might save one object with the WriteNow option selected
because it is unnecessary to perform a deferred transaction (Obj-Save or Obj-Delete) for one object
that is immediately followed by a Commit transaction.
Write to a log or history class to report progress during a larger transaction.
Write a new object out to disk during a larger transaction so that a subsequent database browse
picks it up.

Additional information
Troubleshooting: Error - Flow Not At Task with incorrect use of WriteNow parameter in Obj-Sav method

Design Time Warnings for WriteNow and Obj-Save

How to correct the Write Now warning for activity rules

How to write an agent activity

How to create activities that attach files to work

Use the Obj-Filter method to refine results of the Obj-List-


View method

Summary
A developer asks:

How can I create a list — a Page List of embedded pages —for selected instances of a
class, where the selection criteria involve some properties that are exposed as
database columns, and other properties that are embedded within the instances?

I understand that the Obj-List-View method can create a clipboard page listing those
objects that meet certain selection criteria (as recorded on on the Content tab of a
list view rule). However, in the list view rule, the criteria can test only values of top-
level properties that correspond to exposed database table columns.

How can I then delete those initially selected pages that don't meet my other
criteria (based on properties that are embedded)? Finally, I want to rearrange the
remaining pages so that there is no gap in the index numbers
Suggested Approach
The question has two parts. To answer the second part first, the system automatically adjusts
the index numbers of embedded pages so that, when you remove a page, there is no gap in
the index numbers.

The requirement: A developer wants to get a Page List of Operator IDs who belong to the
AlphaCorp organization and who have at least one period when they will not be available.

The example activity below first uses the Obj-List-View method and a criterion
(.pyOrganization EQUALS "AlphaCorp.com") based on an exposed column, pyOrganization.
The result of the Obj-List-View method is a page of class Code-Pega-List containing an
embedded page (pxResults(1), pxResults(2)....) for each operator in the AlphaCorp.com
organization.

Next, the activity uses the Obj-Filter method and a When rule to retain only the embedded
pages for operators who have at least one value for the embedded property
pyUnavailablePeriod(1).pyUnavailableFrom .

Example

To set operator availability, select View > Organization > Operators, and select any operator.
You can set or modify the operator's unavailable periods at the bottom of the Work Settings
tab:

To see the effect of Obj-Filter on the Page List, make sure at least one operator in a specific
organization (AlphaCorp.com in this example) has an unavailable period entered.

1. Create a list view report of the operator IDs in the system. On the Display Fields and
Content tabs, include .pyUnavailablePeriod(1).pyUnavailableFrom and, optionally,
.pyUnavailablePeriod(1).pyUnavailableTo (if an operator has multiple unavailable periods,
the report only lists the first one).
2. On the Content tab, select only those operators belonging to the AlphaCorp.com
organization. The pyOrganization property is exposed as a column in the operator table.

3. On thePages & Classes tab, specify a page of class Code-Pega-List to receive the results
of the report. This example uses AbsentOperatorsList as the page name. Reference
this page on the Content tab.

4. Create an activity to call the list view. In the first step of the activity, call the Obj-List-
View method. Reference the three key parts of the list view rule as values for the Obj-
Class, ListView, and Owner method parameters.

5. On the Security tab, check the May Start? check box.


6. Run the activity and view the clipboard. The AbsentOperatorsList page has one
embedded page for each Operator ID in the system who belongs to the AlphaCorp.com
organization.

Note that the second embedded page has no values for an unavailable period.
7. Create a When rule to check for unavailable periods:

If an operator has listed an unavailable period, the when rule returns the value True for
that operator.
8. Add a step to the activity that calls the Obj-Filter method and references the when rule
you created. This step removes the embedded pages of operators who do not have a
listed unavailable period:

9. Run the activity again and refresh the clipboard display. Now the AbsentOperatorsList
page only has embedded pages for the operators who had listed an unavailable period.
Note that the second embedded page now represents an operator who has an
unavailable period, and that the system has adjusted the index numbers for the
embedded pages:
When and how to use the Flow-New method
Summary
This article summarizes how to use the Flow-New method in an activity step.

Suggested Approach
In V3.2, the Flow-New method can only be used on an activity with a primary page that is either the
work object, or an embedded page of the work object. The new flow is added to the work object, and
the flow's primary page -- also known as the interest page -- is set to the step page.

In V4.1, the Flow-New method exclusively uses the step page. This allows an activity to create a page
and start a flow execution on it (which in V3.2 required two activities or a Java step).

If the step page is an embedded page, then the flow is added to the top-level page containing the step
page. The flow's primary page (the interest page) is still the step page.

Use the Obj-List method to determine whether an object


exists without opening it
Summary
A developer asks: I need a test that efficiently verifies that a Loan work object already exists in the
database.

I don't need any information from this object - I just need to know whether it already exists. What's the
most efficient mechanism for implementing this? The Obj-Open method seems too expensive

Suggested Approach
Define an activity dedicated to such duplicate-checking that does a simple query.

For example, you can use the Obj-List method for the query, specifying criteria to get only exact
matches. Specify only a very short list of properties to be returned as results.

How the Obj-List method processes blank database columns


(versus V4.2SP1)
Summary
The Obj-List method filters data in the database, based on the information specified in the activity
fields.

In the above example, the method returns all instances of the Data-Admin-WorkBasket class where the
property .pyWorkGroup has a value between "pxRequestor.pxWorkGroup" and "
pxRequestor.pxWorkGroup". (This can specific a range, or just one value repeated.)

If the SelectFrom and SelectTo parameters are blank, processing depends on the Process
Commander release:

In Version 4.2 Service Pack 1, if these fields are blank, then at runtime the system ignores the
SelectionProperty row. Thus, if there is only one SelectionProperty, and it has empty From and To
fields, the system ignores it and returns all instances of the specified ObjClass, up to the
MaxRecords limit. If there is more than one SelectionProperty row, the system ignores the blank
rows, and processes only with the rows that have From or To values.
In V4.2SP2 SmartBuild and later, if these fields are left blank, then at runtime the system returns
instances of the ObjClass where the specified property has a blank value. Thus, in the above
example, if SelectFrom and SelectTo were blank, then the system will return all instances of the
Data-Admin-WorkBasket class where the value of property .pyWorkGroup is blank.

Suggested Approach
If your system includes activities you developed in Version 4.2SP1 or earlier versions, these activities
may depend on the old behavior.

If you are unable to research and adjust Obj-List steps, set the list42sp1 setting in the Compatibility node of the
pegarules.xml file to provide backward compatibility. (This feature is available in V4.2SP6 and later
versions.)

<node name="Compatibility">
<map>
<entry key="list42sp1" value="false" />
</map>
</node>

The default for this boolean entry is false.

When the entry is set to false , the system uses V4.2SP4+ behavior, where it selects values of the
property equal to "blank."

When the entry is set to true , then the system uses V4.2Service Pack 1 behavior, and ignores any
SelectionProperty where the values are blank.

Understanding the Obj-Refresh-And-Lock method


Question
How does the Obj-Refresh-And-Lock activity method work, and what benefit does it provide over Obj-
Open?

Response
Use Obj-Refresh-And-Lock when you have a clipboard page containing an instance that you do not have
a lock on, and you decide to update the instance. It may also be used in cases where you are not sure
whether the instance is locked (such as in utility activities that may be called in various places).

Obj-Refresh-And-Lock locks the instance and ensures that the version you have on a clipboard page is
the same as or newer than the version currently in the database. This ensures that you will not
overwrite anyone else’s changes when you ultimately save the instance, and it also ensures that
nobody else will overwrite any of your changes.

You can use this method, for example, after displaying an instance to a user in read-only mode, when
that user indicates that he would like to update the instance.

Calling Obj-Refresh-And-Lock is similar to, but not identical to, calling Obj-Open with the Lock parameter
set to true. The difference is that Obj-Refresh-And-Lock does not read the instance from the database if
the version of the instance on the clipboard is the same as or newer than the version in the database.
So if any changes were made to the instance on the clipboard page since it was previously opened, they
are preserved.

On the other hand, when you call Obj-Open, it always overwrites the instance on the clipboard page
with the version from the database — even if this means overwriting changes that you had made to the
clipboard page.

Because of these differences, Obj-Refresh-And-Lock is in many cases more efficient than Obj-Open, and
it is safer.

To determine whether the version of an instance on a clipboard page is the same as the version in the
database, Obj-Refresh-And-Lock compares the values of the pxCreateDateTime and pxUpdateDateTime
properties on the clipboard page to the values of the pxCreateDateTime and pxUpdateDateTime
columns of the corresponding database record.

When to use Obj-Refresh-And-Lock

Use Obj-Refresh-And-Lock when you have a lockable instance but you do not know whether it is
locked, and you need to update that instance. Use Obj-Refresh-And-Lock only if there’s a good
chance that the version you have on the clipboard is the most up-to-date.

For this activity method to work correctly, follow these best practices:

Do not update clipboard pages containing instances that come from the database unless you
hold a lock on the instance.

Also, be sure that the pxCreateDateTime and/or the pxUpdateDateTime properties of an


instance are correct before you save the instance..

Finally, do not take out locks by directly calling a lock API method. You should always use Obj-
Refresh-And-Lock or another Open-* method to lock instances.

Note that this method does not work with instances of classes that use rule resolution.

Details

Obj-Refresh-And-Lock is called on the clipboard page containing the instance that you wish to ensure is
current.

First, the Obj-Refresh-And-Lock method checks to see if its caller already holds a lock on this instance.
If this is the case (and assuming that the best practices have been followed) then it must be true that
the version of the instance on the caller’s clipboard page is already the most up-to-date — otherwise the
caller would not have been able to lock the instance. In this case, Obj-Refresh-And-Lock does not need
to read the instance from the database.

If the instance is not already locked by the caller, then Obj-Refresh-And-Lock attempts to lock the
instance. If it cannot do so because the instance is locked by someone else, then Obj-Refresh-And-Lock
indicates failure: the instance is still read from the database, but the processing status is set to Error with
message Database-LockFailure-LockHeldByAnother. Additionally, the lock status page specified in the LockInfoPage
parameter identified which requestor currently owns the lock. The caller must detect this failure..

If Obj-Refresh-And-Lock is able to lock the instance, then it compares pxCreateDateTime and


pxUpdateDateTime of the version of the instance on the clipboard page with pxCreateDateTime and
pxUpdateDateTime of the version of the instance in the database, to see which is newer. It compares
dates as follows:

It compares the pxUpdateDateTime of the clipboard page with the pxUpdateDateTime column of
the instance in the database. If pxUpdateDateTime is not set on either, then it goes on to compare
pxCreateDateTime. If pxUpdateDateTime is the same in both versions (within a tolerance that
accounts for rounding in the database column), then Obj-Refresh-And-Lock knows that the version
of the instance on the clipboard page is the most up-to-date—so Obj-Refresh-And-Lock does not
need to read the instance from the database. If pxUpdateDateTime is different in the two
versions, then it must be the case that the instance in the database has been updated since the
instance on the clipboard page was read—so Obj-Refresh-And-Lock reads the entire instance from
the database.

Note on the rounding: Since different databases round date/time amounts to different
precisions, the value of a date/time database column may not always be exactly equal to the
value in the corresponding database column in the storage stream. For this reason, when
comparing date/times from a clipboard page to date/times in a database column, Process
Commander cannot expect an exact match.

If pxUpdateDateTime is not set on either version of the instance, then Obj-Refresh-And-Lock


compares the pxCreateDateTime of the two versions. If pxCreateDateTime is the same in each
version (within a tolerance), then Obj-Refresh-And-Lock knows that the version of the instance on
the clipboard page is the most up-to-date, so it does not need to read the instance from the
database. If pxCreateDateTime is different in the two versions, then the instance in the database
must have been updated since the instance on the clipboard page was read—so Obj-Refresh-And-
Lock reads the entire instance from the database.

If the instance being opened is on the deferred operation list—that is, the instance has previously been
saved by the caller but the Commit method has not yet been called—then the timestamps on the
version of the instance on the clipboard page are compared with the timestamps of the version of the
instance on the deferred operation list, not the version in the database, in the manner described above.

Diagnostics for Obj-Refresh-And-Lock

You can get diagnostic information for Obj-Refresh-And-Lock by setting to debug the log4j diagnostic
level for the following Java class:

com.pega.pegarules.engine.database.Opener.

Use the Property-Remove method to delete an embedded


page
Summary
A developer asks: If you have a page containing several embedded pages in the property
ADataPartyPageList, how can you delete a specific page and rearrange the remaining embedded pages
so that there is no gap in the index?

Example

In the following example, steps 1 through 6 create a top-level page and two embedded pages named
ADataPartyPageList(1) and ADataPartyPageList(2). Step 8 then deletes the embedded page
ADataPartyPageList(1).

Suggested Approach
Use the Property-Remove method with the embedded page ADataPartyPageList(1) as the parameter.

Deleting one page from a Page List property causes the remaining pages to be adjusted so that there is no
gap in the indext. Note that the method used is Property-Remove, not Page-Remove, as the page you
wish to delete is embedded.

Example
Continuing the above example, enter the following for step 8:

How to evaluate a map value rule and handle errors


Summary
Use one of two methods to call a map value rule (Rule-Obj-MapValue rule type) from an activity and
properly handle any errors it may return.

Suggested Approach

Activity approach
In an activity, use the Property-Map-Value or Property-Map-ValuePair methods. The Property-Map-Value
method evaluates the map value as one-dimensional. The Property-Map-ValuePair evalates the map
value rule as two-dimensional.

Complete the method parameters:

The return value from the map value is stored into the property (or parameter or local variable)
specified in the PropertyName field, much as with the left-hand side of a Property-Set.
The MapName field is the second key part of the map value rule; do not include a class like Work-
.myMapValue.
The RowInput field (and ColumnInput for Property-Map-ValuePair) is optional and overrides the
default input (if one is specified) in the map value.
Check the AllowMissingProperties parameter if processing is to continue normally when a
referenced property is not present. (For scalars, a missing property is one with a value of ""; for
other property modes, results are unpredictable.)

Allowing missing properties


If AllowMissingProperties is not checked, then your application needs to handle the possibility of a
missing property.

This functionality is useful. For example, a map value calculates the value of a used vehicle. When
given input of a motorcycle, it needs values for the mileage. If a property value for mileage is not
present on the page, the user can then be prompted for the mileage.

To check for this situation, include the following test in the step's transition (or the next step's
precondition):

Param.DecisionMapStatus == "NotFound"

If true, the missing property information is stored in:

Param.DecisionMapInvalidProperty

-- in the syntax:

[class].[property name]

Also, when the DecisionMapStatus is "NotFound", the return value is always "".

Function rules
To evaluate a map value rule an expression (rather than an activity step), your application can call one
of two standard functions: ObtainValue() or ObtainValuePair().
If the final Boolean two parameter is omitted, it defaults to false. In these examples, the first two call
have bAllowMissingProperties set to false:

@(Pega-RULES:Map).ObtainValue(tools, myStepPage, [map value name], [row input])

@(Pega-RULES:Map).ObtainValuePair(tools, myStepPage, [map value name], [row input],


[column input])

@(Pega-RULES:Map).ObtainValue(tools, myStepPage, [map value name], [row input],


[bAllowMissingProperties])

@(Pega-RULES:Map).ObtainValuePair(tools, myStepPage, [map value name], [row input],


[column input], [bAllowMissingProperties])

If a two-dimensional map value rule is called by the one-dimensional Property-Map-Value method or


ObtainValue function, the first column's values are chosen (as opposed to values from the Default
column).

Calling a map value from other rule types


In a flow rule, use the Decision shape to call a map value rule. Missing properties are always allowed.

In Declare Expression rules, you can set a property to the outcome of a map value rule. Missing
properties are handled by the Expressions facility.

Additional information
How to evaluate a decision tree and handle errors

How to evaluate a decision tree rule and handle errors


Summary
Your application can call a decision tree rule from an activity, or in an expression.

Suggested Approach

From an activity
Use the Property-Map-DecisionTree method. The return value from the decision tree is stored into the
property (or parameter or local variable) specified in the 'PropertyName' field, much as in the left-hand
side of a Property-Set.

Forthe DecisionTreeName parameter, enter the second key part of Rule-Declare-DecisionTree rule.

The Input parameter is optional and, if not blank, overrides the default input (if one is specified) in the
decision tree rule.

Check AllowMissingProperties to cause processing to continue normally even when if a referenced


property is not present (has no value). For scalar property, a property is missing if it has a value of ""./.

If you do not check the AllowMissingProperties parameter, then your application must handle the case of
a missing property. This functionality is useful. For example, assume you have a decision tree that
calculates the value of a used vehicle. When given input of "motorcycle", it needs a value for the
mileage. If the property mileage is not present or has a null value, the user can then be prompted for
the mileage.

To check for this occurrence, include the following test in the step's transition (or the next step's
precondition). Execution of a decisiont ree rule returns an output parameter.

Param.DecisionTreeStatus == "NotFound"

If true, the missing property information is stored in:


Param.DecisionTreeInvalidProperty

-- in the syntax [class].[property name].

Also, when the ParamDecisionTreeStatus is "NotFound", the return value is always "".

From an expression
In an expression, call the ObtainValue() standard function to access the value of a decision tree. The
first format always has parameter bAllowMissingProperties set to false.

@(Pega-RULES:DecisionTree).ObtainValue(tools, myStepPage, [decision tree name], [input])

@(Pega-RULES:DecisionTree).ObtainValue(tools, myStepPage, [decision tree name], [input],


[bAllowMissingProperties])

In a flow, you can use the Decision shape to call a decision tree rule. Missing properties are always
allowed.

In Declare Expression rules, you can set a property to the outcome of a decision tree. Missing
properties are handled by the Expressions facility.

Additional information
How to: call a map value rule and handle errors

How to write a structured output file using XML rules


Summary
A developer asks:

Is there a way to write a structured output file?

We require the results of work object processing for a day to be output to a structured file that becomes
an input file fed into our nightly batch process.

Update: Beginning with V5.4, you can use a Map Structured rule to create a fixed format text value
corresponding to a record. That approach is easier than the XML rule approach suggested here.

Suggested Approach
You can accomplish this using XML rules (Rule-Obj-XML rule type). Although it's a facility to create XML,
you can use it more generally.

The only thing that makes its output XML is the bracket-XML-bracket that you type yourself. Invoke the
XML rule in an activity, with the Property-Set-XML method..

Use the standard library function WriteFileOutput() to create the file.

Building and Testing Activities


Save work object details in embedded pages
Summary
A developer asks: A key task for my application is copying information from one deeply-nested page
into seven other deeply-nested pages -- then assuring that each of the seven "to" pages is valid.

The "from" is a deeply-nested page in my work object, and in the end each of the 7 'to' pages must also
be embedded into the work object.

What is the best-practice design pattern for this? By "best", I'm looking for a combination of ease of
development and high performance.

OPTION 1 - Use embedded pages within the work object. This has the advantage that both the "from"
and "to" pages can be navigated using SmartPrompts, without requiring the manual addition of Pages
and Classes entries for these deeply-nested objects.

1. Do the mapping to create the first "to" embedded page.


2. Validate this embedded page.
3. If OK, move on to the next embedded page.
4. If not OK, then back out this "to" embedded page by doing a Property-Remove.

OPTION 1A . Do the mapping for all of the embedded pages.

1. Validate the entire work object.


2. If not OK, then back out all the "to" embedded pages by doing a Property-Remove.

OPTION 2 - Use Named Pages (requires manual addition of Pages & Classes entries for each branch of
the deeply-nested "to" object.

1. Create a named page for the first "to" page.


2. Use Page-Validate to validate the named page.
3. If valid, copy this page into the work object and continue with the remaining "to" pages.

Suggested Approach
Presuming you have to do such manipulations, you should try to make it so that you do as few of them
as necessary. If you're going to have to back out, you'll want to be in a position to do that as soon as
you know that you should, in order to minimize the amount of garbage that your process produces.

Following that logic, it's better to use Option 1 of validating as you go rather than Option 1A of validating
them all in one fell swoop.

Creating a lot of nested structure that you don't really need, for the sole benefit of not having to type
entries into the Pages & Classes tab at design time, is not a good or recommended tradeoff.

How to use multistep loops and nested loops in activities


(V5.5)
Summary
Use the Add Nested Step button on the Steps tab of the Activity form to create a multistep loop. You can
nest loops within loops.

Suggested Approach
In V5.4 and earlier releases, iteration within an activity is limited to a single step. If your processing
need requires two or more steps, you must make a separate activity and include the Call statement in
the original activity.

This restriction forces activities to be shorter — and so easier to review and understand — but can
result in a large number of separate activities that are the loop "bodies".

Beginning with V5.5, the activity form includes an option that lets the scope of an iteration be multiple
steps, and allows nested iterations. Step numbering is automatic, and reflects the loop structure:

Top- level steps are numbered 1, 2, 3, as always.


An iteration that requires only a single step does not affect step numbering.
The first step in a multistep iteration has ".0" as the final portion of the step number.
Periods in the step number show the depth of a multistep iteration.

So, for example, a step numbered 11.6.0 is the starting step of an iteration that is within an iteration
that starts at step 11.0.

Procedure
To create a multistep iteration:

1. Click the iteration button to the right of the step number. Complete the fields that define the iteration
criteria.

2. In most situations, it is convenient to identify the aggregate property (such as a Page List or Page
Group) as the Step Page of that step.

3. Complete the Method and method parameters for the first step.

4. Click the Add Nested Step button ( ) to renumber this first step with a ".0" suffix. A second step
with a ".1" suffix appears immediately below the step. Click the same button again to create a third
step, and so on. Additional steps are appended below the last step of the iteration.

The page you supply in the Step Page field of the 0-numbered step applies to all later steps within the
iteration, unless you explicitly supply a different step page.

To create a nested multistep iteration, click the Add Nested Step button ( ) on a step.

Jump To Labels
Using a transition, a step can jump to another labeled step. To help prevent infinite loops and promote
good practice, the following restrictions on jumps are enforced:

The Jump To destination must be to a higher-numbered step.


Iterations are entered only at the 0-numbered step. You can't jump into a labeled step from above
the iteration.
You can exit an iteration by jumping to a labeled step that is below (has a higher number than the
number of ) the current step.
Label names (other than the // that indicates a comment step) are unique across all steps of the
activity.

Example
The Emerald Club application uses the standard Page Group property Work-.pyWorkParty. (This
property allows a work object to contain information about multiple participants ("parties") that are
involved, each identified by a role. Each page of the Page Group has a class of Data-Party.

In the Emerald Club application, some parties contained a list of "allowed-to-ship" states. The allowed
states varied from work object to work object, even for one customer.
To record this restriction, developers created a Value List property ShipToStates in the application:

For example, this clipboard presentation of one Emerald Club work object shows that the party
identified by role Depot_2 has four states for which shipping is allowed - Vermont, New Hampshire,
Massachusetts and Connecticut.

On the pyWorkPage page, the full reference of the first value is:

.pyWorkParty("Depot_02").ShipToStates(1)

The Emerald Club activity CountShipToStates uses two levels of iteration:

Step 2.0 begins an iteration over the pages in the pyWorkParty property This iteration scope ends at
step 2.2.

Step 2.1.0 begins an iteration over the values in the ShipToStates property. This iteration scope ends at
step 2.1.1.
This processing is achieved in a single activity using no CALL statements.

Use an activity, not an OnChange rule, to search elements of


a Page List
Question
A developer asks: In an activity, I am working with a Page List property that is embedded:

.ChhSvcRq.ChhNotificationAddRq.ChhParty

I need to find the unique entry on this list for which the .id property has the value "EMPLOYEE". When I
find this member of the list, I need to execute a Property-Set method.

What is the best design approach for this?

Procedurally, in an activity - putting the step in a loop to look for .id = EMPLOYEE and, when equal,
performing the Property-Set operations.

Declaratively, in an OnChange rule in the class of ChhParty.

When .id = EMPLOYEE then execute the OnChange that does the Property-Sets.

Note: This activity supports a service.

Response
Since you're calling the processing as a service, it is better to perform this processing in an activity,
procedurally.

The drawback of the OnChange approach is that the OnChange rule re-evaluates each time an element
is added to the Page List.

In a service, it is likely that it is known when all the pages of the Page List are present. After all pages
are present, the activity can run once, looping as proposed. The activity runs only once; the OnChange
rule may run dozens or hundreds of times.

How activity processing handles an exception when no Jump


To Step is specified
Summary
A developer asks: In an activity's transition, if I do not place an entry in the Jump to Step field, what
happens when the step encounters an exception?

Suggested Approach
When you specify a value in the Jump to Step field, the exception is caught and handled by transferring
control to the step you've specified. In that case, you will not see the exception in the logfile.

When you don't specify a value in the Jump to Step field, the exception is not trapped, so the exception
is displayed to the user, usually in a pop-up window with the "red X".. That is, it behaves as if no
transition was enabled.

The Pages and Classes tab must identify all referenced


embedded pages
Summary
A developer asks: In activity development, we're trying to use a page that has several embedded pages
within it. I specify a step page of .EmbeddedPage1 with method Property-Set. When I open the method
parameters, the Activity form indicates that the step page class is the class of my activity rather than
the correct class of the embedded page.

As the step page is a subpage in my primary page, I have not specified it in my Pages &Classes tab. I
would expect the rule form to recognize its correct class without my explicitly specifying it in Pages &
Classes.

Suggested Approach
You must specify the page in the Activity rule form's Pages & Classes tab to get the class recognition
that you describe.

How to return results from a called activity to the caller


Summary
A developer asks: I have an activity that calls another activity. I want the called activity to signal back
to the calling activity that things did not go well.

Is the recommended way to do that to do a Task-Status-Set, and then in the calling activity to test for
that? What is the recommended activity-to-activity return communication?

Suggested Approach
The Task-Status-Set method is for telling flows where to proceed, rather than for activity-to-activity
return messaging.

Two ways to accomplish this are routinely used:

1. Call the second activity passing a parameter page, and then in the second activity, set a
parameter on that page.

2. Set a message on the primary page of the called activity, and in the transition of the Call step in
the calling activity, check for the message.

The pxThread page contains two relevant properties: pxMethodStatus , which the StepStatusFail test
looks at; the other is pxLastActivityStatus.

You have to create a Java step to set the fail status.

The StepStatusFail test is usually sufficient in the transition of the calling activity. The overall activity
status of the called activity is considered the step status of the step in the calling activity. And the
"overall activity status" reflects the "worst error."

How to correct the Commit warning for activity rules


Summary
Remediate this high-priority warning before using the rule in a production environment.

In v5.4 sp2 or greater, use the Download High Priority Warnings option in the Application Preflight tool to
research all high-priority warnings in your application. As a best practice, perform the preflight check
before you lock a RuleSet version.

Rule
Warning Type
Type
Rule-Obj-
DataIntegrity
Activity
Name Commit
Use of the Commit method should be carefully considered to insure data integrity. In most
Message
cases, you will want to allow PRPC to handle committing a transaction.
Details N/A
Severity 1
Suggested Approach
Do not use the Commit method in an activity that has an Activity Type of Utility, Route, Assign, Notify,
or Integrator.

Flow processing performs commits automatically when the flow ends and when an assignment is
created or completed. To avoid interference with this approach, do not use Commit in the flow-related
activities in your application. (When you save an activity that uses Commit, if the Applies To key part of
the activity is derived from the Work- base class, a warning message appears).

Explicit use of the Commit method can cause data integrity issues. Flow processing already manages
the boundaries of work-related database transactions and adding commits can create synchronization
problems between what is assumed to be in the database and what actually is in the database. This
situation can make it extremely difficult to track bugs and cause data integrity issues. Additionally,
object locks are often released upon the commits, which can make it even more difficult to track and
recreate data integrity issues.

How to correct the Write Now warning for activity rules


Summary

In v5.4 sp2 or greater, use the Download High Priority Warnings option in the Application Preflight tool to
research all high-priority warnings in your application. As a best practice, perform the preflight check
before you lock a RuleSet version.

Rule
Warning Type
Type
Rule-Obj-
DataIntegrity
Activity
Name Write Now
Use of the Write Now option should be carefully considered to insure data integrity. In most
Message
cases, you will want to allow PRPC to handle committing a transaction.
Details N/A
Severity 1

Suggested Approach
Do not select WriteNow option in the Parameter Value section (on the Steps tab) when you use the Obj-
Save or Obj-Delete methods in an activity with Activity Type of Trigger, Utility, Notify, Assign, Route, or
Integrator. Use of this option is implicitly a write to the database as performed by the Commit method.
As described in Understanding the Commit warning for activity rules, flow processing performs commits
automatically when the flow ends and when an assignment is created or completed. Leave locking and
committing changes to work objects and assignments to standard activities that support flow execution.

Typically, when activity methods that save or delete objects are used, they don't cause the object to be
saved or deleted immediately. Instead, these methods set up deferred write or deferred delete
operations that are stored on a list of deferred operations. As a debugging aid, the standard HTML rule
@baseclass.DeferredOps interrogates system internals and presents an ordered list of non-immediate
(uncommitted) database operations, including Obj-Save and Obj-Delete operations. Your activity can
display this HTML rule using the Show-Page method.

Use PageExists() to test for a page before loading or clearing


the page
Summary
A developer asks:

In an activity, I want to use the Obj-Open-By-Handle method to fetch an object from the database into a
page named Customer. How do I make sure that a page with that name isn't already present on the
clipboard before I open the object?

Suggested Approach
In the activity step's precondition, use the function:

= @PageExists("Customer, tools)

--where Customer is the name of the clipboard page. Then you might want to check if the page on the
clipboard is really the same one you are about to open. Let's say you are about to do an Obj-Open-By-
Handle, and you have the handle (pzInsKey property value) stored in the variable Local.strHandle.

After the PageExists check, do the following check:

@GetInstanceHandle("Customer", tools) == Local.strHandle

If both checks return true, that means the page on the clipboard is exactly the same as the one you are
planning to open, so you can skip the Open step.

How to read the user's organization details in an activity


Summary
A developer asks: I need to access Operator ID information in one of my activities. I didn't see anything
on the clipboard that could be used. What is the best way to access this and other organization
information?

Suggested Approach
For authenticated requestors, four named pages identifying the organization, division, access group and
Operator ID are available.
The proper way to access organization information from an activity is to reference properties on these
(read-only) pages:

Org (Data-Admin-Organization class)

OrgDivision (Data-Admin-OrgDivision class)

AccessGroup (Data-Admin-Operator-AccessGroup class)

OperatorID (Data-Admin-Operator-ID class)

param.pyForEachCount holds the index of an activity ForEach


loop
Summary
A developer asks: In an activity For loop, I can specify as integer constants the start, stop, and
increment values.

1. We'd like to call, within the iteration, an activity that computes something that depends on the
current iteration number.

2. If what we're computing in that activity is, for example, a number between zero and one hundred,
we'd like to stop the iteration if the previous value is greater than 90.

How can these be done?

Suggested Approach
The activity's generated Java includes a parameter called pyForEachCount. Therefore, by sharing the
parameter page with the called activity you can compute based on the current interaction number..

For question 2, configure a transition that exits the iterations on the step.

You could also introduce a property on the primary page of the called activity, and the called activity
could modify it — and the calling activity would be able to use it in a transition step.

How to exclude a Page List element within a For loop


Summary
A developer asks: I have an embedded Page List property In an activity step, I want to loop calling
another activity. In this loop, I want to exclude the first entry in the Page List.

That is, I want the loop to call the activity on every member of the Page List except the first. What is the
recommended looping construct and precondition that I should use?

Suggested Approach
You can reference the parameter pyForEachCount that in the precondition for each embedded page
to enable you to skip the first entry. Your approach will be to the effect of the following pseudo-code:

For each embedded page, if param.pyForEachCount = 1 then exit this iteration.

When to use OUT parameters in activities


Question
On the Parameters tab of an activity, when do you use Out parameters?

Response
You can use parameters marked as out to support pass-by-reference semantics to change the value of
properties in the calling activity..
Parameters marked as In are for input only.

In parameters work as you'd expect — a value placed in the prompted-for parameter page is passed to
the called activity.

Out parameters work by expecting a property reference as values. When an out parameter is read, the
value comes from the property reference that the parameter contains. Writing to the Out parameter
causes the value to be stored in the property reference that the parameter contains.

For example: You have an activity with a parameter newLabel which is a string type, marked as an Out
parameter. The activity assigns the literal text string "Hello, World!" to param.newLabel using an
ordinary Property-Set method.

In a calling activity, you are prompted for a value for the newLabel parameter; a small red icon indicates
"out parameter". Into this field, you can enter a reference to the property that you want assignments to
that parameter to change.

At runtime, when the called activity modifies (or even reads) param.newLabel, the value is changed in
the reference that it contains.

How to provide SmartPrompts for activity parameter values


Summary
A developer asks: In activity B, I have declared a string input parameter. In every case, I expect that
activities that call activity B to use a property reference for this parameter.

For example, in a step in Activity A, I would have Call B, and for the parameter value I'd like to type:

.BusinessVariables.MyLocation

In Activity A, how can I get Activity B's parameter text box to use SmartPrompt, to help our
development team enter this property reference correctly when calling B?

Suggested Approach
On the Parameter tab of the called activity, there's a field (for each parameter in its expanded display)
labeled Type for SmartPrompt .

Specify the class Rule-Obj-Property in that field to get the SmartPrompt behavior you want.

Another field in the parameter array of the Parameter tab is labeled Validate As. The Validate As field
enables you to specify another property in the class of the activity that you can model this parameter
after. The idea of the Validate As field is that you have a parameter that has the same values as a
property in the class of the activity.

So Validate As allows values that are the same as a property that already exists, since Process
Commander has strong typing for properties but not for parameters.

For example, you can use this if you have values for a property defined on the Table Edits tab, and you
wish the same values to be in effect for a parameter.

Call the getWorstMessage() function to check for step-level


error conditions

Summary
A developer asks: I'm calling the standard activity GenerateEform to create a PDF file. I'm
getting a failure. When I trace this, I see the following error at the Java step of GenerateEform.

mStepStatus FAIL

mStepStatusInfo The property pyWorkPage.IMBRQuote.floodDeductible was of mode


Page while
com.pega.pegarules.engine.clipboard.ClipboardPropertyImpl.getStringValue() was
expecting String mode. Details: (none)
How can I programmatically get hold of the mStepStatusInfo error message, so that I can pass this
back to the caller? I've tried using @getMessagesAll (Pdf) but this doesn't seem to return any
values. (Pdf is the name of the page that will be generated.)

Suggested Approach
Use the standard function rule getWorstMessage() to obtain the step error messages.

Not every error that happens on the server is added to the page. In general, for example
when an Obj-Save fails, the message is added to the page. But something like your example is
just in the step status.

That's why you need to use getWorstMessage().

Note: If there are four or five failures, getWorstMessage just returns the most recent – as
"everything that's wrong" is not tracked.

How to create activities that run multiple connectors in


parallel
Summary
RunInParallel.

By default, a connector takes control of the requestor session until it returns a response to the
connector activity. However, when the RunInParallel parameter is selected, the connector runs as a child
requester and the activity, the parent requestor, retains control of the session. The activity can then call
another connector with a subsequent task to accomplish, and the second connector does not have to
wait for the first connector to return a response before it can start its task.

Connector activities that run connectors in parallel should do the following:

1. Because each connector needs its own copy of the step page, create a separate step page for each
connector, even if they share the same applies to class. Each child requestor (connector) makes a
copy of the step page and then returns the results in its copy. Therefore, if the activity runs each
connector on the same step page, the results from the connector that finishes last overwrite the
results from the other connectors.
2. For each connector that runs in parallel, invoke the appropriate Connect-* method with the
RunInParallel parameter selected. (For SOAP connectors, use Connect-SOAP; for JMS connectors, use
Connect-JMS; and so on.)
3. After the last Connect-* step, invoke the Connect-Wait method. This method tells Process
Commander how long to wait for all the child requestors (connectors) to return their responses.
This step should use a transition to check the step status before continuing to the next step.
4. After the Connect-Wait step, invoke the Page-Merge-Into method to copy the returned values from
all the step pages into the appropriate page.

About Child Requestors and Pages

Note the following about configuring connectors that will be invoked as child requestors:

Named pages are not passed to child requestors, so do not use named pages in the data mappings
on the Request or Response tabs of the connector rules. Also, because the connector simulator
feature works by storing the names of simulation activities on a named page (pyISSimulation), you
cannot use the connector simulator for connectors that run in parallel.
While parameter pages are passed to child requestors, they are not passed back to the parent
requestor. That is, a connector running in parallel does not return the parameter page back to the
connector activity. Therefore, you can use the parameter page in the data mapping for the request
(Map From), but not for the response (Map To).

To summarize:

To provide request properties from the connector activity (parent requestor) to the connector
(child requestor), use the step page and/or the parameter page.
To provide the response back to the connector activity, use the step page only.
Suggested Approach
Figure 1 shows an example of an activity that runs two SOAP connectors in parallel.

Figure 1. Steps tab of an example activity

Because the connectors have the same applies to class, steps 1 and 2 create individual step pages of
the same class for each of the connectors. Steps 3 and 4 provide the input for the messages that the
SOAP connectors send to the external system.

Figure 2 shows the steps that invoke the connectors.

Figure 2. Running the connectors in parallel

Step 5 uses the Connect-SOAP method with the RunInParallel parameter selected to invoke the first
connector, CreatePhoneBook1. Step 6 invokes the second connector, CreatePhoneBook2. Step 7 uses
the Connect-Wait method and to tell Process Commander to wait 2 seconds for the connectors to return
a response.

As shown in Figure 3, step 8 then calls the Page-Merge-Into method to copy the response from the
second connector into the page that holds the response from the first connector.
Figure 3. Consolidating the information returned by the connectors

About the Process Commander 5.1 Class Paths


Question
How does Process Commander load Java classes?

Response
As do many Java applications, Process Commander has more than one classloader, which means it has
more than one class path.

When you are implementing integration solutions that use Java-based services and connectors it is
important to understand

the classloader hierarchy


differences between the Process Commander runtime class path and the compile time class path
which functions and features rely on which class path (runtime versus. compile time).

This knowledge enables you to configure Process Commander so that it can successfully interact with
external class or jar files and helps you to troubleshoot NoClassDefFoundError, ClassCastException, and other Java
exceptions.

Runtime and compile time


When a requestor accesses a rule for the first time, Process Commander generates Java source files,
compiles the source files into Java class files, and then stores the files in its work (or temp) directory.
This file generation process occurs at compile time, and is called rules assembly. (In V4.X , this was
called first use assembly (FUA). You may find references to the acronym "FUA" in log and system files.)
During the compilation process, Process Commander has access to its compile time class path.

At runtime, Process Commander locates and runs the generated Java that implements the appropriate
rules in response to user or programmatic interactions. At this point, Process Commander classloader
has access to the Java classes on the runtime class path.

Location of Temp Directory

The location of the temp directory varies by system and must be unique for each node in that system.
By default, the temp directory is the work directory supplied by the application server to the Web
application component of Process Commander. If Process Commander is deployed as an embedded
application without a web component, the temp directory is located under the directory specified by the
Java system property java.io.tmpdir. To determine the current location of the temp directory, check
the PegaRULES log file.

1. From the Developer portal menu, select Tools > Log Files.
2. Select the PegaRULES log file to display it in the window.
3. On the first page of the log file, look for the message "PegaRULES effective temp path." It specifies
the current location of the temp directory.

Because the path to the application server work directory can cause the names of the generated files to
be too long on some operating systems, the location of the temp directory should have been set to a
top-level directory during installation. If it has not yet been set, configure an application server resource
setting named url/initialization/explicittempdir to set it to a top-level directory now. See the appropriate Process
Commander installation guide for guidance.
Remember that the temp directory must be unique for each node in a Process Commander system.
Multiple nodes cannot share the same temp directory.

Runtime Class Path


At runtime, Process Commander relies on the classloaders in the following list, starting at the bottom of
the hierarchy:

The Process Commander classloader, which loads all the classes (in all the jars) it finds in the
following directories:

PRGenClasses subdirectory of the temp directory.


Any .jar files specified in the prconfig.xml file through the classloader/classpath entry.

This classloader is sometimes referred to as PRClassloader.

The application server classloader that loads the Process Commander application. This classloader
loads all the classes (in all the .jars) it finds in the WEB-INF/lib and WEB-INF/classes directories when
deployed as a web application, and the APP-INF/lib directory when deployed as an enterprise
application.
Any additional application server classloaders. For example, Tomcat has a separate classloader
that loads classes from its shared directory.

The Process Commander "runtime class path" means all the class paths of all the classloaders in the
classloader hierarchy described above.

The following are examples of Process Commander processing or components that rely on the runtime
class path:

Requests made from external systems to service rules


Requests made from connectors to external systems
Data mapping for services and connectors
The integration services accelerators
HTML or XML rules that use Java code
Activities with Java steps
Function rules

If, while using any of the things in this list, your application needs a Java class that is not initially
installed with Process Commander and is not loaded by one of the other classloaders in the hierarchy,
you must add that Java class to the Process Commander runtime class path.

Compile Time Class Path


Process Commander uses a Java compiler to compile code during rules assembly. At compile time, the
Process Commander compiler has access to all the classes (in all the jars) it finds in the following
directories:

The Process Commander WEB-INF/lib and WEB-INF/classes directories when deployed as a web
application, and APP-INF/lib directory when deployed as an enterprise application.
The PRGenClasses subdirectory of the Process Commander temp directory (that is, the Java
generated by Process Commander).
Any jar files specified in the prconfig.xml file through the defaultPaths entry of the compiler node.
Any jar files supplied by the JVM as Java core classes. (For example, for Sun JVM, the rt.jar file.)

The compile time classpath does not contain classes loaded by other classloaders in the classloader
hierarchy. However, if at compile time your implementation needs access to Java classes that are
loaded by an application server classloader at runtime, you can use the following dynamic system
settings (Data-Admin-System-Settings class ) to point to those classes:

Dynamic System
Description
Setting

When you specify the fully qualified name of a Java class in this setting,
Process Commander performs a lookup to identify the location of the class—
whether it is located in a jar file or in a directory as an unarchived Java class
file. If it is available to any of the classloaders in the classloader hierarchy,
Process Commander can find it. The location of the Java class is added to the
compile time class path on system startup or when you use the Refresh
Dynamic System External Jars feature in the System Management application.
Description
Setting
The syntax convention you use to enter a value for this setting is different in
compiler/defaultClasses V5.2 than it was in V5.1. For example, say you want to add the Java classes
big.blue.Sky and big.blue.Water:

In 5.1: big/blue/Sky.class;big/blue/Water.class
In 5.2: big.blue.Sky;big.blue.Water

On a multinode system, any Java classes specified with this system setting
must be located in the same location on each server.

Note that there is no equivalent prconfig.xml file setting for this dynamic
system setting

Functions like the compiler/defaultPaths entry in the prconfig.xml file. You can use
it to specify the name of a jar file (including the path to it) or a directory with
unarchived Java classes. The specified jars and directories are added to the
compiler/defaultPaths compile time class path at system startup or when you use the Refresh
External Jars feature in the System Management application.

On a multiple node system, any jar files specified with this system setting must
be located in the same location on each server.

The following are examples of Process Commander processing or components that rely on the compile-
time class path:

Activities that call connector rules. Underlying the Call Connect-* activity methods are Invoke
activities that use PRCompiler.
The integration services accelerators.
The Test Connectivity buttons on connector and listener rule forms.
Activities with Java steps. The Java in the step is compiled each time it is used and each time it is
saved.
HTML or XML rules that use Java code.
Utility function rules.
In some cases, interactions with Java pages on the clipboard. For more information, see Working
with the Java Pages feature.

If, while using any of the things on this list, your application needs access to a Java class that does not
ship with Process Commander, you must add that Java class to the compile time class path.

Adding Third-Party jar or Java Class Files to the Class Paths


This section describes how to add third-party jar or Java class files to the Process Commander class
paths.

Runtime Class Path

To add the jar or Java class file to the runtime class path, place it in a directory where it will be loaded
by one of the classloaders in the classloader hierarchy. The best approach is to use or create a shared
directory in the application server level of the directory structure. For example:

For Tomcat, put it in the common\lib directory.


For WebSphere, use the admin console to create a Shared Library and put the .jar file there.
For WebLogic, put it in the common\lib directory.

You will most likely need to restart the application server so the appropriate classloader will find it.

Compile Time Class Path

To add a jar or Java class to the compile time class path, use the compiler's dynamic system settings.
Complete the following steps:

1. Add the jar or Java class file to the runtime class path. (Verify that the Java class or jar file is
located in Process Commander's classloader hierarchy.)
2. In Process Commander, from the Rules by Type explorer, select SysAdmin > Dynamic System
Settings.
3. Select either the compiler/defaultClasses setting or the compiler/defaultPaths setting, as
appropriate.
4. If you are using the compiler/defaultClasses setting, enter the fully qualified Java class name. If you
are using the compiler/defaultPaths setting, enter the full path to and name of the jar, or the path
to and directory name of the unarchived Java classes. In either case, use semicolons (;) to separate
entries from each other in the Value field.
5. Save the setting.
6. From the menu, select Tools > System Management Application.
7. In the System Management application, select Advanced > Class Loader Management.
8. Click Refresh External Jars to add the class or jar to the compile time class path. If it is already
included, it is not added again.

About the Compiler and Classloader Entries in prconfig.xml

In versions before V5.1, you used settings in the configuration file (formerly called pegarules.xml) to add
Java classes to the class paths. In V5.1 you can still use the configuration file to add classes to the class
paths, but to do so:

1. Undeploy Process Commander


2. Extract the prconfig.xml file
3. Make the changes
4. Repackage the Process Commander application
5. And then redeploy Process Commander.

For information about using settings in the prconfig.xml file, see the prconfig.xml File Settings Reference .

Notes and Tips

If you are working on an application in which the data passed between an external system and Process
Commander includes instances of external Java classes, verify that you are using the exact same
version of the Java class on the Process Commander system and the external system. Using different
versions of the same Java class will cause class cast exceptions.

Never place a third-party jar or Java class file in a Process Commander directory if that class file is
already being loaded by another classloader in the Process Commander classloader hierarchy. If you
need to put on the compile time class path a jar file that is loaded by the application server, use the
dynamic system settings to identify it. Do not copy the jar into a Process Commander directory. Having
the same .jar file loaded twice can cause various class loading errors.

In another example, imagine that you are configuring a service or connector that interacts with an
external application that is deployed by the same application server as is Process Commander. In this
case, you would put the third-party file in a place that is accessible to both applications, preferably in a
location where the application server will find and load it, once, for both applications. Then, you would
use the compiler's dynamic system settings to add the third-party file to the compile time class path.

Related topics

Classloading Survival Guide, a presentation from the 2004 JavaOne conference


Java.sun.com: The Source for Java Developers

About the Process Commander V4.2 class paths


Summary
As do many Java applications, Process Commander has more than one classloader, which means it
has more than one class path.

When you are implementing integration solutions that use Java-based services and connectors, it is
important to understand

the classloader hierarchy


differences between the Process Commander runtime class path and the compile time class
path
which functions and features rely on which class path (runtime versus. compile time).

This knowledge enables you to configure Process Commander so that it can successfully interact
with external class or jar files and helps you to troubleshoot class cast exceptions, class not found
exceptions, and other Java exceptions.

Runtime and Compile Time


Process Commander compiles rules into Java classes and then runs the compiled classes when it
needs them.

When Process Commander accesses rules for the first time, it generates Java source files, compiles
the source files into Java class files, and then stores the files in its work (or temp) directory. This
file generation process occurs at compile time and is called rules assembly. (In previous versions of
Process Commander, it was called first use assembly (FUA). You may still find references to the
acronym "FUA" in log and system files.) During the compilation process, Process Commander has
access to its compile time class path.

At runtime, Process Commander locates and runs the generated Java that implements the
appropriate rules in response to user or programmatic interactions. At this point, Process
Commander classloader has access to the Java classes on the runtime class path.

Location of Temp Directory

The location of the temp directory varies by system. By default, the temp directory is the work
directory supplied by the application server to the Web application component of Process
Commander. If Process Commander is deployed as an embedded application without a Web
component, the temp directory is located under the directory specified by the Java system
property java.io.tmpdir.

Because the path to the application server work directory can cause the names of the generated
files to be too long on some operating systems, you can change the location of the temp directory
to a top-level directory. You can use either the explicitTempDir parameter or the useJavaIoTempDir
parameter in the pegarules.xml file to specify the location of the temp directory. Note that as with any
change to a setting in the pegarules.xml file, you must restart Process Commander before the new
location of the temp directory is used.

Runtime Class Path


At runtime, Process Commander relies on the classloaders in the following list, starting at the
bottom of the hierarchy:

The Process Commander classloader, which loads all the classes (in all the jars) it finds in
the following directories:

PRGenClasses subdirectory of the temp directory.


Process Commander ext/lib and ext/classes directories.
Any .jar files specified in the pegarules.xml file through the classpath entry of the classloader
node.

This classloader is sometimes referred to as PRClassloader.

The application server classloader that loads the Process Commander application. This
classloader loads all the classes (in all the .jars) it finds in the Process Commander WEB-INF/lib
and WEB-INF/classes directories when deployed as a web application, and the APP-INF/lib and APP-
INF/classes directories when deployed as an enterprise application.
Any additional application server classloaders. For example, Tomcat has a separate
classloader that loads classes from its shared directory.

The Process Commander "runtime class path" means all the class paths of all the classloaders in
the classloader hierarchy described above.

The following are examples of Process Commander processing or components that rely on the
runtime class path. If while using any of the things in this list your application needs access to a
Java class that does not ship with Process Commander and is not loaded by one of the other
classloaders in the hierarchy, you must add that Java class to the runtime class path:

Requests made from external systems to service rules


Requests made from connectors to external systems
Data mapping for services and connectors
The integration services accelerators
HTML or XML stream rules that use Java code
Activities with Java steps
Utility function rules

Compile Time Class Path


Process Commander uses a Java compiler to compile code during rules assembly. At compile time,
the Process Commander compiler has access to all the classes (in all the jars) it finds in the
following directories:

The Process Commander WEB-INF/lib and WEB-INF/classes directories when deployed as a Web
application, and APP-INF/lib and APP-INF/classes when deployed as an enterprise application.
The PRGenClasses subdirectory of the Process Commander temp directory (that is, the Java
generated by Process Commander).
The Process Commander ext/lib and ext/classes directories.
Any jar files specified in the pegarules.xml file through the defaultPaths entry of the compiler node.
The servlet jar that contains the Java classes javax.servlet.http.HttpServletRequest and
javax.servlet.jsp.PageContext. The name and location of the jar depend on the application server
running Process Commander.
If it is available, the EJB jar that contains the Java class javax.ejb.EJBHome. The name and location
of the jar depend on the application server running Process Commander. If Process
Commander is running in Apache Tomcat or another non-J2EE application server, this jar
cannot be added.

The compile time classpath does not contain classes loaded by other classloaders in the
classloader hierarchy. If at compile time your implementation needs access to Java classes that are
loaded by an application server classloader at runtime, use the compiler node in the pegarules.xml file to
point to those classes. Do not place a class that is loaded by the application server in the ext\lib or
ext\classes directory.

The following are examples of Process Commander processing or components that rely on the
compile time class path. If while using any of the things on this list your application needs access
to a Java class that does not ship with Process Commander, you must add that Java class to the
compile time class path:

Activities that call connector rules. Underlying the Call Connect-* activity methods are Invoke
activities that use PRCompiler.
The integration services accelerators.
The Test Connectivity buttons on connector and listener rule forms.
Activities with Java steps. The Java in the step is compiled each time it is used and each time
it is saved.
HTML or XML rules that use Java code.
Ffunction rules.
In some cases, interactions with Java pages on the clipboard. For more information, see
Working with Java Objects.

Adding Third-Party jar or Java Class Files to the Class Paths


How you add external jars or Java classes to the Process Commander class paths depends on the
setup of the system and your intentions for the application you are developing.

For example, you should never put a third-party jar or Java class file in the Process Commander
ext/lib or ext/classes directory if that class file is already being being loaded by another classloader in
the Process Commander classloader hierarchy. If you need to put on the compile time class path a
jar file that is loaded by the application server, use the compiler node in the pegarules.xml file: do not
copy the jar into the ext/lib directory. Having the same .jar file loaded twice can cause various
class loading errors.

In another example, imagine that you are configuring a service or connector that interacts with an
external application that is deployed by the same application server as is Process Commander. In
this case, you would put the third-party file in a place that is accessible to both applications,
preferably in a location where the application server will find and load it, once, for both
applications. Then, you would use the compiler node in the pegarules.xml file to add the third-party
file to the compile time class path.

Using ext/lib and ext/classes

The easiest way to add third-party Java classes to both class paths at the same time is to put
archived classes (jar files) in the ext/lib directory and put unarchived Java classes in the ext\classes
directory. Then use an option in the System Console to refresh the class paths. (As described in the
preceding paragraphs, however, you cannot always use the ext/lib and ext/classes directories.)

Note the following:

If you are working on an application in which the data passed between an external
system and Process Commander includes instances of non-Pega Java classes, verify that
you are putting a copy of the exact same version of the Java class in the ext directory.
Using different versions of the same Java class will cause class cast exceptions.
For unarchived Java classes, the directory and subdirectory structure in the ext/classes
directory must reflect the Java package name of the classes. For example, if the fully-
qualified name of the class is com.big.blue.Sky, you would copy the Sky.class file into the
following directory:

path-to-process-commander/ ext/classes/com/big/blue

Complete the following steps:

Put the third-party Java class in the appropriate ext directory – ext/lib for jar files and ext/classes
for unarchived Java classes.
From the Administer toolbar, select System Console, and then select the Class Loader Status
link.
On the Class Summary page, do one of the following:
If you put a jar file in the ext/lib directory, click Refresh Ext Jars to add all the jar files
located in the ext/lib directory to both of the the Process Commander class paths.
If you put unarchived Java classes in the ext/classes directory, click Refresh Known
Packages to add the external Java classes to the list of known packages (which means
they are available to both class paths).

When Process Commander starts, it creates a list of all the unarchived Java packages in the
ext/classes and the temp directory. Then at runtime or compile time, Process Commander can
determine right away whether it knows about an unarchived Java class and can pass the request to
a parent classloader if it does not.

Using the Compiler and Classloader Nodes in pegarules.xml

The pegarules.xml configuration file provides a way to add Java classes to the runtime and compile
time class paths when you cannot use the ext/lib or ext/classes directory.

Use the classpath entry in the classloader node to add Java classes to the run time class path .
The pegarules.xml file should contain one classloader node only. If the file already contains a
classloader node, append your path statement to the existing classpath entry, separated by the
semicolon (;) character (even on UNIX systems). For example:

<node name="classloader">
<map>
<entry key="classpath" value="path-to-external-jar/name-of-external-jar.jar;path-to-another-
external-jar/name-of-the-other-jar.jar"/>
</map>
</node>

Use the defaultPaths entry in the compiler node to add Java classes to the compile time class path.
The pegarules.xml file should contain one compiler node only. If the file already contains a
compiler, append your path statement to the existing classpath entry, separated by the semicolon
(;) character (even on UNIX systems). For example:

<node name="compiler">
<map>
<entry key="defaultPaths"
value="path-to-external-jar/name-of-external-jar.jar;path-to-another-external-jar/name-of-the-
other-jar.jar"/>
</map>
</node>
Remember that for a jar file, you include the complete path to and name of the jar. For unarchived
Java classes, include the complete path to the directory where the class file is located.

After making changes to the pegarules.xml file, you must restart the application server hosting Process
Commander.

How to identify the class and name of a locate page


Summary
A developer asks:

I inherited responsibility for an activity that uses a page named promptMyPage. My understanding is
that if this page doesn't already exist on the clipboard, it will be created as needed. I believe that an
activity is used to create this page.

How can I discover the class and name of the activity that creates this page?

Suggested Approach
APrompt pages (also called indirect pages) appear in the parameter list of the activity when it is called
from another activity. When the activity is called, the system searches the clipbaord; if no page
matching the name after the prefix prompt is present, the activity throws an exception.

It appears that you are thinking of locatable pages, a different facility for page names that start with
the locate prefix. At run time, if such a page name is present in the clipboard when needed, its content
is validated using a supplied in the Pages & Classes definition. If the content is wrong or the page is not
in the clipboard, an activity is called to load the page.

The class of the activity may be explicitly specified on the Pages & Classes tab (using the normal format
class.activity), or it defaults to the Applies To key part of the activity. At runtime, the system uses rule
resolution to find the activity.

Locatable pages are supported by the When form, but not by the Activity form.

How to update your application when external Java classes it


uses change
When your application interacts with an external system by exchanging data that contains Java objects,
you use either the Import JavaBeans Accelerator (for services) or the Connector Accelerator (for
connectors). These accelerators examine the external Java class you identify and create Process
Commander class and property rules that represent the data model described in the Java class.

For JavaBeans, the accelerators also create Java wrapper classes that access the get and set methods
from the source Java class through the PRObjectWrapper interface of the Clipboard Public API.

Now, what do you do when the Java class that represents the objects your application exchanges is
modified? For example, perhaps the source Java class for the Java objects exchanged with an EJB
service is updated to include a new method.

This article describes several approaches for updating your Process Commander application in response
to several kinds of changes in an external Java class.

For information about enabling your application to interact with external Java objects as though they
were pages and properties on the clipboard, see Working with the Java Pages Feature . For information
about building EJB or Java connectors, see Using the Connector Accelerator .

Suggested Approach
Before you begin, remember the following

Make a backup of your application with a product zip file (Rule-Admin-Product) and store it with
your other backups. That way you can revert back to it if you need to.
If you need help putting the new Java class on the Process Commander class path, see About the
Process Commander Class Paths and Using the Connector Accelerator.

Additionally, examine the Process Commander rules (classes and properties) that represent the data
model of the data being exchanged, and determine what the Process Commander application does with
that data.

Using the "clean slate approach" for EJB and Java connectors

When you know that something has changed but you don't know exactly what the change is, or, your
application is still in development, it's best to start with a clean slate. Here are the general steps:

1. Back up your application by creating a product archive (Rule-Admin-Product). Save the connector
activities and connector rules into a different RuleSet so you can use them as a reference when
modifying the newly generated connector activities and connectors.
2. If the RuleSet is not locked, delete the existing rules by using the Cleanup function in the interface
generator record (instance of Data-Admin-InterfaceGenerator) that stores the list of rules that were
generated for the connectors(s). You can obtain the ID of the appropriate record from the Usage
field on the History tab of any of the generated rules.
3. If the RuleSet is locked and you can't delete rules, create a higher version of the RuleSet.
4. Run the Accelerator again. If you weren't able to run the Cleanup function because the RuleSet is
locked, specify that the new rules should be generated in the higher version of the RuleSet.
5. Modify the generated rules as necessary. Consult the saved activities and connectors to determine
which modifications are necessary.

Managing small, well-understood changes for EJB and Java connectors

For small, well-understood changes such as the addition of a method or a single parameter, you may
decide that it's easier to edit the existing rules than to start over with a clean slate. If you take this
approach, be sure to keep track of your modifications.

New method added

If a new method is added, determine whether your application needs to use it. If it does, you have two
options: the clean slate approach described above, or, run the Connector Accelerator, target the same
base class that you used the first time, and select the new method. After the accelerator generates the
new connector and connector activity, modify your flows as necessary to invoke the new connector.

Note that when you run the Accelerator more than once, you now have additional interface generator
records to keep track of. If at a future date you decide to use the clean slate approach, remember to use
the cleanup function for each interface generator record associated with the implementation.

New parameter added or parameter removed

If a change in a parameter was a simple change, and small in scope, you can probably just edit the
existing rules.

If there is new input to provide to a method, assess how the application will provide that input. Do you
need to create a new property? Do you need to modify a flow form to gather new data? If so, create or
edit the appropriate rules.

In the connector activity, edit the list on the Parameters tab to reflect the change. Then, on the Steps
tab, edit the Property-Set step that provides the input data for the connector.

Changes in the return value

Assess the change and determine which rules use the value returned by the connector. Update those
rules and edit the data mapping in the connector rule, as well.

Changes in the package or class name

Select the Service tab in the connector rule and edit the name specified in the Java class field.

Using the "clean slate" approach for services

When the Java class of an object that a service exchanges with an external system changes, the best
way to update your Process Commander application is to import the new JavaBean and regenerate the
Process Commander rules.

Note: You cannot change the type of an existing property rule. For example, if the type of an existing
property rule is string, you cannot change it to decimal, and neither can the accelerator. In such a case,
you must create a new property and then modify the Process Commander application to use the new
property.

Before you begin: about changes in the serialization profile

If the source Java class implements the Serializable interface, Process Commander can persist instances of
the Java class with other clipboard data. For example, it can save information from the Java object with
work items.

If your application is designed to save information from a Java object with work items, be sure to
consider possible changes to the Java source class carefully; remember that standard Java Serialization
rules apply. That is, if there are changes to the class signature of Java objects that are saved with work,
older objects won't be successfully retrieved from the database because they won't be able to be
deserialized.

Therefore, before you make any changes to a Java class, consult the following resources to learn
strategies for versioning objects:

http://java.sun.com/developer/technical
Articles/Programming/serialization/
http://java.sun.com/j2se/1.5.0/docs/guide
/serialization/spec/serialTOC.html

Import the new version of the JavaBean

1. Back up your application by creating a product archive (Rule-Admin-Product rule type).


2. If the RuleSet is not locked, delete the existing rules by using the Cleanup function in the interface
generator record (instance of Data-Admin-InterfaceGenerator) that stores the list of rules that were
generated for the connectors(s). You can obtain the ID of the appropriate record from the Usage
field on the History tab of any of the generated rules.
3. If the RuleSet is locked and you can't delete rules, create a higher version of the RuleSet.
4. Run the Import JavaBean Accelerator again. If you weren't able to run the Cleanup function
because the RuleSet is locked, specify that the new rules should be generated in the higher version
of the RuleSet.
5. Modify your application as necessary. For example, if the name of a class rule for an embedded
page property that links the data model to work objects changes, make the appropriate changes to
the work object so it is using the new class.

Java in Activities and Other Rules


A Java step requires an existing step page
Summary
A developer asks:

I have a Java step, with the embedded page .PrintResponse as the step page. In the Java, I do the
following:

ClipboardProperty base64Prop = myStepPage.getProperty(base64PropName)

This fails -- I believe because the .PrintResponse page doesn't exist (as this is the first time that I
reference any properties on this page). If I add a Page-New of .PrintResponse before calling this Java
step, all is well.

Is there a better way of doing this -- perhaps by using a method that would "create the property if its
page didn't exist"?

Suggested Approach
The step page must exist before the step begins.

The exception is a small number of activity methods that are documented to create a step page
internally, such as Page-New.

In particular, in a Java step the step page must exist before you enter your Java code.
Using Connect Java rules versus function rules to call
external Java methods
Summary
A developer asks: I have an existing Java class with fewer than a dozen methods that do computation
and return a result (no I/O, no external data, no side effects). I need to integrate these within a Process
Commander application. I have the Java source code for the class.

Design A:

Create a Rule-Utility-Library. Create a Rule-Utility-Function for each method. Call the functions from an
activity, expression, anywhere.

Design B:

Use a Rule-Connect-Java. Create an activity that accepts a parameter to determine which original Java
method to call.

When is Design B preferable? Why? Also, we do observe that for Design B, the app server needs to be
stopped and restarted whenever the CLASS files change.

Suggested Approach
if it's a simple calculation you're trying to perform, where methods don't depend on each other, where
you don't need to keep the code organized, where you don't need member variables – that is, it's less
object-oriented and instead mere calculation - then the library and function rule approach is fine..

But if you're doing something that's more complex, requires saving state, and so on, it is better to code
it in a Java class and then plug it in with a Connect Java rule.

The other benefits of Connect Java rules are:

You can use the Performance tool


You don't need the source code but can work with just the class files.
Tracer output is more complete. With Tracer you don't see the step where you're calling an
external class if that's embedded within a function.

Use Connect Java rules to call an external Java interface


Summary
This article describes two approaches to importing Java interfaces into Process Commander.

Suggested Approach
Generally when you have a Java interface, it is implemented by a class. A class may be instantiated with
a constructor or it may have a static method such as 'getInstance' by which it returns the interface.
Then, anywhere downstream you pass the interface around, and as long as the other classes are written
to talk to the interface, you're fine.

But there's always a starting point where you have to get a hook into a Java class; you can't instance an
interface.

Rule-Connect-Java rules are good for calling a single method on something. If you're stringing together
logic over several calls, it's more difficult to do.

For example, suppose you have one static method on a class, which performs some external
integration. And suppose that method takes as input a complex JavaBean. Connect Java rules are fine
for that.
But if you need to make a series of calls — for example some class that you need to instantiate, and
then call a method to get a proxy, and then call a method on the proxy to do something, etc. - is is
better to write a wrapper class that encapsulates that logic into a single method call.

In sum: If there's one class with one method that you need to call, then Connect Java is a good
candidate. If you need to make a series of calls, you probably want to wrap them in a function rule or an
external Java class that can be boiled down to one method. You can manipulate Javabeans through the
clipboard.

Working with Java Objects in Process Commander (V5.3) describes how to implement the data model of
an external Java object. It covers:

Java pages
Process Commander Java Properties
the Import Java Beans Accelerator (formerly the Create Import Rules Accelerator)
linking the data model to an application (work object)
attaching Java objects to clipboard pages (Java pages,
retrieving Java objects from clipboard pages
receiving Java objects from services
sending Java objects with connectors

Benefits of Connect Java rules


Summary
A developer asks: In V4.2, you can call (in a Java step) the Java methods in an external library after
loading the library JAR file into a certain directory on the application server.

What are the advantages and disadvantages of using Connect Java rules to reach an external library,
versus such a direct approach? That is, why use Rule-Connect-Java rules?

Suggested Approach
Here are two distinctive advantages of Connect Java rules:

1. At runtime, Rule-Connect-Java rule execution sets the Performance tool (PAL) timers for external
connections. If you have a performance issue or question, you want to learn how much elapsed time is
due to inside Process Commander processing versus outside the system. The PAL statistics available
when using Rule-Connect-Java will provide you with such data.

2. Optionally, connectors can run asynchronously, and then can sync up on the responses.

To take advantage of some such connector-like capabilities, use the Rule-Connect-Java rules.

If on the other hand, your application is simply performing a computation, there isn't a special reason to
use the Rule-Connect-Java approach versus the Java activity step approach; you can use either
approach.

Use getIfPresent() or PropertyHasValue() to test whether a


property exists
Summary
he com.pega.pegarules.pub.generator Interface CodeGenerator interface has the following function:

setUseIfPresent public void


setUseIfPresent(boolean aUseIfPresent)

Sets the flag that requests the expression code generator to use getIfPresent instead of
getProperty to resolve property references. Parameters: aUseIfPresent - true if
somePage.getIfPresent should be used.

A developer asks : Can we call this function to set the flag to true, so that if we reference a non-existing
property in our code (whether as a target of a property-set or in a when condition), it will return an error
instead of creating a new property on the clipboard?

I assume this works for referencing pages as well?

Suggested Approach
You cannot call that function directly. That Java interface is used in the rule assembly process, so
internal components like the activity assembler, and decision tree assembler,. have access to that
interface. But there's no runtime access to that Java interface..

But it sounds like your question is really: Can an activity test whether a property exists without the test
itself causing the property's creation?

You can accomplish that in a Java step with getIfPresent(). You cannot accomplish it through a normal
expression.

In other situations (outside a Java step), call the standard function rule PropertyHasValue() .

Reviewing generated Java code


Question
A developer asks: How do Process Commander rules create Java code?

Does Java generation (first use assembly) use a standard layout or template, consistent with industry-
standard approaches?.

If such a template is employed in the process, can we impose our own form of template between the
rules and the generated Java?

Our goal is that the resulting Java code comply with our organization's l standards.

Response
As you increase your use of and familiarity with rule forms, you will have less and less need or desire to
examine the generated Java in most cases.

But in the normal course of development, you either use the rule forms to create rules -- or you use your
own Java to create rules.. When you use the rule forms, there is rarely a need for you to regard the
generated Java. Most importantly, you never need to maintain by hand the code that is generated
through rule forms.

If you write your own Java code into rules — for example, edit input rules (Rule-Edit-Input rule type) or
function rules (Rule-Utility-Function rule type) — you can write it in your own preferred formats, and you
can read and recognize it in those formats.

The Java code that Process Commander generates from rules is produced by internal Java classes in the
Process Commander engine. There is no template file you can access and adapt, for two reasons:

The generated Java is very situation-specific to its environment, precluding use of a general-
purpose standard template.
The parsing and use of a template file would produce considerably more garbage for Java garbage
collection.

Within Java activity steps, edit input rules, and function rules, you can use your own Java standards and
styles.

Troubleshooting
Troubleshooting: Tracer message "Issue Loading:TraceEvent"
when testing an activity
Summary
With the Tracer on, when you try to run a specific activity, the Tracer stops and displays the error
message: Issue Loading: TraceEvent. You must close and start the Tracer again before it works. Then
you are completely unable to trace this activity.

Suggested Approach
To troubleshoot and resolve this issue, follow these steps:

1. When you test the activity, run the Fiddler Web Debugging Proxy to trace the requests and
responses of the browser session. Be sure to capture the Web traffic in an HTTP log file.
2. Check the Fiddler log. The Fiddler trace results will most likely indicate that one of the XML streams
that is generated on the application server and sent back to the Tracer is invalid. Because the
Tracer cannot parse one of the XML streams sent by the server, it displays the error message Issue
Loading:TraceEvent.
3. Check the SQL queries from the activity. If a query exists in which the system tries to obtain a
property from a TimeStamp value in the query and creates an XML element that starts with a
numeric digit, this is the cause of the problem. A valid XML document cannot contain an element
name that starts with a digit; the element must start with an alphabetic character.
4. Modify the SQL query to ensure that it creates valid XML, that is, an XML element that starts with
an alphabetic character.

Troubleshooting: differenceBetweenDates() function is


blocked
Symptom
The Release Notes for V4.2SP5 indicate that the standard Rule-Utility-Function
differenceBetweenDates() is blocked.

A developer asks: Why? This function is used in our application and seems to be working fine.

Solution
Pegasystems blocked this rule begining in V4.2SP5 because it is an exact duplicate of
differenceBetweenDays().

Adjust your application to call differenceBetweenDays().

Troubleshooting: "Invalid expression or reference" upon first


use of a new library and function
Symptom
In Version 4.1, if after you add a new library (Rule-Utility-Library instance) to the system you attempt to
reference a function from the library without first re-extracting all libraries, Process Commander reports
the following error:

Invalid expression or reference: No candidates found [possible function name, ruleset/version or


number of parameter problem] for Rule-Utility-Function
Lib( Libname :NX).CrossMultiply(vector1,vector2)

This issue is fixed in V4.2 and later.

Solution
Workaround
After adding a new library, you must re-extract all Libraries in order make activity references to
functions in the new library. To re-extract all libraries, use the System Console:

Using the System Console, select the Administration/Extract Files link from the left hand panel and
then click the ExtractLibraries button. The libraries will be re-extracted, and developers may then save
their activities.
The Extract files choice on the menu displays the Rule-Utility-Library extractor. It is possible to extract
one library in the system by entering the appropriate RuleSet and Library Name, or or all libraries by
leaving those fields blank.

Click the ExtractLibraries button to re-extract libraries.

Background
When Rule-Utility-Function rules are used in expressions (in activities or elsewhere), the Expression
Parser needs to be able to identify that particular string of characters as a Function, and validate it
against the appropriate library. In order to do this validation of function names, there are data
structures generated at the time all the Libraries are extracted and built into the library code; these
structures (lists) detail all functions, parameters, and versions that are available for that library. Since
each library is generated as a different class, there is a system class named
pega_rules_rule_utility_library.java that gets generated with the "master query function" in it that
the Expression Parser uses. This master query function knows about the list for each library, and calls
that library's function query method to get the detailed list for validation.

When a new function is added, the library of that function is regenerated. This process also regenerates
the internal list of functions for that library; since this library is already in the
pega_rules_rule_utility_library.java class, the system immediately 'notices the new function (and
therefore can validate references to it).

When a new Library is added, a rebuild of the master query function -


pega_rules_rule_utility_library.java - is required because it needs to know that there is another library to
include in its list. Unfortunately, pega_rules_rule_utility_library.java is only generated when all libraries
are extracted. Therefore, when a new library is added to the system, all libraries must be extracted to
update this class.

Resolution
This issue is fixed in V4.2 and later.

Known Issues
Issue: Invalid date format and parse errors

Symptom
Process Commander has several date formatting and retrieval functions. For example:

The Apply-Parse-XML method is used in an activity to parse an XML document to locate a


specific property value and place it on a page in the clipboard. For example, you can use
Apply-Parse-XML to locate a specific date.
The standard function rule PegaRULES.currentDate() assigns a value during a Property-Set
method. For example, the value "@CurrentDate("yyyyMMddHHmmss", "America/New York")
can be used in Property-Set method.

Certain date formatting routines may return incorrect or unexpected values. Using the two
examples above, the following error conditions may arise.:

If you use the Apply-Parse-XML method to parse an XML document to locate a specific
property value, you may receive an error stating that an incorrect date has been found.
If you call the function PegaRULES.currentDate() you may receive a string that contains an
invalid value (for example, a month number greater than 12).

Similar problems can occur when formatting or parsing numeric values, including amounts.

The cause of this error is a defect in the ICU4j library causing the library to create instances of
DateFormat and DecimalFormat.

Update: This issue is resolved in V5.3 and later versions.

Solution

To resolve this issue, you need to download and install a HotFix-419 (3 MB). file. Then follow the
instructions below to replace the pricu4j-3.4.4.jar with an updated version.

Install the Hot Fix as follows:

1. Stop the application server.


2. Depending on your deployment method, backup your current pricu4j-3.4.4.jar file which
resides in either:

-WEB-INF/lib
or
-APP-INF/lib
3. Unzip HFix-419.zip and save the updated pricu4j-3.4.4,jar as follows:

- If you have a multi-node system, repackage the existing prweb.war/ear archive with the new
pricu4j-3.4.4.jar file and re deploy the war/ear file.

- If you have a single node system. place the updated pricu4j-3.4.4.jar under directory
prweb.ear\APP-INF\lib .
4. Repackage the entire preweb.war/ear archive with the new pricu4j-3.3.4.jar file and redeploy
the war/ear file.
5. Restart the application server.

NOTES:

HFix-419 supersedes HFix-38 released in April 2007.


In addition to resolving the issues described here, HFix-419.zip includes the 2007h time zone
data that accounts for recent changes to the start and end times for Daylight Savings in some
locations.

If you experience any issues implementing this hotfix, contact Pegasystems Global Customer
Support at [email protected]

NullPointerException in ThreadLocal when running Date/Time


operations
Symptom

Update: This issue is resolved in V5.1 and later releases.

Process Commander provides a range of date/time utility functions. For example, you can call the
standard function rule named currentDate() in the DateTime library, Pega-RULES RuleSet) to assign a
value with a Property-Set method. This function has two parameters; the call:

@CurrentDate("yyyyMMddHHmmss", "America/New_York")

returns the current date in the indicated Java format for the Eastern U.S. time zone.

When you run a DateTime utility function, you may receive the following NullPointerException:

This error occurs because of the way that Process Commander initializes objects inside
ThreadLocal.initialValue().

Initializing objects inside of ThreadLocal.initialValue may cause an error if another ThreadLocal variable
has its value set directly or indirectly by any code invoked from initialValue().

For example, executing the constructor of ICU’s DateFormat results in a different ThreadLocal variable
being executed.

Solution

Workaround

To resolve this issue, obtain the correct version of B-19229.zip for your release from Global Customer
Support . This file contains a hot fix for this issue.

After obtaining the zip file, install the hot fix as follows:

1. Stop the application server


2. Backup prpublic.jar in the WEB-INF/lib directory.
3. Unzip B-19229.zip.
4. Replace the following classes:

com/pega/pegarules/pub/util/PerThreadCache.class
com/pega/pegarules/pub/util/PerThreadCache$CreateInstanceInfo.class
com/pega/pegarules/pub/util/PerThreadCache$1.class
com/pega/pegarules/pub/util/PerThreadCache$2.class
5. Zip up the new prpublic.jar.
6. Restart the application server.

Issue: Function nextBusinessDay() not working properly


Symptom
The nextBusinessDay() function locates the next business day after a date based on a Calendar:

This function uses the current or a specified date to calculate the next business day on the calendar. If a
Calendar is not identified in the function, it uses the default calendar. Access the default Calendar by
selecting View > Organization > Calendars:
The nextBusinessDay() function incorrectly calculates the next business day due to a bug in the
following JDKs:

Version 1.4.2_12
Version 5.0u8
Version 6

This bug calculates Daylight Savings Time incorrectly for the Eastern, Mountain, and Hawaiian time
zones if either of the following is true:

You use the three-letter designations (EST, MST, or HST).


You parse time settings that contain EDT, MDT, or, HDT.

Solution
To resolve this issue, do either of the following:

Download and install Sun’s fix for this issue from http://sunsolve.sun.com/show.do?target=tous
Follow the PRKB article Avoid three-character time-zone codes because they do not support
Daylight Savings Time consistently for instructions on using other indicators rather than the three-
code designations.

Issue: You can overwrite changes to Java code with "dueling"


editors
Symptom
When editing Java code in a rule form, opening an external editor window for the Java text field always
causes the contents of the Java field on the rule form to be overwritten when the external editor is later
closed.

That is, the Java text field in the rule form remains modifiable even after the external editor starts -- and
the Java text in the external editor always overwrites that in the rule form field upon the closing of the
external editor window. Unintended edits can result from two editing windows being writeable at the
same time if care is not observed.

If you make edits to the Java code in the rule form even after opening the external editor, and don't
propagate those edits to the window displaying the external editor, the changes made solely to the rule
form field will be overwritten by the text in the external editor when you close the external editor
window..
Solution
Explanation
For any rule which contains Java code, you can edit the code in the form itself:

You can click the "pencil" icon at the upper right of the text field in the form, to use an external editor to
edit the Java:

While the external editor window is opened, it is still possible to edit the Java code directly in the Rule
text field. If the external editor window is then cancelled or closed, whether or not changes have
been made or saved in that external editor, any changes made directly in the Rule text field will be
overwritten with the code from the external editor window.

Resolution
To avoid data loss, do not make Java code changes to a text field in a rule when that field is also
displayed in an external editor.

Issue: FormatDateTime() function for date and time


formatting
Symptom
A developer asks: My application accesses a Progress Software relational database that requires a time
value to be in the format:

hh:mm AM

The standard HTML Property rule Time-Short seems to do exactly what I need.
Can I to leverage this rule to format the time value before calling the RDB-Save method?

Solution
What you want is a function rule that formats the value in the desired display pattern. However, a
known issue in V4.2 is that the FormatDateTime() function ignores the format pattern
specified.

Update: This issue in FormatDateTime() is fixed in V4.2SP5 and later versions. The workaround
described in this article is necessary only with V4.2 through V4.2SP4..

Workaround
Use the standard Java SimpleDateFormat (though it generates more garbage than the function rule).

For example, for a standard datetimestamp of the current time in local time zone, you could use:

@CurrentDate("yyyyMMdd'T'HHmmss'.'SSS z", null)

-- or specify an explicit timezone as the second parameter.

Function call
When using a Process Commander V4.2SP5 or later system with the corrected FormatDateTime()
function, you can format date/time values in any way desired. For example:

@FormatDateTime(@getCurrentTimeStamp(), "dd/MMM/yyyy hh.mm a", "GMT-1", "en-US")

So for your example, use "hh:mm a" as the pattern and pick the timezone of your choice. Specify the
property or expression containing the date/time value as the first parameter..

You might also like