Previous Contents Index DocHome Next |
Process Manager 6.0 Programmer's Guide |
Chapter 1 Writing Custom Activities
This chapter describes how to write and use custom activities. The sections in this document are:
Introduction
Implementing ISimpleWorkPerformer
Writing the XML Description File
Adding a Custom Activity to the Process Map
Introduction
Process Manager lets you create custom activities as Java classes and bring them into your process definitions.Custom activities are useful when you want to do more than can easily be done in an automation script, such as when the programming logic or data resides outside of Process Manager. For example, you might build a custom activity to interface with external applications and databases. Custom activities might also run local applications and then interact with mail gateways or FAX servers.
Comparison to Automated Activities
Custom activities are similar to automated activities. In both cases:
You place them on the process map by dragging and dropping them from the Palette.
Automated and custom activities have one main difference: an automated activity is carried out by an automation script, whereas a custom activity is carried out by a Java class.They can have completion scripts.
They are triggered as soon as the process instance reaches the activity, unless the activity is deferred. A deferred activity is triggered at its specified date and time.
Usage Overview
Creating and using a custom activity involves the following major steps:
Write and compile a Java class that implements the ISimpleWorkPerformer interface.
Define an XML description file for the activity.
Package the Java class and the XML description file as a zip or jar file.
Implementing ISimpleWorkPerformer
The first step in creating a custom activity is to write a Java class that implements ISimpleWorkPerformer, an interface in the package com.netscape.pm.model. The Java class must reside in the server class path. Note also that the ISimpleWorkPerformer class you create will be stateless.ISimpleWorkPerformer defines a custom activity that:
Other than getting and setting data field values, your ISimpleWorkPerformer class has no access to information on the work item or the process instance.
Note: You can find the ISimpleWorkPerformer class in the pm60classes.jar file in the api directory on the Process Manager 6.0 CD.
This section describes the following topics:
Methods of ISimpleWorkPerformer
Methods of ISimpleWorkPerformer
ISimpleWorkPerformer has three methods:
The init( ) method is called when the application starts.
The perform( ) method is called each time the custom activity is executed. This method must be thread-safe.
The destroy( ) method is called when the application is unloaded or removed.
The init( ) method
public void init (Hashtable environment) throws ExceptionThe init() method performs initialization tasks that the custom activity requires when the application starts. For example, use init() to set up database connections that are shared by all instances of the activity, or use init() to define variables that are constant across all instances of the activity.
The init() method does not execute each time a custom activity is created in a process instance. Instead, this method is called only oncewhen the application starts.
As its input argument, init() takes a hashtable of environment variables. A hashtable is a java.util.Hashtable object that contains a series of parameter-value pairs. The parameters in the environment hashtable are defined in the ENVIRONMENT section of an XML description file.
A process designer sets the values of the hashtable parameters while creating the process map.
For example, suppose a Language parameter is defined in the environment hashtable of a custom activity. In Process Builder, the Language parameter would appear as a property for the custom activity (you would open the Inspector window and view the Properties tab).
In your Java class, define the init() method to perform the desired initialization tasks. Then, to obtain the value of a parameter in the environment hashtable, call the get() method on the environment hashtable. The get() method returns either the value of the parameter, or null if the parameter doesn't exist.
The perform( ) method
public void perform (Hashtable in, Hashtable out) throws ExceptionThe perform() method does whatever tasks must be done for the activity. This method takes two java.util.Hashtable arguments. The input hashtable contains values taken from data fields, and the output hashtable contains values to put into data fields.
The parameters in the input and output hashtables are defined in the INPUT and OUTPUT sections, respectively, of an XML description file.
The Input Hashtable
To obtain the value of a parameter in the input hashtable, call the get() method on the input hashtable. The get() method returns either the value of the parameter, or null if the parameter doesn't exist. Note that the get() method returns a Java object, so you must cast this object to the object class type that your custom activity is expecting. For example:String sizeOrder = (String) input.get("order");
The Output Hashtable
To set data field values, the perform() method must put values into the output hashtable by calling put() on the output hashtable. When the perform() method finishes executing, you then assign the values to the corresponding data fields.
The destroy( ) method
public void destroy()The destroy() method is called when the application that uses the custom activity is unloaded or removed. Typically, you use the destroy() method to clean up resources that were used by the init() method.
Sample Java Class
The following code samples are from HelloWorldPerformer.java, the class that implements the HelloWorld custom activity. HelloWorld is included in Process Manager as a sample custom activity, so you can view the source code directly.HelloWorld constructs a welcome message in either French or English. The message value is derived from two things: the value of the customerName data field in the process instance, and the Language property of the HelloWorld activity instance. The HelloWorld activity puts the welcome message in the greeting data field.
Creating HelloWorldPerformer.java
Using your favorite Java editor and compiler, create and compile a Java class that implements the ISimpleWorkPerformer interface. The compiled class file must reside in the server class path. When you use Process Builder to add a custom activity, Process Manager automatically places the custom activity's class file in the server's class path.
Note. Don't define any constructors in classes implementing ISimpleWorkPerformer, because Process Manager does not use them. A Java exception will be thrown. Defining a class without any constructors is the same as defining one with just a default constructor.
Here are the steps for creating HelloWorldPerformer.java:
Define a package for your class:
package com.netscape.pm.sample;
Import the required standard Java packages:
Define the class HelloWorldPerformer to implement com.netscape.pm.model.ISimpleWorkPerformer, as follows:
public class HelloWorldPerformer Define two variables to hold the English and French parts of the greeting. Define another variable to hold the complete greeting when it has been derived (such as "Bonjour Nikki.")
Define the init() method to get the value of the Language environment variable and to set the language-specific part of the greeting. In addition, throw an exception if the language is not provided, or if the language is neither English nor French. For example:
Define the perform() method to construct a welcome message consisting of the language-specific part of the greeting and the user's name, for example "Hello Billy." The value of the userName parameter is derived laterfrom a data field in a process instance that uses the custom activity.
- Later, you will set the exact value of the Language environment. You'll do this in Process Builder, when you set up the custom activity in a process definition.
Finally, define the destroy() method, which is invoked when the application is unloaded from the application server. In this case, the method does nothing because no resource cleanup is needed.
- Use the get() method on the input parameter to get the value of an input parameter.
public void destroy( )
{
}
// End of class }Compile HelloWorldPerformer.java to get a class file, HelloWorldPerformer.class.
Writing the XML Description File
After you write and compile the Java class that implements ISimpleWorkPerformer, your next step is to define an XML description file for the class. This XML file specifies the environment, input, and output parameters that the class uses. In addition, the XML file specifies some optional design parameters. Design parameters control the custom activity's appearance in Process Builder.This section describes the following topics:
File Format
File Format
The XML description file starts with a tag indicating the XML version, such as:The body of the description is contained between an opening <WORKPERFORMER> tag and a closing </WORKPERFORMER> tag. Within the WORKPERFORMER section you define four sections, as summarized in the following table.
Here is the structural overview of an XML description file:
WORKPERFORMER Tag
The <WORKPERFORMER> tag has four attributes: TYPE, NAME, CLASS_ID, and VERSION.
TYPE is the full package name for the Java class for this type of activity. For a simple custom activity, TYPE is always this:
Here is a sample <WORKPERFORMER> tag:com.netscape.pm.model.ISimpleWorkPerformer
NAME is the name of the custom activity (which is the same as the name of the XML description file and the jar file that contains the custom activity). This name is not currently used anywhere.
CLASS_ID is the full package name for the Java class that implements the custom activity.
VERSION is the version of the custom activity. VERSION is currently unused, but you could use it to keep version information about the description file.
<WORKPERFORMER
TYPE="com.netscape.pm.model.ISimpleWorkPerformer"
NAME="HelloWorld"
CLASS_ID="com.netscape.pm.sample.HelloWorldPerformer"
VERSION="1.1">
ENVIRONMENT Section
The <ENVIRONMENT> tag defines environment parameters that are constant within all instances of the custom activity. For example, suppose that in an application named HelloWorld, you set the value of the Language environment parameter to French. Then, the value is always French in every process instance of that application.The ENVIRONMENT section contains embedded <PARAMETER> tags. Each <PARAMETER> tag describes a parameter in the environment hashtablethe argument used by the init() method. The <ENVIRONMENT> tag has a corresponding closing </ENVIRONMENT> tag , and each <PARAMETER> tag has a closing </PARAMETER> tag.
When you add the custom activity to the process map in Process Builder, each parameter in the <ENVIRONMENT> tag will appear as a field in the Inspector Window.
Here's a sample ENVIRONMENT section:
<ENVIRONMENT>
<PARAMETER NAME="Language">"French"</PARAMETER>
</ENVIRONMENT>
Warning. Parameter values (such as "French" in the example above) are actually JavaScript expressions, so you can supply the value as a string, integer, or function. However, be sure to quote any string expression. Note that French (without quotes) and "French" (with quotes) mean different things.
For details on the syntax of the <PARAMETER> tag, see the section "PARAMETER Tag".
INPUT Section
The <INPUT> tag contains embedded <PARAMETER> tags. Each <PARAMETER> tag describes a parameter in the input hashtable, the input argument of the perform() method. The <INPUT> tag has a corresponding closing </INPUT> tag , and each <PARAMETER> tag has a closing </PARAMETER> tag.To set the value of the parameter to the value of a data field in the process instance, embed a call to getData() in the <PARAMETER> tag. For example, the following code sets the value of the userName parameter in the input hashtable to the value of the customerName data field in the process instance.
<INPUT>
<PARAMETER
NAME="userName"
DISPLAYNAME="User Name"
TYPE="java.lang.String"
DESCRIPTION="Last Name">
getData("customerName")
</PARAMETER>
</INPUT>For details on the syntax of the <PARAMETER> tag, see the section "PARAMETER Tag".
The corresponding code in your Java class file uses the perform() method to get the value of the userName parameter. Within the perform() method, you call the get() method. Here is a code fragment:
OUTPUT Section
The <OUTPUT> tag contains embedded <PARAMETER> tags. Each <PARAMETER> tag describes a parameter in the output hashtable, the output argument of the perform() method. The <OUTPUT> tag has a corresponding closing </OUTPUT> tag , and each <PARAMETER> tag has a closing </PARAMETER> tag.The output hashtable contains parameters whose values will be automatically installed in data fields in the process instance. For each parameter, embed a call to mapTo() to indicate which data field in the process instance is to receive the value of the parameter.
For example, the following code specifies that when the perform() method has finished executing, the value of the welcomeMsg parameter in the output hashtable is automatically installed in the greeting data field in the process instance.
<OUTPUT>
<PARAMETER
NAME="welcomeMsg"
DISPLAYNAME="Welcome Message"
TYPE="java.lang.String"
DESCRIPTION="Greeting for the user">
mapTo("greeting")
</PARAMETER>
</OUTPUT>For details on the syntax of the <PARAMETER> tag, see the section "PARAMETER Tag".
The corresponding code in your Java class file uses the perform() method to put a value in the welcomeMsg parameter of the output hashtable. Within the perform() method, call the put() method:
output.put( "welcomeMessage" , msg );
PARAMETER Tag
The <PARAMETER> tag has the attributes as summarized in the following table. When you define parameters within the DESIGN section of the XML description file, only the NAME and DESCRIPTION attributes apply. However, within the ENVIRONMENT, INPUT, or OUTPUT sections, all of the attributes apply.
DESIGN Section
The <DESIGN> tag contains embedded <PARAMETER> tags. Each <PARAMETER> tag describes a parameter in the output hashtable, the output argument of the perform() method. The <DESIGN> tag has a corresponding closing </DESIGN> tag , and each <PARAMETER> tag has a closing </PARAMETER> tag.Use the DESIGN section to define the custom activity's user interface within Process Builder. In the DESIGN section, the <PARAMETER> tag accepts two attributes: NAME and DESCRIPTION.
By setting the NAME attribute, you define a particular aspect of the custom activity's user interface. The following table summarizes the available values for the NAME attribute:
Sample XML Description File
Define a file called HelloWorld.xml as shown below. Things to note are:
This file specifies userName as a parameter in the input hash table. However, the value of this parameter is obtained from the customerName data field in the process instance.
Here is the entire code for the HelloWorld.xml description file:Similarly, the file specifies welcomeMsg as a parameter in the output hashtable, and maps its value back into the greeting data field in the process instance.
Packaging a Custom Activity
After you create the Java class file and the XML description file, the next step is to package the custom activity. A custom activity consists of the following files:
One or more Java classes. At least one of these classes must implement ISimpleWorkPerformer.
Create a zip or jar archive that contains these files. The archive must have the same root name as the XML file. For example, if the XML file is HelloWorld.xml, then name the zip file HelloWorld.zip.As you create the archive, check that the directory structure reflects the package structure of the class. For example, the HelloWorldPerformer class is in the package com.netscape.pm.sample. Therefore, the class file must be in the directory com/netscape/pm/sample, as shown in Figure 1-1. The HelloWorld.xml file must be at the top level.
Figure 1-1    Directory structure for the HelloWorld activity
Note the two image files, drap_fr2.gif and drap_uk2.gif. These images will be used by Process Builder in the process map. The images, shown in Figure 1-2, will correspond to the selected state of the Language property, either French or English.
Figure 1-2    Image files in the HelloWorld activity
Adding a Custom Activity to the Process Map
There are two ways to add a custom activity to the process map:
In one case you create a custom palette. This approach is useful if you intend to use a custom activity often, either within a single application or across several applications.
In the other case, you don't create a custom palette, and you simply use the Custom Activity icon provided with Process Builder. This approach might be better if you rarely use custom activities, and you don't want to create a custom palette for them.
Adding a Custom Activity from a Custom Palette
To use a custom activity from a custom palette, do the following:
In the palette, right-click the area below the title bar, and choose "Add custom palette," as shown in Figure 1-3. This adds a new tab to the palette.
Figure 1-3    Adding a custom palette
In the "New palette name" dialog box (shown in Figure 1-4), type the label for the new tab. For example, enter "HelloWorld".
Figure 1-4    Enter a name for the new palette
Click your new custom tab to make it active. Note that the area contains no icons.
Right-click in the empty area under the tabs, and select "Add Custom Activity ...". See Figure 1-5.
Figure 1-5    Add a custom activity to the palette
Using the file selection window, locate the archive file that represents the custom activity, and select the file. For example, Figure 1-6 show the selection of HelloWorld.zip:
Figure 1-6    Select the file that represents a custom activity
- The custom activity is added to your new palette. For example, as shown in Figure 1-7, the HelloWorld activity appears on the palette like this:
Figure 1-7    A custom activity icon appearing on the HelloWorld custom palette
Adding a Custom Activity without Using a Custom Palette
If you don't have a custom palette icon or don't want to create one, you can add a custom activity as follows:
In the palette, drag the Custom Activity icon
to the process map.Select the custom activity and open the Inspector window.
On the Properties tab of the Inspector, locate the property named Custom Activity.
Click the Browse button to bring up a file selection window, and locate the zip or jar file that represents the custom activity. An example is shown in Figure 1-8.
Figure 1-8    Setting the Custom Activity property
Click Open to associate the selected file with the Custom Activity icon. The Custom Activity icon now has the characteristics defined by the file.
Working with a Custom Activity
After you place a custom activity on the process map, you can view or set its properties in the Inspector window. For example, Figure 1-9 shows the Inspector window's Input tab for HelloWorld.
Figure 1-9    Input properties for a custom activity
The Input tab shows the parameter names in the input hashtable, and shows how the value for each parameter is derived. In this case, the value for the input parameter userName is derived by getting the value of the customerName datafield.
The INPUT section of the XML description file determines the appearance of the Input tab in the Inspector window. For example, note that the userName parameter displays as "User Name," which was specified through the DISPLAYNAME attribute in the XML file.
Similarly, the Output tab shows the parameter names in the output hashtable, and shows how the value for each parameter is mapped back into the process instance. In this case, the value for the output parameter welcomeMsg is put in the greeting data field.
As you design the process, be sure to add the data fields that are used by the custom activity. For example, the HelloWorld activity uses two Textfields: greeting and customerName.
Implementation Tips
This section describes some of the design tips you should consider as you create and implement a custom activity.
Avoid Instance Data
Custom activities, like custom fields, are stateless entities. There can be only one instance of a custom activity per Java Virtual Machine. The custom activity must be multithreaded. This means the activity must safely handle calls from concurrent requests.As a result, it's recommended that you avoid using instance data in the class that implements a custom activity, particularly if the perform() method is likely to change this data. If you can't avoid using instance data, be sure to synchronize the data. With unsynchronized data, a variable set during one request might not exist for the next request.
Use Consistent Data Types
Watch for consistent data typing. Make sure that the data types you specify in the XML file are consistent with the corresponding values you pass to the input and output hashtables. Although Process Manager performs some basic data matching for you, inconsistent data is likely to generate an error.
Avoid Non-default Constructors
In classes that implement ISimpleWorkPerformer, avoid defining non-default constructors (meaning constructors with non-zero arguments). Otherwise, you may encounter problems during dynamic loading. The problem may arise because Process Manager dynamically loads the class that implements your custom activity. In other words, Process Manager has no prior awareness of non-default constructors and therefore cannot call them.
When to Use a Custom Activity
Custom activities are useful when you want to integrate an existing legacy process into a Process Manager process through a well-defined interface. For example, use a custom activity in a Process Manager process that exchanges data with external resources such as a CORBA server, a CICS system, or the business logic in an EJB component.By contrast, custom activities are not a good solution if you must represent a complex data structure from an external source. For example, to represent result sets or other data types from Oracle databases or SAP R/3 systems, you are better off using a custom field. Reserve custom activities for situations where data can be easily parsed and stored (either directly in a data field or in the content store).
Previous Contents Index DocHome Next
Copyright © 2000 Sun Microsystems, Inc. Some preexisting portions Copyright © 2000 Netscape Communications Corp. All rights reserved.
Last Updated May 02, 2000